2 * ctxt - A small and simple pdf viewer using gtk+ and poppler
4 * Copyright (C) 2009 Ali Gholami Rudi
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License, as published by the
8 * Free Software Foundation.
13 #include <gdk/gdkkeysyms.h>
14 #include <glib/poppler.h>
20 static GtkWidget
*bar
;
21 static GtkWidget
*img
;
22 static GtkAdjustment
*vadjst
;
23 static GtkAdjustment
*hadjst
;
24 static PopplerDocument
*doc
;
25 static PopplerPage
*page
;
26 static GdkPixbuf
*pixbuf
;
27 static char filename
[PATH_MAX
];
40 static void on_destroy(GtkWidget
*w
, gpointer data
)
47 int val
= gtk_adjustment_get_value(vadjst
) +
48 gtk_adjustment_get_page_size(vadjst
);
49 int max
= gtk_adjustment_get_upper(vadjst
);
50 int pages
= poppler_document_get_n_pages(doc
);
52 sprintf(msg
, "%s\t%d%%\t\t\t%d/%d",
53 filename
, val
* 100 / max
, num
+ 1, pages
);
54 gtk_entry_set_text(GTK_ENTRY(bar
), msg
);
60 double z
= (float) zoom
/ (float) 10;
63 poppler_page_get_size(page
, &w
, &h
);
67 g_object_unref(G_OBJECT(pixbuf
));
68 pixbuf
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, FALSE
, 8, w
, h
);
69 poppler_page_render_to_pixbuf(page
, 0, 0, w
, h
, z
, 0, pixbuf
);
70 gtk_image_set_from_pixbuf(GTK_IMAGE(img
), pixbuf
);
77 g_object_unref(G_OBJECT(pixbuf
));
79 g_object_unref(G_OBJECT(page
));
81 g_object_unref(G_OBJECT(doc
));
84 static int get_arg(int def
)
86 return !arg
? def
: arg
;
89 static void scroll(enum location loc
, int n
)
91 int val
= gtk_adjustment_get_value(vadjst
);
92 int page
= gtk_adjustment_get_page_size(vadjst
);
93 int end
= gtk_adjustment_get_upper(vadjst
);
98 val
+= n
* gtk_adjustment_get_page_increment(vadjst
);
101 val
+= n
* gtk_adjustment_get_step_increment(vadjst
);
107 val
= (end
- page
) / 2;
114 gtk_adjustment_set_value(vadjst
, MAX(0, MIN(max
, val
)));
118 static void hscroll(int n
)
120 int val
= gtk_adjustment_get_value(hadjst
);
121 int page
= gtk_adjustment_get_page_size(hadjst
);
122 int end
= gtk_adjustment_get_upper(hadjst
);
123 int max
= end
- page
;
125 val
+= n
* get_arg(1) * gtk_adjustment_get_step_increment(hadjst
);
126 gtk_adjustment_set_value(hadjst
, MAX(0, MIN(max
, val
)));
129 static void showpage(int p
)
131 if (p
< 0 || p
>= poppler_document_get_n_pages(doc
))
135 g_object_unref(G_OBJECT(page
));
136 page
= poppler_document_get_page(doc
, p
);
138 gtk_adjustment_set_value(vadjst
, 0);
141 static void nextpage(int n
)
143 showpage(num
+ n
* get_arg(1));
147 static gboolean
on_key_press(GtkWidget
*widget
, GdkEventKey
*event
,
150 int mod
= event
->state
& gtk_accelerator_get_default_mod_mask();
151 if (mod
== GDK_CONTROL_MASK
) {
152 switch (event
->keyval
) {
160 gtk_widget_queue_draw(img
);
167 switch (event
->keyval
) {
174 scroll(LOC_STEP
, -1);
185 showpage(get_arg(poppler_document_get_n_pages(doc
)) - 1);
197 scroll(LOC_CENTER
, 1);
205 scroll(LOC_PAGE
, -1);
211 if (get_arg(0) > 5 && get_arg(0) < 50)
220 if (isdigit(event
->keyval
))
221 arg
= arg
* 10 + event
->keyval
- '0';
227 static void on_size_allocate(GtkWidget
*w
, GtkAllocation
*a
,
233 static int load_document(void)
235 char abspath
[PATH_MAX
];
236 char uri
[PATH_MAX
+ 16];
237 realpath(filename
, abspath
);
238 snprintf(uri
, sizeof(uri
), "file://%s", abspath
);
239 doc
= poppler_document_new_from_file(uri
, NULL
, NULL
);
243 static void create_window(void)
249 win
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
250 gtk_window_set_title(GTK_WINDOW(win
), "mypdf");
251 g_signal_connect(G_OBJECT(win
), "destroy",
252 G_CALLBACK(on_destroy
), NULL
);
254 vbox
= gtk_vbox_new(FALSE
, 2);
255 gtk_container_add(GTK_CONTAINER(win
), vbox
);
257 /* create the image */
258 wrap
= gtk_scrolled_window_new(NULL
, NULL
);
259 gtk_box_pack_start(GTK_BOX(vbox
), wrap
, 1, 1, 0);
260 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(wrap
),
263 vadjst
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(wrap
));
264 hadjst
= gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(wrap
));
265 img
= gtk_image_new();
266 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(wrap
), img
);
268 /* create the minibuffer */
269 bar
= gtk_entry_new();
270 gtk_box_pack_start(GTK_BOX(vbox
), bar
, 0, 0, 0);
271 gtk_signal_connect(GTK_OBJECT(bar
), "key_press_event",
272 GTK_SIGNAL_FUNC(on_key_press
), NULL
);
273 gtk_signal_connect(GTK_OBJECT(win
), "key_press_event",
274 GTK_SIGNAL_FUNC(on_key_press
), NULL
);
275 gtk_signal_connect(GTK_OBJECT(win
), "size_allocate",
276 GTK_SIGNAL_FUNC(on_size_allocate
), NULL
);
278 gtk_widget_set_size_request(win
, 800, 600);
279 gtk_window_set_default_size(GTK_WINDOW(win
), 1024, 768);
280 gtk_widget_show_all(win
);
283 static int read_args(int argc
, char *argv
[])
287 if (!strcmp("-z", argv
[i
]))
288 zoom
= atoi(argv
[++i
]);
289 else if (!strcmp("-p", argv
[i
]))
290 num
= atoi(argv
[++i
]) - 1;
292 strcpy(filename
, argv
[i
]);
297 int main(int argc
, char *argv
[])
299 gtk_init(&argc
, &argv
);
300 if (read_args(argc
, argv
) || load_document()) {
301 puts("Usage: cpdf [-p page] [-z zoom] path\n");