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 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_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 @@ -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); @@ -397,6 +410,139 @@ sqlite_load_bookmarks(zathura_database_t* db, const char* file) return result; } +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 */ @@ -82,11 +86,32 @@ bool zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const 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 a858b1c..4e77b66 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; @@ -1224,27 +1238,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; + jump->page = 0; + jump->x = 0.0; + jump->y = 0.0; + girara_list_append(zathura->jumplist.list, jump); - /* 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); + if (zathura->jumplist.size == 0) { + zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list); + } - girara_list_append(zathura->jumplist.list, jump); + ++zathura->jumplist.size; + zathura_jumplist_trim(zathura); +} - if (zathura->jumplist.size == 0) { - zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list); +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; } } @@ -1258,12 +1288,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); @@ -1271,6 +1305,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 @@ -387,6 +387,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 *