Mercurial > geeqie
annotate src/editors.c @ 135:15c1925b3bfb
improved external delete command
| author | nadvornik |
|---|---|
| date | Thu, 16 Aug 2007 20:57:09 +0000 |
| parents | 9009856628f7 |
| children | 18c2a29e681c |
| rev | line source |
|---|---|
| 9 | 1 /* |
| 2 * GQview | |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
3 * (C) 2006 John Ellis |
| 9 | 4 * |
| 5 * Author: John Ellis | |
| 6 * | |
| 7 * This software is released under the GNU General Public License (GNU GPL). | |
| 8 * Please read the included file COPYING for more information. | |
| 9 * This software comes with no warranty of any kind, use at your own risk! | |
| 10 */ | |
| 11 | |
| 12 | |
| 13 #include "gqview.h" | |
| 14 #include "editors.h" | |
| 15 | |
| 16 #include "utilops.h" | |
| 17 #include "ui_fileops.h" | |
| 18 #include "ui_spinner.h" | |
| 19 #include "ui_utildlg.h" | |
| 20 | |
| 21 #include <errno.h> | |
| 22 | |
| 23 | |
| 24 #define EDITOR_WINDOW_WIDTH 500 | |
| 25 #define EDITOR_WINDOW_HEIGHT 300 | |
| 26 | |
| 27 #define COMMAND_SHELL "sh" | |
| 28 #define COMMAND_OPT "-c" | |
| 29 | |
| 30 | |
| 31 typedef struct _EditorVerboseData EditorVerboseData; | |
| 32 struct _EditorVerboseData { | |
| 33 int fd; | |
| 34 | |
| 35 GenericDialog *gd; | |
| 36 GtkWidget *button_close; | |
| 37 GtkWidget *button_stop; | |
| 38 GtkWidget *text; | |
| 39 GtkWidget *progress; | |
| 40 GtkWidget *spinner; | |
| 41 gint count; | |
| 42 gint total; | |
| 43 | |
| 44 gchar *command_template; | |
| 45 GList *list; | |
| 46 }; | |
| 47 | |
| 48 | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
49 static gchar *editor_slot_defaults[GQVIEW_EDITOR_SLOTS * 2] = { |
| 9 | 50 N_("The Gimp"), "gimp-remote -n %f", |
| 51 N_("XV"), "xv %f", | |
| 52 N_("Xpaint"), "xpaint %f", | |
| 53 NULL, NULL, | |
| 54 NULL, NULL, | |
| 55 NULL, NULL, | |
| 56 NULL, NULL, | |
| 57 NULL, NULL, | |
| 58 N_("Rotate jpeg clockwise"), "%vif jpegtran -rotate 90 -copy all -outfile %p_tmp %p; then mv %p_tmp %p;else rm %p_tmp;fi", | |
| 59 N_("Rotate jpeg counterclockwise"), "%vif jpegtran -rotate 270 -copy all -outfile %p_tmp %p; then mv %p_tmp %p;else rm %p_tmp;fi", | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
60 /* special slots */ |
|
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
61 "External Copy command", NULL, |
|
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
62 "External Move command", NULL, |
|
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
63 "External Rename command", NULL, |
|
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
64 "External Delete command", NULL, |
|
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
65 "External New Folder command", NULL |
| 9 | 66 }; |
| 67 | |
| 68 static void editor_verbose_window_progress(EditorVerboseData *vd, const gchar *text); | |
| 69 static gint editor_command_next(EditorVerboseData *vd); | |
| 70 | |
| 71 | |
| 72 /* | |
| 73 *----------------------------------------------------------------------------- | |
| 74 * external editor routines | |
| 75 *----------------------------------------------------------------------------- | |
| 76 */ | |
| 77 | |
| 78 void editor_reset_defaults(void) | |
| 79 { | |
| 80 gint i; | |
| 81 | |
| 82 for (i = 0; i < GQVIEW_EDITOR_SLOTS; i++) | |
| 83 { | |
| 84 g_free(editor_name[i]); | |
| 85 editor_name[i] = g_strdup(_(editor_slot_defaults[i * 2])); | |
| 86 g_free(editor_command[i]); | |
| 87 editor_command[i] = g_strdup(editor_slot_defaults[i * 2 + 1]); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 static void editor_verbose_window_close(GenericDialog *gd, gpointer data) | |
| 92 { | |
| 93 EditorVerboseData *vd = data; | |
| 94 | |
| 95 generic_dialog_close(gd); | |
| 96 g_free(vd->command_template); | |
| 97 g_free(vd); | |
| 98 } | |
| 99 | |
| 100 static void editor_verbose_window_stop(GenericDialog *gd, gpointer data) | |
| 101 { | |
| 102 EditorVerboseData *vd = data; | |
| 103 | |
| 104 path_list_free(vd->list); | |
| 105 vd->list = NULL; | |
| 106 | |
| 107 vd->count = 0; | |
| 108 editor_verbose_window_progress(vd, _("stopping...")); | |
| 109 } | |
| 110 | |
| 111 static void editor_verbose_window_enable_close(EditorVerboseData *vd) | |
| 112 { | |
| 113 vd->gd->cancel_cb = editor_verbose_window_close; | |
| 114 | |
| 115 spinner_set_interval(vd->spinner, -1); | |
| 116 gtk_widget_set_sensitive(vd->button_stop, FALSE); | |
| 117 gtk_widget_set_sensitive(vd->button_close, TRUE); | |
| 118 } | |
| 119 | |
| 120 static EditorVerboseData *editor_verbose_window(const gchar *template, const gchar *text) | |
| 121 { | |
| 122 EditorVerboseData *vd; | |
| 123 GtkWidget *scrolled; | |
| 124 GtkWidget *hbox; | |
| 125 gchar *buf; | |
| 126 | |
| 127 vd = g_new0(EditorVerboseData, 1); | |
| 128 | |
| 129 vd->list = NULL; | |
| 130 vd->command_template = g_strdup(template); | |
| 131 vd->total = 0; | |
| 132 vd->count = 0; | |
| 133 vd->fd = -1; | |
| 134 | |
| 135 vd->gd = file_util_gen_dlg(_("Edit command results"), "GQview", "editor_results", | |
| 136 NULL, FALSE, | |
| 137 NULL, vd); | |
| 138 buf = g_strdup_printf(_("Output of %s"), text); | |
| 139 generic_dialog_add_message(vd->gd, NULL, buf, NULL); | |
| 140 g_free(buf); | |
| 141 vd->button_stop = generic_dialog_add_button(vd->gd, GTK_STOCK_STOP, NULL, | |
| 142 editor_verbose_window_stop, FALSE); | |
| 143 gtk_widget_set_sensitive(vd->button_stop, FALSE); | |
| 144 vd->button_close = generic_dialog_add_button(vd->gd, GTK_STOCK_CLOSE, NULL, | |
| 145 editor_verbose_window_close, TRUE); | |
| 146 gtk_widget_set_sensitive(vd->button_close, FALSE); | |
| 147 | |
| 148 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
| 149 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
| 150 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
| 151 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 152 gtk_box_pack_start(GTK_BOX(vd->gd->vbox), scrolled, TRUE, TRUE, 5); | |
| 153 gtk_widget_show(scrolled); | |
| 154 | |
| 155 vd->text = gtk_text_view_new(); | |
| 156 gtk_text_view_set_editable(GTK_TEXT_VIEW(vd->text), FALSE); | |
| 157 gtk_widget_set_size_request(vd->text, EDITOR_WINDOW_WIDTH, EDITOR_WINDOW_HEIGHT); | |
| 158 gtk_container_add(GTK_CONTAINER(scrolled), vd->text); | |
| 159 gtk_widget_show(vd->text); | |
| 160 | |
| 161 hbox = gtk_hbox_new(FALSE, 0); | |
| 162 gtk_box_pack_start(GTK_BOX(vd->gd->vbox), hbox, FALSE, FALSE, 0); | |
| 163 gtk_widget_show(hbox); | |
| 164 | |
| 165 vd->progress = gtk_progress_bar_new(); | |
| 166 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(vd->progress), 0.0); | |
| 167 gtk_box_pack_start(GTK_BOX(hbox), vd->progress, TRUE, TRUE, 0); | |
| 168 gtk_widget_show(vd->progress); | |
| 169 | |
| 170 vd->spinner = spinner_new(NULL, SPINNER_SPEED); | |
| 171 gtk_box_pack_start(GTK_BOX(hbox), vd->spinner, FALSE, FALSE, 0); | |
| 172 gtk_widget_show(vd->spinner); | |
| 173 | |
| 174 gtk_widget_show(vd->gd->dialog); | |
| 175 | |
| 176 return vd; | |
| 177 } | |
| 178 | |
| 179 static void editor_verbose_window_fill(EditorVerboseData *vd, gchar *text, gint len) | |
| 180 { | |
| 181 GtkTextBuffer *buffer; | |
| 182 GtkTextIter iter; | |
| 183 | |
| 184 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vd->text)); | |
| 185 gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1); | |
| 186 gtk_text_buffer_insert(buffer, &iter, text, len); | |
| 187 } | |
| 188 | |
| 189 static void editor_verbose_window_progress(EditorVerboseData *vd, const gchar *text) | |
| 190 { | |
| 191 if (vd->total) | |
| 192 { | |
| 193 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(vd->progress), (double)vd->count / vd->total); | |
| 194 } | |
| 195 | |
| 196 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(vd->progress), (text) ? text : ""); | |
| 197 } | |
| 198 | |
| 199 static gboolean editor_verbose_io_cb(GIOChannel *source, GIOCondition condition, gpointer data) | |
| 200 { | |
| 201 EditorVerboseData *vd = data; | |
| 202 gchar buf[512]; | |
| 203 gsize count; | |
| 204 | |
| 205 switch (condition) | |
| 206 { | |
| 207 case G_IO_IN: | |
| 208 while (g_io_channel_read_chars(source, buf, sizeof(buf), &count, NULL) == G_IO_STATUS_NORMAL) | |
| 209 { | |
| 210 if (!g_utf8_validate(buf, count, NULL)) | |
| 211 { | |
| 212 gchar *utf8; | |
| 213 utf8 = g_locale_to_utf8(buf, count, NULL, NULL, NULL); | |
| 214 if (utf8) | |
| 215 { | |
| 216 editor_verbose_window_fill(vd, utf8, -1); | |
| 217 g_free(utf8); | |
| 218 } | |
| 219 else | |
| 220 { | |
| 221 editor_verbose_window_fill(vd, "GQview: Error converting text to valid utf8\n", -1); | |
| 222 } | |
| 223 } | |
| 224 else | |
| 225 { | |
| 226 editor_verbose_window_fill(vd, buf, count); | |
| 227 } | |
| 228 } | |
| 229 break; | |
| 230 case G_IO_ERR: | |
| 231 printf("Error reading from command\n"); | |
| 232 case G_IO_HUP: | |
| 233 if (debug) printf("Editor command HUP\n"); | |
| 234 default: | |
| 235 while (g_source_remove_by_user_data(vd)); | |
| 236 close(vd->fd); | |
| 237 vd->fd = -1; | |
| 238 editor_command_next(vd); | |
| 239 return FALSE; | |
| 240 break; | |
| 241 } | |
| 242 | |
| 243 return TRUE; | |
| 244 } | |
| 245 | |
| 246 static int command_pipe(char *command) | |
| 247 { | |
| 248 char *args[4]; | |
| 249 int fpipe[2]; | |
| 250 pid_t fpid; | |
| 251 | |
| 252 args[0] = COMMAND_SHELL; | |
| 253 args[1] = COMMAND_OPT; | |
| 254 args[2] = command; | |
| 255 args[3] = NULL; | |
| 256 | |
| 257 if (pipe(fpipe) < 0) | |
| 258 { | |
| 259 printf("pipe setup failed: %s\n", strerror(errno)); | |
| 260 return -1; | |
| 261 } | |
| 262 | |
| 263 fpid = fork(); | |
| 264 if (fpid < 0) | |
| 265 { | |
| 266 /* fork failed */ | |
| 267 printf("fork failed: %s\n", strerror(errno)); | |
| 268 } | |
| 269 else if (fpid == 0) | |
| 270 { | |
| 271 /* child */ | |
| 272 gchar *msg; | |
| 273 | |
| 274 dup2(fpipe[1], 1); | |
| 275 dup2(fpipe[1], 2); | |
| 276 close(fpipe[0]); | |
| 277 | |
| 278 execvp(args[0], args); | |
| 279 | |
| 280 msg = g_strdup_printf("Unable to exec command:\n%s\n\n%s\n", command, strerror(errno)); | |
| 281 write(1, msg, strlen(msg)); | |
| 282 | |
| 283 _exit(1); | |
| 284 } | |
| 285 else | |
| 286 { | |
| 287 /* parent */ | |
| 288 fcntl(fpipe[0], F_SETFL, O_NONBLOCK); | |
| 289 close(fpipe[1]); | |
| 290 | |
| 291 return fpipe[0]; | |
| 292 } | |
| 293 | |
| 294 return -1; | |
| 295 } | |
| 296 | |
| 297 static gint editor_verbose_start(EditorVerboseData *vd, gchar *command) | |
| 298 { | |
| 299 GIOChannel *channel; | |
| 300 int fd; | |
| 301 | |
| 302 fd = command_pipe(command); | |
| 303 if (fd < 0) | |
| 304 { | |
| 305 gchar *buf; | |
| 306 | |
| 307 buf = g_strdup_printf(_("Failed to run command:\n%s\n"), command); | |
| 308 editor_verbose_window_fill(vd, buf, strlen(buf)); | |
| 309 g_free(buf); | |
| 310 | |
| 311 return FALSE; | |
| 312 } | |
| 313 | |
| 314 vd->fd = fd; | |
| 315 channel = g_io_channel_unix_new(fd); | |
| 316 | |
| 317 g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_IN, | |
| 318 editor_verbose_io_cb, vd, NULL); | |
| 319 g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_ERR, | |
| 320 editor_verbose_io_cb, vd, NULL); | |
| 321 g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, G_IO_HUP, | |
| 322 editor_verbose_io_cb, vd, NULL); | |
| 323 g_io_channel_unref(channel); | |
| 324 | |
| 325 return TRUE; | |
| 326 } | |
| 327 | |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
328 static gchar *editor_command_path_parse(const gchar *path) |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
329 { |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
330 GString *string; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
331 gchar *pathl; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
332 const gchar *p; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
333 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
334 string = g_string_new(""); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
335 p = path; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
336 while (*p != '\0') |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
337 { |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
338 /* must escape \, ", `, and $ to avoid problems, |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
339 * we assume system shell supports bash-like escaping |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
340 */ |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
341 if (strchr("\\\"`$", *p) != NULL) |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
342 { |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
343 string = g_string_append_c(string, '\\'); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
344 } |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
345 string = g_string_append_c(string, *p); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
346 p++; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
347 } |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
348 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
349 pathl = path_from_utf8(string->str); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
350 g_string_free(string, TRUE); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
351 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
352 return pathl; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
353 } |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
354 |
| 9 | 355 static gint editor_command_one(const gchar *template, const gchar *path, EditorVerboseData *vd) |
| 356 { | |
| 357 GString *result = NULL; | |
| 358 gchar *pathl; | |
| 359 gchar *found; | |
| 360 const gchar *ptr; | |
| 361 gchar path_buffer[512]; | |
| 362 gchar *current_path; | |
| 363 gint path_change = FALSE; | |
| 364 gint ret; | |
| 365 | |
| 366 current_path = getcwd(path_buffer, sizeof(path_buffer)); | |
| 367 | |
| 368 result = g_string_new(""); | |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
369 pathl = editor_command_path_parse(path); |
| 9 | 370 |
| 371 ptr = template; | |
| 372 while ( (found = strstr(ptr, "%p")) ) | |
| 373 { | |
| 374 result = g_string_append_len(result, ptr, found - ptr); | |
| 375 ptr = found + 2; | |
| 376 result = g_string_append_c(result, '"'); | |
| 377 result = g_string_append(result, pathl); | |
| 378 result = g_string_append_c(result, '"'); | |
| 379 } | |
| 380 result = g_string_append(result, ptr); | |
| 381 | |
| 382 if (debug) printf("system command: %s\n", result->str); | |
| 383 | |
| 384 if (current_path) | |
| 385 { | |
| 386 gchar *base; | |
| 387 base = remove_level_from_path(path); | |
| 388 if (chdir(base) == 0) path_change = TRUE; | |
| 389 g_free(base); | |
| 390 } | |
| 391 | |
| 392 if (vd) | |
| 393 { | |
| 394 result = g_string_append(result, " 2>&1"); | |
| 395 ret = editor_verbose_start(vd, result->str); | |
| 396 } | |
| 397 else | |
| 398 { | |
| 135 | 399 ret = !system(result->str); |
| 9 | 400 } |
| 401 | |
| 402 if (path_change) chdir(current_path); | |
| 403 | |
| 404 g_string_free(result, TRUE); | |
| 405 g_free(pathl); | |
| 406 | |
| 407 return ret; | |
| 408 } | |
| 409 | |
| 410 static gint editor_command_next(EditorVerboseData *vd) | |
| 411 { | |
| 412 const gchar *text; | |
| 413 | |
| 414 editor_verbose_window_fill(vd, "\n", 1); | |
| 415 | |
| 416 while (vd->list) | |
| 417 { | |
| 418 gchar *path; | |
| 419 gint success; | |
| 420 | |
| 421 path = vd->list->data; | |
| 422 vd->list = g_list_remove(vd->list, path); | |
| 423 | |
| 424 editor_verbose_window_progress(vd, path); | |
| 425 | |
| 426 vd->count++; | |
| 427 success = editor_command_one(vd->command_template, path, vd); | |
| 428 if (success) | |
| 429 { | |
| 430 gtk_widget_set_sensitive(vd->button_stop, (vd->list != NULL) ); | |
| 431 editor_verbose_window_fill(vd, path, strlen(path)); | |
| 432 editor_verbose_window_fill(vd, "\n", 1); | |
| 433 } | |
| 434 | |
| 435 g_free(path); | |
| 436 if (success) return TRUE; | |
| 437 } | |
| 438 | |
| 439 if (vd->count == vd->total) | |
| 440 { | |
| 441 text = _("done"); | |
| 442 } | |
| 443 else | |
| 444 { | |
| 445 text = _("stopped by user"); | |
| 446 } | |
| 447 vd->count = 0; | |
| 448 editor_verbose_window_progress(vd, text); | |
| 449 editor_verbose_window_enable_close(vd); | |
| 450 return FALSE; | |
| 451 } | |
| 452 | |
| 135 | 453 static gint editor_command_start(const gchar *template, const gchar *text, GList *list) |
| 9 | 454 { |
| 455 EditorVerboseData *vd; | |
| 456 | |
| 457 vd = editor_verbose_window(template, text); | |
| 458 vd->list = path_list_copy(list); | |
| 459 vd->total = g_list_length(list); | |
| 460 | |
| 135 | 461 return editor_command_next(vd); |
| 9 | 462 } |
| 463 | |
| 464 static gint editor_line_break(const gchar *template, gchar **front, const gchar **end) | |
| 465 { | |
| 466 gchar *found; | |
| 467 | |
| 468 *front = g_strdup(template); | |
| 469 found = strstr(*front, "%f"); | |
| 470 | |
| 471 if (found) | |
| 472 { | |
| 473 *found = '\0'; | |
| 474 *end = found + 2; | |
| 475 return TRUE; | |
| 476 } | |
| 477 | |
| 478 *end = ""; | |
| 479 return FALSE; | |
| 480 } | |
| 481 | |
| 482 /* | |
| 483 * The supported macros for editor commands: | |
| 484 * | |
| 485 * %f first occurence replaced by quoted sequence of filenames, command is run once. | |
| 486 * only one occurence of this macro is supported. | |
| 487 * ([ls %f] results in [ls "file1" "file2" ... "lastfile"]) | |
| 488 * %p command is run for each filename in turn, each instance replaced with single filename. | |
| 489 * multiple occurences of this macro is supported for complex shell commands. | |
| 490 * This macro will BLOCK THE APPLICATION until it completes, since command is run once | |
| 491 * for every file in syncronous order. To avoid blocking add the %v macro, below. | |
| 492 * ([ls %p] results in [ls "file1"], [ls "file2"] ... [ls "lastfile"]) | |
| 493 * none if no macro is supplied, the result is equivalent to "command %f" | |
| 494 * ([ls] results in [ls "file1" "file2" ... "lastfile"]) | |
| 495 * | |
| 496 * Only one of the macros %f or %p may be used in a given commmand. | |
| 497 * | |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
498 * %v must be the first two characters[1] in a command, causes a window to display |
| 9 | 499 * showing the output of the command(s). |
| 500 * %V same as %v except in the case of %p only displays a window for multiple files, | |
| 501 * operating on a single file is suppresses the output dialog. | |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
502 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
503 * %w must be first two characters in a command, presence will disable full screen |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
504 * from exiting upon invocation. |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
505 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
506 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
507 * [1] Note: %v,%V may also be preceded by "%w". |
| 9 | 508 */ |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
509 static gint editor_command_run(const gchar *template, const gchar *text, GList *list) |
| 9 | 510 { |
| 511 gint verbose = FALSE; | |
| 512 gint for_each = FALSE; | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
513 gint ret = TRUE; |
| 9 | 514 |
| 515 if (!template || template[0] == '\0') return; | |
| 516 | |
| 517 for_each = (strstr(template, "%p") != NULL); | |
| 518 | |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
519 /* no window state change flag, skip */ |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
520 if (strncmp(template, "%w", 2) == 0) template += 2; |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
521 |
| 9 | 522 if (strncmp(template, "%v", 2) == 0) |
| 523 { | |
| 524 template += 2; | |
| 525 verbose = TRUE; | |
| 526 } | |
| 527 else if (strncmp(template, "%V", 2) == 0) | |
| 528 { | |
| 529 template += 2; | |
| 530 if (!for_each || list->next) verbose = TRUE; | |
| 531 } | |
| 532 | |
| 533 if (for_each) | |
| 534 { | |
| 535 if (verbose) | |
| 536 { | |
| 537 editor_command_start(template, text, list); | |
| 538 } | |
| 539 else | |
| 540 { | |
| 541 GList *work; | |
| 542 | |
| 543 work = list; | |
| 544 while (work) | |
| 545 { | |
| 546 gchar *path = work->data; | |
| 135 | 547 ret = editor_command_one(template, path, NULL); |
| 9 | 548 work = work->next; |
| 549 } | |
| 550 } | |
| 551 } | |
| 552 else | |
| 553 { | |
| 554 gchar *front; | |
| 555 const gchar *end; | |
| 556 GList *work; | |
| 557 GString *result = NULL; | |
| 558 gint parser_match; | |
| 559 | |
| 560 parser_match = editor_line_break(template, &front, &end); | |
| 561 result = g_string_new((parser_match) ? "" : " "); | |
| 562 | |
| 563 work = list; | |
| 564 while (work) | |
| 565 { | |
| 566 gchar *path = work->data; | |
| 567 gchar *pathl; | |
| 568 | |
| 569 if (work != list) g_string_append_c(result, ' '); | |
| 570 result = g_string_append_c(result, '"'); | |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
571 pathl = editor_command_path_parse(path); |
| 9 | 572 result = g_string_append(result, pathl); |
| 573 g_free(pathl); | |
| 574 result = g_string_append_c(result, '"'); | |
| 575 work = work->next; | |
| 576 } | |
| 577 | |
| 578 result = g_string_prepend(result, front); | |
| 579 result = g_string_append(result, end); | |
| 580 if (verbose) result = g_string_append(result, " 2>&1 "); | |
| 581 result = g_string_append(result, "&"); | |
| 582 | |
| 583 if (debug) printf("system command: %s\n", result->str); | |
| 584 | |
| 585 if (verbose) | |
| 586 { | |
| 587 EditorVerboseData *vd; | |
| 588 | |
| 589 vd = editor_verbose_window(template, text); | |
| 590 editor_verbose_window_progress(vd, _("running...")); | |
| 135 | 591 ret = editor_verbose_start(vd, result->str); |
| 9 | 592 } |
| 593 else | |
| 594 { | |
| 135 | 595 ret = !system(result->str); |
| 9 | 596 } |
| 597 | |
| 598 g_free(front); | |
| 599 g_string_free(result, TRUE); | |
| 600 } | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
601 return ret; |
| 9 | 602 } |
| 603 | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
604 gint start_editor_from_path_list(gint n, GList *list) |
| 9 | 605 { |
| 606 gchar *command; | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
607 gint ret; |
| 9 | 608 |
| 609 if (n < 0 || n >= GQVIEW_EDITOR_SLOTS || !list || | |
| 610 !editor_command[n] || | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
611 strlen(editor_command[n]) == 0) return FALSE; |
| 9 | 612 |
| 613 command = g_locale_from_utf8(editor_command[n], -1, NULL, NULL, NULL); | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
614 ret = editor_command_run(command, editor_name[n], list); |
| 9 | 615 g_free(command); |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
616 return ret; |
| 9 | 617 } |
| 618 | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
619 gint start_editor_from_file(gint n, const gchar *path) |
| 9 | 620 { |
| 621 GList *list; | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
622 gint ret; |
| 9 | 623 |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
624 if (!path) return FALSE; |
| 9 | 625 |
| 626 list = g_list_append(NULL, (gchar *)path); | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
627 ret = start_editor_from_path_list(n, list); |
| 9 | 628 g_list_free(list); |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
629 return ret; |
| 9 | 630 } |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
631 |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
632 gint editor_window_flag_set(gint n) |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
633 { |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
634 if (n < 0 || n >= GQVIEW_EDITOR_SLOTS || |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
635 !editor_command[n] || |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
636 strlen(editor_command[n]) == 0) return TRUE; |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
637 |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
638 return (strncmp(editor_command[n], "%w", 2) == 0); |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
639 } |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
640 |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
641 |
