replaced directory path with FileData* dir_fd
[geeqie.git] / src / main.c
1 /*
2  * Geeqie
3  * (C) 2006 John Ellis
4  * Copyright (C) 2008 The Geeqie Team
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
14 #include "main.h"
15
16 #include "cache.h"
17 #include "collect.h"
18 #include "collect-io.h"
19 #include "filedata.h"
20 #include "filefilter.h"
21 #include "image-overlay.h"
22 #include "layout.h"
23 #include "layout_image.h"
24 #include "rcfile.h"
25 #include "remote.h"
26 #include "similar.h"
27 #include "ui_bookmark.h"
28 #include "ui_fileops.h"
29 #include "ui_utildlg.h"
30
31 #include <gdk/gdkkeysyms.h> /* for keyboard values */
32
33
34 #include <math.h>
35 #ifdef G_OS_UNIX
36 #include <pwd.h>
37 #endif
38
39
40 static RemoteConnection *remote_connection = NULL;
41
42
43 /*
44  *-----------------------------------------------------------------------------
45  * misc (public)
46  *-----------------------------------------------------------------------------
47  */
48
49
50 gdouble get_zoom_increment(void)
51 {
52         return ((options->image.zoom_increment != 0) ? (gdouble)options->image.zoom_increment / 10.0 : 1.0);
53 }
54
55 gchar *utf8_validate_or_convert(const gchar *text)
56 {
57         gint len;
58
59         if (!text) return NULL;
60         
61         len = strlen(text);
62         if (!g_utf8_validate(text, len, NULL))
63                 return g_convert(text, len, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
64
65         return g_strdup(text);
66 }
67
68 /* Borrowed from gtkfilesystemunix.c */
69 gchar *expand_tilde(const gchar *filename)
70 {
71 #ifndef G_OS_UNIX
72         return g_strdup(filename);
73 #else
74         const char *notilde;
75         const char *slash;
76         const char *home;
77
78         if (filename[0] != '~')
79                 return g_strdup(filename);
80
81         notilde = filename + 1;
82         slash = strchr(notilde, G_DIR_SEPARATOR);
83         if (slash == notilde || !*notilde)
84                 {
85                 home = g_get_home_dir();
86                 if (!home)
87                         return g_strdup(filename);
88                 }
89         else
90                 {
91                 gchar *username;
92                 struct passwd *passwd;
93
94                 if (slash)
95                         username = g_strndup(notilde, slash - notilde);
96                 else
97                         username = g_strdup(notilde);
98
99                 passwd = getpwnam(username);
100                 g_free(username);
101
102                 if (!passwd)
103                         return g_strdup(filename);
104
105                 home = passwd->pw_dir;
106                 }
107
108         if (slash)
109                 return g_build_filename(home, G_DIR_SEPARATOR_S, slash + 1, NULL);
110         else
111                 return g_build_filename(home, G_DIR_SEPARATOR_S, NULL);
112 #endif
113 }
114
115
116 /*
117  *-----------------------------------------------------------------------------
118  * keyboard functions
119  *-----------------------------------------------------------------------------
120  */
121
122 void keyboard_scroll_calc(gint *x, gint *y, GdkEventKey *event)
123 {
124         static gint delta = 0;
125         static guint32 time_old = 0;
126         static guint keyval_old = 0;
127
128         if (event->state & GDK_CONTROL_MASK)
129                 {
130                 if (*x < 0) *x = G_MININT / 2;
131                 if (*x > 0) *x = G_MAXINT / 2;
132                 if (*y < 0) *y = G_MININT / 2;
133                 if (*y > 0) *y = G_MAXINT / 2;
134
135                 return;
136                 }
137
138         if (options->progressive_key_scrolling)
139                 {
140                 guint32 time_diff;
141
142                 time_diff = event->time - time_old;
143
144                 /* key pressed within 125ms ? (1/8 second) */
145                 if (time_diff > 125 || event->keyval != keyval_old) delta = 0;
146
147                 time_old = event->time;
148                 keyval_old = event->keyval;
149
150                 delta += 2;
151                 }
152         else
153                 {
154                 delta = 8;
155                 }
156
157         *x = *x * delta;
158         *y = *y * delta;
159 }
160
161
162
163 /*
164  *-----------------------------------------------------------------------------
165  * command line parser (private) hehe, who needs popt anyway?
166  *-----------------------------------------------------------------------------
167  */
168
169 static gint startup_blank = FALSE;
170 static gint startup_full_screen = FALSE;
171 static gint startup_in_slideshow = FALSE;
172 static gint startup_command_line_collection = FALSE;
173
174
175 static void parse_command_line_add_file(const gchar *file_path, gchar **path, gchar **file,
176                                         GList **list, GList **collection_list)
177 {
178         gchar *path_parsed;
179
180         path_parsed = g_strdup(file_path);
181         parse_out_relatives(path_parsed);
182
183         if (file_extension_match(path_parsed, GQ_COLLECTION_EXT))
184                 {
185                 *collection_list = g_list_append(*collection_list, path_parsed);
186                 }
187         else
188                 {
189                 if (!*path) *path = remove_level_from_path(path_parsed);
190                 if (!*file) *file = g_strdup(path_parsed);
191                 *list = g_list_prepend(*list, file_data_new_simple(path_parsed));
192                 }
193 }
194
195 static void parse_command_line_add_dir(const gchar *dir, gchar **path, gchar **file,
196                                        GList **list)
197 {
198         GList *files;
199         gchar *path_parsed;
200         FileData *dir_fd;
201
202         path_parsed = g_strdup(dir);
203         parse_out_relatives(path_parsed);
204         dir_fd = file_data_new_simple(path_parsed);
205         
206
207         if (filelist_read(dir_fd, &files, NULL))
208                 {
209                 GList *work;
210
211                 files = filelist_filter(files, FALSE);
212                 files = filelist_sort_path(files);
213
214                 work = files;
215                 while (work)
216                         {
217                         FileData *fd = work->data;
218                         if (!*path) *path = remove_level_from_path(fd->path);
219                         if (!*file) *file = g_strdup(fd->path);
220                         *list = g_list_prepend(*list, fd);
221
222                         work = work->next;
223                         }
224
225                 g_list_free(files);
226                 }
227
228         g_free(path_parsed);
229         file_data_unref(dir_fd);
230 }
231
232 static void parse_command_line_process_dir(const gchar *dir, gchar **path, gchar **file,
233                                            GList **list, gchar **first_dir)
234 {
235
236         if (!*list && !*first_dir)
237                 {
238                 *first_dir = g_strdup(dir);
239                 }
240         else
241                 {
242                 if (*first_dir)
243                         {
244                         parse_command_line_add_dir(*first_dir, path, file, list);
245                         g_free(*first_dir);
246                         *first_dir = NULL;
247                         }
248                 parse_command_line_add_dir(dir, path, file, list);
249                 }
250 }
251
252 static void parse_command_line_process_file(const gchar *file_path, gchar **path, gchar **file,
253                                             GList **list, GList **collection_list, gchar **first_dir)
254 {
255
256         if (*first_dir)
257                 {
258                 parse_command_line_add_dir(*first_dir, path, file, list);
259                 g_free(*first_dir);
260                 *first_dir = NULL;
261                 }
262         parse_command_line_add_file(file_path, path, file, list, collection_list);
263 }
264
265 static void parse_command_line(int argc, char *argv[], gchar **path, gchar **file,
266                                GList **cmd_list, GList **collection_list,
267                                gchar **geometry)
268 {
269         GList *list = NULL;
270         GList *remote_list = NULL;
271         GList *remote_errors = NULL;
272         gint remote_do = FALSE;
273         gchar *first_dir = NULL;
274
275         if (argc > 1)
276                 {
277                 gint i;
278                 gchar *base_dir = get_current_dir();
279                 i = 1;
280                 while (i < argc)
281                         {
282                         const gchar *cmd_line = argv[i];
283                         gchar *cmd_all = g_build_filename(base_dir, cmd_line, NULL);
284
285                         if (cmd_line[0] == G_DIR_SEPARATOR && isdir(cmd_line))
286                                 {
287                                 parse_command_line_process_dir(cmd_line, path, file, &list, &first_dir);
288                                 }
289                         else if (isdir(cmd_all))
290                                 {
291                                 parse_command_line_process_dir(cmd_all, path, file, &list, &first_dir);
292                                 }
293                         else if (cmd_line[0] == G_DIR_SEPARATOR && isfile(cmd_line))
294                                 {
295                                 parse_command_line_process_file(cmd_line, path, file,
296                                                                 &list, collection_list, &first_dir);
297                                 }
298                         else if (isfile(cmd_all))
299                                 {
300                                 parse_command_line_process_file(cmd_all, path, file,
301                                                                 &list, collection_list, &first_dir);
302                                 }
303                         else if (strncmp(cmd_line, "--debug", 7) == 0 && (cmd_line[7] == '\0' || cmd_line[7] == '='))
304                                 {
305                                 /* do nothing but do not produce warnings */
306                                 }
307                         else if (strcmp(cmd_line, "+t") == 0 ||
308                                  strcmp(cmd_line, "--with-tools") == 0)
309                                 {
310                                 options->layout.tools_float = FALSE;
311                                 options->layout.tools_hidden = FALSE;
312
313                                 remote_list = g_list_append(remote_list, "+t");
314                                 }
315                         else if (strcmp(cmd_line, "-t") == 0 ||
316                                  strcmp(cmd_line, "--without-tools") == 0)
317                                 {
318                                 options->layout.tools_hidden = TRUE;
319
320                                 remote_list = g_list_append(remote_list, "-t");
321                                 }
322                         else if (strcmp(cmd_line, "-f") == 0 ||
323                                  strcmp(cmd_line, "--fullscreen") == 0)
324                                 {
325                                 startup_full_screen = TRUE;
326                                 }
327                         else if (strcmp(cmd_line, "-s") == 0 ||
328                                  strcmp(cmd_line, "--slideshow") == 0)
329                                 {
330                                 startup_in_slideshow = TRUE;
331                                 }
332                         else if (strcmp(cmd_line, "-l") == 0 ||
333                                  strcmp(cmd_line, "--list") == 0)
334                                 {
335                                 startup_command_line_collection = TRUE;
336                                 }
337                         else if (strncmp(cmd_line, "--geometry=", 11) == 0)
338                                 {
339                                 if (!*geometry) *geometry = g_strdup(cmd_line + 11);
340                                 }
341                         else if (strcmp(cmd_line, "-r") == 0 ||
342                                  strcmp(cmd_line, "--remote") == 0)
343                                 {
344                                 if (!remote_do)
345                                         {
346                                         remote_do = TRUE;
347                                         remote_list = remote_build_list(remote_list, argc - i, &argv[i], &remote_errors);
348                                         }
349                                 }
350                         else if (strcmp(cmd_line, "-rh") == 0 ||
351                                  strcmp(cmd_line, "--remote-help") == 0)
352                                 {
353                                 remote_help();
354                                 exit(0);
355                                 }
356                         else if (strcmp(cmd_line, "--blank") == 0)
357                                 {
358                                 startup_blank = TRUE;
359                                 }
360                         else if (strcmp(cmd_line, "-v") == 0 ||
361                                  strcmp(cmd_line, "--version") == 0)
362                                 {
363                                 printf_term("%s %s\n", GQ_APPNAME, VERSION);
364                                 exit(0);
365                                 }
366                         else if (strcmp(cmd_line, "--alternate") == 0)
367                                 {
368                                 /* enable faster experimental algorithm */
369                                 log_printf("Alternate similarity algorithm enabled\n");
370                                 image_sim_alternate_set(TRUE);
371                                 }
372                         else if (strcmp(cmd_line, "-h") == 0 ||
373                                  strcmp(cmd_line, "--help") == 0)
374                                 {
375                                 printf_term("%s %s\n", GQ_APPNAME, VERSION);
376                                 printf_term(_("Usage: %s [options] [path]\n\n"), GQ_APPNAME_LC);
377                                 print_term(_("valid options are:\n"));
378                                 print_term(_("  +t, --with-tools           force show of tools\n"));
379                                 print_term(_("  -t, --without-tools        force hide of tools\n"));
380                                 print_term(_("  -f, --fullscreen           start in full screen mode\n"));
381                                 print_term(_("  -s, --slideshow            start in slideshow mode\n"));
382                                 print_term(_("  -l, --list                 open collection window for command line\n"));
383                                 print_term(_("      --geometry=GEOMETRY    set main window location\n"));
384                                 print_term(_("  -r, --remote               send following commands to open window\n"));
385                                 print_term(_("  -rh,--remote-help          print remote command list\n"));
386 #ifdef DEBUG
387                                 print_term(_("  --debug[=level]            turn on debug output\n"));
388 #endif
389                                 print_term(_("  -v, --version              print version info\n"));
390                                 print_term(_("  -h, --help                 show this message\n\n"));
391
392 #if 0
393                                 /* these options are not officially supported!
394                                  * only for testing new features, no need to translate them */
395                                 print_term(  "  --alternate                use alternate similarity algorithm\n");
396 #endif
397
398                                 exit(0);
399                                 }
400                         else if (!remote_do)
401                                 {
402                                 printf_term(_("invalid or ignored: %s\nUse --help for options\n"), cmd_line);
403                                 }
404
405                         g_free(cmd_all);
406                         i++;
407                         }
408                 g_free(base_dir);
409                 parse_out_relatives(*path);
410                 parse_out_relatives(*file);
411                 }
412
413         list = g_list_reverse(list);
414
415         if (!*path && first_dir)
416                 {
417                 *path = first_dir;
418                 first_dir = NULL;
419
420                 parse_out_relatives(*path);
421                 }
422         g_free(first_dir);
423
424         if (remote_do)
425                 {
426                 if (remote_errors)
427                         {
428                         GList *work = remote_errors;
429                         
430                         printf_term(_("Invalid or ignored remote options: "));
431                         while (work)
432                                 {
433                                 gchar *opt = work->data;
434                                                 
435                                 printf_term("%s%s", (work == remote_errors) ? "" : ", ", opt);
436                                 work = work->next;
437                                 }
438
439                         printf_term(_("\nUse --remote-help for valid remote options.\n"));
440                         }
441
442                 remote_control(argv[0], remote_list, *path, list, *collection_list);
443                 }
444         g_list_free(remote_list);
445
446         if (list && list->next)
447                 {
448                 *cmd_list = list;
449                 }
450         else
451                 {
452                 filelist_free(list);
453                 *cmd_list = NULL;
454                 }
455 }
456
457 static void parse_command_line_for_debug_option(int argc, char *argv[])
458 {
459 #ifdef DEBUG
460         const gchar *debug_option = "--debug";
461         gint len = strlen(debug_option);
462
463         if (argc > 1)
464                 {
465                 gint i;
466
467                 for (i = 1; i < argc; i++)
468                         {
469                         const gchar *cmd_line = argv[i];
470                         if (strncmp(cmd_line, debug_option, len) == 0)
471                                 {
472                                 gint cmd_line_len = strlen(cmd_line);
473
474                                 /* we now increment the debug state for verbosity */
475                                 if (cmd_line_len == len)
476                                         debug_level_add(1);
477                                 else if (cmd_line[len] == '=' && g_ascii_isdigit(cmd_line[len+1]))
478                                         {
479                                         gint n = atoi(cmd_line + len + 1);
480                                         if (n < 0) n = 1;
481                                         debug_level_add(n);
482                                         }
483                                 }
484                         }
485                 }
486
487         DEBUG_1("debugging output enabled (level %d)", get_debug_level());
488 #endif
489 }
490
491 /*
492  *-----------------------------------------------------------------------------
493  * startup, init, and exit
494  *-----------------------------------------------------------------------------
495  */
496
497 #define RC_HISTORY_NAME "history"
498
499 static void keys_load(void)
500 {
501         gchar *path;
502
503         path = g_build_filename(homedir(), GQ_RC_DIR, RC_HISTORY_NAME, NULL);
504         history_list_load(path);
505         g_free(path);
506 }
507
508 static void keys_save(void)
509 {
510         gchar *path;
511
512         path = g_build_filename(homedir(), GQ_RC_DIR, RC_HISTORY_NAME, NULL);
513         history_list_save(path);
514         g_free(path);
515 }
516
517 static void check_for_home_path(gchar *path)
518 {
519         gchar *buf;
520
521         buf = g_build_filename(homedir(), path, NULL);
522         if (!isdir(buf))
523                 {
524                 log_printf(_("Creating %s dir:%s\n"), GQ_APPNAME, buf);
525
526                 if (!mkdir_utf8(buf, 0755))
527                         {
528                         log_printf(_("Could not create dir:%s\n"), buf);
529                         }
530                 }
531         g_free(buf);
532 }
533
534
535 static void exit_program_final(void)
536 {
537         gchar *path;
538         gchar *pathl;
539
540         remote_close(remote_connection);
541
542         collect_manager_flush();
543
544         sync_options_with_current_state(options);
545         save_options(options);
546         keys_save();
547
548         path = g_build_filename(homedir(), GQ_RC_DIR, "accels", NULL);
549         pathl = path_from_utf8(path);
550         gtk_accel_map_save(pathl);
551         g_free(pathl);
552         g_free(path);
553
554         gtk_main_quit();
555 }
556
557 static GenericDialog *exit_dialog = NULL;
558
559 static void exit_confirm_cancel_cb(GenericDialog *gd, gpointer data)
560 {
561         exit_dialog = NULL;
562         generic_dialog_close(gd);
563 }
564
565 static void exit_confirm_exit_cb(GenericDialog *gd, gpointer data)
566 {
567         exit_dialog = NULL;
568         generic_dialog_close(gd);
569         exit_program_final();
570 }
571
572 static gint exit_confirm_dlg(void)
573 {
574         GtkWidget *parent;
575         LayoutWindow *lw;
576         gchar *msg;
577
578         if (exit_dialog)
579                 {
580                 gtk_window_present(GTK_WINDOW(exit_dialog->dialog));
581                 return TRUE;
582                 }
583
584         if (!collection_window_modified_exists()) return FALSE;
585
586         parent = NULL;
587         lw = NULL;
588         if (layout_valid(&lw))
589                 {
590                 parent = lw->window;
591                 }
592
593         msg = g_strdup_printf("%s - %s", GQ_APPNAME, _("exit"));
594         exit_dialog = generic_dialog_new(msg,
595                                 GQ_WMCLASS, "exit", parent, FALSE,
596                                 exit_confirm_cancel_cb, NULL);
597         g_free(msg);
598         msg = g_strdup_printf(_("Quit %s"), GQ_APPNAME);
599         generic_dialog_add_message(exit_dialog, GTK_STOCK_DIALOG_QUESTION,
600                                    msg, _("Collections have been modified. Quit anyway?"));
601         g_free(msg);
602         generic_dialog_add_button(exit_dialog, GTK_STOCK_QUIT, NULL, exit_confirm_exit_cb, TRUE);
603
604         gtk_widget_show(exit_dialog->dialog);
605
606         return TRUE;
607 }
608
609 void exit_program(void)
610 {
611         layout_image_full_screen_stop(NULL);
612
613         if (exit_confirm_dlg()) return;
614
615         exit_program_final();
616 }
617
618 int main(int argc, char *argv[])
619 {
620         LayoutWindow *lw;
621         gchar *path = NULL;
622         gchar *cmd_path = NULL;
623         gchar *cmd_file = NULL;
624         GList *cmd_list = NULL;
625         GList *collection_list = NULL;
626         CollectionData *first_collection = NULL;
627         gchar *geometry = NULL;
628         gchar *buf;
629         gchar *bufl;
630         CollectionData *cd = NULL;
631
632         /* init execution time counter (debug only) */
633         init_exec_time();
634
635         /* setup locale, i18n */
636         gtk_set_locale();
637
638 #ifdef ENABLE_NLS
639         bindtextdomain(PACKAGE, GQ_LOCALEDIR);
640         bind_textdomain_codeset(PACKAGE, "UTF-8");
641         textdomain(PACKAGE);
642 #endif
643     
644         /* setup random seed for random slideshow */
645         srand(time(NULL));
646
647 #if 1
648         log_printf("%s %s, This is an alpha release.\n", GQ_APPNAME, VERSION);
649 #endif
650         parse_command_line_for_debug_option(argc, argv);
651
652         options = init_options(NULL);
653         setup_default_options(options);
654         load_options(options);
655
656         parse_command_line(argc, argv, &cmd_path, &cmd_file, &cmd_list, &collection_list, &geometry);
657
658         /* If a gtkrc file exists in the rc directory, add it to the
659          * list of files to be parsed at the end of gtk_init() */
660         buf = g_build_filename(homedir(), GQ_RC_DIR, "gtkrc", NULL);
661         bufl = path_from_utf8(buf);
662         if (access(bufl, R_OK) == 0)
663                 gtk_rc_add_default_file(bufl);
664         g_free(bufl);
665         g_free(buf);
666
667         gtk_init(&argc, &argv);
668
669         if (gtk_major_version < GTK_MAJOR_VERSION ||
670             (gtk_major_version == GTK_MAJOR_VERSION && gtk_minor_version < GTK_MINOR_VERSION) )
671                 {
672                 log_printf("!!! This is a friendly warning.\n");
673                 log_printf("!!! The version of GTK+ in use now is older than when %s was compiled.\n", GQ_APPNAME);
674                 log_printf("!!!  compiled with GTK+-%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION);
675                 log_printf("!!!   running with GTK+-%d.%d\n", gtk_major_version, gtk_minor_version);
676                 log_printf("!!! %s may quit unexpectedly with a relocation error.\n", GQ_APPNAME);
677                 }
678
679         check_for_home_path(GQ_RC_DIR);
680         check_for_home_path(GQ_RC_DIR_COLLECTIONS);
681         check_for_home_path(GQ_CACHE_RC_THUMB);
682         check_for_home_path(GQ_CACHE_RC_METADATA);
683
684         keys_load();
685         filter_add_defaults();
686         filter_rebuild();
687
688         buf = g_build_filename(homedir(), GQ_RC_DIR, "accels", NULL);
689         bufl = path_from_utf8(buf);
690         gtk_accel_map_load(bufl);
691         g_free(bufl);
692         g_free(buf);
693
694         if (startup_blank)
695                 {
696                 g_free(cmd_path);
697                 cmd_path = NULL;
698                 g_free(cmd_file);
699                 cmd_file = NULL;
700                 filelist_free(cmd_list);
701                 cmd_list = NULL;
702                 string_list_free(collection_list);
703                 collection_list = NULL;
704
705                 path = NULL;
706                 }
707         else if (cmd_path)
708                 {
709                 path = g_strdup(cmd_path);
710                 }
711         else if (options->startup.restore_path && options->startup.path && isdir(options->startup.path))
712                 {
713                 path = g_strdup(options->startup.path);
714                 }
715         else
716                 {
717                 path = get_current_dir();
718                 }
719
720         lw = layout_new_with_geometry(NULL, options->layout.tools_float, options->layout.tools_hidden, geometry);
721         layout_sort_set(lw, options->file_sort.method, options->file_sort.ascending);
722
723         if (collection_list && !startup_command_line_collection)
724                 {
725                 GList *work;
726
727                 work = collection_list;
728                 while (work)
729                         {
730                         CollectWindow *cw;
731                         const gchar *path;
732
733                         path = work->data;
734                         work = work->next;
735
736                         cw = collection_window_new(path);
737                         if (!first_collection && cw) first_collection = cw->cd;
738                         }
739                 }
740
741         if (cmd_list ||
742             (startup_command_line_collection && collection_list))
743                 {
744                 GList *work;
745
746                 if (startup_command_line_collection)
747                         {
748                         CollectWindow *cw;
749
750                         cw = collection_window_new("");
751                         cd = cw->cd;
752                         }
753                 else
754                         {
755                         cd = collection_new("");        /* if we pass NULL, untitled counter is falsely increm. */
756                         }
757
758                 g_free(cd->path);
759                 cd->path = NULL;
760                 g_free(cd->name);
761                 cd->name = g_strdup(_("Command line"));
762
763                 collection_path_changed(cd);
764
765                 work = cmd_list;
766                 while (work)
767                         {
768                         collection_add(cd, file_data_new_simple((gchar *)work->data), FALSE);
769                         work = work->next;
770                         }
771
772                 work = collection_list;
773                 while (work)
774                         {
775                         collection_load(cd, (gchar *)work->data, COLLECTION_LOAD_APPEND);
776                         work = work->next;
777                         }
778
779                 layout_set_path(lw, path);
780                 if (cd->list) layout_image_set_collection(lw, cd, cd->list->data);
781
782                 /* mem leak, we never unref this collection when !startup_command_line_collection
783                  * (the image view of the main window does not hold a ref to the collection)
784                  * this is sort of unavoidable, for if it did hold a ref, next/back
785                  * may not work as expected when closing collection windows.
786                  *
787                  * collection_unref(cd);
788                  */
789
790                 }
791         else if (cmd_file)
792                 {
793                 layout_set_path(lw, cmd_file);
794                 }
795         else
796                 {
797                 layout_set_path(lw, path);
798                 if (first_collection)
799                         {
800                         layout_image_set_collection(lw, first_collection,
801                                                     collection_get_first(first_collection));
802                         }
803                 }
804
805         image_osd_set(lw->image, options->image_overlay.common.state | (options->image_overlay.common.show_at_startup ? OSD_SHOW_INFO : OSD_SHOW_NOTHING));
806
807         g_free(geometry);
808         g_free(cmd_path);
809         g_free(cmd_file);
810         filelist_free(cmd_list);
811         string_list_free(collection_list);
812         g_free(path);
813
814         if (startup_full_screen) layout_image_full_screen_start(lw);
815         if (startup_in_slideshow) layout_image_slideshow_start(lw);
816
817         buf = g_build_filename(homedir(), GQ_RC_DIR, ".command", NULL);
818         remote_connection = remote_server_init(buf, cd);
819         g_free(buf);
820
821         gtk_main();
822         return 0;
823 }