1
|
1 /*
|
|
2 * GQview image viewer
|
|
3 * (C)1999 John Ellis
|
|
4 *
|
|
5 * Author: John Ellis
|
|
6 *
|
|
7 */
|
|
8
|
|
9 #include "gqview.h"
|
|
10 #include <gdk/gdkkeysyms.h> /* for keyboard values */
|
|
11
|
|
12 static void parse_command_line(int argc, char *argv[], gchar **path, gchar **file);
|
|
13 static void setup_default_options();
|
|
14
|
|
15 /*
|
|
16 *-----------------------------------------------------------------------------
|
|
17 * path manipulation routines (public)
|
|
18 *-----------------------------------------------------------------------------
|
|
19 */
|
|
20
|
|
21 gchar *filename_from_path(char *t)
|
|
22 {
|
|
23 char *p;
|
|
24
|
|
25 p = t + strlen(t);
|
|
26 while(p > t && p[0] != '/') p--;
|
|
27 if (p[0] == '/') p++;
|
|
28 return p;
|
|
29 }
|
|
30
|
|
31 gchar *remove_level_from_path(gchar *path)
|
|
32 {
|
|
33 gchar *new_path;
|
|
34 gchar *ptr = path;
|
|
35 gint p;
|
|
36
|
|
37 if (!path) return NULL;
|
|
38
|
|
39 p = strlen(path) - 1;
|
|
40 if (p < 0) return NULL;
|
|
41 while(ptr[p] != '/' && p > 0) p--;
|
|
42 if (p == 0 && ptr[p] == '/') p++;
|
|
43 new_path = g_strndup(path, (guint)p);
|
|
44 return new_path;
|
|
45 }
|
|
46
|
|
47 void parse_out_relatives(gchar *path)
|
|
48 {
|
|
49 gint s, t;
|
|
50
|
|
51 if (!path) return;
|
|
52
|
|
53 s = t = 0;
|
|
54
|
|
55 while (path[s] != '\0')
|
|
56 {
|
|
57 if (path[s] == '/' && path[s+1] == '.' && (path[s+2] == '/' || path[s+2] == '\0') )
|
|
58 {
|
|
59 s += 2;
|
|
60 }
|
|
61 else if (path[s] == '/' && path[s+1] == '.' && path[s+2] == '.' && (path[s+3] == '/' || path[s+3] == '\0') )
|
|
62 {
|
|
63 s += 3;
|
|
64 if (t > 0) t--;
|
|
65 while (path[t] != '/' && t > 0) t--;
|
|
66 }
|
|
67 else
|
|
68 {
|
|
69 if (s != t) path[t] = path[s];
|
|
70 t++;
|
|
71 s++;
|
|
72 }
|
|
73 }
|
|
74 if (t == 0 && path[t] == '/') t++;
|
|
75 if (t > 1 && path[t-1] == '/') t--;
|
|
76 path[t] = '\0';
|
|
77 }
|
|
78
|
|
79 /*
|
|
80 *-----------------------------------------------------------------------------
|
|
81 * external editor start routines (public)
|
|
82 *-----------------------------------------------------------------------------
|
|
83 */
|
|
84
|
|
85 void start_editor_from_file(gint n, gchar *path)
|
|
86 {
|
|
87 gchar *cmd;
|
|
88 if (!path) return;
|
|
89 cmd = g_strdup_printf("%s \"%s\" &", editor_command[n], path);
|
|
90 printf(_("GQview running: %s\n"),cmd);
|
|
91 system(cmd);
|
|
92 g_free(cmd);
|
|
93 }
|
|
94
|
|
95 void start_editor_from_image(gint n)
|
|
96 {
|
|
97 start_editor_from_file(n, image_get_path());
|
|
98 }
|
|
99
|
|
100 void start_editor_from_list(gint n)
|
|
101 {
|
|
102 gchar *cmd;
|
|
103 gchar *buf;
|
|
104 GList *list = file_get_selected_list();
|
|
105 GList *work;
|
|
106 if (!list) return;
|
|
107 work = list;
|
|
108 cmd = g_strconcat(editor_command[n], " ", NULL);
|
|
109 while(work)
|
|
110 {
|
|
111 buf = cmd;
|
|
112 cmd = g_strconcat(buf, "\"", work->data, "\" ", NULL);
|
|
113 g_free(buf);
|
|
114 work = work->next;
|
|
115 }
|
|
116 buf = cmd;
|
|
117 cmd = g_strconcat(buf, "&", NULL);
|
|
118 g_free(buf);
|
|
119 printf(_("GQview running: %s\n"),cmd);
|
|
120 system(cmd);
|
|
121 g_free(cmd);
|
|
122 free_selected_list(list);
|
|
123 }
|
|
124
|
|
125 /*
|
|
126 *-----------------------------------------------------------------------------
|
|
127 * keyboard functions
|
|
128 *-----------------------------------------------------------------------------
|
|
129 */
|
|
130
|
|
131 void keyboard_scroll_calc(gint *x, gint *y, GdkEventKey *event)
|
|
132 {
|
|
133 static gint delta = 0;
|
|
134 static guint32 time_old = 0;
|
|
135 static guint keyval_old = 0;
|
|
136
|
|
137 if (progressive_key_scrolling)
|
|
138 {
|
|
139 guint32 time_diff;
|
|
140
|
|
141 time_diff = event->time - time_old;
|
|
142
|
|
143 /* key pressed within 125ms ? (1/8 second) */
|
|
144 if (time_diff > 125 || event->keyval != keyval_old) delta = 0;
|
|
145
|
|
146 time_old = event->time;
|
|
147 keyval_old = event->keyval;
|
|
148
|
|
149 delta += 2;
|
|
150 }
|
|
151 else
|
|
152 {
|
|
153 delta = 8;
|
|
154 }
|
|
155
|
|
156 *x = *x * delta;
|
|
157 *y = *y * delta;
|
|
158 }
|
|
159
|
|
160 gint key_press_cb(GtkWidget *widget, GdkEventKey *event)
|
|
161 {
|
|
162 gint stop_signal = FALSE;
|
|
163 gint x = 0;
|
|
164 gint y = 0;
|
|
165
|
|
166 if (GTK_WIDGET_HAS_FOCUS(path_entry))
|
|
167 {
|
|
168 if (event->keyval == GDK_Escape)
|
|
169 gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
|
|
170 return stop_signal;
|
|
171 }
|
|
172
|
|
173 if (full_screen_window || GTK_WIDGET_HAS_FOCUS(main_image->viewport))
|
|
174 {
|
|
175 switch (event->keyval)
|
|
176 {
|
|
177 case GDK_Left:
|
|
178 x -= 1;
|
|
179 stop_signal = TRUE;
|
|
180 break;
|
|
181 case GDK_Right:
|
|
182 x += 1;
|
|
183 stop_signal = TRUE;
|
|
184 break;
|
|
185 case GDK_Up:
|
|
186 y -= 1;
|
|
187 stop_signal = TRUE;
|
|
188 break;
|
|
189 case GDK_Down:
|
|
190 y += 1;
|
|
191 stop_signal = TRUE;
|
|
192 break;
|
|
193 case GDK_BackSpace:
|
|
194 file_prev_image();
|
|
195 stop_signal = TRUE;
|
|
196 break;
|
|
197 case GDK_space:
|
|
198 file_next_image();
|
|
199 stop_signal = TRUE;
|
|
200 break;
|
|
201 }
|
|
202 }
|
|
203
|
|
204 switch (event->keyval)
|
|
205 {
|
|
206 case '+':
|
|
207 image_adjust_zoom(1);
|
|
208 break;
|
|
209 case GDK_Page_Up:
|
|
210 file_prev_image();
|
|
211 stop_signal = TRUE;
|
|
212 break;
|
|
213 case GDK_Page_Down:
|
|
214 file_next_image();
|
|
215 stop_signal = TRUE;
|
|
216 break;
|
|
217 case GDK_Home:
|
|
218 file_first_image();
|
|
219 stop_signal = TRUE;
|
|
220 break;
|
|
221 case GDK_End:
|
|
222 file_last_image();
|
|
223 stop_signal = TRUE;
|
|
224 break;
|
|
225 case GDK_Delete:
|
|
226 file_util_delete(image_get_path(), NULL);
|
|
227 stop_signal = TRUE;
|
|
228 break;
|
|
229 case GDK_Escape:
|
|
230 interrupt_thumbs();
|
|
231 stop_signal = TRUE;
|
|
232 break;
|
|
233 case 'Q': case 'q':
|
|
234 if (event->state == 0 || (event->state & GDK_MODIFIER_MASK) == GDK_LOCK_MASK)
|
|
235 {
|
|
236 exit_gqview();
|
|
237 return FALSE;
|
|
238 }
|
|
239 break;
|
|
240 }
|
|
241
|
|
242 if (event->state & GDK_SHIFT_MASK)
|
|
243 {
|
|
244 x *= 3;
|
|
245 y *= 3;
|
|
246 }
|
|
247
|
|
248 if (x != 0 || y!= 0)
|
|
249 {
|
|
250 keyboard_scroll_calc(&x, &y, event);
|
|
251 image_scroll(x, y);
|
|
252 }
|
|
253
|
|
254 if (stop_signal) gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
|
|
255
|
|
256 return stop_signal;
|
|
257 }
|
|
258
|
|
259 /*
|
|
260 *-----------------------------------------------------------------------------
|
|
261 * command line parser (private)
|
|
262 *-----------------------------------------------------------------------------
|
|
263 */
|
|
264
|
|
265 static void parse_command_line(int argc, char *argv[], gchar **path, gchar **file)
|
|
266 {
|
|
267 if (argc > 1)
|
|
268 {
|
|
269 gint i;
|
|
270 gchar *base_dir = get_current_dir();
|
|
271 i = 1;
|
|
272 while (i < argc)
|
|
273 {
|
|
274 gchar *cmd_line = argv[i];
|
|
275 gchar *cmd_all = g_strconcat(base_dir, "/", cmd_line, NULL);
|
|
276
|
|
277 if (!*path && cmd_line[0] == '/' && isdir(cmd_line))
|
|
278 {
|
|
279 *path = g_strdup(cmd_line);
|
|
280 }
|
|
281 else if (!*path && isdir(cmd_all))
|
|
282 {
|
|
283 *path = g_strdup(cmd_all);
|
|
284 }
|
|
285 else if (!*file && cmd_line[0] == '/' && isfile(cmd_line))
|
|
286 {
|
|
287 g_free(*path);
|
|
288 *path = remove_level_from_path(cmd_line);
|
|
289 *file = g_strdup(cmd_line);
|
|
290 }
|
|
291 else if (!*file && isfile(cmd_all))
|
|
292 {
|
|
293 g_free(*path);
|
|
294 *path = remove_level_from_path(cmd_all);
|
|
295 *file = g_strdup(cmd_all);
|
|
296 }
|
|
297 else if (strcmp(cmd_line, "-debug") == 0)
|
|
298 {
|
|
299 debug = TRUE;
|
|
300 printf("debugging output enabled\n");
|
|
301 }
|
|
302 else if (strcmp(cmd_line, "+t") == 0 ||
|
|
303 strcmp(cmd_line, "+tools") == 0)
|
|
304 {
|
|
305 tools_float = FALSE;
|
|
306 tools_hidden = FALSE;
|
|
307 }
|
|
308 else if (strcmp(cmd_line, "-t") == 0 ||
|
|
309 strcmp(cmd_line, "-tools") == 0)
|
|
310 {
|
|
311 tools_hidden = TRUE;
|
|
312 }
|
|
313 else if (strcmp(cmd_line, "-help") == 0)
|
|
314 {
|
|
315 printf("GQview version %s\n", VERSION);
|
|
316 printf(_("Usage: gqview [options] [path]\n\n"));
|
|
317 printf(_("valid options are:\n"));
|
|
318 printf(_(" +t, +tools force show of tools\n"));
|
|
319 printf(_(" -t, -tools force hide of tools\n"));
|
|
320 printf(_(" -debug turn on debug output\n"));
|
|
321 printf(_(" -help this message\n\n"));
|
|
322 exit (0);
|
|
323 }
|
|
324 else
|
|
325 {
|
|
326 printf(_("invalid or ignored: %s\nUse -help for options\n"), cmd_line);
|
|
327 }
|
|
328 g_free(cmd_all);
|
|
329 i++;
|
|
330 }
|
|
331 g_free(base_dir);
|
|
332 parse_out_relatives(*path);
|
|
333 parse_out_relatives(*file);
|
|
334 }
|
|
335 }
|
|
336
|
|
337 /*
|
|
338 *-----------------------------------------------------------------------------
|
|
339 * startup, init, and exit
|
|
340 *-----------------------------------------------------------------------------
|
|
341 */
|
|
342
|
|
343 static void setup_default_options()
|
|
344 {
|
|
345 gint i;
|
|
346
|
|
347 for(i=0; i<8; i++)
|
|
348 {
|
|
349 editor_name[i] = NULL;
|
|
350 editor_command[i] = NULL;
|
|
351 }
|
|
352
|
|
353 editor_name[0] = g_strdup(_("The Gimp"));
|
|
354 editor_command[0] = g_strdup("gimp");
|
|
355
|
|
356 editor_name[1] = g_strdup(_("Electric Eyes"));
|
|
357 editor_command[1] = g_strdup("ee");
|
|
358
|
|
359 editor_name[2] = g_strdup(_("XV"));
|
|
360 editor_command[2] = g_strdup("xv");
|
|
361
|
|
362 editor_name[3] = g_strdup(_("Xpaint"));
|
|
363 editor_command[3] = g_strdup("xpaint");
|
|
364
|
|
365 custom_filter = g_strdup(".eim;");
|
|
366 }
|
|
367
|
|
368 void exit_gqview()
|
|
369 {
|
|
370 full_screen_stop();
|
|
371
|
|
372 gdk_window_get_position (mainwindow->window, &main_window_x, &main_window_y);
|
|
373 gdk_window_get_size(mainwindow->window, &main_window_w, &main_window_h);
|
|
374
|
|
375 if (toolwindow)
|
|
376 {
|
|
377 gdk_window_get_position (toolwindow->window, &float_window_x, &float_window_y);
|
|
378 gdk_window_get_size(toolwindow->window, &float_window_w, &float_window_h);
|
|
379 }
|
|
380 save_options();
|
|
381
|
|
382 gtk_main_quit();
|
|
383 }
|
|
384
|
|
385 int main (int argc, char *argv[])
|
|
386 {
|
|
387 gchar *cmd_path = NULL;
|
|
388 gchar *cmd_file = NULL;
|
|
389
|
|
390 /* setup locale, i18n */
|
|
391 gtk_set_locale();
|
|
392 bindtextdomain (PACKAGE, LOCALEDIR);
|
|
393 textdomain (PACKAGE);
|
|
394
|
|
395 /* setup random seed for random slideshow */
|
|
396 srand (time (0));
|
|
397
|
|
398 gtk_init (&argc, &argv);
|
|
399 gdk_imlib_init();
|
|
400
|
|
401 /* push the correct color depths to gtk, (for 8-bit psuedo color displays)
|
|
402 * they should be popped, too, I guess...
|
|
403 */
|
|
404 gtk_widget_push_visual(gdk_imlib_get_visual());
|
|
405 gtk_widget_push_colormap(gdk_imlib_get_colormap());
|
|
406
|
|
407 setup_default_options();
|
|
408 load_options();
|
|
409
|
|
410 parse_command_line(argc, argv, &cmd_path, &cmd_file);
|
|
411
|
|
412 if (cmd_path)
|
|
413 current_path = g_strdup(cmd_path);
|
|
414 else if (startup_path_enable && startup_path && isdir(startup_path))
|
|
415 current_path = g_strdup(startup_path);
|
|
416 else
|
|
417 current_path = get_current_dir();
|
|
418
|
|
419 create_main_window();
|
|
420 update_edit_menus(mainwindow_accel_grp);
|
|
421 rebuild_file_filter();
|
|
422 filelist_refresh();
|
|
423
|
|
424 init_dnd();
|
|
425
|
|
426 while(gtk_events_pending()) gtk_main_iteration();
|
|
427 image_change_to(cmd_file);
|
|
428
|
|
429 g_free(cmd_path);
|
|
430 g_free(cmd_file);
|
|
431
|
|
432 gtk_main ();
|
|
433 return 0;
|
|
434 }
|
|
435
|
|
436
|