Discussion:
[zathura] [Zathura PATCH v2] Make the jumplist persistent on a per-file basis
Marwan Tanager
2013-06-21 12:30:04 UTC
Permalink
This patch implements two new ZathuraDatabaseInterface functions, save_jumplist
and load_jumplist, for both the plain and sqlite backends (along with some
cleanups).

---
config.c | 14 ++++-
database-plain.c | 133 +++++++++++++++++++++++++++++-----------
database-sqlite.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++-----
database.c | 16 +++++
database.h | 35 +++++++++--
zathura.c | 107 +++++++++++++++++++++++++-------
zathura.h | 17 ++++++
7 files changed, 418 insertions(+), 80 deletions(-)

diff --git a/config.c b/config.c
index 6914efb..4adab3a 100644
--- a/config.c
+++ b/config.c
@@ -27,10 +27,18 @@ cb_jumplist_change(girara_session_t* session, const char* name,
g_return_if_fail(session->global.data != NULL);
g_return_if_fail(name != NULL);
zathura_t* zathura = session->global.data;
- if (g_strcmp0(name, "jumplist-size") == 0) {
- int* max_size = (int*) value;
- zathura->jumplist.max_size = *max_size;
+
+ if (g_strcmp0(name, "jumplist-size") != 0) {
+ return;
}
+
+ if (*(int *)value < 0) {
+ zathura->jumplist.max_size = 0;
+ } else {
+ zathura->jumplist.max_size = *(int *)value;
+ }
+
+ zathura_jumplist_trim(zathura);
}

static void
diff --git a/database-plain.c b/database-plain.c
index fdb69e6..39033c1 100644
--- a/database-plain.c
+++ b/database-plain.c
@@ -15,18 +15,19 @@

#include "database-plain.h"

-#define BOOKMARKS "bookmarks"
-#define HISTORY "history"
-#define INPUT_HISTORY "input-history"
-
-#define KEY_PAGE "page"
-#define KEY_OFFSET "offset"
-#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"
+#define BOOKMARKS "bookmarks"
+#define HISTORY "history"
+#define INPUT_HISTORY "input-history"
+
+#define KEY_PAGE "page"
+#define KEY_OFFSET "offset"
+#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"
+#define KEY_JUMPLIST "jumplist"

#ifdef __GNU__
#include <sys/file.h>
@@ -46,28 +47,23 @@ G_DEFINE_TYPE_WITH_CODE(ZathuraPlainDatabase, zathura_plaindatabase, G_TYPE_OBJE
G_IMPLEMENT_INTERFACE(ZATHURA_TYPE_DATABASE, zathura_database_interface_init)
G_IMPLEMENT_INTERFACE(GIRARA_TYPE_INPUT_HISTORY_IO, io_interface_init))

-static void plain_finalize(GObject* object);
-static bool plain_add_bookmark(zathura_database_t* db, const char* file,
- zathura_bookmark_t* bookmark);
-static bool plain_remove_bookmark(zathura_database_t* db, const char* file,
- const char* id);
-static girara_list_t* plain_load_bookmarks(zathura_database_t* db,
- const char* file);
-static bool plain_set_fileinfo(zathura_database_t* db, const char* file,
- zathura_fileinfo_t* file_info);
-static bool plain_get_fileinfo(zathura_database_t* db, const char* file,
- zathura_fileinfo_t* file_info);
-static void plain_set_property(GObject* object, guint prop_id,
- const GValue* value, GParamSpec* pspec);
-static void plain_io_append(GiraraInputHistoryIO* db, const char*);
+static void plain_finalize(GObject* object);
+static bool plain_add_bookmark(zathura_database_t* db, const char* file, zathura_bookmark_t* bookmark);
+static bool plain_remove_bookmark(zathura_database_t* db, const char* file, const char* id);
+static girara_list_t* plain_load_bookmarks(zathura_database_t* db, const char* file);
+static girara_list_t* plain_load_jumplist(zathura_database_t* db, const char* file);
+static bool plain_save_jumplist(zathura_database_t* db, const char* file, girara_list_t* jumplist);
+static bool plain_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t* file_info);
+static bool plain_get_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t* file_info);
+static void plain_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
+static void plain_io_append(GiraraInputHistoryIO* db, const char*);
static girara_list_t* plain_io_read(GiraraInputHistoryIO* db);

/* forward declaration */
-static bool zathura_db_check_file(const char* path);
-static GKeyFile* zathura_db_read_key_file_from_file(const char* path);
-static void zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file);
-static void cb_zathura_db_watch_file(GFileMonitor* monitor, GFile* file, GFile*
- other_file, GFileMonitorEvent event, zathura_database_t* database);
+static bool zathura_db_check_file(const char* path);
+static GKeyFile* zathura_db_read_key_file_from_file(const char* path);
+static void zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file);
+static void cb_zathura_db_watch_file(GFileMonitor* monitor, GFile* file, GFile* other_file, GFileMonitorEvent event, zathura_database_t* database);

typedef struct zathura_plaindatabase_private_s {
char* bookmark_path;
@@ -110,6 +106,8 @@ zathura_database_interface_init(ZathuraDatabaseInterface* iface)
iface->add_bookmark = plain_add_bookmark;
iface->remove_bookmark = plain_remove_bookmark;
iface->load_bookmarks = plain_load_bookmarks;
+ iface->load_jumplist = plain_load_jumplist;
+ iface->save_jumplist = plain_save_jumplist;
iface->set_fileinfo = plain_set_fileinfo;
iface->get_fileinfo = plain_get_fileinfo;
}
@@ -427,6 +425,73 @@ plain_load_bookmarks(zathura_database_t* db, const char* file)
return result;
}

+static girara_list_t*
+get_jumplist_from_str(const char* str)
+{
+ g_return_val_if_fail(str != NULL, NULL);
+
+ if (*str == 0) {
+ return girara_list_new2(g_free);
+ }
+
+ girara_list_t* result = girara_list_new2(g_free);
+ char* copy = g_strdup(str);
+ char* token = strtok(copy, " ");
+
+ while (token != NULL) {
+ zathura_jump_t* jump = g_malloc0(sizeof(zathura_jump_t));
+
+ jump->page = strtoul(token, NULL, 0);
+ token = strtok(NULL, " ");
+ jump->x = strtod(token, NULL);
+ token = strtok(NULL, " ");
+ jump->y = strtod(token, NULL);
+ girara_list_append(result, jump);
+ token = strtok(NULL, " ");
+ }
+
+ g_free(copy);
+
+ return result;
+}
+
+static girara_list_t*
+plain_load_jumplist(zathura_database_t* db, const char* file)
+{
+ g_return_val_if_fail(db != NULL && file != NULL, NULL);
+
+ zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
+ char* str_value = g_key_file_get_string(priv->history, file, KEY_JUMPLIST, NULL);
+
+ if (str_value == NULL) {
+ return girara_list_new2(g_free);
+ }
+
+ return get_jumplist_from_str(str_value);
+}
+
+static bool
+plain_save_jumplist(zathura_database_t* db, const char* file, girara_list_t* jumplist)
+{
+ g_return_val_if_fail(db != NULL && file != NULL && jumplist != NULL, false);
+
+ GString* str_val = g_string_new(NULL);
+
+ GIRARA_LIST_FOREACH(jumplist, zathura_jump_t*, iter, jump)
+ g_string_append(str_val, g_strdup_printf("%d ", jump->page));
+ g_string_append(str_val, g_strdup_printf("%.20f ", jump->x));
+ g_string_append(str_val, g_strdup_printf("%.20f ", jump->y));
+ GIRARA_LIST_FOREACH_END(jumplist, zathura_jump_t*, iter, jump);
+
+ zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
+
+ g_key_file_set_string(priv->history, file, KEY_JUMPLIST, str_val->str);
+ zathura_db_write_key_file_to_file(priv->history_path, priv->history);
+ g_string_free(str_val, TRUE);
+
+ return true;
+}
+
static bool
plain_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t*
file_info)
@@ -441,7 +506,7 @@ plain_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t*
g_key_file_set_integer(priv->history, name, KEY_PAGE, file_info->current_page);
g_key_file_set_integer(priv->history, name, KEY_OFFSET, file_info->page_offset);

- char* tmp = g_strdup_printf("%f", file_info->scale);
+ char* tmp = g_strdup_printf("%.20f", file_info->scale);
g_key_file_set_string (priv->history, name, KEY_SCALE, tmp);
g_free(tmp);

@@ -449,11 +514,11 @@ plain_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t*
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);
+ tmp = g_strdup_printf("%.20f", file_info->position_x);
g_key_file_set_string(priv->history, name, KEY_POSITION_X, tmp);
g_free(tmp);

- tmp = g_strdup_printf("%f", file_info->position_y);
+ tmp = g_strdup_printf("%.20f", file_info->position_y);
g_key_file_set_string(priv->history, name, KEY_POSITION_Y, tmp);
g_free(tmp);

diff --git a/database-sqlite.c b/database-sqlite.c
index 05f78ad..9c11775 100644
--- a/database-sqlite.c
+++ b/database-sqlite.c
@@ -15,21 +15,17 @@ G_DEFINE_TYPE_WITH_CODE(ZathuraSQLDatabase, zathura_sqldatabase, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(ZATHURA_TYPE_DATABASE, zathura_database_interface_init)
G_IMPLEMENT_INTERFACE(GIRARA_TYPE_INPUT_HISTORY_IO, io_interface_init))

-static bool check_column(sqlite3* session, const char* table, const char* col, bool* result);
-static void sqlite_finalize(GObject* object);
-static bool sqlite_add_bookmark(zathura_database_t* db, const char* file,
- zathura_bookmark_t* bookmark);
-static bool sqlite_remove_bookmark(zathura_database_t* db, const char* file,
- const char* id);
-static girara_list_t* sqlite_load_bookmarks(zathura_database_t* db,
- const char* file);
-static bool sqlite_set_fileinfo(zathura_database_t* db, const char* file,
- zathura_fileinfo_t* file_info);
-static bool sqlite_get_fileinfo(zathura_database_t* db, const char* file,
- zathura_fileinfo_t* file_info);
-static void sqlite_set_property(GObject* object, guint prop_id,
- const GValue* value, GParamSpec* pspec);
-static void sqlite_io_append(GiraraInputHistoryIO* db, const char*);
+static bool check_column(sqlite3* session, const char* table, const char* col, bool* result);
+static void sqlite_finalize(GObject* object);
+static bool sqlite_add_bookmark(zathura_database_t* db, const char* file, zathura_bookmark_t* bookmark);
+static bool sqlite_remove_bookmark(zathura_database_t* db, const char* file, const char* id);
+static girara_list_t* sqlite_load_bookmarks(zathura_database_t* db, const char* file);
+static girara_list_t* sqlite_load_jumplist(zathura_database_t* db, const char* file);
+static bool sqlite_save_jumplist(zathura_database_t* db, const char* file, girara_list_t* jumplist);
+static bool sqlite_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t* file_info);
+static bool sqlite_get_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t* file_info);
+static void sqlite_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
+static void sqlite_io_append(GiraraInputHistoryIO* db, const char*);
static girara_list_t* sqlite_io_read(GiraraInputHistoryIO* db);

typedef struct zathura_sqldatabase_private_s {
@@ -51,6 +47,8 @@ zathura_database_interface_init(ZathuraDatabaseInterface* iface)
iface->add_bookmark = sqlite_add_bookmark;
iface->remove_bookmark = sqlite_remove_bookmark;
iface->load_bookmarks = sqlite_load_bookmarks;
+ iface->load_jumplist = sqlite_load_jumplist;
+ iface->save_jumplist = sqlite_save_jumplist;
iface->set_fileinfo = sqlite_set_fileinfo;
iface->get_fileinfo = sqlite_get_fileinfo;
}
@@ -128,6 +126,15 @@ sqlite_db_init(ZathuraSQLDatabase* db, const char* path)
"vadj_ratio FLOAT,"
"PRIMARY KEY(file, id));";

+ static const char SQL_JUMPLIST_INIT[] =
+ "CREATE TABLE IF NOT EXISTS jumplist ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "file TEXT,"
+ "page INTEGER,"
+ "hadj_ratio FLOAT,"
+ "vadj_ratio FLOAT"
+ ");";
+
/* create fileinfo table */
static const char SQL_FILEINFO_INIT[] =
"CREATE TABLE IF NOT EXISTS fileinfo ("
@@ -177,6 +184,12 @@ sqlite_db_init(ZathuraSQLDatabase* db, const char* path)
return;
}

+ if (sqlite3_exec(session, SQL_JUMPLIST_INIT, NULL, 0, NULL) != SQLITE_OK) {
+ girara_error("Failed to initialize database: %s\n", path);
+ sqlite3_close(session);
+ return;
+ }
+
if (sqlite3_exec(session, SQL_FILEINFO_INIT, NULL, 0, NULL) != SQLITE_OK) {
girara_error("Failed to initialize database: %s\n", path);
sqlite3_close(session);
@@ -398,6 +411,139 @@ sqlite_load_bookmarks(zathura_database_t* db, const char* file)
}

static bool
+sqlite_save_jumplist(zathura_database_t* db, const char* file, girara_list_t* jumplist)
+{
+ g_return_val_if_fail(db != NULL && file != NULL && jumplist != NULL, false);
+
+ zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
+ static const char SQL_INSERT_JUMP[] = "INSERT INTO jumplist (file, page, hadj_ratio, vadj_ratio) VALUES (?, ?, ?, ?);";
+ static const char SQL_REMOVE_JUMPLIST[] = "DELETE FROM jumplist WHERE file = ?;";
+ sqlite3_stmt* stmt = NULL;
+ int res = 0;
+
+ if (sqlite3_exec(priv->session, "BEGIN;", NULL, 0, NULL) != SQLITE_OK) {
+ return false;
+ }
+
+ stmt = prepare_statement(priv->session, SQL_REMOVE_JUMPLIST);
+
+ if (stmt == NULL) {
+ sqlite3_exec(priv->session, "ROLLBACK;", NULL, 0, NULL);
+ return false;
+ }
+
+ if (sqlite3_bind_text(stmt, 1, file, -1, NULL) != SQLITE_OK) {
+ sqlite3_finalize(stmt);
+ sqlite3_exec(priv->session, "ROLLBACK;", NULL, 0, NULL);
+ girara_error("Failed to bind arguments.");
+ return false;
+ }
+
+ res = sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+
+ if (res != SQLITE_DONE) {
+ sqlite3_exec(priv->session, "ROLLBACK;", NULL, 0, NULL);
+ return false;
+ }
+
+ if (girara_list_size(jumplist) == 0) {
+ sqlite3_exec(priv->session, "COMMIT;", NULL, 0, NULL);
+ return true;
+ }
+
+ girara_list_iterator_t* cur = girara_list_iterator(jumplist);
+ bool status = true;
+
+ while (true) {
+ zathura_jump_t* jump = girara_list_iterator_data(cur);
+
+ stmt = prepare_statement(priv->session, SQL_INSERT_JUMP);
+
+ if (stmt == NULL) {
+ status = false;
+ break;
+ }
+
+ if (sqlite3_bind_text(stmt, 1, file, -1, NULL) != SQLITE_OK ||
+ sqlite3_bind_int(stmt, 2, jump->page) != SQLITE_OK ||
+ sqlite3_bind_double(stmt, 3, jump->x) != SQLITE_OK ||
+ sqlite3_bind_double(stmt, 4, jump->y) != SQLITE_OK) {
+
+ sqlite3_finalize(stmt);
+ girara_error("Failed to bind arguments.");
+ status = false;
+ break;
+ }
+
+ res = sqlite3_step(stmt);
+ sqlite3_finalize(stmt);
+
+ if (res != SQLITE_DONE) {
+ status = false;
+ break;
+ }
+
+ if (girara_list_iterator_has_next(cur) == true) {
+ girara_list_iterator_next(cur);
+ } else {
+ break;
+ }
+ }
+
+ if (status == false) {
+ sqlite3_exec(priv->session, "ROLLBACK;", NULL, 0, NULL);
+ return false;
+ } else {
+ sqlite3_exec(priv->session, "COMMIT;", NULL, 0, NULL);
+ return true;
+ }
+}
+
+static girara_list_t*
+sqlite_load_jumplist(zathura_database_t* db, const char* file)
+{
+ g_return_val_if_fail(db != NULL && file != NULL, NULL);
+
+ zathura_sqldatabase_private_t* priv = ZATHURA_SQLDATABASE_GET_PRIVATE(db);
+ static const char SQL_GET_JUMPLIST[] = "SELECT page, hadj_ratio, vadj_ratio FROM jumplist WHERE file = ? ORDER BY id ASC;";
+ sqlite3_stmt* stmt = prepare_statement(priv->session, SQL_GET_JUMPLIST);
+
+ if (stmt == NULL) {
+ return NULL;
+ }
+
+ if (sqlite3_bind_text(stmt, 1, file, -1, NULL) != SQLITE_OK) {
+ sqlite3_finalize(stmt);
+ girara_error("Failed to bind arguments.");
+
+ return NULL;
+ }
+
+ girara_list_t* jumplist = girara_list_new2(g_free);
+ int res = 0;
+
+ while ((res = sqlite3_step(stmt)) == SQLITE_ROW) {
+ zathura_jump_t* jump = g_malloc0(sizeof(zathura_jump_t));
+
+ jump->page = sqlite3_column_int(stmt, 0);
+ jump->x = sqlite3_column_double(stmt, 1);
+ jump->y = sqlite3_column_double(stmt, 2);
+ girara_list_append(jumplist, jump);
+ }
+
+ sqlite3_finalize(stmt);
+
+ if (res != SQLITE_DONE) {
+ girara_list_free(jumplist);
+
+ return NULL;
+ }
+
+ return jumplist;
+}
+
+static bool
sqlite_set_fileinfo(zathura_database_t* db, const char* file,
zathura_fileinfo_t* file_info)
{
diff --git a/database.c b/database.c
index 81e3a27..92a8c34 100644
--- a/database.c
+++ b/database.c
@@ -35,6 +35,22 @@ zathura_db_load_bookmarks(zathura_database_t* db, const char* file)
return ZATHURA_DATABASE_GET_INTERFACE(db)->load_bookmarks(db, file);
}

+girara_list_t*
+zathura_db_load_jumplist(zathura_database_t* db, const char* file)
+{
+ g_return_val_if_fail(ZATHURA_IS_DATABASE(db) && file != NULL, NULL);
+
+ return ZATHURA_DATABASE_GET_INTERFACE(db)->load_jumplist(db, file);
+}
+
+bool
+zathura_db_save_jumplist(zathura_database_t* db, const char* file, girara_list_t* jumplist)
+{
+ g_return_val_if_fail(ZATHURA_IS_DATABASE(db) && file != NULL && jumplist != NULL, NULL);
+
+ return ZATHURA_DATABASE_GET_INTERFACE(db)->save_jumplist(db, file, jumplist);
+}
+
bool
zathura_db_set_fileinfo(zathura_database_t* db, const char* file,
zathura_fileinfo_t* file_info)
diff --git a/database.h b/database.h
index 0c8dd44..5cc5eea 100644
--- a/database.h
+++ b/database.h
@@ -43,6 +43,10 @@ struct _ZathuraDatabaseInterface

girara_list_t* (*load_bookmarks)(ZathuraDatabase* db, const char* file);

+ girara_list_t* (*load_jumplist)(ZathuraDatabase* db, const char* file);
+
+ bool (*save_jumplist)(ZathuraDatabase* db, const char* file, girara_list_t* jumplist);
+
bool (*set_fileinfo)(ZathuraDatabase* db, const char* file, zathura_fileinfo_t* file_info);

bool (*get_fileinfo)(ZathuraDatabase* db, const char* file, zathura_fileinfo_t* file_info);
@@ -54,7 +58,7 @@ GType zathura_database_get_type(void);
* Add or update bookmark in the database.
*
* @param db The database instance
- * @param file The file to which the bookmark belongs to.
+ * @param file The file to which the bookmark belongs.
* @param bookmark The bookmark instance.
* @return true on success, false otherwise
*/
@@ -62,10 +66,10 @@ bool zathura_db_add_bookmark(zathura_database_t* db, const char* file,
zathura_bookmark_t* bookmark);

/**
- * Add or update bookmark in the database.
+ * Remove a bookmark from the database.
*
* @param db The database instance
- * @param file The file to which the bookmark belongs to.
+ * @param file The file to which the bookmark belongs.
* @param id The id of the bookmark
* @return true on success, false otherwise
*/
@@ -83,10 +87,31 @@ girara_list_t* zathura_db_load_bookmarks(zathura_database_t* db, const char*
file);

/**
+ * Load the jumplist belonging to the specified file from the database.
+ *
+ * @param db The database instance.
+ * @param file The file to which the jumplist belongs.
+ *
+ * return A linked list constituting the jumplist of the specified file.
+ */
+girara_list_t* zathura_db_load_jumplist(ZathuraDatabase* db, const char* file);
+
+/**
+ * Save the jumplist belonging to the specified file to the database.
+ *
+ * @param db The database instance.
+ * @param file The file to which the jumplist belongs.
+ * @param jumplist The jumplist to be saved
+ *
+ * return true on success, false otherwise.
+ */
+bool zathura_db_save_jumplist(ZathuraDatabase* db, const char* file, girara_list_t* jumplist);
+
+/**
* Set file info (last site, ...) in the database.
*
* @param db The database instance
- * @param file The file to which the file info belongs to.
+ * @param file The file to which the file info belongs.
* @param file_info The file info
* @return true on success, false otherwise.
*/
@@ -96,7 +121,7 @@ bool zathura_db_set_fileinfo(zathura_database_t* db, const char* file,
/* Get file info (last site, ...) from the database.
*
* @param db The database instance
- * @param file The file to which the file info belongs to.
+ * @param file The file to which the file info belongs.
* @param file_info The file info
* @return true on success, false otherwise.
*/
diff --git a/zathura.c b/zathura.c
index 7e38040..3f2555f 100644
--- a/zathura.c
+++ b/zathura.c
@@ -273,10 +273,11 @@ zathura_init(zathura_t* zathura)

/* jumplist */

- zathura->jumplist.max_size = 20;
- girara_setting_get(zathura->ui.session, "jumplist-size", &(zathura->jumplist.max_size));
+ int jumplist_size = 20;
+ girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size);

- zathura->jumplist.list = girara_list_new2(g_free);
+ zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size;
+ zathura->jumplist.list = NULL;
zathura->jumplist.size = 0;
zathura->jumplist.cur = NULL;

@@ -770,6 +771,11 @@ document_open(zathura_t* zathura, const char* path, const char* password,
/* bookmarks */
zathura_bookmarks_load(zathura, file_path);

+ /* jumplist */
+ if (zathura_jumplist_load(zathura, file_path) == false) {
+ zathura->jumplist.list = girara_list_new2(g_free);
+ }
+
/* update title */
basename_only = false;
girara_setting_get(zathura->ui.session, "window-title-basename", &basename_only);
@@ -930,6 +936,14 @@ document_close(zathura_t* zathura, bool keep_monitor)
/* save file info */
zathura_db_set_fileinfo(zathura->database, path, &file_info);

+ /* save jumplist */
+ zathura_db_save_jumplist(zathura->database, path, zathura->jumplist.list);
+ girara_list_iterator_free(zathura->jumplist.cur);
+ zathura->jumplist.cur = NULL;
+ girara_list_free(zathura->jumplist.list);
+ zathura->jumplist.list = NULL;
+ zathura->jumplist.size = 0;
+
/* release render thread */
render_free(zathura->sync.render_thread);
zathura->sync.render_thread = NULL;
@@ -1220,27 +1234,43 @@ zathura_jumplist_reset_current(zathura_t* zathura)
static void
zathura_jumplist_append_jump(zathura_t* zathura)
{
+ g_return_if_fail(zathura != NULL && zathura->jumplist.list != NULL);
+
zathura_jump_t *jump = g_malloc(sizeof(zathura_jump_t));
- if (jump != NULL) {
- jump->page = 0;
- jump->x = 0;
- jump->y = 0;
-
- /* trim from beginning until max_size */
- girara_list_iterator_t *it = girara_list_iterator(zathura->jumplist.list);
- while (zathura->jumplist.size >= zathura->jumplist.max_size && girara_list_iterator_is_valid(it)) {
- girara_list_iterator_remove(it);
- zathura->jumplist.size = zathura->jumplist.size - 1;
- }
- g_free(it);
+ jump->page = 0;
+ jump->x = 0.0;
+ jump->y = 0.0;
+ girara_list_append(zathura->jumplist.list, jump);

- girara_list_append(zathura->jumplist.list, jump);
+ if (zathura->jumplist.size == 0) {
+ zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list);
+ }

- if (zathura->jumplist.size == 0) {
- zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list);
+ ++zathura->jumplist.size;
+ zathura_jumplist_trim(zathura);
+}
+
+void
+zathura_jumplist_trim(zathura_t* zathura)
+{
+ g_return_if_fail(zathura != NULL && zathura->jumplist.list != NULL && zathura->jumplist.size != 0);
+
+ girara_list_iterator_t* cur = girara_list_iterator(zathura->jumplist.list);
+
+ while (zathura->jumplist.size > zathura->jumplist.max_size) {
+ if (girara_list_iterator_data(cur) == girara_list_iterator_data(zathura->jumplist.cur)) {
+ girara_list_iterator_free(zathura->jumplist.cur);
+ zathura->jumplist.cur = NULL;
}

- zathura->jumplist.size = zathura->jumplist.size + 1;
+ girara_list_iterator_remove(cur);
+ --zathura->jumplist.size;
+ }
+
+ if (zathura->jumplist.size == 0) {
+ girara_list_iterator_free(cur);
+ } else if (zathura->jumplist.cur == NULL) {
+ zathura->jumplist.cur = cur;
}
}

@@ -1254,12 +1284,16 @@ zathura_jumplist_add(zathura_t* zathura)
double x = zathura_adjustment_get_ratio(gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)));
double y = zathura_adjustment_get_ratio(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)));

- zathura_jumplist_reset_current(zathura);
+ if (zathura->jumplist.size != 0) {
+ zathura_jumplist_reset_current(zathura);

- zathura_jump_t* cur = zathura_jumplist_current(zathura);
+ zathura_jump_t* cur = zathura_jumplist_current(zathura);

- if (cur && cur->page == pagenum && cur->x == x && cur->y == y) {
- return;
+ if (cur != NULL) {
+ if (cur->page == pagenum && cur->x == x && cur->y == y) {
+ return;
+ }
+ }
}

zathura_jumplist_append_jump(zathura);
@@ -1267,6 +1301,33 @@ zathura_jumplist_add(zathura_t* zathura)
zathura_jumplist_save(zathura);
}

+bool
+zathura_jumplist_load(zathura_t* zathura, const char* file)
+{
+ g_return_val_if_fail(zathura != NULL && zathura->database != NULL && file != NULL, false);
+
+ zathura->jumplist.list = zathura_db_load_jumplist(zathura->database, file);
+
+ if (zathura->jumplist.list == NULL) {
+ girara_error("Failed to load the jumplist from the database");
+
+ return false;
+ }
+
+ zathura->jumplist.size = girara_list_size(zathura->jumplist.list);
+
+ if (zathura->jumplist.size != 0) {
+ zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list);
+ zathura_jumplist_reset_current(zathura);
+ zathura_jumplist_trim(zathura);
+ girara_debug("Loaded the jumplist from the database");
+ } else {
+ girara_debug("No jumplist for this file in the database yet");
+ }
+
+ return true;
+}
+
static void
zathura_jumplist_save(zathura_t* zathura)
{
diff --git a/zathura.h b/zathura.h
index c67446d..ac22636 100644
--- a/zathura.h
+++ b/zathura.h
@@ -388,6 +388,23 @@ void zathura_jumplist_backward(zathura_t* zathura);
void zathura_jumplist_add(zathura_t* zathura);

/**
+ * Trim entries from the beginning of the jumplist to maintain it's maximum size constraint.
+ *
+ * @param zathura The zathura session
+ */
+void zathura_jumplist_trim(zathura_t* zathura);
+
+/**
+ * Load the jumplist of the specified file
+ *
+ * @param zathura The zathura session
+ * @param file The file whose jumplist is to be loaded
+ *
+ * return A linked list of zathura_jump_t structures constituting the jumplist of the specified file, or NULL.
+ */
+bool zathura_jumplist_load(zathura_t* zathura, const char* file);
+
+/**
* Add a page to the page cache
*
* @param zathura The zathura session
--
1.7.10.4
Loading...