0.8.0
[geeqie.git] / src / main.c
1 /*
2  * GQview image viewer
3  * (C)2000 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) hehe, who needs popt anyway?
262  *-----------------------------------------------------------------------------
263  */ 
264
265 static gint startup_full_screen = FALSE;
266 static gint startup_in_slideshow = FALSE;
267
268 static void parse_command_line(int argc, char *argv[], gchar **path, gchar **file)
269 {
270         if (argc > 1)
271                 {
272                 gint i;
273                 gchar *base_dir = get_current_dir();
274                 i = 1;
275                 while (i < argc)
276                         {
277                         gchar *cmd_line = argv[i];
278                         gchar *cmd_all = g_strconcat(base_dir, "/", cmd_line, NULL);
279
280                         if (!*path && cmd_line[0] == '/' && isdir(cmd_line))
281                                 {
282                                 *path = g_strdup(cmd_line);
283                                 }
284                         else if (!*path && isdir(cmd_all))
285                                 {
286                                 *path = g_strdup(cmd_all);
287                                 }
288                         else if (!*file && cmd_line[0] == '/' && isfile(cmd_line))
289                                 {
290                                 g_free(*path);
291                                 *path = remove_level_from_path(cmd_line);
292                                 *file = g_strdup(cmd_line);
293                                 }
294                         else if (!*file && isfile(cmd_all))
295                                 {
296                                 g_free(*path);
297                                 *path = remove_level_from_path(cmd_all);
298                                 *file = g_strdup(cmd_all);
299                                 }
300                         else if (strcmp(cmd_line, "--debug") == 0)
301                                 {
302                                 debug = TRUE;
303                                 printf("debugging output enabled\n");
304                                 }
305                         else if (strcmp(cmd_line, "+t") == 0 ||
306                                  strcmp(cmd_line, "--with-tools") == 0)
307                                 {
308                                 tools_float = FALSE;
309                                 tools_hidden = FALSE;
310                                 }
311                         else if (strcmp(cmd_line, "-t") == 0 ||
312                                  strcmp(cmd_line, "--without-tools") == 0)
313                                 {
314                                 tools_hidden = TRUE;
315                                 }
316                         else if (strcmp(cmd_line, "-f") == 0 ||
317                                  strcmp(cmd_line, "--fullscreen") == 0)
318                                 {
319                                 startup_full_screen = TRUE;
320                                 }
321                         else if (strcmp(cmd_line, "-s") == 0 ||
322                                  strcmp(cmd_line, "--slideshow") == 0)
323                                 {
324                                 startup_in_slideshow = TRUE;
325                                 }
326                         else if (strcmp(cmd_line, "-h") == 0 ||
327                                  strcmp(cmd_line, "--help") == 0)
328                                 {
329                                 printf("GQview version %s\n", VERSION);
330                                 printf(_("Usage: gqview [options] [path]\n\n"));
331                                 printf(_("valid options are:\n"));
332                                 printf(_("  +t, --with-tools           force show of tools\n"));
333                                 printf(_("  -t, --without-tools        force hide of tools\n"));
334                                 printf(_("  -f, --fullscreen           start in full screen mode\n"));
335                                 printf(_("  -s, --slideshow            start in slideshow mode\n"));
336                                 printf(_("  --debug                    turn on debug output\n"));
337                                 printf(_("  -h, --help                 show this message\n\n"));
338                                 exit (0);
339                                 }
340                         else 
341                                 {
342                                 printf(_("invalid or ignored: %s\nUse -help for options\n"), cmd_line);
343                                 }
344                         g_free(cmd_all);
345                         i++;
346                         }
347                 g_free(base_dir);
348                 parse_out_relatives(*path);
349                 parse_out_relatives(*file);
350                 }
351 }
352
353 /*
354  *-----------------------------------------------------------------------------
355  * startup, init, and exit
356  *-----------------------------------------------------------------------------
357  */ 
358
359 static void setup_default_options()
360 {
361         gint i;
362
363         for(i=0; i<8; i++)
364                 {
365                 editor_name[i] = NULL;
366                 editor_command[i] = NULL;
367                 }
368
369         editor_name[0] = g_strdup(_("The Gimp"));
370         editor_command[0] = g_strdup("gimp");
371
372         editor_name[1] = g_strdup(_("Electric Eyes"));
373         editor_command[1] = g_strdup("ee");
374
375         editor_name[2] = g_strdup(_("XV"));
376         editor_command[2] = g_strdup("xv");
377
378         editor_name[3] = g_strdup(_("Xpaint"));
379         editor_command[3] = g_strdup("xpaint");
380
381         custom_filter = g_strdup(".eim;");
382 }
383
384 void exit_gqview()
385 {
386         full_screen_stop();
387
388         gdk_window_get_position (mainwindow->window, &main_window_x, &main_window_y);
389         gdk_window_get_size(mainwindow->window, &main_window_w, &main_window_h);
390
391         if (toolwindow)
392                 {
393                 gdk_window_get_position (toolwindow->window, &float_window_x, &float_window_y);
394                 gdk_window_get_size(toolwindow->window, &float_window_w, &float_window_h);
395                 }
396         save_options();
397
398         gtk_main_quit();
399 }
400
401 int main (int argc, char *argv[])
402 {
403         gchar *cmd_path = NULL;
404         gchar *cmd_file = NULL;
405
406         /* setup locale, i18n */
407         gtk_set_locale();
408         bindtextdomain (PACKAGE, LOCALEDIR);
409         textdomain (PACKAGE);
410
411         /* setup random seed for random slideshow */
412         srand (time (0));
413
414         gtk_init (&argc, &argv);
415         gdk_imlib_init();
416
417         /* push the correct color depths to gtk, (for 8-bit psuedo color displays)
418          * they should be popped, too, I guess...
419          */
420         gtk_widget_push_visual(gdk_imlib_get_visual());
421         gtk_widget_push_colormap(gdk_imlib_get_colormap());
422
423         setup_default_options();
424         load_options();
425
426         parse_command_line(argc, argv, &cmd_path, &cmd_file);
427
428         if (cmd_path)
429                 current_path = g_strdup(cmd_path);
430         else if (startup_path_enable && startup_path && isdir(startup_path))
431                 current_path = g_strdup(startup_path);
432         else
433                 current_path = get_current_dir();
434
435         create_main_window();
436         update_edit_menus(mainwindow_accel_grp);
437         rebuild_file_filter();
438         filelist_refresh();
439
440         init_dnd();
441
442         while(gtk_events_pending()) gtk_main_iteration();
443         image_change_to(cmd_file);
444
445         g_free(cmd_path);
446         g_free(cmd_file);
447
448         if (startup_full_screen) full_screen_toggle();
449         if (startup_in_slideshow) slideshow_start();
450
451         gtk_main ();
452         return 0;
453 }
454
455