Code

tpdfview(1), help output: Added '-P' switch.
[tpdfview.git] / src / tpdfview.c
1 /*
2  * tpdfview - src/tpdfview.c
3  * Copyright (C) 2011 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 /*
29  * A tiny PDF viewer.
30  */
32 #if HAVE_CONFIG_H
33 #       include "config.h"
34 #endif /* HAVE_CONFIG_H */
36 #include "tpdfv.h"
37 #include "tpdfv_features.h"
39 #include "gtk-tpdfv.h"
40 #include "tpdfv-ctl.h"
42 #if HAVE_LIBGEN_H
43 #       include <libgen.h>
44 #else /* HAVE_LIBGEN_H */
45 #       define basename(path) (path)
46 #endif /* ! HAVE_LIBGEN_H */
48 #include <assert.h>
50 #include <stdio.h>
51 #include <stdlib.h>
53 #include <string.h>
55 #include <unistd.h>
57 #include <gtk/gtk.h>
58 #include <gdk/gdkkeysyms.h>
60 /*
61  * Global variables.
62  */
63 static gtk_tpdfv_screens_t *screens = NULL;
65 static void
66 exit_usage(char *name, int status)
67 {
68         printf(
69 "Usage: %s [<options>] <filename>\n"
71 "\nA tiny PDF viewer.\n"
73 "\nOptions:\n"
74 "  -P    enable presentation mode\n"
75 "\n"
76 "  -h    display this help and exit\n"
77 "  -V    display the version number and copyright\n"
79 "\ntpdfview "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "PACKAGE_URL"\n"
80 "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n",
81 basename(name));
82         exit(status);
83 } /* exit_usage */
85 static void
86 exit_version(void)
87 {
88         printf("tpdfview version "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "
89                         "built "BUILD_DATE"\n"
90                         "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n"
92                         "\nThis is free software under the terms of the BSD license, see "
93                         "the source for\ncopying conditions. There is NO WARRANTY; not "
94                         "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
95                         "PURPOSE.\n");
96         exit(0);
97 } /* exit_version */
99 static void
100 toggle_fullscreen(GtkWindow *win)
102         GdkWindowState state;
104         if (! gtk_widget_get_realized(GTK_WIDGET(win)))
105                 return;
107         state = gdk_window_get_state(GTK_WIDGET(win)->window);
109         if (state & GDK_WINDOW_STATE_FULLSCREEN)
110                 gtk_window_unfullscreen(win);
111         else
112                 gtk_window_fullscreen(win);
113 } /* toggle_fullscreen */
115 static void
116 on_destroy(GtkWidget __attribute__((unused)) *widget,
117                 gpointer __attribute__((unused)) data)
119         gtk_main_quit();
120 } /* on_destroy */
122 static gboolean
123 key_press(GtkWidget *window, GdkEventKey *event, gpointer data)
125         GObject *obj;
127         obj = G_OBJECT(data);
128         assert(obj);
130         switch (event->keyval) {
131                 case GDK_q:
132                         gtk_main_quit();
133                         break;
135                 case GDK_r:
136                         tpdfv_ctl_reload(obj);
137                         break;
139                 case GDK_F:
140                         toggle_fullscreen(GTK_WINDOW(window));
141                         break;
143                 /* navigation */
144                 case GDK_Page_Up:
145                         tpdfv_ctl_page_up(obj);
146                         break;
147                 case GDK_Page_Down:
148                         /* fall through */
149                 case GDK_space:
150                         tpdfv_ctl_page_down(obj);
151                         break;
152                 case GDK_Home:
153                         tpdfv_ctl_first_page(obj);
154                         break;
155                 case GDK_End:
156                         tpdfv_ctl_last_page(obj);
157                         break;
159                 /* zoom */
160                 case GDK_plus:
161                         tpdfv_ctl_zoom_in(obj);
162                         break;
163                 case GDK_minus:
164                         tpdfv_ctl_zoom_out(obj);
165                         break;
166                 case GDK_1:
167                         tpdfv_ctl_zoom_1(obj);
168                         break;
169                 case GDK_w:
170                         tpdfv_ctl_zoom_width(obj);
171                         break;
172                 case GDK_h:
173                         tpdfv_ctl_zoom_height(obj);
174                         break;
175                 case GDK_z:
176                         tpdfv_ctl_zoom_fit(obj);
177                         break;
179                 /* scrolling */
180                 case GDK_Up:
181                         tpdfv_ctl_scroll_up(obj);
182                         break;
183                 case GDK_Down:
184                         tpdfv_ctl_scroll_down(obj);
185                         break;
186                 case GDK_Left:
187                         tpdfv_ctl_scroll_left(obj);
188                         break;
189                 case GDK_Right:
190                         tpdfv_ctl_scroll_right(obj);
191                         break;
193                 /* screen management */
194                 case GDK_M:
195                         {
196                                 gint n_screens = gtk_tpdfv_screens_number(screens);
197                                 gint screen = gtk_tpdfv_screens_window_get(screens,
198                                                 GTK_WINDOW(window));
200                                 gtk_tpdfv_screens_window_set(screens,
201                                                 GTK_WINDOW(window), (screen + 1) % n_screens);
202                         }
203                         break;
204         }
205         return FALSE;
206 } /* key_press */
208 int
209 main(int argc, char **argv)
211         GtkWidget *win;
212         GtkWidget *tpdfv;
214         GObject *ctl;
216         char win_title[1024];
218         _Bool presentation_mode = 0;
220         GdkColor bg_color;
222         char *filename;
224         gtk_init(&argc, &argv);
226         while (42) {
227                 int opt = getopt(argc, argv, "PhV");
229                 if (-1 == opt)
230                         break;
232                 switch (opt) {
233                         case 'P':
234                                 presentation_mode = 1;
235                                 break;
237                         case 'h':
238                                 exit_usage(argv[0], 0);
239                                 break;
240                         case 'V':
241                                 exit_version();
242                                 break;
243                         default:
244                                 exit_usage(argv[0], 1);
245                 }
246         }
248         if (argc - optind != 1) {
249                 fprintf(stderr, "%s: missing filename\n", argv[0]);
250                 exit_usage(argv[0], 1);
251         }
253         filename = argv[optind];
255         tpdfv = gtk_tpdfv_new(filename);
256         if (! tpdfv)
257                 return 1;
259         win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
260         if (! win)
261                 return 1;
263         screens = gtk_tpdfv_screens_init(/* display = */ NULL);
264         if (! screens)
265                 return 1;
267         snprintf(win_title, sizeof(win_title), "tpdfview: %s",
268                         basename(filename));
269         gtk_window_set_title(GTK_WINDOW(win), win_title);
271         gtk_container_add(GTK_CONTAINER(win), tpdfv);
273         ctl = tpdfv_ctl_new(GTK_TPDFV(tpdfv));
274         if (! ctl)
275                 return 1;
277         /* TODO: use resource file */
278         gdk_color_parse("#000000", &bg_color);
280         if (presentation_mode) {
281                 GtkWidget *pres_win;
282                 GtkWidget *paned;
283                 GtkWidget *tpdfv1, *tpdfv2;
285                 tpdfv1 = gtk_tpdfv_new(filename);
286                 if (! tpdfv1)
287                         return 1;
289                 if (! tpdfv_ctl_add_slave(ctl, GTK_TPDFV(tpdfv1),
290                                         /* factor = */ 1, /* offset = */ 0))
291                         return 1;
293                 tpdfv2 = gtk_tpdfv_new(filename);
294                 if (! tpdfv2)
295                         return 1;
297                 if (! tpdfv_ctl_add_slave(ctl, GTK_TPDFV(tpdfv2),
298                                         /* factor = */ 1, /* offset = */ 1))
299                         return 1;
301                 paned = gtk_hpaned_new();
302                 if (! paned)
303                         return 1;
305                 gtk_paned_pack1(GTK_PANED(paned), tpdfv1, TRUE, TRUE);
306                 gtk_paned_pack2(GTK_PANED(paned), tpdfv2, TRUE, TRUE);
308                 gtk_tpdfv_zoom_fit(tpdfv1);
309                 gtk_tpdfv_zoom_fit(tpdfv2);
311                 pres_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
312                 if (! pres_win)
313                         return 1;
315                 gtk_window_set_title(GTK_WINDOW(pres_win), win_title);
317                 gtk_container_add(GTK_CONTAINER(pres_win), paned);
319                 gtk_widget_modify_bg(tpdfv1, GTK_STATE_NORMAL, &bg_color);
320                 gtk_widget_modify_bg(tpdfv2, GTK_STATE_NORMAL, &bg_color);
322                 g_signal_connect(G_OBJECT(pres_win), "destroy",
323                                 G_CALLBACK(on_destroy), NULL);
324                 g_signal_connect(G_OBJECT(pres_win), "key-press-event",
325                                 G_CALLBACK(key_press), ctl);
327                 gtk_widget_modify_bg(pres_win, GTK_STATE_NORMAL, &bg_color);
328                 gtk_widget_modify_bg(tpdfv1, GTK_STATE_NORMAL, &bg_color);
329                 gtk_widget_modify_bg(tpdfv2, GTK_STATE_NORMAL, &bg_color);
331                 gtk_widget_show_all(pres_win);
332         }
334         g_signal_connect(G_OBJECT(win), "destroy",
335                         G_CALLBACK(on_destroy), NULL);
336         g_signal_connect(G_OBJECT(win), "key-press-event",
337                         G_CALLBACK(key_press), ctl);
339         gtk_widget_modify_bg(tpdfv, GTK_STATE_NORMAL, &bg_color);
341         gtk_widget_show_all(win);
343         gtk_main();
345         gtk_tpdfv_screens_destroy(screens);
346         return 0;
347 } /* main */
349 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */