Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
main.c
Go to the documentation of this file.
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 G_OS_WIN32
37 #include <io.h>
38 #include <conio.h>
39 #if !(_WIN32_WINNT >= 0x0500)
40 #error "_WIN32_WINNT must be defined >= 0x0500"
41 #endif
42 #include <windows.h>
43 #endif
44 
45 static gchar *ev_page_label;
46 static gchar *ev_find_string;
47 static gint ev_page_index = 0;
48 static gchar *ev_named_dest;
49 static gboolean preview_mode = FALSE;
50 static gboolean fullscreen_mode = FALSE;
51 static gboolean presentation_mode = FALSE;
52 static gboolean unlink_temp_file = FALSE;
53 static gchar *print_settings;
54 static const char **file_arguments = NULL;
55 
56 
57 static gboolean
58 option_version_cb (const gchar *option_name,
59  const gchar *value,
60  gpointer data,
61  GError **error)
62 {
63  g_print ("%s %s\n", _("GNOME Document Viewer"), VERSION);
64 
65  exit (0);
66  return FALSE;
67 }
68 
69 static const GOptionEntry goption_options[] =
70 {
71  { "page-label", 'p', 0, G_OPTION_ARG_STRING, &ev_page_label, N_("The page label of the document to display."), N_("PAGE")},
72  { "page-index", 'i', 0, G_OPTION_ARG_INT, &ev_page_index, N_("The page number of the document to display."), N_("NUMBER")},
73  { "named-dest", 'n', 0, G_OPTION_ARG_STRING, &ev_named_dest, N_("Named destination to display."), N_("DEST")},
74  { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen_mode, N_("Run evince in fullscreen mode"), NULL },
75  { "presentation", 's', 0, G_OPTION_ARG_NONE, &presentation_mode, N_("Run evince in presentation mode"), NULL },
76  { "preview", 'w', 0, G_OPTION_ARG_NONE, &preview_mode, N_("Run evince as a previewer"), NULL },
77  { "find", 'l', 0, G_OPTION_ARG_STRING, &ev_find_string, N_("The word or phrase to find in the document"), N_("STRING")},
78  { "unlink-tempfile", 'u', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &unlink_temp_file, NULL, NULL },
79  { "print-settings", 't', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &print_settings, NULL, NULL },
80  { "version", 0, G_OPTION_FLAG_NO_ARG | G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
81  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &file_arguments, NULL, N_("[FILEā€¦]") },
82  { NULL }
83 };
84 
85 static gboolean
87 {
88  GString *cmd_str;
89  gchar *cmd;
90  gboolean retval = FALSE;
91  GError *error = NULL;
92 
93  /* Rebuild the command line, ignoring options
94  * not supported by the previewer and taking only
95  * the first path given
96  */
97  cmd_str = g_string_new ("evince-previewer");
98 
99  if (print_settings) {
100  gchar *quoted;
101 
102  quoted = g_shell_quote (print_settings);
103  g_string_append_printf (cmd_str, " --print-settings %s", quoted);
104  g_free (quoted);
105  }
106 
107  if (unlink_temp_file)
108  g_string_append (cmd_str, " --unlink-tempfile");
109 
110  if (file_arguments) {
111  gchar *quoted;
112 
113  quoted = g_shell_quote (file_arguments[0]);
114  g_string_append_printf (cmd_str, " %s", quoted);
115  g_free (quoted);
116  }
117 
118  cmd = g_string_free (cmd_str, FALSE);
119 
120  if (!error) {
121  GAppInfo *app;
122 
123  app = g_app_info_create_from_commandline (cmd, NULL, 0, &error);
124 
125  if (app != NULL) {
126  retval = g_app_info_launch (app, NULL, NULL, &error);
127  g_object_unref (app);
128  }
129  }
130 
131  if (error) {
132  g_warning ("Error launching previewer: %s\n", error->message);
133  g_error_free (error);
134  }
135 
136  g_free (cmd);
137 
138  return retval;
139 }
140 
141 static gchar *
142 get_label_from_filename (const gchar *filename)
143 {
144  GFile *file;
145  gchar *label;
146  gboolean exists;
147 
148  label = g_strrstr (filename, "#");
149  if (!label)
150  return NULL;
151 
152  /* Filename contains a #, check
153  * whether it's part of the path
154  * or a label
155  */
156  file = g_file_new_for_commandline_arg (filename);
157  exists = g_file_query_exists (file, NULL);
158  g_object_unref (file);
159 
160  return exists ? NULL : label;
161 }
162 
163 static void
164 load_files (const char **files)
165 {
166  GdkScreen *screen = gdk_screen_get_default ();
168  gint i;
169  EvLinkDest *global_dest = NULL;
170 
171  if (!files) {
173  ev_application_open_recent_view (EV_APP, screen, GDK_CURRENT_TIME);
174  return;
175  }
176 
177  if (ev_page_label)
179  else if (ev_page_index)
180  global_dest = ev_link_dest_new_page (MAX (0, ev_page_index - 1));
181  else if (ev_named_dest)
182  global_dest = ev_link_dest_new_named (ev_named_dest);
183 
184  if (fullscreen_mode)
186  else if (presentation_mode)
188 
189  for (i = 0; files[i]; i++) {
190  const gchar *filename;
191  gchar *uri;
192  gchar *label;
193  GFile *file;
194  EvLinkDest *dest = NULL;
195  const gchar *app_uri;
196 
197  filename = files[i];
198  label = get_label_from_filename (filename);
199  if (label) {
200  *label = 0;
201  label++;
202  dest = ev_link_dest_new_page_label (label);
203  } else if (global_dest) {
204  dest = g_object_ref (global_dest);
205  }
206 
207  file = g_file_new_for_commandline_arg (filename);
208  uri = g_file_get_uri (file);
209  g_object_unref (file);
210 
211  app_uri = ev_application_get_uri (EV_APP);
212  if (app_uri && strcmp (app_uri, uri) == 0) {
213  g_free (uri);
214  continue;
215  }
216 
217 
218 
219  ev_application_open_uri_at_dest (EV_APP, uri, screen, dest,
220  mode, ev_find_string,
221  GDK_CURRENT_TIME);
222 
223  if (dest)
224  g_object_unref (dest);
225  g_free (uri);
226  }
227 }
228 
229 int
230 main (int argc, char *argv[])
231 {
232  EvApplication *application;
233  GOptionContext *context;
234  GError *error = NULL;
235  int status;
236 
237 #ifdef G_OS_WIN32
238 
239  if (fileno (stdout) != -1 &&
240  _get_osfhandle (fileno (stdout)) != -1)
241  {
242  /* stdout is fine, presumably redirected to a file or pipe */
243  }
244  else
245  {
246  typedef BOOL (* WINAPI AttachConsole_t) (DWORD);
247 
248  AttachConsole_t p_AttachConsole =
249  (AttachConsole_t) GetProcAddress (GetModuleHandle ("kernel32.dll"), "AttachConsole");
250 
251  if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS))
252  {
253  freopen ("CONOUT$", "w", stdout);
254  dup2 (fileno (stdout), 1);
255  freopen ("CONOUT$", "w", stderr);
256  dup2 (fileno (stderr), 2);
257 
258  }
259  }
260 #endif
261 
262 #ifdef ENABLE_NLS
263  /* Initialize the i18n stuff */
264  bindtextdomain (GETTEXT_PACKAGE, ev_get_locale_dir());
265  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
266  textdomain (GETTEXT_PACKAGE);
267 #endif
268 
269  context = g_option_context_new (N_("GNOME Document Viewer"));
270  g_option_context_set_translation_domain(context, GETTEXT_PACKAGE);
271  g_option_context_add_main_entries (context, goption_options, GETTEXT_PACKAGE);
272 
273  g_option_context_add_group (context, gtk_get_option_group (TRUE));
274 
275  if (!g_option_context_parse (context, &argc, &argv, &error)) {
276  g_printerr ("Cannot parse arguments: %s\n", error->message);
277  g_error_free (error);
278  g_option_context_free (context);
279 
280  return 1;
281  }
282  g_option_context_free (context);
283 
284  if (preview_mode) {
285  gboolean retval;
286 
287  retval = launch_previewer ();
288 
289  return retval ? 0 : 1;
290  }
291 
292  if (!ev_init ())
293  return 1;
294 
296 
297  /* Manually set name and icon */
298  g_set_application_name (_("Document Viewer"));
299  gtk_window_set_default_icon_name ("evince");
300 
301  application = ev_application_new ();
302  if (!g_application_register (G_APPLICATION (application), NULL, &error)) {
303  g_printerr ("Failed to register: %s\n", error->message);
304  g_error_free (error);
305  status = 1;
306  goto done;
307  }
308 
310 
311  /* Change directory so we don't prevent unmounting in case the initial cwd
312  * is on an external device (see bug #575436)
313  */
314  g_chdir (g_get_home_dir ());
315 
316  status = g_application_run (G_APPLICATION (application), 0, NULL);
317 
318  done:
319  ev_shutdown ();
321 
322  g_object_unref (application);
323  return status;
324 }