Commit 2f53f09e authored by Sebastian Ramacher's avatar Sebastian Ramacher
Browse files

Merge branch 'develop' of pwmt.org:zathura into develop

parents 0b966dbe 3d96d440
...@@ -4,8 +4,8 @@ include config.mk ...@@ -4,8 +4,8 @@ include config.mk
include colors.mk include colors.mk
include common.mk include common.mk
OSOURCE = $(filter-out css-definitions.c, $(filter-out dbus-interface-definitions.c, $(wildcard *.c))) OSOURCE = $(filter-out css-definitions.c, $(filter-out dbus-interface-definitions.c, $(wildcard *.c))) $(wildcard synctex/*.c)
HEADER = $(wildcard *.h) HEADER = $(wildcard *.h) $(wildcard synctex/*.h)
HEADERINST = version.h document.h macros.h page.h types.h plugin-api.h links.h HEADERINST = version.h document.h macros.h page.h types.h plugin-api.h links.h
ifneq (${WITH_SQLITE},0) ifneq (${WITH_SQLITE},0)
...@@ -36,6 +36,13 @@ endif ...@@ -36,6 +36,13 @@ endif
ifeq (,$(findstring -DLOCALEDIR,${CPPFLAGS})) ifeq (,$(findstring -DLOCALEDIR,${CPPFLAGS}))
CPPFLAGS += -DLOCALEDIR=\"${LOCALEDIR}\" CPPFLAGS += -DLOCALEDIR=\"${LOCALEDIR}\"
endif endif
ifeq (,$(findstring -Isynctex,${CPPFLAGS}))
CPPFLAGS += -Isynctex
endif
ifeq (,$(findstring -DSYNCTEX_VERBOSE=0,${CPPFLAGS}))
CPPFLAGS += -DSYNCTEX_VERBOSE=0
endif
OBJECTS = $(patsubst %.c, %.o, $(SOURCE)) dbus-interface-definitions.o css-definitions.o OBJECTS = $(patsubst %.c, %.o, $(SOURCE)) dbus-interface-definitions.o css-definitions.o
DOBJECTS = $(patsubst %.o, %.do, $(OBJECTS)) DOBJECTS = $(patsubst %.o, %.do, $(OBJECTS))
...@@ -83,7 +90,7 @@ css-definitions.c: data/zathura.css_t ...@@ -83,7 +90,7 @@ css-definitions.c: data/zathura.css_t
%.o: %.c %.o: %.c
$(call colorecho,CC,$<) $(call colorecho,CC,$<)
$(QUIET) mkdir -p .depend $(QUIET) mkdir -p $(shell dirname .depend/$@.dep)
$(QUIET)${CC} -c ${CPPFLAGS} ${CFLAGS} -o $@ $< -MMD -MF .depend/$@.dep $(QUIET)${CC} -c ${CPPFLAGS} ${CFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
%.do: %.c %.do: %.c
......
...@@ -63,9 +63,17 @@ position_to_page_number(zathura_document_t* document, double pos_x, ...@@ -63,9 +63,17 @@ position_to_page_number(zathura_document_t* document, double pos_x,
unsigned int c0 = zathura_document_get_first_page_column(document); unsigned int c0 = zathura_document_get_first_page_column(document);
unsigned int npag = zathura_document_get_number_of_pages(document); unsigned int npag = zathura_document_get_number_of_pages(document);
unsigned int ncol = zathura_document_get_pages_per_row(document); unsigned int ncol = zathura_document_get_pages_per_row(document);
unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol; /* number of rows */ unsigned int nrow = 0;
unsigned int pad = zathura_document_get_page_padding(document); unsigned int pad = zathura_document_get_page_padding(document);
if (c0 == 1) {
/* There is no offset, so this is easy. */
nrow = (npag + ncol - 1) / ncol;
} else {
/* If there is a offset, we handle the first row extra. */
nrow = 1 + (npag - (ncol - c0 - 1) + (ncol - 1)) / ncol;
}
unsigned int col = floor(pos_x * (double)doc_width / (double)(cell_width + pad)); unsigned int col = floor(pos_x * (double)doc_width / (double)(cell_width + pad));
unsigned int row = floor(pos_y * (double)doc_height / (double)(cell_height + pad)); unsigned int row = floor(pos_y * (double)doc_height / (double)(cell_height + pad));
...@@ -73,7 +81,7 @@ position_to_page_number(zathura_document_t* document, double pos_x, ...@@ -73,7 +81,7 @@ position_to_page_number(zathura_document_t* document, double pos_x,
if (page < c0 - 1) { if (page < c0 - 1) {
return 0; return 0;
} else { } else {
return page - (c0 - 1); return MIN(page - (c0 - 1), npag - 1);
} }
} }
......
...@@ -137,60 +137,54 @@ cb_view_vadjustment_value_changed(GtkAdjustment* adjustment, gpointer data) ...@@ -137,60 +137,54 @@ cb_view_vadjustment_value_changed(GtkAdjustment* adjustment, gpointer data)
statusbar_page_number_update(zathura); statusbar_page_number_update(zathura);
} }
void static void
cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data) cb_view_adjustment_changed(GtkAdjustment* adjustment, zathura_t* zathura,
bool width)
{ {
zathura_t* zathura = data;
g_return_if_fail(zathura != NULL);
zathura_adjust_mode_t adjust_mode =
zathura_document_get_adjust_mode(zathura->document);
/* Do nothing in index mode */ /* Do nothing in index mode */
if (girara_mode_get(zathura->ui.session) == zathura->modes.index) { if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
return; return;
} }
/* Don't scroll we're focusing the inputbar. */ const zathura_adjust_mode_t adjust_mode =
zathura_document_get_adjust_mode(zathura->document);
/* Don't scroll, we're focusing the inputbar. */
if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) { if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
return; return;
} }
/* save the viewport size */ /* Save the viewport size */
unsigned int view_width = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment)); unsigned int size = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment));
zathura_document_set_viewport_width(zathura->document, view_width); if (width == true) {
zathura_document_set_viewport_width(zathura->document, size);
} else {
zathura_document_set_viewport_height(zathura->document, size);
}
/* reset the adjustment, in case bounds have changed */ /* reset the adjustment, in case bounds have changed */
double ratio = zathura_document_get_position_x(zathura->document); const double ratio = width == true ?
zathura_document_get_position_x(zathura->document) :
zathura_document_get_position_x(zathura->document);
zathura_adjustment_set_value_from_ratio(adjustment, ratio); zathura_adjustment_set_value_from_ratio(adjustment, ratio);
} }
void void
cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data) cb_view_hadjustment_changed(GtkAdjustment* adjustment, gpointer data)
{ {
zathura_t* zathura = data; zathura_t* zathura = data;
g_return_if_fail(zathura != NULL); g_return_if_fail(zathura != NULL);
zathura_adjust_mode_t adjust_mode = cb_view_adjustment_changed(adjustment, zathura, true);
zathura_document_get_adjust_mode(zathura->document); }
/* Do nothing in index mode */
if (girara_mode_get(zathura->ui.session) == zathura->modes.index) {
return;
}
/* Don't scroll we're focusing the inputbar. */
if (adjust_mode == ZATHURA_ADJUST_INPUTBAR) {
return;
}
/* save the viewport size */ void
unsigned int view_height = (unsigned int)floor(gtk_adjustment_get_page_size(adjustment)); cb_view_vadjustment_changed(GtkAdjustment* adjustment, gpointer data)
zathura_document_set_viewport_height(zathura->document, view_height); {
zathura_t* zathura = data;
g_return_if_fail(zathura != NULL);
/* reset the adjustment, in case bounds have changed */ cb_view_adjustment_changed(adjustment, zathura, false);
double ratio = zathura_document_get_position_y(zathura->document);
zathura_adjustment_set_value_from_ratio(adjustment, ratio);
} }
void void
...@@ -233,7 +227,7 @@ cb_page_layout_value_changed(girara_session_t* session, const char* name, girara ...@@ -233,7 +227,7 @@ cb_page_layout_value_changed(girara_session_t* session, const char* name, girara
if (pages_per_row == 0) { if (pages_per_row == 0) {
pages_per_row = 1; pages_per_row = 1;
girara_setting_set(session, name, &pages_per_row); girara_setting_set(session, name, &pages_per_row);
girara_notify(session, GIRARA_WARNING, _("'%s' must not be 0. Set to 1.."), name); girara_notify(session, GIRARA_WARNING, _("'%s' must not be 0. Set to 1."), name);
return; return;
} }
} }
......
...@@ -77,8 +77,11 @@ MAGIC_INC ?= ...@@ -77,8 +77,11 @@ MAGIC_INC ?=
MAGIC_LIB ?= -lmagic MAGIC_LIB ?= -lmagic
endif endif
INCS = ${GIRARA_INC} ${GTK_INC} ${GTHREAD_INC} ${GMODULE_INC} ${GLIB_INC} ZLIB_INC ?= $(shell pkg-config --cflags zlib)
LIBS = ${GIRARA_LIB} ${GTK_LIB} ${GTHREAD_LIB} ${GMODULE_LIB} ${GLIB_LIB} -lpthread -lm ZLIB_LIB ?= $(shell pkg-config --libs zlib)
INCS = ${GIRARA_INC} ${GTK_INC} ${GTHREAD_INC} ${GMODULE_INC} ${GLIB_INC} $(ZLIB_INC)
LIBS = ${GIRARA_LIB} ${GTK_LIB} ${GTHREAD_LIB} ${GMODULE_LIB} ${GLIB_LIB} $(ZLIB_LIB) -lpthread -lm
# flags # flags
CFLAGS += -std=c99 -pedantic -Wall -Wno-format-zero-length -Wextra $(INCS) CFLAGS += -std=c99 -pedantic -Wall -Wno-format-zero-length -Wextra $(INCS)
......
...@@ -545,17 +545,17 @@ zathura_dbus_goto_page_and_highlight(const char* filename, unsigned int page, ...@@ -545,17 +545,17 @@ zathura_dbus_goto_page_and_highlight(const char* filename, unsigned int page,
} }
bool bool
zathura_dbus_synctex_position(const char* filename, const char* position, zathura_dbus_synctex_position(const char* filename, const char* input_file,
pid_t hint) int line, int column, pid_t hint)
{ {
if (filename == NULL || position == NULL) { if (filename == NULL || input_file == NULL) {
return false; return false;
} }
unsigned int page = 0; unsigned int page = 0;
girara_list_t* secondary_rects = NULL; girara_list_t* secondary_rects = NULL;
girara_list_t* rectangles = synctex_rectangles_from_position( girara_list_t* rectangles = synctex_rectangles_from_position(
filename, position, &page, &secondary_rects); filename, input_file, line, column, &page, &secondary_rects);
if (rectangles == NULL) { if (rectangles == NULL) {
return false; return false;
} }
......
...@@ -57,7 +57,7 @@ bool zathura_dbus_goto_page_and_highlight(const char* filename, ...@@ -57,7 +57,7 @@ bool zathura_dbus_goto_page_and_highlight(const char* filename,
unsigned int page, girara_list_t* rectangles, girara_list_t* secondary_rects, unsigned int page, girara_list_t* rectangles, girara_list_t* secondary_rects,
pid_t pidhint); pid_t pidhint);
bool zathura_dbus_synctex_position(const char* filename, const char* position, bool zathura_dbus_synctex_position(const char* filename, const char* input_file,
pid_t pidhint); int line, int column, pid_t hint);
#endif #endif
...@@ -106,11 +106,25 @@ main(int argc, char* argv[]) ...@@ -106,11 +106,25 @@ main(int argc, char* argv[])
return -1; return -1;
} }
if (zathura_dbus_synctex_position(real_path, synctex_fwd, synctex_pid) == true) { char** split_fwd = g_strsplit(synctex_fwd, ":", 0);
if (split_fwd == NULL || split_fwd[0] == NULL || split_fwd[1] == NULL ||
split_fwd[2] == NULL || split_fwd[3] != NULL) {
girara_error("Failed to parse argument to --synctex-forward.");
free(real_path);
g_strfreev(split_fwd);
return -1;
}
const int line = MIN(INT_MAX, g_ascii_strtoll(split_fwd[0], NULL, 10));
const int column = MIN(INT_MAX, g_ascii_strtoll(split_fwd[1], NULL, 10));
const bool ret = zathura_dbus_synctex_position(real_path, split_fwd[2], line, column, synctex_pid);
g_strfreev(split_fwd);
if (ret == true) {
free(real_path); free(real_path);
return 0; return 0;
} else { } else {
girara_error("Could not find open instance for '%s' or got no usable output from 'synctex view'.", real_path); girara_error("Could not find open instance for '%s' or got no usable data from synctex.", real_path);
free(real_path); free(real_path);
return -1; return -1;
} }
......
...@@ -8,49 +8,12 @@ ...@@ -8,49 +8,12 @@
#include "page.h" #include "page.h"
#include "document.h" #include "document.h"
#include "utils.h" #include "utils.h"
#include "synctex/synctex_parser.h"
enum {
SYNCTEX_RESULT_BEGIN = 1,
SYNCTEX_RESULT_END,
SYNCTEX_PROP_PAGE,
SYNCTEX_PROP_H,
SYNCTEX_PROP_V,
SYNCTEX_PROP_WIDTH,
SYNCTEX_PROP_HEIGHT,
};
typedef struct token_s {
const char* name;
guint token;
} token_t;
static token_t scanner_tokens[] = {
{"SyncTeX result begin", SYNCTEX_RESULT_BEGIN},
{"SyncTeX result end", SYNCTEX_RESULT_END},
{"Page:", SYNCTEX_PROP_PAGE},
{"h:", SYNCTEX_PROP_H},
{"v:", SYNCTEX_PROP_V},
{"W:", SYNCTEX_PROP_WIDTH},
{"H:", SYNCTEX_PROP_HEIGHT},
{NULL, 0}
};
static GScannerConfig scanner_config = {
.cset_skip_characters = "\n\r",
.cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z,
.cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z ": ",
.cpair_comment_single = NULL,
.case_sensitive = TRUE,
.scan_identifier = TRUE,
.scan_symbols = TRUE,
.scan_float = TRUE,
.numbers_2_int = TRUE,
};
void void
synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
{ {
if (zathura == NULL || page == NULL) { if (zathura == NULL || page == NULL || zathura->synctex.editor == NULL) {
return; return;
} }
...@@ -64,212 +27,123 @@ synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) ...@@ -64,212 +27,123 @@ synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
return; return;
} }
char** argv = g_try_malloc0(sizeof(char*) * (zathura->synctex.editor != NULL ? synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1);
7 : 5)); if (scanner == NULL) {
if (argv == NULL) { girara_debug("Failed to create synctex scanner.");
return; return;
} }
argv[0] = g_strdup("synctex"); synctex_scanner_t temp = synctex_scanner_parse(scanner);
argv[1] = g_strdup("edit"); if (temp == NULL) {
argv[2] = g_strdup("-o"); girara_debug("Failed to parse synctex file.");
argv[3] = g_strdup_printf("%d:%d:%d:%s", zathura_page_get_index(page) + 1, x, synctex_scanner_free(scanner);
y, filename); return;
if (zathura->synctex.editor != NULL) {
argv[4] = g_strdup("-x");
argv[5] = g_strdup(zathura->synctex.editor);
} }
g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); if (synctex_edit_query(scanner, zathura_page_get_index(page) + 1, x, y) > 0) {
g_strfreev(argv); /* Assume that a backward search returns either at most one result. */
} synctex_node_t node = synctex_next_result(scanner);
if (node != NULL) {
const char* input_file = synctex_scanner_get_name(scanner, synctex_node_tag(node));
const int line = synctex_node_line(node);
const int column = synctex_node_column (node);
char* linestr = g_strdup_printf("%d", line);
char* columnstr = g_strdup_printf("%d", column);
gchar** argv = NULL;
gint argc = 0;
if (g_shell_parse_argv(zathura->synctex.editor, &argc, &argv, NULL) == TRUE) {
for (gint i = 0; i != argc; ++i) {
char* temp = girara_replace_substring(argv[i], "%{line}", linestr);
g_free(argv[i]);
argv[i] = temp;
temp = girara_replace_substring(argv[i], "%{column}", columnstr);
g_free(argv[i]);
argv[i] = temp;
temp = girara_replace_substring(argv[i], "%{input}", input_file);
g_free(argv[i]);
argv[i] = temp;
}
static double g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
scan_float(GScanner* scanner) g_strfreev(argv);
{ }
switch (g_scanner_get_next_token(scanner)) {
case G_TOKEN_FLOAT: g_free(linestr);
return g_scanner_cur_value(scanner).v_float; g_free(columnstr);
case G_TOKEN_INT: }
return g_scanner_cur_value(scanner).v_int;
default:
return 0.0;
} }
synctex_scanner_free(scanner);
} }
girara_list_t* girara_list_t*
synctex_rectangles_from_position(const char* filename, const char* position, synctex_rectangles_from_position(const char* filename, const char* input_file,
unsigned int* page, int line, int column, unsigned int* page,
girara_list_t** secondary_rects) girara_list_t** secondary_rects)
{ {
if (filename == NULL || position == NULL || page == NULL) { if (filename == NULL || input_file == NULL || page == NULL) {
return NULL; return NULL;
} }
char** argv = g_try_malloc0(sizeof(char*) * 7); synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1);
if (argv == NULL) { if (scanner == NULL) {
girara_debug("Failed to create synctex scanner.");
return NULL; return NULL;
} }
argv[0] = g_strdup("synctex"); synctex_scanner_t temp = synctex_scanner_parse(scanner);
argv[1] = g_strdup("view"); if (temp == NULL) {
argv[2] = g_strdup("-i"); girara_debug("Failed to parse synctex file.");
argv[3] = g_strdup(position); synctex_scanner_free(scanner);
argv[4] = g_strdup("-o"); return NULL;
argv[5] = g_strdup(filename);
gint output = -1;
bool ret = g_spawn_async_with_pipes(NULL, argv, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL,
&output, NULL, NULL);
g_strfreev(argv);
if (ret == false) {
return false;
}
GScanner* scanner = g_scanner_new(&scanner_config);
token_t* tokens = scanner_tokens;
while (tokens->name != NULL) {
g_scanner_add_symbol(scanner, tokens->name, GINT_TO_POINTER(tokens->token));
tokens++;
}
g_scanner_input_file(scanner, output);
bool found_begin = false, found_end = false;
while (found_begin == false && found_end == false) {
switch (g_scanner_get_next_token(scanner)) {
case G_TOKEN_EOF:
found_end = true;
break;
case G_TOKEN_SYMBOL:
switch (GPOINTER_TO_INT(g_scanner_cur_value(scanner).v_identifier)) {
case SYNCTEX_RESULT_BEGIN:
found_begin = true;
break;
}
break;
default:
/* skip everything else */
break;
}
} }
ret = false;
unsigned int rpage = 0;
unsigned int current_page = 0;
girara_list_t* hitlist = girara_list_new2(g_free); girara_list_t* hitlist = girara_list_new2(g_free);
girara_list_t* other_rects = girara_list_new2(g_free); girara_list_t* other_rects = girara_list_new2(g_free);
bool got_rect = false;
zathura_rectangle_t rectangle;
while (found_end == false) {
switch (g_scanner_get_next_token(scanner)) {
case G_TOKEN_EOF:
found_end = true;
break;
case G_TOKEN_SYMBOL:
switch (GPOINTER_TO_INT(g_scanner_cur_value(scanner).v_identifier)) {
case SYNCTEX_RESULT_END:
found_end = true;
break;
case SYNCTEX_PROP_PAGE:
if (g_scanner_get_next_token(scanner) == G_TOKEN_INT) {
current_page = g_scanner_cur_value(scanner).v_int - 1;
if (ret == false) {
ret = true;
rpage = current_page;
}
if (got_rect == false) {
continue;
}
got_rect = false;
if (*page == current_page) {
zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t));
if (real_rect == NULL) {
continue;
}
*real_rect = rectangle; if (synctex_display_query(scanner, input_file, line, column) > 0) {
girara_list_append(hitlist, real_rect); synctex_node_t node = NULL;
} else { bool got_page = false;
synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t));
if (page_rect == NULL) {
continue;
}
page_rect->page = current_page; while ((node = synctex_next_result (scanner)) != NULL) {
page_rect->rect = rectangle; const unsigned int current_page = synctex_node_page(node) - 1;
if (got_page == false) {
girara_list_append(other_rects, page_rect); got_page = true;
} *page = current_page;
} }
break;
case SYNCTEX_PROP_H:
rectangle.x1 = scan_float(scanner);
got_rect = true;
break;
case SYNCTEX_PROP_V:
rectangle.y2 = scan_float(scanner);
got_rect = true;
break;
case SYNCTEX_PROP_WIDTH: zathura_rectangle_t rect = { 0, 0, 0, 0 };
rectangle.x2 = rectangle.x1 + scan_float(scanner); rect.x1 = synctex_node_box_visible_h(node);
got_rect = true; rect.y1 = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node);
break; rect.x2 = rect.x1 + synctex_node_box_visible_width(node);
rect.y2 = synctex_node_box_visible_depth(node) + synctex_node_box_visible_height (node) + rect.y1;