zathura/zathura.c

1495 lines
44 KiB
C
Raw Normal View History

/* See LICENSE file for license and copyright information */
2011-10-21 15:00:22 +02:00
#define _BSD_SOURCE
2011-10-23 20:18:44 +02:00
#define _XOPEN_SOURCE 700
2011-10-21 15:00:22 +02:00
#include <errno.h>
2010-12-28 09:47:09 +01:00
#include <stdlib.h>
#include <unistd.h>
2012-02-08 21:34:53 +01:00
#include <math.h>
2010-12-28 09:47:09 +01:00
#include <girara/datastructures.h>
#include <girara/utils.h>
#include <girara/session.h>
#include <girara/statusbar.h>
#include <girara/settings.h>
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
#include <girara/shortcuts.h>
2011-10-21 15:00:22 +02:00
#include <glib/gstdio.h>
2012-03-04 18:35:16 +01:00
#include <glib/gi18n.h>
2011-04-18 17:03:08 +02:00
2011-09-01 15:43:34 +02:00
#include "bookmarks.h"
2010-11-12 13:48:18 +01:00
#include "callbacks.h"
#include "config.h"
#ifdef WITH_SQLITE
#include "database-sqlite.h"
#endif
#include "database-plain.h"
#include "document.h"
2010-11-12 13:48:18 +01:00
#include "shortcuts.h"
2010-11-10 19:18:01 +01:00
#include "zathura.h"
2010-12-28 09:47:09 +01:00
#include "utils.h"
2012-04-21 04:59:58 +02:00
#include "marks.h"
2011-04-18 18:19:41 +02:00
#include "render.h"
2012-03-26 14:44:56 +02:00
#include "page.h"
#include "page-widget.h"
2012-03-27 13:30:04 +02:00
#include "plugin.h"
#include "adjustment.h"
2009-12-26 17:57:46 +01:00
2012-10-09 01:12:18 +02:00
typedef struct zathura_document_info_s {
2011-04-18 21:22:35 +02:00
zathura_t* zathura;
const char* path;
const char* password;
int page_number;
2011-04-18 21:22:35 +02:00
} zathura_document_info_t;
2012-10-09 01:12:18 +02:00
typedef struct page_set_delayed_s {
zathura_t* zathura;
unsigned int page;
} page_set_delayed_t;
2012-10-09 01:12:18 +02:00
typedef struct position_set_delayed_s {
zathura_t* zathura;
2012-04-21 04:59:58 +02:00
double position_x;
double position_y;
} position_set_delayed_t;
static gboolean document_info_open(gpointer data);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
static void zathura_jumplist_reset_current(zathura_t* zathura);
static void zathura_jumplist_append_jump(zathura_t* zathura);
static void zathura_jumplist_save(zathura_t* zathura);
2009-12-26 17:57:46 +01:00
2010-11-10 19:18:01 +01:00
/* function implementation */
2011-04-18 17:27:49 +02:00
zathura_t*
2012-08-05 15:34:10 +02:00
zathura_create(void)
2010-06-03 18:05:34 +02:00
{
zathura_t* zathura = g_malloc0(sizeof(zathura_t));
2012-07-12 10:37:58 +02:00
/* global settings */
zathura->global.update_page_number = true;
zathura->global.search_direction = FORWARD;
2012-07-12 10:37:58 +02:00
/* plugins */
2012-04-01 18:32:16 +02:00
zathura->plugins.manager = zathura_plugin_manager_new();
if (zathura->plugins.manager == NULL) {
2012-08-05 15:34:10 +02:00
goto error_out;
2012-04-01 18:32:16 +02:00
}
2012-08-05 15:34:10 +02:00
/* UI */
if ((zathura->ui.session = girara_session_create()) == NULL) {
goto error_out;
2011-04-19 14:46:08 +02:00
}
2012-08-05 15:34:10 +02:00
zathura->ui.session->global.data = zathura;
return zathura;
error_out:
zathura_free(zathura);
return NULL;
}
2011-04-19 14:46:08 +02:00
2012-08-05 15:34:10 +02:00
bool
zathura_init(zathura_t* zathura)
{
if (zathura == NULL) {
return false;
}
/* create zathura (config/data) directory */
if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) {
girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno));
}
if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) {
girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno));
}
2012-07-12 10:37:58 +02:00
/* load plugins */
zathura_plugin_manager_load(zathura->plugins.manager);
/* configuration */
config_load_default(zathura);
2011-10-30 11:46:30 +01:00
/* load global configuration files */
2012-02-28 08:32:34 +01:00
char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS);
girara_list_t* config_dirs = girara_split_path_array(config_path);
2011-10-30 11:46:30 +01:00
ssize_t size = girara_list_size(config_dirs) - 1;
for (; size >= 0; --size) {
const char* dir = girara_list_nth(config_dirs, size);
char* file = g_build_filename(dir, ZATHURA_RC, NULL);
config_load_file(zathura, file);
g_free(file);
}
girara_list_free(config_dirs);
2012-02-28 08:32:34 +01:00
g_free(config_path);
2011-10-30 11:46:30 +01:00
config_load_file(zathura, GLOBAL_RC);
/* load local configuration files */
char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL);
config_load_file(zathura, configuration_file);
g_free(configuration_file);
2012-08-05 15:34:10 +02:00
/* UI */
2011-12-13 19:59:59 +01:00
if (girara_session_init(zathura->ui.session, "zathura") == false) {
2012-04-21 04:59:58 +02:00
goto error_free;
}
/* girara events */
2012-05-01 19:09:33 +02:00
zathura->ui.session->events.buffer_changed = cb_buffer_changed;
zathura->ui.session->events.unknown_command = cb_unknown_command;
/* zathura signals */
zathura->signals.refresh_view = g_signal_new("refresh-view",
GTK_TYPE_WIDGET,
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view",
G_CALLBACK(cb_refresh_view), zathura);
2010-12-29 11:46:13 +01:00
/* page view */
2012-08-05 02:30:03 +02:00
#if (GTK_MAJOR_VERSION == 3)
zathura->ui.page_widget = gtk_grid_new();
2012-08-05 15:56:35 +02:00
gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
2012-08-05 02:30:03 +02:00
#else
2012-02-07 18:30:46 +01:00
zathura->ui.page_widget = gtk_table_new(0, 0, TRUE);
2012-08-05 02:30:03 +02:00
#endif
2012-02-12 16:35:33 +01:00
if (zathura->ui.page_widget == NULL) {
2010-12-29 11:46:13 +01:00
goto error_free;
}
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura);
2012-02-09 01:46:51 +01:00
/* Setup hadjustment tracker */
GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(
GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
zathura->ui.hadjustment = zathura_adjustment_clone(hadjustment);
g_object_ref_sink(zathura->ui.hadjustment);
/* Connect hadjustment signals */
g_signal_connect(G_OBJECT(hadjustment), "value-changed",
G_CALLBACK(cb_view_hadjustment_value_changed), zathura);
g_signal_connect(G_OBJECT(hadjustment), "value-changed",
G_CALLBACK(cb_adjustment_track_value), zathura->ui.hadjustment);
g_signal_connect(G_OBJECT(hadjustment), "changed",
G_CALLBACK(cb_view_hadjustment_changed), zathura);
g_signal_connect(G_OBJECT(hadjustment), "changed",
G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.hadjustment);
/* Setup vadjustment tracker */
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(
GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
zathura->ui.vadjustment = zathura_adjustment_clone(vadjustment);
g_object_ref_sink(zathura->ui.vadjustment);
/* Connect vadjustment signals */
g_signal_connect(G_OBJECT(vadjustment), "value-changed",
G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
g_signal_connect(G_OBJECT(vadjustment), "value-changed",
G_CALLBACK(cb_adjustment_track_value), zathura->ui.vadjustment);
g_signal_connect(G_OBJECT(vadjustment), "changed",
G_CALLBACK(cb_view_vadjustment_changed), zathura);
g_signal_connect(G_OBJECT(vadjustment), "changed",
G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.vadjustment);
2011-04-19 21:42:18 +02:00
2012-01-13 17:39:46 +01:00
/* page view alignment */
2012-02-07 18:30:46 +01:00
zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
2012-02-12 16:35:33 +01:00
if (zathura->ui.page_widget_alignment == NULL) {
2012-01-13 17:39:46 +01:00
goto error_free;
}
2012-02-07 18:30:46 +01:00
gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget);
2012-01-13 17:39:46 +01:00
2012-08-05 15:56:35 +02:00
#if (GTK_MAJOR_VERSION == 3)
gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE);
gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE);
gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE);
gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE);
#endif
2012-02-07 18:30:46 +01:00
gtk_widget_show(zathura->ui.page_widget);
2010-12-26 01:52:17 +01:00
/* statusbar */
2011-04-18 17:27:49 +02:00
zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
if (zathura->ui.statusbar.file == NULL) {
2010-12-26 01:52:17 +01:00
goto error_free;
2010-11-13 12:40:48 +01:00
}
2011-04-18 17:27:49 +02:00
zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
if (zathura->ui.statusbar.buffer == NULL) {
2010-12-26 01:52:17 +01:00
goto error_free;
2010-11-18 21:22:43 +01:00
}
2011-04-18 17:27:49 +02:00
zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
2012-02-12 16:35:33 +01:00
if (zathura->ui.statusbar.page_number == NULL) {
2010-12-26 01:52:17 +01:00
goto error_free;
2010-11-18 21:22:43 +01:00
}
2012-03-16 15:59:23 +01:00
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));
2010-11-18 21:22:43 +01:00
2010-11-12 13:48:18 +01:00
/* signals */
2012-03-07 01:11:18 +01:00
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura);
2010-12-29 11:46:13 +01:00
/* database */
char* database = NULL;
girara_setting_get(zathura->ui.session, "database", &database);
if (g_strcmp0(database, "plain") == 0) {
girara_debug("Using plain database backend.");
zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
} else if (g_strcmp0(database, "sqlite") == 0) {
girara_debug("Using sqlite database backend.");
char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
zathura->database = zathura_sqldatabase_new(tmp);
g_free(tmp);
#endif
} else {
girara_error("Database backend '%s' is not supported.", database);
}
g_free(database);
if (zathura->database == NULL) {
2011-10-03 17:28:14 +02:00
girara_error("Unable to initialize database. Bookmarks won't be available.");
} else {
g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL);
}
2011-09-01 15:43:34 +02:00
/* bookmarks */
2011-10-15 18:42:30 +02:00
zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
2012-10-09 01:12:18 +02:00
(girara_free_function_t) zathura_bookmark_free);
2011-09-01 15:43:34 +02:00
/* jumplist */
int jumplist_size = 20;
girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size);
zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size;
zathura->jumplist.list = NULL;
zathura->jumplist.size = 0;
zathura->jumplist.cur = NULL;
2012-08-05 15:34:10 +02:00
return true;
2010-12-26 01:52:17 +01:00
error_free:
2012-02-12 16:35:33 +01:00
if (zathura->ui.page_widget != NULL) {
2012-02-07 18:30:46 +01:00
g_object_unref(zathura->ui.page_widget);
2010-12-29 11:46:13 +01:00
}
2012-02-12 16:35:33 +01:00
if (zathura->ui.page_widget_alignment != NULL) {
2012-02-07 18:30:46 +01:00
g_object_unref(zathura->ui.page_widget_alignment);
2012-01-13 17:39:46 +01:00
}
2010-12-26 01:52:17 +01:00
2012-08-05 15:34:10 +02:00
return false;
2011-04-18 17:27:49 +02:00
}
void
zathura_free(zathura_t* zathura)
{
if (zathura == NULL) {
return;
}
2012-02-20 20:07:24 +01:00
document_close(zathura, false);
2011-04-18 17:27:49 +02:00
if (zathura->ui.session != NULL) {
girara_session_destroy(zathura->ui.session);
}
if (zathura->ui.hadjustment != NULL) {
g_object_unref(G_OBJECT(zathura->ui.hadjustment));
}
if (zathura->ui.vadjustment != NULL) {
g_object_unref(G_OBJECT(zathura->ui.vadjustment));
}
2011-10-21 15:00:22 +02:00
/* stdin support */
if (zathura->stdin_support.file != NULL) {
g_unlink(zathura->stdin_support.file);
g_free(zathura->stdin_support.file);
}
2011-09-01 15:43:34 +02:00
/* bookmarks */
girara_list_free(zathura->bookmarks.bookmarks);
/* database */
if (zathura->database != NULL) {
g_object_unref(G_OBJECT(zathura->database));
}
2011-04-29 00:28:19 +02:00
/* free print settings */
2012-02-12 16:35:33 +01:00
if (zathura->print.settings != NULL) {
2011-09-21 09:46:54 +02:00
g_object_unref(zathura->print.settings);
}
if (zathura->print.page_setup != NULL) {
g_object_unref(zathura->print.page_setup);
}
2011-04-29 00:28:19 +02:00
2011-04-18 17:27:49 +02:00
/* free registered plugins */
2012-04-01 18:32:16 +02:00
zathura_plugin_manager_free(zathura->plugins.manager);
/* free config variables */
g_free(zathura->config.config_dir);
g_free(zathura->config.data_dir);
2011-09-30 12:33:50 +02:00
/* free jumplist */
if (zathura->jumplist.list != NULL) {
girara_list_free(zathura->jumplist.list);
}
if (zathura->jumplist.cur != NULL) {
girara_list_iterator_free(zathura->jumplist.cur);
}
g_free(zathura);
2010-06-03 18:05:34 +02:00
}
2012-08-05 15:34:10 +02:00
void
#if (GTK_MAJOR_VERSION == 2)
zathura_set_xid(zathura_t* zathura, GdkNativeWindow xid)
#else
zathura_set_xid(zathura_t* zathura, Window xid)
#endif
{
g_return_if_fail(zathura != NULL);
zathura->ui.session->gtk.embed = xid;
}
void
zathura_set_config_dir(zathura_t* zathura, const char* dir)
{
g_return_if_fail(zathura != NULL);
if (dir != NULL) {
zathura->config.config_dir = g_strdup(dir);
} else {
gchar* path = girara_get_xdg_path(XDG_CONFIG);
zathura->config.config_dir = g_build_filename(path, "zathura", NULL);
g_free(path);
}
}
void
zathura_set_data_dir(zathura_t* zathura, const char* dir)
{
if (dir != NULL) {
zathura->config.data_dir = g_strdup(dir);
} else {
gchar* path = girara_get_xdg_path(XDG_DATA);
zathura->config.data_dir = g_build_filename(path, "zathura", NULL);
g_free(path);
}
g_return_if_fail(zathura != NULL);
}
void
zathura_set_plugin_dir(zathura_t* zathura, const char* dir)
{
g_return_if_fail(zathura != NULL);
g_return_if_fail(zathura->plugins.manager != NULL);
if (dir != NULL) {
girara_list_t* paths = girara_split_path_array(dir);
GIRARA_LIST_FOREACH(paths, char*, iter, path)
2012-10-09 01:12:18 +02:00
zathura_plugin_manager_add_dir(zathura->plugins.manager, path);
2012-08-05 15:34:10 +02:00
GIRARA_LIST_FOREACH_END(paths, char*, iter, path);
girara_list_free(paths);
} else {
#ifdef ZATHURA_PLUGINDIR
girara_list_t* paths = girara_split_path_array(ZATHURA_PLUGINDIR);
GIRARA_LIST_FOREACH(paths, char*, iter, path)
2012-10-09 01:12:18 +02:00
zathura_plugin_manager_add_dir(zathura->plugins.manager, path);
2012-08-05 15:34:10 +02:00
GIRARA_LIST_FOREACH_END(paths, char*, iter, path);
girara_list_free(paths);
#endif
}
}
void
zathura_set_synctex_editor_command(zathura_t* zathura, const char* command)
{
g_return_if_fail(zathura != NULL);
if (zathura->synctex.editor != NULL) {
g_free(zathura->synctex.editor);
}
if (command != NULL) {
zathura->synctex.editor = g_strdup(command);
} else {
zathura->synctex.editor = NULL;
}
}
2012-08-13 18:17:20 +02:00
void
zathura_set_synctex(zathura_t* zathura, bool value)
2012-08-13 18:17:20 +02:00
{
g_return_if_fail(zathura != NULL);
g_return_if_fail(zathura->ui.session != NULL);
girara_setting_set(zathura->ui.session, "synctex", &value);
}
2012-08-05 15:34:10 +02:00
void
zathura_set_argv(zathura_t* zathura, char** argv)
{
g_return_if_fail(zathura != NULL);
zathura->global.arguments = argv;
}
2011-10-21 15:00:22 +02:00
static gchar*
prepare_document_open_from_stdin(zathura_t* zathura)
{
g_return_val_if_fail(zathura, NULL);
GError* error = NULL;
gchar* file = NULL;
gint handle = g_file_open_tmp("zathura.stdin.XXXXXX", &file, &error);
2012-07-12 10:39:21 +02:00
if (handle == -1) {
if (error != NULL) {
girara_error("Can not create temporary file: %s", error->message);
g_error_free(error);
}
2011-10-21 15:00:22 +02:00
return NULL;
}
// read from stdin and dump to temporary file
int stdinfno = fileno(stdin);
2012-07-12 10:39:21 +02:00
if (stdinfno == -1) {
2011-10-21 15:00:22 +02:00
girara_error("Can not read from stdin.");
close(handle);
g_unlink(file);
g_free(file);
return NULL;
}
char buffer[BUFSIZ];
ssize_t count = 0;
2012-07-12 10:39:21 +02:00
while ((count = read(stdinfno, buffer, BUFSIZ)) > 0) {
if (write(handle, buffer, count) != count) {
2011-10-21 15:00:22 +02:00
girara_error("Can not write to temporary file: %s", file);
close(handle);
g_unlink(file);
g_free(file);
return NULL;
}
}
2012-07-12 10:39:21 +02:00
2011-10-21 15:00:22 +02:00
close(handle);
2012-07-12 10:39:21 +02:00
if (count != 0) {
2011-10-21 15:00:22 +02:00
girara_error("Can not read from stdin.");
g_unlink(file);
g_free(file);
return NULL;
}
return file;
}
static gboolean
2011-04-18 21:22:35 +02:00
document_info_open(gpointer data)
{
zathura_document_info_t* document_info = data;
g_return_val_if_fail(document_info != NULL, FALSE);
if (document_info->zathura != NULL && document_info->path != NULL) {
2011-10-21 15:00:22 +02:00
char* file = NULL;
if (g_strcmp0(document_info->path, "-") == 0) {
file = prepare_document_open_from_stdin(document_info->zathura);
if (file == NULL) {
girara_notify(document_info->zathura->ui.session, GIRARA_ERROR,
2012-10-09 01:12:18 +02:00
"Could not read file from stdin and write it to a temporary file.");
2011-10-23 17:34:10 +02:00
} else {
document_info->zathura->stdin_support.file = g_strdup(file);
2011-10-21 15:00:22 +02:00
}
} else {
file = g_strdup(document_info->path);
}
if (file != NULL) {
document_open(document_info->zathura, file, document_info->password,
document_info->page_number);
2011-10-21 15:00:22 +02:00
g_free(file);
}
2011-04-18 21:22:35 +02:00
}
g_free(document_info);
2011-04-18 21:22:35 +02:00
return FALSE;
2010-06-03 18:05:34 +02:00
}
2010-12-12 22:04:42 +01:00
bool
document_open(zathura_t* zathura, const char* path, const char* password,
int page_number)
2010-12-12 22:04:42 +01:00
{
if (zathura == NULL || zathura->plugins.manager == NULL || path == NULL) {
2010-12-29 11:46:13 +01:00
goto error_out;
2010-12-12 22:04:42 +01:00
}
gchar* file_uri = NULL;
zathura_error_t error = ZATHURA_ERROR_OK;
zathura_document_t* document = zathura_document_open(zathura->plugins.manager, path, password, &error);
2010-12-12 22:04:42 +01:00
2012-02-12 16:35:33 +01:00
if (document == NULL) {
if (error == ZATHURA_ERROR_INVALID_PASSWORD) {
zathura_password_dialog_info_t* password_dialog_info = malloc(sizeof(zathura_password_dialog_info_t));
if (password_dialog_info != NULL) {
password_dialog_info->zathura = zathura;
if (path != NULL) {
password_dialog_info->path = g_strdup(path);
girara_dialog(zathura->ui.session, "Enter password:", true, NULL,
2012-10-09 01:12:18 +02:00
(girara_callback_inputbar_activate_t) cb_password_dialog, password_dialog_info);
goto error_out;
} else {
free(password_dialog_info);
}
}
goto error_out;
}
2013-05-28 18:12:15 +02:00
if (error == ZATHURA_ERROR_OK ) {
girara_notify(zathura->ui.session, GIRARA_ERROR, _("Unsupported file type. Please install the necessary plugin."));
}
2010-12-29 11:46:13 +01:00
goto error_out;
2010-12-12 22:04:42 +01:00
}
const char* file_path = zathura_document_get_path(document);
unsigned int number_of_pages = zathura_document_get_number_of_pages(document);
if (number_of_pages == 0) {
girara_notify(zathura->ui.session, GIRARA_WARNING,
_("Document does not contain any pages"));
goto error_free;
}
/* read history file */
2012-07-13 14:05:07 +02:00
zathura_fileinfo_t file_info = { 0, 0, 1, 0, 0, 0, 0, 0 };
bool known_file = zathura_db_get_fileinfo(zathura->database, file_path, &file_info);
2012-04-22 10:04:46 +02:00
/* set page offset */
zathura_document_set_page_offset(document, file_info.page_offset);
/* check for valid scale value */
if (file_info.scale <= FLT_EPSILON) {
girara_warning("document info: '%s' has non positive scale", file_path);
zathura_document_set_scale(document, 1);
} else {
zathura_document_set_scale(document, file_info.scale);
}
/* check current page number */
/* if it wasn't specified on the command-line, get it from file_info */
if (page_number == ZATHURA_PAGE_NUMBER_UNSPECIFIED)
page_number = file_info.current_page;
if (page_number < 0)
page_number += number_of_pages;
if ((unsigned)page_number > number_of_pages) {
girara_warning("document info: '%s' has an invalid page number", file_path);
zathura_document_set_current_page_number(document, 0);
} else {
zathura_document_set_current_page_number(document, page_number);
}
/* check for valid rotation */
if (file_info.rotation % 90 != 0) {
girara_warning("document info: '%s' has an invalid rotation", file_path);
zathura_document_set_rotation(document, 0);
} else {
zathura_document_set_rotation(document, file_info.rotation % 360);
}
/* jump to first page if setting enabled */
bool always_first_page = false;
girara_setting_get(zathura->ui.session, "open-first-page", &always_first_page);
if (always_first_page == true) {
zathura_document_set_current_page_number(document, 0);
}
/* apply open adjustment */
char* adjust_open = "best-fit";
if (known_file == false && girara_setting_get(zathura->ui.session, "adjust-open", &(adjust_open)) == true) {
if (g_strcmp0(adjust_open, "best-fit") == 0) {
zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_BESTFIT);
} else if (g_strcmp0(adjust_open, "width") == 0) {
zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_WIDTH);
} else {
zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_NONE);
}
g_free(adjust_open);
} else {
zathura_document_set_adjust_mode(document, ZATHURA_ADJUST_NONE);
}
/* initialize bisect state */
zathura->bisect.start = 0;
zathura->bisect.last_jump = zathura_document_get_current_page_number(document);
zathura->bisect.end = number_of_pages - 1;
/* update statusbar */
bool basename_only = false;
girara_setting_get(zathura->ui.session, "statusbar-basename", &basename_only);
if (basename_only == false) {
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, file_path);
} else {
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, zathura_document_get_basename(document));
}
2012-02-20 20:07:24 +01:00
/* install file monitor */
file_uri = g_filename_to_uri(file_path, NULL, NULL);
2012-02-20 20:07:24 +01:00
if (file_uri == NULL) {
goto error_free;
}
if (zathura->file_monitor.file == NULL) {
zathura->file_monitor.file = g_file_new_for_uri(file_uri);
if (zathura->file_monitor.file == NULL) {
goto error_free;
}
2012-02-20 20:07:24 +01:00
}
if (zathura->file_monitor.monitor == NULL) {
zathura->file_monitor.monitor = g_file_monitor_file(zathura->file_monitor.file, G_FILE_MONITOR_NONE, NULL, NULL);
if (zathura->file_monitor.monitor == NULL) {
goto error_free;
}
g_signal_connect(G_OBJECT(zathura->file_monitor.monitor), "changed", G_CALLBACK(cb_file_monitor), zathura->ui.session);
2012-02-20 20:07:24 +01:00
}
if (zathura->file_monitor.file_path == NULL) {
zathura->file_monitor.file_path = g_strdup(file_path);
if (zathura->file_monitor.file_path == NULL) {
goto error_free;
}
2012-02-20 20:07:24 +01:00
}
if (password != NULL) {
g_free(zathura->file_monitor.password);
zathura->file_monitor.password = g_strdup(password);
2012-02-20 20:07:24 +01:00
if (zathura->file_monitor.password == NULL) {
goto error_free;
}
}
2012-04-21 04:59:58 +02:00
/* create marks list */
zathura->global.marks = girara_list_new2((girara_free_function_t) mark_free);
if (zathura->global.marks == NULL) {
goto error_free;
}
2011-04-18 17:27:49 +02:00
zathura->document = document;
2010-12-12 22:04:42 +01:00
/* page cache size */
int cache_size = 0;
girara_setting_get(zathura->ui.session, "page-cache-size", &cache_size);
if (cache_size <= 0) {
girara_warning("page-cache-size is not positive, using %d instead",
ZATHURA_PAGE_CACHE_DEFAULT_SIZE);
cache_size = ZATHURA_PAGE_CACHE_DEFAULT_SIZE;
}
/* threads */
zathura->sync.render_thread = zathura_renderer_new(cache_size);
if (zathura->sync.render_thread == NULL) {
goto error_free;
}
/* set up recolor info in ZathuraRenderer */
char* recolor_dark = NULL;
char* recolor_light = NULL;
girara_setting_get(zathura->ui.session, "recolor-darkcolor", &recolor_dark);
girara_setting_get(zathura->ui.session, "recolor-lightcolor", &recolor_light);
zathura_renderer_set_recolor_colors_str(zathura->sync.render_thread,
recolor_light, recolor_dark);
g_free(recolor_dark);
g_free(recolor_light);
bool recolor = false;
girara_setting_get(zathura->ui.session, "recolor", &recolor);
zathura_renderer_enable_recolor(zathura->sync.render_thread, recolor);
girara_setting_get(zathura->ui.session, "recolor-keephue", &recolor);
zathura_renderer_enable_recolor_hue(zathura->sync.render_thread, recolor);
/* create blank pages */
zathura->pages = calloc(number_of_pages, sizeof(GtkWidget*));
if (zathura->pages == NULL) {
goto error_free;
}
for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
zathura_page_t* page = zathura_document_get_page(document, page_id);
if (page == NULL) {
goto error_free;
}
GtkWidget* page_widget = zathura_page_widget_new(zathura, page);
if (page_widget == NULL) {
goto error_free;
}
zathura->pages[page_id] = page_widget;
/* set widget size */
unsigned int page_height = 0;
unsigned int page_width = 0;
double height = zathura_page_get_height(page);
double width = zathura_page_get_width(page);
page_calc_height_width(zathura->document, height, width, &page_height, &page_width, true);
gtk_widget_set_size_request(page_widget, page_width, page_height);
g_signal_connect(G_OBJECT(page_widget), "text-selected",
G_CALLBACK(cb_page_widget_text_selected), zathura);
g_signal_connect(G_OBJECT(page_widget), "image-selected",
G_CALLBACK(cb_page_widget_text_selected), zathura);
}
2011-03-18 18:40:20 +01:00
/* view mode */
unsigned int pages_per_row = 1;
unsigned int first_page_column = 1;
unsigned int page_padding = 1;
girara_setting_get(zathura->ui.session, "page-padding", &page_padding);
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);
}
2012-04-29 06:26:38 +02:00
if (file_info.first_page_column > 0) {
first_page_column = file_info.first_page_column;
} else {
girara_setting_get(zathura->ui.session, "first-page-column", &first_page_column);
}
2012-04-29 06:26:38 +02:00
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, page_padding, pages_per_row, first_page_column);
zathura_document_set_page_layout(zathura->document, page_padding, pages_per_row, first_page_column);
2010-12-28 09:47:09 +01:00
2012-02-07 18:30:46 +01:00
girara_set_view(zathura->ui.session, zathura->ui.page_widget_alignment);
2010-12-28 09:47:09 +01:00
for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
gtk_widget_realize(zathura->pages[page_id]);
2010-12-29 11:46:13 +01:00
}
2010-12-12 22:04:42 +01:00
2011-09-03 14:21:36 +02:00
/* bookmarks */
zathura_bookmarks_load(zathura, file_path);
2011-09-03 14:21:36 +02:00
/* jumplist */
if (zathura_jumplist_load(zathura, file_path) == false) {
zathura->jumplist.list = girara_list_new2(g_free);
}
2012-03-16 07:58:55 +01:00
/* update title */
basename_only = false;
girara_setting_get(zathura->ui.session, "window-title-basename", &basename_only);
if (basename_only == false) {
girara_set_window_title(zathura->ui.session, file_path);
} else {
girara_set_window_title(zathura->ui.session, zathura_document_get_basename(document));
}
2012-03-16 07:58:55 +01:00
g_free(file_uri);
2012-02-20 20:07:24 +01:00
/* adjust_view and set position*/
adjust_view(zathura);
/* set position */
page_set(zathura, zathura_document_get_current_page_number(document));
if (file_info.position_x != 0 || file_info.position_y != 0) {
position_set(zathura, file_info.position_x, file_info.position_y);
}
2010-12-12 22:04:42 +01:00
return true;
2010-12-29 11:46:13 +01:00
error_free:
2012-02-20 20:07:24 +01:00
if (file_uri != NULL) {
g_free(file_uri);
}
2010-12-29 11:46:13 +01:00
zathura_document_free(document);
error_out:
return false;
2010-12-12 22:04:42 +01:00
}
2012-08-05 15:34:10 +02:00
void
document_open_idle(zathura_t* zathura, const char* path, const char* password,
int page_number)
2012-08-05 15:34:10 +02:00
{
if (zathura == NULL || path == NULL) {
return;
}
zathura_document_info_t* document_info = g_malloc0(sizeof(zathura_document_info_t));
document_info->zathura = zathura;
document_info->path = path;
document_info->password = password;
document_info->page_number = page_number;
2012-08-05 15:34:10 +02:00
gdk_threads_add_idle(document_info_open, document_info);
}
2011-09-01 11:51:49 +02:00
bool
document_save(zathura_t* zathura, const char* path, bool overwrite)
{
g_return_val_if_fail(zathura, false);
g_return_val_if_fail(zathura->document, false);
g_return_val_if_fail(path, false);
gchar* file_path = girara_fix_path(path);
/* use current basename if path points to a directory */
if (g_file_test(file_path, G_FILE_TEST_IS_DIR) == TRUE) {
char* basename = g_path_get_basename(zathura_document_get_path(zathura->document));
char* tmp = file_path;
file_path = g_strconcat(file_path, "/", basename, NULL);
g_free(tmp);
g_free(basename);
}
2012-10-09 01:12:18 +02:00
if ((overwrite == false) && g_file_test(file_path, G_FILE_TEST_EXISTS)) {
girara_error("File already exists: %s. Use :write! to overwrite it.", file_path);
2011-10-21 15:00:22 +02:00
g_free(file_path);
2011-09-01 11:51:49 +02:00
return false;
}
2012-03-27 13:30:04 +02:00
zathura_error_t error = zathura_document_save_as(zathura->document, file_path);
2011-09-01 11:51:49 +02:00
g_free(file_path);
2012-03-27 13:30:04 +02:00
return (error == ZATHURA_ERROR_OK) ? true : false;
2011-09-01 11:51:49 +02:00
}
static void
remove_page_from_table(GtkWidget* page, gpointer permanent)
{
2012-02-12 16:35:33 +01:00
if (permanent == false) {
g_object_ref(G_OBJECT(page));
}
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(page)), page);
}
2010-12-12 22:04:42 +01:00
bool
2012-02-20 20:07:24 +01:00
document_close(zathura_t* zathura, bool keep_monitor)
2010-12-12 22:04:42 +01:00
{
2012-02-20 20:07:24 +01:00
if (zathura == NULL || zathura->document == NULL) {
2010-12-12 22:04:42 +01:00
return false;
}
/* stop rendering */
zathura_renderer_stop(zathura->sync.render_thread);
2012-02-20 20:07:24 +01:00
/* remove monitor */
if (keep_monitor == false) {
if (zathura->file_monitor.monitor != NULL) {
g_file_monitor_cancel(zathura->file_monitor.monitor);
g_object_unref(zathura->file_monitor.monitor);
zathura->file_monitor.monitor = NULL;
}
if (zathura->file_monitor.file != NULL) {
g_object_unref(zathura->file_monitor.file);
zathura->file_monitor.file = NULL;
}
if (zathura->file_monitor.file_path != NULL) {
g_free(zathura->file_monitor.file_path);
zathura->file_monitor.file_path = NULL;
}
if (zathura->file_monitor.password != NULL) {
g_free(zathura->file_monitor.password);
zathura->file_monitor.password = NULL;
}
}
2012-04-21 04:59:58 +02:00
/* remove marks */
if (zathura->global.marks != NULL) {
girara_list_free(zathura->global.marks);
zathura->global.marks = NULL;
}
/* store file information */
const char* path = zathura_document_get_path(zathura->document);
zathura_fileinfo_t file_info = { 0, 0, 1, 0, 1, 1, 0, 0 };
file_info.current_page = zathura_document_get_current_page_number(zathura->document);
file_info.page_offset = zathura_document_get_page_offset(zathura->document);
file_info.scale = zathura_document_get_scale(zathura->document);
file_info.rotation = zathura_document_get_rotation(zathura->document);
girara_setting_get(zathura->ui.session, "pages-per-row", &(file_info.pages_per_row));
girara_setting_get(zathura->ui.session, "first-page-column", &(file_info.first_page_column));
/* get position */
file_info.position_x = zathura_document_get_position_x(zathura->document);
file_info.position_y = zathura_document_get_position_y(zathura->document);
/* save file info */
zathura_db_set_fileinfo(zathura->database, path, &file_info);
2011-10-06 17:57:26 +02:00
/* 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 */
g_object_unref(zathura->sync.render_thread);
zathura->sync.render_thread = NULL;
/* remove widgets */
gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), remove_page_from_table, (gpointer) 1);
2012-05-08 17:10:57 +02:00
for (unsigned int i = 0; i < zathura_document_get_number_of_pages(zathura->document); i++) {
g_object_unref(zathura->pages[i]);
2013-04-17 13:42:03 +02:00
g_object_unref(zathura->pages[i]); // FIXME
2012-05-08 17:10:57 +02:00
}
free(zathura->pages);
zathura->pages = NULL;
2011-01-24 12:43:39 +01:00
/* remove document */
2011-04-18 17:27:49 +02:00
zathura_document_free(zathura->document);
zathura->document = NULL;
2012-04-16 09:17:25 +02:00
/* remove index */
if (zathura->ui.index != NULL) {
g_object_ref_sink(zathura->ui.index);
zathura->ui.index = NULL;
}
2012-02-07 18:30:46 +01:00
gtk_widget_hide(zathura->ui.page_widget);
statusbar_page_number_update(zathura);
if (zathura->ui.session != NULL && zathura->ui.statusbar.file != NULL) {
2012-03-16 13:42:15 +01:00
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));
}
2010-12-12 22:04:42 +01:00
2012-03-16 07:58:55 +01:00
/* update title */
girara_set_window_title(zathura->ui.session, "zathura");
2010-12-12 22:04:42 +01:00
return true;
}
static gboolean
2011-12-11 19:30:36 +01:00
page_set_delayed_impl(gpointer data)
{
page_set_delayed_t* p = data;
page_set(p->zathura, p->page);
g_free(p);
return FALSE;
}
bool
page_set_delayed(zathura_t* zathura, unsigned int page_id)
{
if (zathura == NULL || zathura->document == NULL ||
(page_id >= zathura_document_get_number_of_pages(zathura->document))) {
return false;
}
page_set_delayed_t* p = g_malloc(sizeof(page_set_delayed_t));
p->zathura = zathura;
p->page = page_id;
gdk_threads_add_idle(page_set_delayed_impl, p);
return true;
}
2010-12-12 22:04:42 +01:00
bool
2011-04-18 17:27:49 +02:00
page_set(zathura_t* zathura, unsigned int page_id)
2010-12-12 22:04:42 +01:00
{
if (zathura == NULL || zathura->document == NULL) {
2010-12-26 01:52:17 +01:00
goto error_out;
2010-12-12 22:04:42 +01:00
}
zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
2012-02-12 16:35:33 +01:00
if (page == NULL) {
goto error_out;
}
zathura_document_set_current_page_number(zathura->document, page_id);
/* negative position means auto */
return position_set(zathura, -1, -1);
2010-12-26 01:52:17 +01:00
error_out:
return false;
2010-12-12 22:04:42 +01:00
}
void
statusbar_page_number_update(zathura_t* zathura)
{
if (zathura == NULL || zathura->ui.statusbar.page_number == NULL) {
return;
}
unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
unsigned int current_page_number = zathura_document_get_current_page_number(zathura->document);
if (zathura->document != NULL) {
char* page_number_text = g_strdup_printf("[%d/%d]", current_page_number + 1, number_of_pages);
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.page_number, page_number_text);
bool page_number_in_window_title = false;
girara_setting_get(zathura->ui.session, "window-title-page", &page_number_in_window_title);
if (page_number_in_window_title == true) {
bool basename_only = false;
girara_setting_get(zathura->ui.session, "window-title-basename", &basename_only);
char* title = g_strdup_printf("%s %s",
(basename_only == true)
? zathura_document_get_basename(zathura->document)
: zathura_document_get_path(zathura->document),
page_number_text);
girara_set_window_title(zathura->ui.session, title);
g_free(title);
}
g_free(page_number_text);
} else {
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.page_number, "");
}
}
2011-03-18 18:40:20 +01:00
void
page_widget_set_mode(zathura_t* zathura, unsigned int page_padding,
unsigned int pages_per_row, unsigned int first_page_column)
2011-03-18 18:40:20 +01:00
{
2011-04-25 16:54:21 +02:00
/* show at least one page */
if (pages_per_row == 0) {
pages_per_row = 1;
}
2012-10-09 01:12:18 +02:00
/* 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;
}
2012-02-07 18:30:46 +01:00
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);
2012-08-05 02:30:03 +02:00
#if (GTK_MAJOR_VERSION == 3)
gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding);
gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding);
2012-08-05 02:30:03 +02:00
#else
gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding);
gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding);
unsigned int ncol = pages_per_row;
unsigned int nrow = (number_of_pages + first_page_column - 1 + ncol - 1) / ncol;
gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), nrow, ncol);
2012-08-05 02:30:03 +02:00
#endif
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;
2012-03-26 14:44:56 +02:00
zathura_page_t* page = zathura_document_get_page(zathura->document, i);
GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
2012-08-05 02:30:03 +02:00
#if (GTK_MAJOR_VERSION == 3)
gtk_grid_attach(GTK_GRID(zathura->ui.page_widget), page_widget, x, y, 1, 1);
#else
2012-03-26 14:44:56 +02:00
gtk_table_attach(GTK_TABLE(zathura->ui.page_widget), page_widget, x, x + 1, y, y + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
2012-08-05 02:30:03 +02:00
#endif
2011-03-18 18:40:20 +01:00
}
2012-02-07 18:30:46 +01:00
gtk_widget_show_all(zathura->ui.page_widget);
2011-03-18 18:40:20 +01:00
}
static gboolean
2012-04-21 04:59:58 +02:00
position_set_delayed_impl(gpointer data)
{
position_set_delayed_t* p = (position_set_delayed_t*) data;
GtkScrolledWindow *window = GTK_SCROLLED_WINDOW(p->zathura->ui.session->gtk.view);
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(window);
GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(window);
/* negative values mean: don't set the position */
if (p->position_x >= 0) {
zathura_adjustment_set_value(hadjustment, p->position_x);
}
if (p->position_y >= 0) {
zathura_adjustment_set_value(vadjustment, p->position_y);
}
2012-05-08 17:02:18 +02:00
g_free(p);
return FALSE;
}
2012-04-21 04:59:58 +02:00
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
void
2012-04-21 04:59:58 +02:00
position_set_delayed(zathura_t* zathura, double position_x, double position_y)
{
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
g_return_if_fail(zathura != NULL);
2012-04-21 04:59:58 +02:00
position_set_delayed_t* p = g_malloc0(sizeof(position_set_delayed_t));
p->zathura = zathura;
p->position_x = position_x;
p->position_y = position_y;
gdk_threads_add_idle(position_set_delayed_impl, p);
}
bool
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
position_set(zathura_t* zathura, double position_x, double position_y)
{
if (zathura == NULL || zathura->document == NULL) {
goto error_out;
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
double comppos_x, comppos_y;
unsigned int page_id = zathura_document_get_current_page_number(zathura->document);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
/* xalign = 0.5: center horizontally (with the page, not the document) */
/* yalign = 0.0: align page an viewport edges at the top */
page_number_to_position(zathura->document, page_id, 0.5, 0.0, &comppos_x, &comppos_y);
/* automatic horizontal adjustment */
zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document);
/* negative position_x mean: use the computed value */
if (position_x < 0) {
position_x = comppos_x;
bool zoom_center = false;
girara_setting_get(zathura->ui.session, "zoom-center", &zoom_center);
/* center horizontally */
if (adjust_mode == ZATHURA_ADJUST_BESTFIT ||
adjust_mode == ZATHURA_ADJUST_WIDTH ||
zoom_center) {
position_x = 0.5;
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
}
if (position_y < 0) {
position_y = comppos_y;
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
}
/* set the position */
zathura_document_set_position_x(zathura->document, position_x);
zathura_document_set_position_y(zathura->document, position_y);
/* prevent cb_view_adjustment_value_changed from updating document page number and
position from the adjustments. */
zathura->global.update_page_number = false;
/* trigger a 'change' event for both adjustments */
refresh_view(zathura);
return true;
error_out:
return false;
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
}
void
refresh_view(zathura_t* zathura) {
g_return_if_fail(zathura != NULL);
/* emit a custom refresh-view signal */
g_signal_emit(zathura->ui.session->gtk.view, zathura->signals.refresh_view,
0, zathura);
}
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
static void
zathura_jumplist_hide_inputbar(zathura_t* zathura)
{
g_return_if_fail(zathura != NULL && zathura->ui.session->gtk.inputbar != NULL);
girara_argument_t arg = { GIRARA_HIDE, NULL };
girara_isc_completion(zathura->ui.session, &arg, NULL, 0);
if (zathura->ui.session->global.autohide_inputbar == true) {
/* XXX: This is a workaround for incremental-search. We should revisit this
* when we drop GTK+3 support and the inputbar is placed in a GtkOverlay
* widget. */
char *input = gtk_editable_get_chars(GTK_EDITABLE(zathura->ui.session->gtk.inputbar_entry), 0, -1);
bool res = false;
girara_setting_get(zathura->ui.session, "incremental-search", &res);
if ((*input == '/' || *input == '?') && res == true) {
g_free(input);
return;
}
/* </workaround> */
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
gtk_widget_hide(zathura->ui.session->gtk.inputbar);
}
/* we want to do it immediately */
/* XXX: ... and we want this to go away */
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
while (gtk_events_pending()) {
gtk_main_iteration();
}
}
bool
adjust_view(zathura_t* zathura) {
g_return_val_if_fail(zathura != NULL, false);
if (zathura->ui.page_widget == NULL || zathura->document == NULL) {
goto error_ret;
}
zathura_adjust_mode_t adjust_mode = zathura_document_get_adjust_mode(zathura->document);
if (adjust_mode == ZATHURA_ADJUST_NONE) {
/* there is nothing todo */
goto error_ret;
}
unsigned int cell_height = 0, cell_width = 0;
unsigned int document_height = 0, document_width = 0;
unsigned int view_height = 0, view_width = 0;
zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width);
zathura_document_get_document_size(zathura->document, &document_height, &document_width);
zathura_document_get_viewport_size(zathura->document, &view_height, &view_width);
double scale = zathura_document_get_scale(zathura->document);
if (view_height == 0 || view_width == 0 || cell_height == 0 || cell_width == 0) {
goto error_ret;
}
double page_ratio = (double)cell_height / (double)document_width;
double view_ratio = (double)view_height / (double)view_width;
double newscale = scale;
if (adjust_mode == ZATHURA_ADJUST_WIDTH ||
(adjust_mode == ZATHURA_ADJUST_BESTFIT && page_ratio < view_ratio)) {
newscale = scale * (double)view_width / (double)document_width;
} else if (adjust_mode == ZATHURA_ADJUST_BESTFIT) {
newscale = scale * (double)view_height / (double)cell_height;
} else {
goto error_ret;
}
/* save new scale and recompute cell size */
zathura_document_set_scale(zathura->document, newscale);
unsigned int new_cell_height = 0, new_cell_width = 0;
zathura_document_get_cell_size(zathura->document, &new_cell_height, &new_cell_width);
/* if the change in scale changes page cell dimensions by at least one pixel, render */
if (abs(new_cell_width - cell_width) > 1 ||
abs(new_cell_height - cell_height) > 1) {
render_all(zathura);
refresh_view(zathura);
/* otherwise set the old scale and leave */
} else {
zathura_document_set_scale(zathura->document, scale);
}
error_ret:
return false;
}
bool
zathura_jumplist_has_previous(zathura_t* zathura)
{
return girara_list_iterator_has_previous(zathura->jumplist.cur);
}
bool
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
zathura_jumplist_has_next(zathura_t* zathura)
{
return girara_list_iterator_has_next(zathura->jumplist.cur);
}
zathura_jump_t*
2012-10-09 01:12:18 +02:00
zathura_jumplist_current(zathura_t* zathura)
{
if (zathura->jumplist.cur != NULL) {
return girara_list_iterator_data(zathura->jumplist.cur);
} else {
return NULL;
}
}
void
2012-10-09 01:12:18 +02:00
zathura_jumplist_forward(zathura_t* zathura)
{
if (girara_list_iterator_has_next(zathura->jumplist.cur)) {
girara_list_iterator_next(zathura->jumplist.cur);
}
}
void
2012-10-09 01:12:18 +02:00
zathura_jumplist_backward(zathura_t* zathura)
{
if (girara_list_iterator_has_previous(zathura->jumplist.cur)) {
girara_list_iterator_previous(zathura->jumplist.cur);
}
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
static void
zathura_jumplist_reset_current(zathura_t* zathura)
{
g_return_if_fail(zathura != NULL && zathura->jumplist.cur != NULL);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
while (true) {
if (girara_list_iterator_has_next(zathura->jumplist.cur) == false) {
return;
}
girara_list_iterator_next(zathura->jumplist.cur);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
}
}
static void
2012-10-09 01:12:18 +02:00
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));
jump->page = 0;
jump->x = 0.0;
jump->y = 0.0;
girara_list_append(zathura->jumplist.list, jump);
if (zathura->jumplist.size == 0) {
zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list);
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
++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;
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
}
girara_list_iterator_remove(cur);
--zathura->jumplist.size;
}
if (zathura->jumplist.size == 0 || (zathura->jumplist.size != 0 && zathura->jumplist.cur != NULL)) {
girara_list_iterator_free(cur);
} else {
zathura->jumplist.cur = cur;
}
}
void
2012-10-09 01:12:18 +02:00
zathura_jumplist_add(zathura_t* zathura)
{
g_return_if_fail(zathura != NULL && zathura->document != NULL && zathura->jumplist.list != NULL);
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
zathura_jumplist_hide_inputbar(zathura);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
unsigned int pagenum = zathura_document_get_current_page_number(zathura->document);
double x = zathura_document_get_position_x(zathura->document);
double y = zathura_document_get_position_y(zathura->document);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
if (zathura->jumplist.size != 0) {
zathura_jumplist_reset_current(zathura);
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
zathura_jump_t* cur = zathura_jumplist_current(zathura);
if (cur != NULL) {
if (cur->page == pagenum && cur->x == x && cur->y == y) {
return;
}
}
}
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
zathura_jumplist_append_jump(zathura);
zathura_jumplist_reset_current(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;
}
Enhancements/Cleanups for the jumplist mechansim - Don't delete the elements on the right of the current one, when appending a new jump to the jumplist, because this makes no sense at all; the point of the jumplist in the first place is to remember previously jumped-to positions in the document, so there is no need to delete anythings except to trim the oldest entries from the beginning to maintain the maximum size. This also makes us compatible with the Vim way of doing things. - Make the jumplist mechanism functional on the same page; if we followed a link to a target on the same page, remember the adjustments before and after following the link. The same holds for navigating search results on the same page. - Implement position_set and use it instead of position_set_delayed when following links in order to give zathura_jumplist_save a chance to record the exact adjustments of the link target. Otherwise, it will always record the adjustments after going to the target page, but before going to the exact position within it. - Don't consider movements with ^i and ^o as jumps :) - Don't use page_set followed by setting the adjustments in sc_jumplist, because this is redundant and causes clutter when using ^i and ^o, as the adjustments is set twice this way (once in page_set and again in position_set_delayed). It's enough to only update the page number on the statusbar and then set the adjustments. - Hide implementation details (zathura_jumplist_save and zathura_jumplist_append), and make things more consistent by exporting and using only zathura_jumplist_add for adding new entries. The end result: A more slick jumping experience :-) Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-09 05:53:31 +02:00
static void
2012-10-09 01:12:18 +02:00
zathura_jumplist_save(zathura_t* zathura)
{
g_return_if_fail(zathura != NULL && zathura->document != NULL);
Hide the inputbar and completion menu before saving the adjustments ratios into a new jump structure Since we are now saving the adjustments ratios in the jump structures, we need to take care of the following scenario: - We do an action that results in a new jump structure being added to the jumplist while the inputbar is visible (e.g., search, jumping to a specific page, jumping to a bookmark, or following a link). - Since we are now storing the adjustments ratios in the jump structures, all of the above actions would result in the vertical adjustment ratio being saved while the inputbar and/or the completion menu is visible. - Now we are exactly on the target of the jump (note that the inputbar and completion menu now are hidden), so suppose that we want to go back using ^o (assuming that we didn't change the adjustments after jumping), then the check at sc_jumplist that compares the current adjustments ratios with that of the current jump (the jump that has just been added and which we are currently on it's position) would fail, because after the inputbar (with possibly the completion menu in case of bookmarks) is activated it is hidden, which results in the vertical adjustment upper bound to change, which in turn results in the vertical adjustment ratio returned by zathura_adjustment_get_ratio to become different from what is stored in the current jump structure, even though we haven't changed the adjustments at all after the jump. This would always result in taking us back to the exact position of the jump (which would be slightly different from the current position) when we press ^o. This can be annoying, because it would happen, for example, every time we need to go back quickly after jumping to a link target, a search result, or a bookmark. So, what this patch does is essentially to make the vertical adjustment ratio reflecting the current vertical adjustment after a jump, to always be the same as the one stored in the newly added jump structure, since both are calculated with zathura_adjustment_get_ratio while the inputbar is _not_ visible, so they should be the same. I've elaborated just to make things clear, in case the purpose of the patch isn't obvious. Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
2013-06-21 14:25:29 +02:00
zathura_jump_t* cur = zathura_jumplist_current(zathura);
unsigned int pagenum = zathura_document_get_current_page_number(zathura->document);
if (cur) {
cur->page = pagenum;
cur->x = zathura_document_get_position_x(zathura->document);
cur->y = zathura_document_get_position_y(zathura->document);
}
}