]> www.fi.muni.cz Git - evince.git/blob - shell/main.c
[dualscreen] fix crash on ctrl+w and fix control window closing
[evince.git] / shell / main.c
1 /*
2  *  Copyright (C) 2004 Marco Pesenti Gritti
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <glib/gstdio.h>
26 #include <glib/gi18n.h>
27 #include <gtk/gtk.h>
28
29 #include "ev-application.h"
30 #include "ev-debug.h"
31 #include "ev-init.h"
32 #include "ev-file-helpers.h"
33 #include "ev-stock-icons.h"
34 #include "ev-metadata.h"
35
36 #ifdef WITH_SMCLIENT
37 #include "eggsmclient.h"
38 #ifdef GDK_WINDOWING_X11
39 #include "eggdesktopfile.h"
40 #endif
41 #endif /* WITH_SMCLIENT */
42
43 #ifdef G_OS_WIN32
44 #include <io.h>
45 #include <conio.h>
46 #if !(_WIN32_WINNT >= 0x0500)
47 #error "_WIN32_WINNT must be defined >= 0x0500"
48 #endif
49 #include <windows.h>
50 #endif
51
52 static gchar   *ev_page_label;
53 static gchar   *ev_find_string;
54 static gint     ev_page_index = 0;
55 static gboolean preview_mode = FALSE;
56 static gboolean fullscreen_mode = FALSE;
57 static gboolean presentation_mode = FALSE;
58 static gboolean unlink_temp_file = FALSE;
59 static gchar   *print_settings;
60 static const char **file_arguments = NULL;
61
62
63 static gboolean
64 option_version_cb (const gchar *option_name,
65                    const gchar *value,
66                    gpointer     data,
67                    GError     **error)
68 {
69   g_print ("%s %s\n", _("GNOME Document Viewer"), VERSION);
70
71   exit (0);
72   return FALSE;
73 }
74
75 static const GOptionEntry goption_options[] =
76 {
77         { "page-label", 'p', 0, G_OPTION_ARG_STRING, &ev_page_label, N_("The page label of the document to display."), N_("PAGE")},
78         { "page-index", 'i', 0, G_OPTION_ARG_INT, &ev_page_index, N_("The page number of the document to display."), N_("NUMBER")},
79         { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen_mode, N_("Run evince in fullscreen mode"), NULL },
80         { "presentation", 's', 0, G_OPTION_ARG_NONE, &presentation_mode, N_("Run evince in presentation mode"), NULL },
81         { "preview", 'w', 0, G_OPTION_ARG_NONE, &preview_mode, N_("Run evince as a previewer"), NULL },
82         { "find", 'l', 0, G_OPTION_ARG_STRING, &ev_find_string, N_("The word or phrase to find in the document"), N_("STRING")},
83         { "unlink-tempfile", 'u', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &unlink_temp_file, NULL, NULL },
84         { "print-settings", 't', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &print_settings, NULL, NULL },
85         { "version", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
86         { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &file_arguments, NULL, N_("[FILEā€¦]") },
87         { NULL }
88 };
89
90 static gboolean
91 launch_previewer (void)
92 {
93         GString *cmd_str;
94         gchar   *cmd;
95         gboolean retval = FALSE;
96         GError  *error = NULL;
97
98         /* Rebuild the command line, ignoring options
99          * not supported by the previewer and taking only
100          * the first path given
101          */
102         cmd_str = g_string_new ("evince-previewer");
103                 
104         if (print_settings) {
105                 gchar *quoted;
106
107                 quoted = g_shell_quote (print_settings);
108                 g_string_append_printf (cmd_str, " --print-settings %s", quoted);
109                 g_free (quoted);
110         }
111
112         if (unlink_temp_file)
113                 g_string_append (cmd_str, " --unlink-tempfile");
114
115         if (file_arguments) {
116                 gchar *quoted;
117                 
118                 quoted = g_shell_quote (file_arguments[0]);
119                 g_string_append_printf (cmd_str, " %s", quoted);
120                 g_free (quoted);
121         }
122
123         cmd = g_string_free (cmd_str, FALSE);
124
125         if (!error) {
126                 GAppInfo *app;
127
128                 app = g_app_info_create_from_commandline (cmd, NULL, 0, &error);
129
130                 if (app != NULL) {
131                         retval = g_app_info_launch (app, NULL, NULL, &error);
132                         g_object_unref (app);
133                 }
134         }
135
136         if (error) {
137                 g_warning ("Error launching previewer: %s\n", error->message);
138                 g_error_free (error);
139         }
140
141         g_free (cmd);
142
143         return retval;
144 }
145
146 static gchar *
147 get_label_from_filename (const gchar *filename)
148 {
149         GFile   *file;
150         gchar   *label;
151         gboolean exists;
152
153         label = g_strrstr (filename, "#");
154         if (!label)
155                 return NULL;
156
157         /* Filename contains a #, check
158          * whether it's part of the path
159          * or a label
160          */
161         file = g_file_new_for_commandline_arg (filename);
162         exists = g_file_query_exists (file, NULL);
163         g_object_unref (file);
164
165         return exists ? NULL : label;
166 }
167
168 static void
169 load_files (const char **files)
170 {
171         GdkScreen       *screen = gdk_screen_get_default ();
172         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
173         gint             i;
174         EvLinkDest      *global_dest = NULL;
175
176         if (!files) {
177                 if (!ev_application_has_window (EV_APP))
178                         ev_application_open_window (EV_APP, screen, GDK_CURRENT_TIME);
179                 return;
180         }
181
182         if (ev_page_label)
183                 global_dest = ev_link_dest_new_page_label (ev_page_label);
184         else if (ev_page_index)
185                 global_dest = ev_link_dest_new_page (MAX (0, ev_page_index - 1));
186
187         if (fullscreen_mode)
188                 mode = EV_WINDOW_MODE_FULLSCREEN;
189         else if (presentation_mode)
190                 mode = EV_WINDOW_MODE_PRESENTATION;
191
192         for (i = 0; files[i]; i++) {
193                 const gchar *filename;
194                 gchar       *uri;
195                 gchar       *label;
196                 GFile       *file;
197                 EvLinkDest  *dest = NULL;
198                 const gchar *app_uri;
199
200                 filename = files[i];
201                 label = get_label_from_filename (filename);
202                 if (label) {
203                         *label = 0;
204                         label++;
205                         dest = ev_link_dest_new_page_label (label);
206                 } else if (global_dest) {
207                         dest = g_object_ref (global_dest);
208                 }
209
210                 file = g_file_new_for_commandline_arg (filename);
211                 uri = g_file_get_uri (file);
212                 g_object_unref (file);
213
214                 app_uri = ev_application_get_uri (EV_APP);
215                 if (app_uri && strcmp (app_uri, uri) == 0) {
216                         g_free (uri);
217                         continue;
218                 }
219
220
221
222                 ev_application_open_uri_at_dest (EV_APP, uri, screen, dest,
223                                                  mode, ev_find_string,
224                                                  GDK_CURRENT_TIME);
225
226                 if (dest)
227                         g_object_unref (dest);
228                 g_free (uri);
229         }
230 }
231
232 int
233 main (int argc, char *argv[])
234 {
235         GOptionContext *context;
236         GError         *error = NULL;
237
238 #ifdef G_OS_WIN32
239
240     if (fileno (stdout) != -1 &&
241           _get_osfhandle (fileno (stdout)) != -1)
242         {
243           /* stdout is fine, presumably redirected to a file or pipe */
244         }
245     else
246     {
247           typedef BOOL (* WINAPI AttachConsole_t) (DWORD);
248
249           AttachConsole_t p_AttachConsole =
250             (AttachConsole_t) GetProcAddress (GetModuleHandle ("kernel32.dll"), "AttachConsole");
251
252           if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS))
253       {
254               freopen ("CONOUT$", "w", stdout);
255               dup2 (fileno (stdout), 1);
256               freopen ("CONOUT$", "w", stderr);
257               dup2 (fileno (stderr), 2);
258
259       }
260         }
261 #endif
262
263         /* Init glib threads asap */
264         if (!g_thread_supported ())
265                 g_thread_init (NULL);
266
267 #ifdef ENABLE_NLS
268         /* Initialize the i18n stuff */
269         bindtextdomain (GETTEXT_PACKAGE, ev_get_locale_dir());
270         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
271         textdomain (GETTEXT_PACKAGE);
272 #endif
273
274         context = g_option_context_new (N_("GNOME Document Viewer"));
275         g_option_context_set_translation_domain(context, GETTEXT_PACKAGE);
276         g_option_context_add_main_entries (context, goption_options, GETTEXT_PACKAGE);
277
278 #ifdef WITH_SMCLIENT
279         g_option_context_add_group (context, egg_sm_client_get_option_group ());
280 #endif
281
282         g_option_context_add_group (context, gtk_get_option_group (TRUE));
283
284         if (!g_option_context_parse (context, &argc, &argv, &error)) {
285                 g_printerr ("Cannot parse arguments: %s\n", error->message);
286                 g_error_free (error);
287                 g_option_context_free (context);
288
289                 return 1;
290         }
291         g_option_context_free (context);
292
293         if (preview_mode) {
294                 gboolean retval;
295                 
296                 retval = launch_previewer ();
297                 
298                 return retval ? 0 : 1;
299         }
300
301         if (!ev_init ())
302                 return 1;
303
304         ev_stock_icons_init ();
305
306 #if defined(WITH_SMCLIENT) && defined(GDK_WINDOWING_X11)
307         egg_set_desktop_file (GNOMEDATADIR "/applications/evince.desktop");
308 #else
309         /* Manually set name and icon */
310         g_set_application_name (_("Document Viewer"));
311         gtk_window_set_default_icon_name ("evince");
312 #endif /* WITH_SMCLIENT && GDK_WINDOWING_X11 */
313
314         ev_application_load_session (EV_APP);
315         load_files (file_arguments);
316
317         /* Change directory so we don't prevent unmounting in case the initial cwd
318          * is on an external device (see bug #575436)
319          */
320         g_chdir (g_get_home_dir ());
321
322         gtk_main ();
323
324         ev_shutdown ();
325         ev_stock_icons_shutdown ();
326
327         return 0;
328 }