Mercurial > geeqie
annotate src/editors.c @ 926:978f52f8a79d
Set GIO channels to binary encoding.
This is needed since messages from commands may not be UTF8-encoded
and g_io_channel_read_chars() may incorrectly interpret some characters.
In practice it was truncating some ISO-8859-1 messages containing some
french characters. This fixes it.
| author | zas_ |
|---|---|
| date | Thu, 24 Jul 2008 20:24:04 +0000 |
| parents | 8adf248bf5c9 |
| children | e73552743bda |
| rev | line source |
|---|---|
| 9 | 1 /* |
| 196 | 2 * Geeqie |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
3 * (C) 2006 John Ellis |
| 475 | 4 * Copyright (C) 2008 The Geeqie Team |
| 9 | 5 * |
| 6 * Author: John Ellis | |
| 7 * | |
| 8 * This software is released under the GNU General Public License (GNU GPL). | |
| 9 * Please read the included file COPYING for more information. | |
| 10 * This software comes with no warranty of any kind, use at your own risk! | |
| 11 */ | |
| 12 | |
| 13 | |
| 281 | 14 #include "main.h" |
| 9 | 15 #include "editors.h" |
| 16 | |
| 669 | 17 #include "filedata.h" |
| 18 #include "filefilter.h" | |
| 9 | 19 #include "utilops.h" |
| 20 #include "ui_fileops.h" | |
| 21 #include "ui_spinner.h" | |
| 22 #include "ui_utildlg.h" | |
| 23 | |
| 24 #include <errno.h> | |
| 25 | |
| 26 | |
| 27 #define EDITOR_WINDOW_WIDTH 500 | |
| 28 #define EDITOR_WINDOW_HEIGHT 300 | |
| 29 | |
| 30 | |
| 31 | |
| 32 typedef struct _EditorVerboseData EditorVerboseData; | |
| 33 struct _EditorVerboseData { | |
| 34 GenericDialog *gd; | |
| 35 GtkWidget *button_close; | |
| 36 GtkWidget *button_stop; | |
| 37 GtkWidget *text; | |
| 38 GtkWidget *progress; | |
| 39 GtkWidget *spinner; | |
| 140 | 40 }; |
| 41 | |
| 42 typedef struct _EditorData EditorData; | |
| 43 struct _EditorData { | |
| 44 gint flags; | |
| 45 GPid pid; | |
| 46 gchar *command_template; | |
| 47 GList *list; | |
| 9 | 48 gint count; |
| 49 gint total; | |
| 140 | 50 gboolean stopping; |
| 51 EditorVerboseData *vd; | |
| 52 EditorCallback callback; | |
| 53 gpointer data; | |
| 9 | 54 }; |
| 55 | |
| 56 | |
| 730 | 57 static Editor editor_slot_defaults[GQ_EDITOR_SLOTS] = { |
| 58 { N_("The Gimp"), "gimp-remote %{.cr2;.crw;.nef;.raw;*}f" }, | |
| 59 { N_("XV"), "xv %f" }, | |
| 60 { N_("Xpaint"), "xpaint %f" }, | |
| 61 { N_("UFraw"), "ufraw %{.cr2;.crw;.nef;.raw}p" }, | |
| 62 { N_("Add XMP sidecar"), "%vFILE=%{.cr2;.crw;.nef;.raw}p;XMP=`echo \"$FILE\"|sed -e 's|\\.[^.]*$|.xmp|'`; exiftool -tagsfromfile \"$FILE\" \"$XMP\"" }, | |
| 63 { NULL, NULL }, | |
| 64 { NULL, NULL }, | |
| 65 { NULL, NULL }, | |
| 66 { N_("Rotate jpeg clockwise"), "%vif jpegtran -rotate 90 -copy all -outfile %{.jpg;.jpeg}p_tmp %{.jpg;.jpeg}p; then mv %{.jpg;.jpeg}p_tmp %{.jpg;.jpeg}p;else rm %{.jpg;.jpeg}p_tmp;fi" }, | |
| 67 { N_("Rotate jpeg counterclockwise"), "%vif jpegtran -rotate 270 -copy all -outfile %{.jpg;.jpeg}p_tmp %{.jpg;.jpeg}p; then mv %{.jpg;.jpeg}p_tmp %{.jpg;.jpeg}p;else rm %{.jpg;.jpeg}p_tmp;fi" }, | |
|
134
9009856628f7
started implementation of external commands; external Delete should work
nadvornik
parents:
123
diff
changeset
|
68 /* special slots */ |
| 136 | 69 #if 1 |
| 70 /* for testing */ | |
| 730 | 71 { N_("External Copy command"), "%vset -x;cp %p %d" }, |
| 72 { N_("External Move command"), "%vset -x;mv %p %d" }, | |
| 73 { N_("External Rename command"), "%vset -x;mv %p %d" }, | |
| 74 { N_("External Delete command"), NULL }, | |
| 75 { N_("External New Folder command"), NULL }, | |
| 136 | 76 #else |
| 730 | 77 { N_("External Copy command"), NULL }, |
| 78 { N_("External Move command"), NULL }, | |
| 79 { N_("External Rename command"), NULL }, | |
| 80 { N_("External Delete command"), NULL }, | |
| 81 { N_("External New Folder command"), NULL }, | |
| 136 | 82 #endif |
| 9 | 83 }; |
| 84 | |
| 140 | 85 static void editor_verbose_window_progress(EditorData *ed, const gchar *text); |
| 86 static gint editor_command_next_start(EditorData *ed); | |
| 87 static gint editor_command_next_finish(EditorData *ed, gint status); | |
| 88 static gint editor_command_done(EditorData *ed); | |
| 9 | 89 |
| 90 /* | |
| 91 *----------------------------------------------------------------------------- | |
| 92 * external editor routines | |
| 93 *----------------------------------------------------------------------------- | |
| 94 */ | |
| 95 | |
|
768
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
96 void editor_set_name(gint n, gchar *name) |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
97 { |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
98 if (n < 0 || n >= GQ_EDITOR_SLOTS) return; |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
99 |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
100 g_free(options->editor[n].name); |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
101 |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
102 options->editor[n].name = name ? utf8_validate_or_convert(name) : NULL; |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
103 } |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
104 |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
105 void editor_set_command(gint n, gchar *command) |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
106 { |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
107 if (n < 0 || n >= GQ_EDITOR_SLOTS) return; |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
108 |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
109 g_free(options->editor[n].command); |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
110 options->editor[n].command = command ? utf8_validate_or_convert(command) : NULL; |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
111 } |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
112 |
| 9 | 113 void editor_reset_defaults(void) |
| 114 { | |
| 115 gint i; | |
| 116 | |
| 283 | 117 for (i = 0; i < GQ_EDITOR_SLOTS; i++) |
| 9 | 118 { |
|
768
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
119 editor_set_name(i, _(editor_slot_defaults[i].name)); |
|
ff51413f098d
Use functions to set editors name and command and ensure they are
zas_
parents:
766
diff
changeset
|
120 editor_set_command(i, _(editor_slot_defaults[i].command)); |
| 9 | 121 } |
| 122 } | |
| 123 | |
| 140 | 124 static void editor_verbose_data_free(EditorData *ed) |
| 125 { | |
| 126 if (!ed->vd) return; | |
| 127 g_free(ed->vd); | |
| 128 ed->vd = NULL; | |
| 129 } | |
| 130 | |
| 131 static void editor_data_free(EditorData *ed) | |
| 132 { | |
| 133 editor_verbose_data_free(ed); | |
| 134 g_free(ed->command_template); | |
| 135 g_free(ed); | |
| 136 } | |
| 137 | |
| 9 | 138 static void editor_verbose_window_close(GenericDialog *gd, gpointer data) |
| 139 { | |
| 140 | 140 EditorData *ed = data; |
| 9 | 141 |
| 142 generic_dialog_close(gd); | |
| 140 | 143 editor_verbose_data_free(ed); |
| 144 if (ed->pid == -1) editor_data_free(ed); /* the process has already terminated */ | |
| 9 | 145 } |
| 146 | |
| 147 static void editor_verbose_window_stop(GenericDialog *gd, gpointer data) | |
| 148 { | |
| 140 | 149 EditorData *ed = data; |
| 150 ed->stopping = TRUE; | |
| 151 ed->count = 0; | |
| 152 editor_verbose_window_progress(ed, _("stopping...")); | |
| 9 | 153 } |
| 154 | |
| 155 static void editor_verbose_window_enable_close(EditorVerboseData *vd) | |
| 156 { | |
| 157 vd->gd->cancel_cb = editor_verbose_window_close; | |
| 158 | |
| 159 spinner_set_interval(vd->spinner, -1); | |
| 160 gtk_widget_set_sensitive(vd->button_stop, FALSE); | |
| 161 gtk_widget_set_sensitive(vd->button_close, TRUE); | |
| 162 } | |
| 163 | |
| 140 | 164 static EditorVerboseData *editor_verbose_window(EditorData *ed, const gchar *text) |
| 9 | 165 { |
| 166 EditorVerboseData *vd; | |
| 167 GtkWidget *scrolled; | |
| 168 GtkWidget *hbox; | |
| 169 gchar *buf; | |
| 170 | |
| 171 vd = g_new0(EditorVerboseData, 1); | |
| 172 | |
|
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
238
diff
changeset
|
173 vd->gd = file_util_gen_dlg(_("Edit command results"), GQ_WMCLASS, "editor_results", |
| 9 | 174 NULL, FALSE, |
| 140 | 175 NULL, ed); |
| 9 | 176 buf = g_strdup_printf(_("Output of %s"), text); |
| 177 generic_dialog_add_message(vd->gd, NULL, buf, NULL); | |
| 178 g_free(buf); | |
| 179 vd->button_stop = generic_dialog_add_button(vd->gd, GTK_STOCK_STOP, NULL, | |
| 180 editor_verbose_window_stop, FALSE); | |
| 181 gtk_widget_set_sensitive(vd->button_stop, FALSE); | |
| 182 vd->button_close = generic_dialog_add_button(vd->gd, GTK_STOCK_CLOSE, NULL, | |
| 183 editor_verbose_window_close, TRUE); | |
| 184 gtk_widget_set_sensitive(vd->button_close, FALSE); | |
| 185 | |
| 186 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
| 187 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
| 188 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
| 189 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 190 gtk_box_pack_start(GTK_BOX(vd->gd->vbox), scrolled, TRUE, TRUE, 5); | |
| 191 gtk_widget_show(scrolled); | |
| 192 | |
| 193 vd->text = gtk_text_view_new(); | |
| 194 gtk_text_view_set_editable(GTK_TEXT_VIEW(vd->text), FALSE); | |
| 195 gtk_widget_set_size_request(vd->text, EDITOR_WINDOW_WIDTH, EDITOR_WINDOW_HEIGHT); | |
| 196 gtk_container_add(GTK_CONTAINER(scrolled), vd->text); | |
| 197 gtk_widget_show(vd->text); | |
| 198 | |
| 199 hbox = gtk_hbox_new(FALSE, 0); | |
| 200 gtk_box_pack_start(GTK_BOX(vd->gd->vbox), hbox, FALSE, FALSE, 0); | |
| 201 gtk_widget_show(hbox); | |
| 202 | |
| 203 vd->progress = gtk_progress_bar_new(); | |
| 204 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(vd->progress), 0.0); | |
| 205 gtk_box_pack_start(GTK_BOX(hbox), vd->progress, TRUE, TRUE, 0); | |
| 206 gtk_widget_show(vd->progress); | |
| 207 | |
| 208 vd->spinner = spinner_new(NULL, SPINNER_SPEED); | |
| 209 gtk_box_pack_start(GTK_BOX(hbox), vd->spinner, FALSE, FALSE, 0); | |
| 210 gtk_widget_show(vd->spinner); | |
| 442 | 211 |
| 9 | 212 gtk_widget_show(vd->gd->dialog); |
| 213 | |
| 140 | 214 ed->vd = vd; |
| 9 | 215 return vd; |
| 216 } | |
| 217 | |
| 218 static void editor_verbose_window_fill(EditorVerboseData *vd, gchar *text, gint len) | |
| 219 { | |
| 220 GtkTextBuffer *buffer; | |
| 221 GtkTextIter iter; | |
| 222 | |
| 223 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vd->text)); | |
| 224 gtk_text_buffer_get_iter_at_offset(buffer, &iter, -1); | |
| 225 gtk_text_buffer_insert(buffer, &iter, text, len); | |
| 226 } | |
| 227 | |
| 140 | 228 static void editor_verbose_window_progress(EditorData *ed, const gchar *text) |
| 9 | 229 { |
| 140 | 230 if (!ed->vd) return; |
| 231 | |
| 232 if (ed->total) | |
| 9 | 233 { |
| 140 | 234 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ed->vd->progress), (double)ed->count / ed->total); |
| 9 | 235 } |
| 236 | |
| 140 | 237 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(ed->vd->progress), (text) ? text : ""); |
| 9 | 238 } |
| 239 | |
| 240 static gboolean editor_verbose_io_cb(GIOChannel *source, GIOCondition condition, gpointer data) | |
| 241 { | |
| 140 | 242 EditorData *ed = data; |
| 9 | 243 gchar buf[512]; |
| 244 gsize count; | |
| 245 | |
| 140 | 246 if (condition & G_IO_IN) |
| 9 | 247 { |
| 140 | 248 while (g_io_channel_read_chars(source, buf, sizeof(buf), &count, NULL) == G_IO_STATUS_NORMAL) |
| 249 { | |
| 250 if (!g_utf8_validate(buf, count, NULL)) | |
| 9 | 251 { |
| 140 | 252 gchar *utf8; |
| 444 | 253 |
| 140 | 254 utf8 = g_locale_to_utf8(buf, count, NULL, NULL, NULL); |
| 255 if (utf8) | |
| 9 | 256 { |
| 140 | 257 editor_verbose_window_fill(ed->vd, utf8, -1); |
| 258 g_free(utf8); | |
| 9 | 259 } |
| 260 else | |
| 261 { | |
|
288
d1f74154463e
Replace occurences of Geeqie / geeqie by constants defined in main.h.
zas_
parents:
283
diff
changeset
|
262 editor_verbose_window_fill(ed->vd, "Error converting text to valid utf8\n", -1); |
| 9 | 263 } |
| 264 } | |
| 140 | 265 else |
| 266 { | |
| 267 editor_verbose_window_fill(ed->vd, buf, count); | |
| 268 } | |
| 269 } | |
| 9 | 270 } |
| 271 | |
| 140 | 272 if (condition & (G_IO_ERR | G_IO_HUP)) |
| 9 | 273 { |
| 140 | 274 g_io_channel_shutdown(source, TRUE, NULL); |
| 9 | 275 return FALSE; |
| 276 } | |
| 277 | |
| 278 return TRUE; | |
| 279 } | |
| 280 | |
| 138 | 281 typedef enum { |
| 282 PATH_FILE, | |
| 140 | 283 PATH_DEST |
| 138 | 284 } PathType; |
| 285 | |
| 286 | |
| 140 | 287 static gchar *editor_command_path_parse(const FileData *fd, PathType type, const gchar *extensions) |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
288 { |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
289 GString *string; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
290 gchar *pathl; |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
291 const gchar *p = NULL; |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
292 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
293 string = g_string_new(""); |
| 442 | 294 |
| 138 | 295 if (type == PATH_FILE) |
| 296 { | |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
297 GList *ext_list = filter_to_list(extensions); |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
298 GList *work = ext_list; |
| 442 | 299 |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
300 if (!work) |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
301 p = fd->path; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
302 else |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
303 { |
| 516 | 304 while (work) |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
305 { |
| 444 | 306 GList *work2; |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
307 gchar *ext = work->data; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
308 work = work->next; |
| 442 | 309 |
| 310 if (strcmp(ext, "*") == 0 || | |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
311 strcasecmp(ext, fd->extension) == 0) |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
312 { |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
313 p = fd->path; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
314 break; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
315 } |
| 442 | 316 |
| 444 | 317 work2 = fd->sidecar_files; |
| 516 | 318 while (work2) |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
319 { |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
320 FileData *sfd = work2->data; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
321 work2 = work2->next; |
| 442 | 322 |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
323 if (strcasecmp(ext, sfd->extension) == 0) |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
324 { |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
325 p = sfd->path; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
326 break; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
327 } |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
328 } |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
329 if (p) break; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
330 } |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
331 string_list_free(ext_list); |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
332 if (!p) return NULL; |
|
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
333 } |
| 138 | 334 } |
| 140 | 335 else if (type == PATH_DEST) |
| 138 | 336 { |
| 337 if (fd->change && fd->change->dest) | |
| 338 p = fd->change->dest; | |
| 339 else | |
| 340 p = ""; | |
| 341 } | |
| 444 | 342 |
|
123
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
343 while (*p != '\0') |
|
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 /* must escape \, ", `, and $ to avoid problems, |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
346 * 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
|
347 */ |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
348 if (strchr("\\\"`$", *p) != NULL) |
|
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 string = g_string_append_c(string, '\\'); |
|
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 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
|
353 p++; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
354 } |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
355 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
356 pathl = path_from_utf8(string->str); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
357 g_string_free(string, TRUE); |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
358 |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
359 return pathl; |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
360 } |
|
3602a4aa7c71
Sat Dec 2 20:15:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
60
diff
changeset
|
361 |
| 9 | 362 |
| 363 /* | |
| 364 * The supported macros for editor commands: | |
| 365 * | |
| 366 * %f first occurence replaced by quoted sequence of filenames, command is run once. | |
| 367 * only one occurence of this macro is supported. | |
| 368 * ([ls %f] results in [ls "file1" "file2" ... "lastfile"]) | |
| 369 * %p command is run for each filename in turn, each instance replaced with single filename. | |
| 370 * multiple occurences of this macro is supported for complex shell commands. | |
| 371 * This macro will BLOCK THE APPLICATION until it completes, since command is run once | |
| 372 * for every file in syncronous order. To avoid blocking add the %v macro, below. | |
| 373 * ([ls %p] results in [ls "file1"], [ls "file2"] ... [ls "lastfile"]) | |
| 374 * none if no macro is supplied, the result is equivalent to "command %f" | |
| 375 * ([ls] results in [ls "file1" "file2" ... "lastfile"]) | |
| 376 * | |
| 377 * Only one of the macros %f or %p may be used in a given commmand. | |
| 378 * | |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
379 * %v must be the first two characters[1] in a command, causes a window to display |
| 9 | 380 * showing the output of the command(s). |
| 381 * %V same as %v except in the case of %p only displays a window for multiple files, | |
| 382 * 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
|
383 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
384 * %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
|
385 * from exiting upon invocation. |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
386 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
387 * |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
388 * [1] Note: %v,%V may also be preceded by "%w". |
| 9 | 389 */ |
| 140 | 390 |
| 391 | |
| 392 gint editor_command_parse(const gchar *template, GList *list, gchar **output) | |
| 9 | 393 { |
| 140 | 394 gint flags = 0; |
| 395 const gchar *p = template; | |
| 396 GString *result = NULL; | |
| 397 gchar *extensions = NULL; | |
| 442 | 398 |
| 140 | 399 if (output) |
| 400 result = g_string_new(""); | |
| 401 | |
| 442 | 402 if (!template || template[0] == '\0') |
| 140 | 403 { |
| 404 flags |= EDITOR_ERROR_EMPTY; | |
| 405 goto err; | |
| 406 } | |
| 669 | 407 |
| 408 /* skip leading whitespaces if any */ | |
| 409 while (g_ascii_isspace(*p)) p++; | |
| 442 | 410 |
| 140 | 411 /* global flags */ |
| 412 while (*p == '%') | |
| 413 { | |
| 414 switch (*++p) | |
| 415 { | |
| 416 case 'w': | |
| 417 flags |= EDITOR_KEEP_FS; | |
| 418 p++; | |
| 419 break; | |
| 420 case 'v': | |
| 421 flags |= EDITOR_VERBOSE; | |
| 422 p++; | |
| 423 break; | |
| 424 case 'V': | |
| 425 flags |= EDITOR_VERBOSE_MULTI; | |
| 426 p++; | |
| 427 break; | |
| 669 | 428 default: |
| 429 flags |= EDITOR_ERROR_SYNTAX; | |
| 430 goto err; | |
| 140 | 431 } |
| 432 } | |
| 442 | 433 |
| 669 | 434 /* skip whitespaces if any */ |
| 435 while (g_ascii_isspace(*p)) p++; | |
| 436 | |
| 140 | 437 /* command */ |
| 442 | 438 |
| 140 | 439 while (*p) |
| 440 { | |
| 441 if (*p != '%') | |
| 442 { | |
| 443 if (output) result = g_string_append_c(result, *p); | |
| 444 } | |
| 445 else /* *p == '%' */ | |
| 446 { | |
| 447 extensions = NULL; | |
| 448 gchar *pathl = NULL; | |
| 9 | 449 |
| 140 | 450 p++; |
| 442 | 451 |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
452 /* for example "%f" or "%{.crw;.raw;.cr2}f" */ |
| 140 | 453 if (*p == '{') |
| 454 { | |
| 444 | 455 gchar *end; |
| 456 | |
| 140 | 457 p++; |
| 444 | 458 end = strchr(p, '}'); |
| 140 | 459 if (!end) |
| 460 { | |
| 461 flags |= EDITOR_ERROR_SYNTAX; | |
| 462 goto err; | |
| 463 } | |
| 442 | 464 |
| 140 | 465 extensions = g_strndup(p, end - p); |
| 466 p = end + 1; | |
| 467 } | |
| 442 | 468 |
| 469 switch (*p) | |
| 140 | 470 { |
| 471 case 'd': | |
| 472 flags |= EDITOR_DEST; | |
| 669 | 473 /* fall through */ |
| 140 | 474 case 'p': |
| 475 flags |= EDITOR_FOR_EACH; | |
| 476 if (flags & EDITOR_SINGLE_COMMAND) | |
| 477 { | |
| 478 flags |= EDITOR_ERROR_INCOMPATIBLE; | |
| 479 goto err; | |
| 480 } | |
| 481 if (output) | |
| 482 { | |
| 483 /* use the first file from the list */ | |
| 442 | 484 if (!list || !list->data) |
| 140 | 485 { |
| 486 flags |= EDITOR_ERROR_NO_FILE; | |
| 487 goto err; | |
| 488 } | |
| 669 | 489 pathl = editor_command_path_parse((FileData *)list->data, |
| 490 (flags & EDITOR_DEST) ? PATH_DEST : PATH_FILE, | |
| 491 extensions); | |
| 442 | 492 if (!pathl) |
| 140 | 493 { |
| 494 flags |= EDITOR_ERROR_NO_FILE; | |
| 495 goto err; | |
| 496 } | |
| 497 result = g_string_append_c(result, '"'); | |
| 498 result = g_string_append(result, pathl); | |
| 499 g_free(pathl); | |
| 500 result = g_string_append_c(result, '"'); | |
| 501 } | |
| 442 | 502 break; |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
503 |
| 140 | 504 case 'f': |
| 505 flags |= EDITOR_SINGLE_COMMAND; | |
| 506 if (flags & (EDITOR_FOR_EACH | EDITOR_DEST)) | |
| 507 { | |
| 508 flags |= EDITOR_ERROR_INCOMPATIBLE; | |
| 509 goto err; | |
| 510 } | |
| 511 | |
| 512 if (output) | |
| 513 { | |
| 514 /* use whole list */ | |
| 515 GList *work = list; | |
| 516 gboolean ok = FALSE; | |
| 444 | 517 |
| 140 | 518 while (work) |
| 519 { | |
| 520 FileData *fd = work->data; | |
| 521 pathl = editor_command_path_parse(fd, PATH_FILE, extensions); | |
| 522 | |
| 523 if (pathl) | |
| 524 { | |
| 525 ok = TRUE; | |
| 526 if (work != list) g_string_append_c(result, ' '); | |
| 527 result = g_string_append_c(result, '"'); | |
| 528 result = g_string_append(result, pathl); | |
| 529 g_free(pathl); | |
| 530 result = g_string_append_c(result, '"'); | |
| 531 } | |
| 532 work = work->next; | |
| 533 } | |
| 442 | 534 if (!ok) |
| 140 | 535 { |
| 536 flags |= EDITOR_ERROR_NO_FILE; | |
| 537 goto err; | |
| 538 } | |
| 539 } | |
| 442 | 540 break; |
| 669 | 541 case '%': |
| 542 /* %% = % escaping */ | |
| 543 if (output) result = g_string_append_c(result, *p); | |
| 544 break; | |
| 140 | 545 default: |
| 546 flags |= EDITOR_ERROR_SYNTAX; | |
| 547 goto err; | |
| 548 } | |
| 549 if (extensions) g_free(extensions); | |
| 550 extensions = NULL; | |
| 551 } | |
| 552 p++; | |
| 9 | 553 } |
| 554 | |
| 140 | 555 if (output) *output = g_string_free(result, FALSE); |
| 556 return flags; | |
| 557 | |
| 442 | 558 |
| 140 | 559 err: |
| 442 | 560 if (output) |
| 9 | 561 { |
| 140 | 562 g_string_free(result, TRUE); |
| 563 *output = NULL; | |
| 564 } | |
| 565 if (extensions) g_free(extensions); | |
| 566 return flags; | |
| 567 } | |
| 568 | |
| 569 static void editor_child_exit_cb (GPid pid, gint status, gpointer data) | |
| 570 { | |
| 571 EditorData *ed = data; | |
| 572 g_spawn_close_pid(pid); | |
| 573 ed->pid = -1; | |
| 442 | 574 |
| 140 | 575 editor_command_next_finish(ed, status); |
| 576 } | |
| 577 | |
| 578 | |
| 579 static gint editor_command_one(const gchar *template, GList *list, EditorData *ed) | |
| 580 { | |
| 581 gchar *command; | |
| 582 FileData *fd = list->data; | |
| 583 GPid pid; | |
| 442 | 584 gint standard_output; |
| 585 gint standard_error; | |
| 140 | 586 gboolean ok; |
| 587 | |
| 588 ed->pid = -1; | |
| 589 ed->flags = editor_command_parse(template, list, &command); | |
| 590 | |
| 591 ok = !(ed->flags & EDITOR_ERROR_MASK); | |
| 592 | |
| 593 if (ok) | |
| 594 { | |
|
737
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
595 ok = (options->shell.path && *options->shell.path); |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
596 if (!ok) log_printf("ERROR: empty shell command\n"); |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
597 |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
598 if (ok) |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
599 { |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
600 ok = (access(options->shell.path, X_OK) == 0); |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
601 if (!ok) log_printf("ERROR: cannot execute shell command '%s'\n", options->shell.path); |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
602 } |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
603 |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
604 if (!ok) ed->flags |= EDITOR_ERROR_CANT_EXEC; |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
605 } |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
606 |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
607 if (ok) |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
608 { |
| 443 | 609 gchar *working_directory; |
| 610 gchar *args[4]; | |
|
737
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
611 guint n = 0; |
| 443 | 612 |
| 613 working_directory = remove_level_from_path(fd->path); | |
|
737
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
614 args[n++] = options->shell.path; |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
615 if (options->shell.options && *options->shell.options) |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
616 args[n++] = options->shell.options; |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
617 args[n++] = command; |
|
8a8873e7a552
Make shell command and its option rc file options instead of hardcoded strings.
zas_
parents:
731
diff
changeset
|
618 args[n] = NULL; |
| 443 | 619 |
| 442 | 620 ok = g_spawn_async_with_pipes(working_directory, args, NULL, |
| 140 | 621 G_SPAWN_DO_NOT_REAP_CHILD, /* GSpawnFlags */ |
| 442 | 622 NULL, NULL, |
| 623 &pid, | |
| 624 NULL, | |
| 625 ed->vd ? &standard_output : NULL, | |
| 626 ed->vd ? &standard_error : NULL, | |
| 140 | 627 NULL); |
| 443 | 628 |
| 629 g_free(working_directory); | |
| 442 | 630 |
| 140 | 631 if (!ok) ed->flags |= EDITOR_ERROR_CANT_EXEC; |
| 632 } | |
| 633 | |
| 442 | 634 if (ok) |
| 140 | 635 { |
| 636 g_child_watch_add(pid, editor_child_exit_cb, ed); | |
| 637 ed->pid = pid; | |
| 638 } | |
| 442 | 639 |
| 140 | 640 if (ed->vd) |
| 641 { | |
| 642 if (!ok) | |
| 9 | 643 { |
| 140 | 644 gchar *buf; |
| 645 | |
|
147
b2266996fa83
added possibility to specify prefered file type for external commands
nadvornik
parents:
140
diff
changeset
|
646 buf = g_strdup_printf(_("Failed to run command:\n%s\n"), template); |
| 140 | 647 editor_verbose_window_fill(ed->vd, buf, strlen(buf)); |
| 648 g_free(buf); | |
| 649 | |
| 650 } | |
| 442 | 651 else |
| 140 | 652 { |
| 653 GIOChannel *channel_output; | |
| 654 GIOChannel *channel_error; | |
| 444 | 655 |
| 140 | 656 channel_output = g_io_channel_unix_new(standard_output); |
| 657 g_io_channel_set_flags(channel_output, G_IO_FLAG_NONBLOCK, NULL); | |
| 926 | 658 g_io_channel_set_encoding(channel_output, NULL, NULL); |
| 140 | 659 |
| 660 g_io_add_watch_full(channel_output, G_PRIORITY_HIGH, G_IO_IN | G_IO_ERR | G_IO_HUP, | |
| 661 editor_verbose_io_cb, ed, NULL); | |
| 662 g_io_channel_unref(channel_output); | |
| 663 | |
| 664 channel_error = g_io_channel_unix_new(standard_error); | |
| 665 g_io_channel_set_flags(channel_error, G_IO_FLAG_NONBLOCK, NULL); | |
| 926 | 666 g_io_channel_set_encoding(channel_error, NULL, NULL); |
| 140 | 667 |
| 668 g_io_add_watch_full(channel_error, G_PRIORITY_HIGH, G_IO_IN | G_IO_ERR | G_IO_HUP, | |
| 669 editor_verbose_io_cb, ed, NULL); | |
| 670 g_io_channel_unref(channel_error); | |
| 671 } | |
| 672 } | |
| 442 | 673 |
| 140 | 674 g_free(command); |
| 675 | |
| 676 return ed->flags & EDITOR_ERROR_MASK; | |
| 677 } | |
| 678 | |
| 679 static gint editor_command_next_start(EditorData *ed) | |
| 680 { | |
| 681 if (ed->vd) editor_verbose_window_fill(ed->vd, "\n", 1); | |
| 682 | |
| 683 if (ed->list && ed->count < ed->total) | |
| 684 { | |
| 685 FileData *fd; | |
| 686 gint error; | |
| 687 | |
| 688 fd = ed->list->data; | |
| 689 | |
| 690 if (ed->vd) | |
| 691 { | |
| 692 editor_verbose_window_progress(ed, (ed->flags & EDITOR_FOR_EACH) ? fd->path : _("running...")); | |
| 693 } | |
| 694 ed->count++; | |
| 695 | |
| 696 error = editor_command_one(ed->command_template, ed->list, ed); | |
| 697 if (!error && ed->vd) | |
| 698 { | |
| 699 gtk_widget_set_sensitive(ed->vd->button_stop, (ed->list != NULL) ); | |
| 700 if (ed->flags & EDITOR_FOR_EACH) | |
| 9 | 701 { |
| 140 | 702 editor_verbose_window_fill(ed->vd, fd->path, strlen(fd->path)); |
| 703 editor_verbose_window_fill(ed->vd, "\n", 1); | |
| 9 | 704 } |
| 705 } | |
| 140 | 706 |
| 442 | 707 if (!error) |
| 140 | 708 return 0; |
| 709 else | |
| 710 /* command was not started, call the finish immediately */ | |
| 711 return editor_command_next_finish(ed, 0); | |
| 712 } | |
| 442 | 713 |
| 140 | 714 /* everything is done */ |
|
237
404629011caa
Add missing return at the end of editor_command_next_start().
zas_
parents:
196
diff
changeset
|
715 return editor_command_done(ed); |
| 140 | 716 } |
| 717 | |
| 718 static gint editor_command_next_finish(EditorData *ed, gint status) | |
| 719 { | |
| 720 gint cont = ed->stopping ? EDITOR_CB_SKIP : EDITOR_CB_CONTINUE; | |
| 721 | |
| 722 if (status) | |
| 723 ed->flags |= EDITOR_ERROR_STATUS; | |
| 724 | |
| 725 if (ed->flags & EDITOR_FOR_EACH) | |
| 726 { | |
| 727 /* handle the first element from the list */ | |
| 728 GList *fd_element = ed->list; | |
| 444 | 729 |
| 140 | 730 ed->list = g_list_remove_link(ed->list, fd_element); |
| 731 if (ed->callback) | |
| 911 | 732 { |
| 140 | 733 cont = ed->callback(ed->list ? ed : NULL, ed->flags, fd_element, ed->data); |
| 911 | 734 if (ed->stopping && cont == EDITOR_CB_CONTINUE) cont = EDITOR_CB_SKIP; |
| 735 } | |
| 140 | 736 filelist_free(fd_element); |
| 9 | 737 } |
| 738 else | |
| 739 { | |
| 140 | 740 /* handle whole list */ |
| 741 if (ed->callback) | |
| 742 cont = ed->callback(NULL, ed->flags, ed->list, ed->data); | |
| 743 filelist_free(ed->list); | |
| 744 ed->list = NULL; | |
| 745 } | |
| 9 | 746 |
| 140 | 747 if (cont == EDITOR_CB_SUSPEND) |
| 748 return ed->flags & EDITOR_ERROR_MASK; | |
| 749 else if (cont == EDITOR_CB_SKIP) | |
| 750 return editor_command_done(ed); | |
| 751 else | |
| 752 return editor_command_next_start(ed); | |
| 753 } | |
| 9 | 754 |
| 140 | 755 static gint editor_command_done(EditorData *ed) |
| 756 { | |
| 757 gint flags; | |
| 9 | 758 |
| 140 | 759 if (ed->vd) |
| 760 { | |
| 444 | 761 const gchar *text; |
| 762 | |
| 140 | 763 if (ed->count == ed->total) |
| 9 | 764 { |
| 140 | 765 text = _("done"); |
| 9 | 766 } |
| 767 else | |
| 768 { | |
| 140 | 769 text = _("stopped by user"); |
| 9 | 770 } |
| 140 | 771 editor_verbose_window_progress(ed, text); |
| 772 editor_verbose_window_enable_close(ed->vd); | |
| 773 } | |
| 774 | |
| 775 /* free the not-handled items */ | |
| 776 if (ed->list) | |
| 777 { | |
| 778 ed->flags |= EDITOR_ERROR_SKIPPED; | |
| 779 if (ed->callback) ed->callback(NULL, ed->flags, ed->list, ed->data); | |
| 780 filelist_free(ed->list); | |
| 781 ed->list = NULL; | |
| 782 } | |
| 9 | 783 |
| 140 | 784 ed->count = 0; |
| 785 | |
| 786 flags = ed->flags & EDITOR_ERROR_MASK; | |
| 787 | |
| 788 if (!ed->vd) editor_data_free(ed); | |
| 789 | |
| 790 return flags; | |
| 791 } | |
| 792 | |
| 793 void editor_resume(gpointer ed) | |
| 794 { | |
| 795 editor_command_next_start(ed); | |
| 796 } | |
| 443 | 797 |
| 140 | 798 void editor_skip(gpointer ed) |
| 799 { | |
| 442 | 800 editor_command_done(ed); |
| 9 | 801 } |
| 802 | |
| 140 | 803 static gint editor_command_start(const gchar *template, const gchar *text, GList *list, EditorCallback cb, gpointer data) |
| 804 { | |
| 805 EditorData *ed; | |
| 806 gint flags = editor_command_parse(template, NULL, NULL); | |
| 442 | 807 |
| 140 | 808 if (flags & EDITOR_ERROR_MASK) return flags & EDITOR_ERROR_MASK; |
| 809 | |
| 810 ed = g_new0(EditorData, 1); | |
| 811 ed->list = filelist_copy(list); | |
| 812 ed->flags = flags; | |
| 813 ed->command_template = g_strdup(template); | |
| 814 ed->total = (flags & EDITOR_SINGLE_COMMAND) ? 1 : g_list_length(list); | |
| 815 ed->count = 0; | |
| 816 ed->stopping = FALSE; | |
| 817 ed->callback = cb; | |
| 818 ed->data = data; | |
| 442 | 819 |
| 140 | 820 if ((flags & EDITOR_VERBOSE_MULTI) && list && list->next) |
| 821 flags |= EDITOR_VERBOSE; | |
| 442 | 822 |
| 140 | 823 if (flags & EDITOR_VERBOSE) |
| 824 editor_verbose_window(ed, text); | |
| 442 | 825 |
| 826 editor_command_next_start(ed); | |
| 140 | 827 /* errors from editor_command_next_start will be handled via callback */ |
| 828 return flags & EDITOR_ERROR_MASK; | |
| 829 } | |
| 830 | |
|
766
7148e125bf23
Check for existing editor command using is_valid_editor_command().
zas_
parents:
753
diff
changeset
|
831 gboolean is_valid_editor_command(gint n) |
| 444 | 832 { |
| 833 return (n >= 0 && n < GQ_EDITOR_SLOTS | |
| 730 | 834 && options->editor[n].command |
| 835 && strlen(options->editor[n].command) > 0); | |
| 444 | 836 } |
| 837 | |
| 140 | 838 gint start_editor_from_filelist_full(gint n, GList *list, EditorCallback cb, gpointer data) |
| 9 | 839 { |
| 840 gchar *command; | |
| 140 | 841 gint error; |
| 9 | 842 |
| 444 | 843 if (!list) return FALSE; |
| 844 if (!is_valid_editor_command(n)) return FALSE; | |
| 9 | 845 |
| 730 | 846 command = g_locale_from_utf8(options->editor[n].command, -1, NULL, NULL, NULL); |
| 847 error = editor_command_start(command, options->editor[n].name, list, cb, data); | |
| 9 | 848 g_free(command); |
| 669 | 849 |
| 670 | 850 if (n < GQ_EDITOR_GENERIC_SLOTS && (error & EDITOR_ERROR_MASK)) |
| 669 | 851 { |
| 670 | 852 gchar *text = g_strdup_printf(_("%s\n#%d \"%s\":\n%s"), editor_get_error_str(error), n+1, |
| 730 | 853 options->editor[n].name, options->editor[n].command); |
| 669 | 854 |
| 855 file_util_warning_dialog(_("Invalid editor command"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
| 856 g_free(text); | |
| 857 } | |
| 858 | |
| 140 | 859 return error; |
| 9 | 860 } |
| 861 | |
| 140 | 862 gint start_editor_from_filelist(gint n, GList *list) |
| 863 { | |
| 864 return start_editor_from_filelist_full(n, list, NULL, NULL); | |
| 865 } | |
| 866 | |
| 867 gint start_editor_from_file_full(gint n, FileData *fd, EditorCallback cb, gpointer data) | |
| 9 | 868 { |
| 869 GList *list; | |
| 140 | 870 gint error; |
| 9 | 871 |
| 138 | 872 if (!fd) return FALSE; |
| 9 | 873 |
| 138 | 874 list = g_list_append(NULL, fd); |
| 140 | 875 error = start_editor_from_filelist_full(n, list, cb, data); |
| 9 | 876 g_list_free(list); |
| 140 | 877 return error; |
| 9 | 878 } |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
879 |
| 140 | 880 gint start_editor_from_file(gint n, FileData *fd) |
| 136 | 881 { |
| 140 | 882 return start_editor_from_file_full(n, fd, NULL, NULL); |
| 136 | 883 } |
| 884 | |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
885 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
|
886 { |
| 444 | 887 if (!is_valid_editor_command(n)) return TRUE; |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
888 |
| 730 | 889 return (editor_command_parse(options->editor[n].command, NULL, NULL) & EDITOR_KEEP_FS); |
|
60
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
890 } |
|
9c0c402b0ef3
Mon Jun 13 17:31:46 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
891 |
| 753 | 892 gint editor_is_filter(gint n) |
| 893 { | |
| 894 if (!is_valid_editor_command(n)) return FALSE; | |
| 895 | |
| 896 return (editor_command_parse(options->editor[n].command, NULL, NULL) & EDITOR_DEST); | |
| 897 } | |
| 898 | |
| 140 | 899 const gchar *editor_get_error_str(gint flags) |
| 900 { | |
| 901 if (flags & EDITOR_ERROR_EMPTY) return _("Editor template is empty."); | |
| 902 if (flags & EDITOR_ERROR_SYNTAX) return _("Editor template has incorrect syntax."); | |
| 903 if (flags & EDITOR_ERROR_INCOMPATIBLE) return _("Editor template uses incompatible macros."); | |
| 904 if (flags & EDITOR_ERROR_NO_FILE) return _("Can't find matching file type."); | |
| 905 if (flags & EDITOR_ERROR_CANT_EXEC) return _("Can't execute external editor."); | |
| 906 if (flags & EDITOR_ERROR_STATUS) return _("External editor returned error status."); | |
| 907 if (flags & EDITOR_ERROR_SKIPPED) return _("File was skipped."); | |
| 908 return _("Unknown error."); | |
| 909 } | |
|
731
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
910 |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
911 const gchar *editor_get_name(gint n) |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
912 { |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
913 if (!is_valid_editor_command(n)) return NULL; |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
914 |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
915 if (options->editor[n].name && strlen(options->editor[n].name) > 0) |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
916 return options->editor[n].name; |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
917 |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
918 return _("(unknown)"); |
|
fa8f7d7396cf
Introduce an helper function that returns the name of an editor.
zas_
parents:
730
diff
changeset
|
919 } |
