Code

configure: When doing strict checks, treat Gtk headers as system headers.
[tpdfview.git] / src / gtk-tpdfv.c
index 771dff99871ebd2f2490207790760175caa684e9..d1a377ce4e44bd3d1204b259982f02ded02f533b 100644 (file)
@@ -43,6 +43,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <sys/stat.h>
+
 #define TPDFV_MIN(a, b) ((a) <= (b) ? (a) : (b))
 #define TPDFV_MAX(a, b) ((a) >= (b) ? (a) : (b))
 
@@ -56,6 +58,8 @@ typedef enum {
 typedef struct {
        char *filename;
 
+       time_t mtime;
+
        PopplerDocument *doc;
        PopplerPage     *current_page;
 
@@ -79,11 +83,52 @@ G_DEFINE_TYPE(GtkTPDFV, gtk_tpdfv, GTK_TYPE_DRAWING_AREA);
  * Private helper functions.
  */
 
-static gboolean
-tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
+static void
+tpdfv_open(gtk_tpdfv_t *pdf)
 {
        GError *err = NULL;
 
+       struct stat statbuf;
+
+       if ((! pdf) || (! pdf->filename))
+               return;
+
+       memset(&statbuf, 0, sizeof(statbuf));
+       if (stat(pdf->filename + strlen("file://"), &statbuf) != 0) {
+               char errbuf[1024];
+               strerror_r(errno, errbuf, sizeof(errbuf));
+               fprintf(stderr, "Failed to access PDF: %s.\n", errbuf);
+               return;
+       }
+
+       pdf->mtime = statbuf.st_mtime;
+
+       pdf->doc = poppler_document_new_from_file(pdf->filename,
+                       /* password = */ NULL, &err);
+       if (! pdf->doc) {
+               fprintf(stderr, "Failed to open PDF: %s.\n", err->message);
+               return;
+       }
+
+       pdf->total_pages = poppler_document_get_n_pages(pdf->doc);
+       if (pdf->current_page_no >= pdf->total_pages)
+               pdf->current_page_no = pdf->total_pages - 1;
+} /* tpdfv_open */
+
+static void
+tpdfv_close(gtk_tpdfv_t *pdf)
+{
+       if (! pdf)
+               return;
+
+       g_object_unref(pdf->doc);
+       pdf->doc = NULL;
+       pdf->current_page = NULL;
+} /* tpdfv_close */
+
+static gboolean
+tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
+{
        if (strstr(filename, "://"))
                pdf->filename = strdup(filename);
        else {
@@ -105,12 +150,8 @@ tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
                return FALSE;
        }
 
-       pdf->doc = poppler_document_new_from_file(pdf->filename,
-                       /* password = */ NULL, &err);
-       if (! pdf->doc) {
-               fprintf(stderr, "Failed to open PDF: %s.\n", err->message);
-               return FALSE;
-       }
+       pdf->doc = NULL;
+       tpdfv_open(pdf);
 
        pdf->current_page_no = 0;
        pdf->current_page = poppler_document_get_page(pdf->doc,
@@ -120,8 +161,6 @@ tpdfv_init(gtk_tpdfv_t *pdf, const char *filename)
                return FALSE;
        }
 
-       pdf->total_pages = poppler_document_get_n_pages(pdf->doc);
-
        pdf->zoom_mode   = TPDFV_ZOOM_CUSTOM;
        pdf->zoom_factor = 1.0;
        pdf->delta_x = pdf->delta_y = 0.0;
@@ -134,8 +173,7 @@ tpdfv_clean(gtk_tpdfv_t *pdf)
        if (! pdf)
                return;
 
-       g_object_unref(pdf->doc);
-       pdf->doc          = NULL;
+       tpdfv_close(pdf);
        pdf->current_page = NULL;
        free(pdf->filename);
        pdf->filename = NULL;
@@ -150,8 +188,8 @@ do_redraw(GtkWidget *widget)
 
        pdf = GTK_TPDFV_GET_PRIVATE(widget);
 
-       if (poppler_page_get_index(pdf->current_page)
-                       != pdf->current_page_no) {
+       if ((! pdf->current_page) || (poppler_page_get_index(pdf->current_page)
+                       != pdf->current_page_no)) {
                pdf->current_page = poppler_document_get_page(pdf->doc,
                pdf->current_page_no);
 
@@ -179,6 +217,8 @@ gtk_tpdfv_expose(GtkWidget *tpdfv, GdkEventExpose *event)
        gtk_tpdfv_t *pdf;
        cairo_t *cr;
 
+       struct stat statbuf;
+
        gdouble width, height;
 
        gdouble page_width  = 0.0;
@@ -192,6 +232,17 @@ gtk_tpdfv_expose(GtkWidget *tpdfv, GdkEventExpose *event)
        if (! pdf)
                return FALSE;
 
+       memset(&statbuf, 0, sizeof(statbuf));
+       if (stat(pdf->filename + strlen("file://"), &statbuf)) {
+               char errbuf[1024];
+               strerror_r(errno, errbuf, sizeof(errbuf));
+               fprintf(stderr, "Failed to access PDF: %s.\n", errbuf);
+               return FALSE;
+       }
+
+       if (statbuf.st_mtime > pdf->mtime)
+               gtk_tpdfv_reload(tpdfv);
+
        cr = gdk_cairo_create(tpdfv->window);
        cairo_rectangle(cr, event->area.x, event->area.y,
                        event->area.width, event->area.height);
@@ -228,6 +279,15 @@ gtk_tpdfv_expose(GtkWidget *tpdfv, GdkEventExpose *event)
 
        cairo_translate(cr, x + pdf->delta_x, y + pdf->delta_y);
 
+       /* draw empty white page */
+       cairo_save(cr);
+
+       cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
+       cairo_rectangle(cr, 0.0, 0.0, page_width, page_height);
+       cairo_fill(cr);
+
+       cairo_restore(cr);
+
        poppler_page_render(pdf->current_page, cr);
 
        cairo_destroy(cr);
@@ -287,6 +347,41 @@ gtk_tpdfv_new(const char *filename)
        return GTK_WIDGET(tpdfv);
 } /* gtk_tpdfv_new */
 
+void
+gtk_tpdfv_reload(GtkWidget *widget)
+{
+       gtk_tpdfv_t *pdf;
+
+       pdf = GTK_TPDFV_GET_PRIVATE(widget);
+       tpdfv_close(pdf);
+       tpdfv_open(pdf);
+       do_redraw(widget);
+} /* gtk_tpdfv_reload */
+
+int
+gtk_tpdfv_get_n_pages(GtkWidget *widget)
+{
+       gtk_tpdfv_t *pdf;
+
+       if (! widget)
+               return -1;
+
+       pdf = GTK_TPDFV_GET_PRIVATE(widget);
+       return pdf->total_pages;
+} /* gtk_tpdfv_get_n_pages */
+
+int
+gtk_tpdfv_get_current_page(GtkWidget *widget)
+{
+       gtk_tpdfv_t *pdf;
+
+       if (! widget)
+               return -1;
+
+       pdf = GTK_TPDFV_GET_PRIVATE(widget);
+       return pdf->current_page_no;
+} /* gtk_tpdfv_get_current_page */
+
 void
 gtk_tpdfv_page_up(GtkWidget *widget)
 {
@@ -331,6 +426,20 @@ gtk_tpdfv_last_page(GtkWidget *widget)
        do_redraw(widget);
 } /* gtk_tpdfv_last_page */
 
+void
+gtk_tpdfv_goto_page(GtkWidget *widget, int page)
+{
+       gtk_tpdfv_t *pdf;
+
+       pdf = GTK_TPDFV_GET_PRIVATE(widget);
+
+       if ((page < 0) || (page >= pdf->total_pages))
+               return;
+
+       pdf->current_page_no = page;
+       do_redraw(widget);
+} /* gtk_tpdfv_goto_page */
+
 void
 gtk_tpdfv_zoom_in(GtkWidget *widget)
 {