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"
41 #if HAVE_LIBGEN_H
42 # include <libgen.h>
43 #else /* HAVE_LIBGEN_H */
44 # define basename(path) (path)
45 #endif /* ! HAVE_LIBGEN_H */
47 #include <assert.h>
49 #include <stdio.h>
50 #include <stdlib.h>
52 #include <string.h>
54 #include <unistd.h>
56 #include <gtk/gtk.h>
57 #include <gdk/gdkkeysyms.h>
59 /*
60 * Global variables.
61 */
62 static gtk_tpdfv_screens_t *screens = NULL;
64 static void
65 exit_usage(char *name, int status)
66 {
67 printf(
68 "Usage: %s [<options>] <filename>\n"
70 "\nA tiny PDF viewer.\n"
72 "\nOptions:\n"
73 " -h display this help and exit\n"
74 " -V display the version number and copyright\n"
76 "\ntpdfview "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "PACKAGE_URL"\n"
77 "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n",
78 basename(name));
79 exit(status);
80 } /* exit_usage */
82 static void
83 exit_version(void)
84 {
85 printf("tpdfview version "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "
86 "built "BUILD_DATE"\n"
87 "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n"
89 "\nThis is free software under the terms of the BSD license, see "
90 "the source for\ncopying conditions. There is NO WARRANTY; not "
91 "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
92 "PURPOSE.\n");
93 exit(0);
94 } /* exit_version */
96 static void
97 toggle_fullscreen(GtkWindow *win)
98 {
99 GdkWindowState state;
101 if (! gtk_widget_get_realized(GTK_WIDGET(win)))
102 return;
104 state = gdk_window_get_state(GTK_WIDGET(win)->window);
106 if (state & GDK_WINDOW_STATE_FULLSCREEN)
107 gtk_window_unfullscreen(win);
108 else
109 gtk_window_fullscreen(win);
110 } /* toggle_fullscreen */
112 static void
113 on_destroy(GtkWidget __attribute__((unused)) *widget,
114 gpointer __attribute__((unused)) data)
115 {
116 gtk_main_quit();
117 } /* on_destroy */
119 static gboolean
120 key_press(GtkWidget *window, GdkEventKey *event, gpointer data)
121 {
122 GtkWidget *tpdfv;
124 tpdfv = (GtkWidget *)data;
125 assert(tpdfv);
127 switch (event->keyval) {
128 case GDK_q:
129 gtk_main_quit();
130 break;
132 case GDK_r:
133 gtk_tpdfv_reload(tpdfv);
134 break;
136 case GDK_F:
137 toggle_fullscreen(GTK_WINDOW(window));
138 break;
140 /* navigation */
141 case GDK_Page_Up:
142 gtk_tpdfv_page_up(tpdfv);
143 break;
144 case GDK_Page_Down:
145 /* fall through */
146 case GDK_space:
147 gtk_tpdfv_page_down(tpdfv);
148 break;
149 case GDK_Home:
150 gtk_tpdfv_first_page(tpdfv);
151 break;
152 case GDK_End:
153 gtk_tpdfv_last_page(tpdfv);
154 break;
156 /* zoom */
157 case GDK_plus:
158 gtk_tpdfv_zoom_in(tpdfv);
159 break;
160 case GDK_minus:
161 gtk_tpdfv_zoom_out(tpdfv);
162 break;
163 case GDK_1:
164 gtk_tpdfv_zoom_1(tpdfv);
165 break;
166 case GDK_w:
167 gtk_tpdfv_zoom_width(tpdfv);
168 break;
169 case GDK_h:
170 gtk_tpdfv_zoom_height(tpdfv);
171 break;
172 case GDK_z:
173 gtk_tpdfv_zoom_fit(tpdfv);
174 break;
176 /* scrolling */
177 case GDK_Up:
178 gtk_tpdfv_scroll_up(tpdfv);
179 break;
180 case GDK_Down:
181 gtk_tpdfv_scroll_down(tpdfv);
182 break;
183 case GDK_Left:
184 gtk_tpdfv_scroll_left(tpdfv);
185 break;
186 case GDK_Right:
187 gtk_tpdfv_scroll_right(tpdfv);
188 break;
190 /* screen management */
191 case GDK_M:
192 {
193 gint n_screens = gtk_tpdfv_screens_number(screens);
194 gint screen = gtk_tpdfv_screens_window_get(screens,
195 GTK_WINDOW(window));
197 gtk_tpdfv_screens_window_set(screens,
198 GTK_WINDOW(window), (screen + 1) % n_screens);
199 }
200 break;
201 }
202 return FALSE;
203 } /* key_press */
205 int
206 main(int argc, char **argv)
207 {
208 GtkWidget *win = NULL;
209 GtkWidget *tpdfv = NULL;
211 char win_title[1024];
213 GdkColor bg_color;
215 char *filename;
217 gtk_init(&argc, &argv);
219 while (42) {
220 int opt = getopt(argc, argv, "hV");
222 if (-1 == opt)
223 break;
225 switch (opt) {
226 case 'h':
227 exit_usage(argv[0], 0);
228 break;
229 case 'V':
230 exit_version();
231 break;
232 default:
233 exit_usage(argv[0], 1);
234 }
235 }
237 if (argc - optind != 1) {
238 fprintf(stderr, "%s: missing filename\n", argv[0]);
239 exit_usage(argv[0], 1);
240 }
242 filename = argv[optind];
244 tpdfv = gtk_tpdfv_new(filename);
245 if (! tpdfv)
246 return 1;
248 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
249 if (! win)
250 return 1;
252 screens = gtk_tpdfv_screens_init(/* display = */ NULL);
253 if (! screens)
254 return 1;
256 snprintf(win_title, sizeof(win_title), "tpdfview: %s",
257 basename(filename));
258 gtk_window_set_title(GTK_WINDOW(win), win_title);
260 gtk_container_add(GTK_CONTAINER(win), tpdfv);
262 g_signal_connect(G_OBJECT(win), "destroy",
263 G_CALLBACK(on_destroy), NULL);
264 g_signal_connect(G_OBJECT(win), "key-press-event",
265 G_CALLBACK(key_press), tpdfv);
267 /* TODO: use resource file */
268 gdk_color_parse("#000000", &bg_color);
269 gtk_widget_modify_bg(tpdfv, GTK_STATE_NORMAL, &bg_color);
271 gtk_widget_show_all(win);
273 gtk_main();
275 gtk_tpdfv_screens_destroy(screens);
276 return 0;
277 } /* main */
279 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */