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 " -h display this help and exit\n"
75 " -V display the version number and copyright\n"
77 "\ntpdfview "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "PACKAGE_URL"\n"
78 "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n",
79 basename(name));
80 exit(status);
81 } /* exit_usage */
83 static void
84 exit_version(void)
85 {
86 printf("tpdfview version "TPDFV_VERSION_STRING TPDFV_VERSION_EXTRA", "
87 "built "BUILD_DATE"\n"
88 "Copyright (C) 2011 "PACKAGE_MAINTAINER"\n"
90 "\nThis is free software under the terms of the BSD license, see "
91 "the source for\ncopying conditions. There is NO WARRANTY; not "
92 "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
93 "PURPOSE.\n");
94 exit(0);
95 } /* exit_version */
97 static void
98 toggle_fullscreen(GtkWindow *win)
99 {
100 GdkWindowState state;
102 if (! gtk_widget_get_realized(GTK_WIDGET(win)))
103 return;
105 state = gdk_window_get_state(GTK_WIDGET(win)->window);
107 if (state & GDK_WINDOW_STATE_FULLSCREEN)
108 gtk_window_unfullscreen(win);
109 else
110 gtk_window_fullscreen(win);
111 } /* toggle_fullscreen */
113 static void
114 on_destroy(GtkWidget __attribute__((unused)) *widget,
115 gpointer __attribute__((unused)) data)
116 {
117 gtk_main_quit();
118 } /* on_destroy */
120 static gboolean
121 key_press(GtkWidget *window, GdkEventKey *event, gpointer data)
122 {
123 GObject *obj;
125 obj = G_OBJECT(data);
126 assert(obj);
128 switch (event->keyval) {
129 case GDK_q:
130 gtk_main_quit();
131 break;
133 case GDK_r:
134 tpdfv_ctl_reload(obj);
135 break;
137 case GDK_F:
138 toggle_fullscreen(GTK_WINDOW(window));
139 break;
141 /* navigation */
142 case GDK_Page_Up:
143 tpdfv_ctl_page_up(obj);
144 break;
145 case GDK_Page_Down:
146 /* fall through */
147 case GDK_space:
148 tpdfv_ctl_page_down(obj);
149 break;
150 case GDK_Home:
151 tpdfv_ctl_first_page(obj);
152 break;
153 case GDK_End:
154 tpdfv_ctl_last_page(obj);
155 break;
157 /* zoom */
158 case GDK_plus:
159 tpdfv_ctl_zoom_in(obj);
160 break;
161 case GDK_minus:
162 tpdfv_ctl_zoom_out(obj);
163 break;
164 case GDK_1:
165 tpdfv_ctl_zoom_1(obj);
166 break;
167 case GDK_w:
168 tpdfv_ctl_zoom_width(obj);
169 break;
170 case GDK_h:
171 tpdfv_ctl_zoom_height(obj);
172 break;
173 case GDK_z:
174 tpdfv_ctl_zoom_fit(obj);
175 break;
177 /* scrolling */
178 case GDK_Up:
179 tpdfv_ctl_scroll_up(obj);
180 break;
181 case GDK_Down:
182 tpdfv_ctl_scroll_down(obj);
183 break;
184 case GDK_Left:
185 tpdfv_ctl_scroll_left(obj);
186 break;
187 case GDK_Right:
188 tpdfv_ctl_scroll_right(obj);
189 break;
191 /* screen management */
192 case GDK_M:
193 {
194 gint n_screens = gtk_tpdfv_screens_number(screens);
195 gint screen = gtk_tpdfv_screens_window_get(screens,
196 GTK_WINDOW(window));
198 gtk_tpdfv_screens_window_set(screens,
199 GTK_WINDOW(window), (screen + 1) % n_screens);
200 }
201 break;
202 }
203 return FALSE;
204 } /* key_press */
206 int
207 main(int argc, char **argv)
208 {
209 GtkWidget *win;
210 GtkWidget *tpdfv;
212 GObject *ctl;
214 char win_title[1024];
216 GdkColor bg_color;
218 char *filename;
220 gtk_init(&argc, &argv);
222 while (42) {
223 int opt = getopt(argc, argv, "hV");
225 if (-1 == opt)
226 break;
228 switch (opt) {
229 case 'h':
230 exit_usage(argv[0], 0);
231 break;
232 case 'V':
233 exit_version();
234 break;
235 default:
236 exit_usage(argv[0], 1);
237 }
238 }
240 if (argc - optind != 1) {
241 fprintf(stderr, "%s: missing filename\n", argv[0]);
242 exit_usage(argv[0], 1);
243 }
245 filename = argv[optind];
247 tpdfv = gtk_tpdfv_new(filename);
248 if (! tpdfv)
249 return 1;
251 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
252 if (! win)
253 return 1;
255 screens = gtk_tpdfv_screens_init(/* display = */ NULL);
256 if (! screens)
257 return 1;
259 snprintf(win_title, sizeof(win_title), "tpdfview: %s",
260 basename(filename));
261 gtk_window_set_title(GTK_WINDOW(win), win_title);
263 gtk_container_add(GTK_CONTAINER(win), tpdfv);
265 ctl = tpdfv_ctl_new(GTK_TPDFV(tpdfv));
266 if (! ctl)
267 return 1;
269 g_signal_connect(G_OBJECT(win), "destroy",
270 G_CALLBACK(on_destroy), NULL);
271 g_signal_connect(G_OBJECT(win), "key-press-event",
272 G_CALLBACK(key_press), ctl);
274 /* TODO: use resource file */
275 gdk_color_parse("#000000", &bg_color);
276 gtk_widget_modify_bg(tpdfv, GTK_STATE_NORMAL, &bg_color);
278 gtk_widget_show_all(win);
280 gtk_main();
282 gtk_tpdfv_screens_destroy(screens);
283 return 0;
284 } /* main */
286 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */