Dear all,

Several PDF-readers have an option to read books in dual-view. Due to
the physical nature of books, this means that the first page should
usually be on the right hand side. In particular (if good typography is
used) odd pages are on the right.

At the moment this is not possible with Zathura. I tried to make a patch
for this, and as far as I can see it works correctly.

All I did was adding an option 'first-page-column', which takes an
integer between 1 and pages-per-row. Zathura then displays the first
page of the file in the according column.

I think this patch greatly enhances the capability of using Zathura as
reader for books.

I do not really see use for values of 'first-page-column' higher than 2,
but nevertheless implemented this feature as general as I could think
of.

I am eager to know what you think of this feature.

-- 
Johan Commelin
diff -crB zathura-0.2.0/callbacks.c zathura-dual-view/callbacks.c
*** zathura-0.2.0/callbacks.c   2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/callbacks.c       2012-06-27 17:18:25.953017153 +0200
***************
*** 118,124 ****
      pages_per_row = 1;
    }
  
!   page_widget_set_mode(zathura, pages_per_row);
  
    if (zathura->document != NULL) {
      unsigned int current_page = 
zathura_document_get_current_page_number(zathura->document);
--- 118,152 ----
      pages_per_row = 1;
    }
  
!        unsigned int first_page_column = 1;
!        girara_setting_get(session, "first-page-column", &first_page_column);
! 
!   page_widget_set_mode(zathura, pages_per_row, first_page_column);
! 
!   if (zathura->document != NULL) {
!     unsigned int current_page = 
zathura_document_get_current_page_number(zathura->document);
!     page_set_delayed(zathura, current_page);
!   }
! }
! 
! void
! cb_first_page_column_value_changed(girara_session_t* session, const char* 
UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* 
UNUSED(data))
! {
!   g_return_if_fail(value != NULL);
!   g_return_if_fail(session != NULL);
!   g_return_if_fail(session->global.data != NULL);
!   zathura_t* zathura = session->global.data;
! 
!   int first_page_column = *(int*) value;
! 
!   if (first_page_column < 1) {
!     first_page_column = 1;
!   }
! 
!        unsigned int pages_per_row = 1;
!        girara_setting_get(session, "pages-per-row", &pages_per_row);
! 
!   page_widget_set_mode(zathura, pages_per_row, first_page_column);
  
    if (zathura->document != NULL) {
      unsigned int current_page = 
zathura_document_get_current_page_number(zathura->document);
diff -crB zathura-0.2.0/callbacks.h zathura-dual-view/callbacks.h
*** zathura-0.2.0/callbacks.h   2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/callbacks.h       2012-06-27 14:44:42.202986494 +0200
***************
*** 47,52 ****
--- 47,64 ----
   */
  void cb_pages_per_row_value_changed(girara_session_t* session, const char* 
name,
      girara_setting_type_t type, void* value, void* data);
+ /**
+  * This function gets called when the value of the "first-page-column"
+  * variable changes
+  *
+  * @param session The current girara session
+  * @param name The name of the row
+  * @param type The settings type
+  * @param value The value
+  * @param data Custom data
+  */
+ void cb_first_page_column_value_changed(girara_session_t* session, const 
char* name,
+     girara_setting_type_t type, void* value, void* data);
  
  /**
   * Called when an index element is activated (e.g.: double click)
diff -crB zathura-0.2.0/config.c zathura-dual-view/config.c
*** zathura-0.2.0/config.c      2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/config.c  2012-06-27 14:41:36.637325124 +0200
***************
*** 104,109 ****
--- 104,111 ----
    girara_setting_add(gsession, "page-padding",          &int_value,   INT,    
false, _("Padding between pages"),   cb_page_padding_changed, NULL);
    int_value = 1;
    girara_setting_add(gsession, "pages-per-row",         &int_value,   INT,    
false, _("Number of pages per row"), cb_pages_per_row_value_changed, NULL);
+   int_value = 1;
+   girara_setting_add(gsession, "first-page-column",     &int_value,   INT,    
false, _("Column of the first page"),cb_first_page_column_value_changed, NULL);
    float_value = 40;
    girara_setting_add(gsession, "scroll-step",           &float_value, FLOAT,  
false, _("Scroll step"),             NULL, NULL);
    int_value = 10;
diff -crB zathura-0.2.0/database.h zathura-dual-view/database.h
*** zathura-0.2.0/database.h    2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/database.h        2012-06-27 17:04:35.817514382 +0200
***************
*** 15,20 ****
--- 15,21 ----
    double scale;
    unsigned int rotation;
    unsigned int pages_per_row;
+   unsigned int first_page_column;
    double position_x;
    double position_y;
  } zathura_fileinfo_t;
diff -crB zathura-0.2.0/database-plain.c zathura-dual-view/database-plain.c
*** zathura-0.2.0/database-plain.c      2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/database-plain.c  2012-06-27 17:12:04.808415323 +0200
***************
*** 21,26 ****
--- 21,27 ----
  #define KEY_SCALE "scale"
  #define KEY_ROTATE "rotate"
  #define KEY_PAGES_PER_ROW "pages-per-row"
+ #define KEY_FIRST_PAGE_COLUMN "first-page-column"
  #define KEY_POSITION_X "position-x"
  #define KEY_POSITION_Y "position-y"
  
***************
*** 387,394 ****
    g_key_file_set_string (priv->history, name, KEY_SCALE, tmp);
    g_free(tmp);
  
!   g_key_file_set_integer(priv->history, name, KEY_ROTATE,        
file_info->rotation);
!   g_key_file_set_integer(priv->history, name, KEY_PAGES_PER_ROW, 
file_info->pages_per_row);
  
    tmp = g_strdup_printf("%f", file_info->position_x);
    g_key_file_set_string(priv->history,  name, KEY_POSITION_X, tmp);
--- 388,396 ----
    g_key_file_set_string (priv->history, name, KEY_SCALE, tmp);
    g_free(tmp);
  
!   g_key_file_set_integer(priv->history, name, KEY_ROTATE,            
file_info->rotation);
!   g_key_file_set_integer(priv->history, name, KEY_PAGES_PER_ROW,     
file_info->pages_per_row);
!   g_key_file_set_integer(priv->history, name, KEY_FIRST_PAGE_COLUMN, 
file_info->first_page_column);
  
    tmp = g_strdup_printf("%f", file_info->position_x);
    g_key_file_set_string(priv->history,  name, KEY_POSITION_X, tmp);
***************
*** 424,433 ****
      return false;
    }
  
!   file_info->current_page  = g_key_file_get_integer(priv->history, name, 
KEY_PAGE, NULL);
!   file_info->page_offset   = g_key_file_get_integer(priv->history, name, 
KEY_OFFSET, NULL);
!   file_info->rotation      = g_key_file_get_integer(priv->history, name, 
KEY_ROTATE, NULL);
!   file_info->pages_per_row = g_key_file_get_integer(priv->history, name, 
KEY_PAGES_PER_ROW, NULL);
  
    char* scale_string = g_key_file_get_string(priv->history, name, KEY_SCALE, 
NULL);
    if (scale_string != NULL) {
--- 426,436 ----
      return false;
    }
  
!   file_info->current_page      = g_key_file_get_integer(priv->history, name, 
KEY_PAGE, NULL);
!   file_info->page_offset       = g_key_file_get_integer(priv->history, name, 
KEY_OFFSET, NULL);
!   file_info->rotation          = g_key_file_get_integer(priv->history, name, 
KEY_ROTATE, NULL);
!   file_info->pages_per_row     = g_key_file_get_integer(priv->history, name, 
KEY_PAGES_PER_ROW, NULL);
!   file_info->first_page_column = g_key_file_get_integer(priv->history, name, 
KEY_FIRST_PAGE_COLUMN, NULL);
  
    char* scale_string = g_key_file_get_string(priv->history, name, KEY_SCALE, 
NULL);
    if (scale_string != NULL) {
diff -crB zathura-0.2.0/database-sqlite.c zathura-dual-view/database-sqlite.c
*** zathura-0.2.0/database-sqlite.c     2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/database-sqlite.c 2012-06-27 17:08:57.319431037 +0200
***************
*** 120,131 ****
--- 120,133 ----
        "scale FLOAT,"
        "rotation INTEGER,"
        "pages_per_row INTEGER,"
+       "first_page_column INTEGER,"
        "position_x FLOAT,"
        "position_y FLOAT"
        ");";
  
    static const char SQL_FILEINFO_ALTER[] =
      "ALTER TABLE fileinfo ADD COLUMN pages_per_row INTEGER;"
+     "ALTER TABLE fileinfo ADD COLUMN first_page_column INTEGER;"
      "ALTER TABLE fileinfo ADD COLUMN position_x FLOAT;"
      "ALTER TABLE fileinfo ADD COLUMN position_y FLOAT;";
  
***************
*** 299,305 ****
    zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
  
    static const char SQL_FILEINFO_SET[] =
!     "REPLACE INTO fileinfo (file, page, offset, scale, rotation, 
pages_per_row, position_x, position_y) VALUES (?, ?, ?, ?, ?, ?, ?, ?);";
  
    sqlite3_stmt* stmt = prepare_statement(priv->session, SQL_FILEINFO_SET);
    if (stmt == NULL) {
--- 301,307 ----
    zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
  
    static const char SQL_FILEINFO_SET[] =
!     "REPLACE INTO fileinfo (file, page, offset, scale, rotation, 
pages_per_row, first_page_column, position_x, position_y) VALUES (?, ?, ?, ?, 
?, ?, ?, ?);";
  
    sqlite3_stmt* stmt = prepare_statement(priv->session, SQL_FILEINFO_SET);
    if (stmt == NULL) {
***************
*** 312,317 ****
--- 314,320 ----
        sqlite3_bind_double(stmt, 4, file_info->scale)         != SQLITE_OK ||
        sqlite3_bind_int(stmt,    5, file_info->rotation)      != SQLITE_OK ||
        sqlite3_bind_int(stmt,    6, file_info->pages_per_row) != SQLITE_OK ||
+       sqlite3_bind_int(stmt,    6, file_info->first_page_column) != SQLITE_OK 
||
        sqlite3_bind_double(stmt, 7, file_info->position_x)    != SQLITE_OK ||
        sqlite3_bind_double(stmt, 8, file_info->position_y)    != SQLITE_OK) {
      sqlite3_finalize(stmt);
***************
*** 336,342 ****
    zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
  
    static const char SQL_FILEINFO_GET[] =
!     "SELECT page, offset, scale, rotation, pages_per_row, position_x, 
position_y FROM fileinfo WHERE file = ?;";
  
    sqlite3_stmt* stmt = prepare_statement(priv->session, SQL_FILEINFO_GET);
    if (stmt == NULL) {
--- 339,345 ----
    zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
  
    static const char SQL_FILEINFO_GET[] =
!     "SELECT page, offset, scale, rotation, pages_per_row, first_page_column, 
position_x, position_y FROM fileinfo WHERE file = ?;";
  
    sqlite3_stmt* stmt = prepare_statement(priv->session, SQL_FILEINFO_GET);
    if (stmt == NULL) {
***************
*** 355,367 ****
      return false;
    }
  
!   file_info->current_page  = sqlite3_column_int(stmt, 0);
!   file_info->page_offset   = sqlite3_column_int(stmt, 1);
!   file_info->scale         = sqlite3_column_double(stmt, 2);
!   file_info->rotation      = sqlite3_column_int(stmt, 3);
!   file_info->pages_per_row = sqlite3_column_int(stmt, 4);
!   file_info->position_x    = sqlite3_column_double(stmt, 5);
!   file_info->position_y    = sqlite3_column_double(stmt, 6);
  
    sqlite3_finalize(stmt);
  
--- 358,371 ----
      return false;
    }
  
!   file_info->current_page      = sqlite3_column_int(stmt, 0);
!   file_info->page_offset       = sqlite3_column_int(stmt, 1);
!   file_info->scale             = sqlite3_column_double(stmt, 2);
!   file_info->rotation          = sqlite3_column_int(stmt, 3);
!   file_info->pages_per_row     = sqlite3_column_int(stmt, 4);
!   file_info->first_page_column = sqlite3_column_int(stmt, 5);
!   file_info->position_x        = sqlite3_column_double(stmt, 6);
!   file_info->position_y        = sqlite3_column_double(stmt, 7);
  
    sqlite3_finalize(stmt);
  
diff -crB zathura-0.2.0/shortcuts.c zathura-dual-view/shortcuts.c
*** zathura-0.2.0/shortcuts.c   2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/shortcuts.c       2012-06-27 15:18:43.468594677 +0200
***************
*** 62,67 ****
--- 62,70 ----
    unsigned int pages_per_row = 1;
    girara_setting_get(session, "pages-per-row", &pages_per_row);
  
+   unsigned int first_page_column = 1;
+   girara_setting_get(session, "first-page-column", &first_page_column);
+ 
    if (zathura->ui.page_widget == NULL || zathura->document == NULL) {
      goto error_ret;
    }
***************
*** 894,905 ****
--- 897,912 ----
  
    static bool fullscreen = false;
    static int pages_per_row = 1;
+   static int first_page_column = 1;
    static double zoom = 1.0;
  
    if (fullscreen == true) {
      /* reset pages per row */
      girara_setting_set(session, "pages-per-row", &pages_per_row);
  
+     /* reset first page column */
+     girara_setting_set(session, "first-page-column", &first_page_column);
+ 
      /* show status bar */
      gtk_widget_show(GTK_WIDGET(session->gtk.statusbar));
  
***************
*** 914,919 ****
--- 921,929 ----
      /* backup pages per row */
      girara_setting_get(session, "pages-per-row", &pages_per_row);
  
+     /* backup first page column */
+     girara_setting_get(session, "first-page-column", &first_page_column);
+ 
      /* set single view */
      int int_value = 1;
      girara_setting_set(session, "pages-per-row", &int_value);
diff -crB zathura-0.2.0/zathura.c zathura-dual-view/zathura.c
*** zathura-0.2.0/zathura.c     2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/zathura.c 2012-06-27 17:03:46.914445979 +0200
***************
*** 622,635 ****
  
    /* view mode */
    int pages_per_row = 1;
    if (file_info.pages_per_row > 0) {
      pages_per_row = file_info.pages_per_row;
    } else {
      girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row);
    }
  
    girara_setting_set(zathura->ui.session, "pages-per-row", &pages_per_row);
!   page_widget_set_mode(zathura, pages_per_row);
  
    girara_set_view(zathura->ui.session, zathura->ui.page_widget_alignment);
  
--- 622,639 ----
  
    /* view mode */
    int pages_per_row = 1;
+   int first_page_column = 1;
    if (file_info.pages_per_row > 0) {
      pages_per_row = file_info.pages_per_row;
+     first_page_column = file_info.first_page_column;
    } else {
      girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row);
+     girara_setting_get(zathura->ui.session, "first-page-column", 
&first_page_column);
    }
  
    girara_setting_set(zathura->ui.session, "pages-per-row", &pages_per_row);
!   girara_setting_set(zathura->ui.session, "first-page-column", 
&first_page_column);
!   page_widget_set_mode(zathura, pages_per_row, first_page_column);
  
    girara_set_view(zathura->ui.session, zathura->ui.page_widget_alignment);
  
***************
*** 884,896 ****
  }
  
  void
! page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row)
  {
    /* show at least one page */
    if (pages_per_row == 0) {
      pages_per_row = 1;
    }
  
    if (zathura->document == NULL) {
      return;
    }
--- 888,909 ----
  }
  
  void
! page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, unsigned 
int first_page_column)
  {
    /* show at least one page */
    if (pages_per_row == 0) {
      pages_per_row = 1;
    }
  
+       /* ensure: 0 < first_page_column <= pages_per_row */
+       if (first_page_column < 1) {
+               first_page_column = 1;
+       }
+ 
+       if (first_page_column > pages_per_row) {
+               first_page_column = ((first_page_column - 1) % pages_per_row) + 
1;
+       }
+ 
    if (zathura->document == NULL) {
      return;
    }
***************
*** 898,908 ****
    gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), 
remove_page_from_table, (gpointer)0);
  
    unsigned int number_of_pages     = 
zathura_document_get_number_of_pages(zathura->document);
!   gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), ceil(number_of_pages / 
pages_per_row), pages_per_row);
    for (unsigned int i = 0; i < number_of_pages; i++)
    {
!     int x = i % pages_per_row;
!     int y = i / pages_per_row;
  
      zathura_page_t* page   = zathura_document_get_page(zathura->document, i);
      GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
--- 911,921 ----
    gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), 
remove_page_from_table, (gpointer)0);
  
    unsigned int number_of_pages     = 
zathura_document_get_number_of_pages(zathura->document);
!   gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), ceil((number_of_pages 
+ first_page_column - 1) / pages_per_row), pages_per_row);
    for (unsigned int i = 0; i < number_of_pages; i++)
    {
!     int x = (i + first_page_column - 1) % pages_per_row;
!     int y = (i + first_page_column - 1) / pages_per_row;
  
      zathura_page_t* page   = zathura_document_get_page(zathura->document, i);
      GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
diff -crB zathura-0.2.0/zathura.h zathura-dual-view/zathura.h
*** zathura-0.2.0/zathura.h     2012-06-09 23:37:42.000000000 +0200
--- zathura-dual-view/zathura.h 2012-06-27 17:15:58.447149593 +0200
***************
*** 194,201 ****
   *
   * @param zathura The zathura session
   * @param pages_per_row Number of shown pages per row
   */
! void page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row);
  
  /**
   * Updates the page number in the statusbar. Note that 1 will be added to the
--- 194,202 ----
   *
   * @param zathura The zathura session
   * @param pages_per_row Number of shown pages per row
+  * @param first_page_column Column on which first page start
   */
! void page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row, 
unsigned int first_page_column);
  
  /**
   * Updates the page number in the statusbar. Note that 1 will be added to the
_______________________________________________
zathura mailing list
zathura@lists.pwmt.org
http://lists.pwmt.org/mailman/listinfo/zathura

Reply via email to