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