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