mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2025-01-30 10:24:57 +01:00
Merge branch 'develop'
This commit is contained in:
commit
de0890c215
40 changed files with 4123 additions and 1088 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -7,3 +7,7 @@
|
|||
zathura
|
||||
zathura-debug
|
||||
zathura.pc
|
||||
*.info
|
||||
*.gcno
|
||||
*.gcda
|
||||
gcov/
|
||||
|
|
30
Doxyfile
Normal file
30
Doxyfile
Normal file
|
@ -0,0 +1,30 @@
|
|||
# See LICENSE file for license and copyright information
|
||||
|
||||
# General information
|
||||
PROJECT_NAME = zathura
|
||||
OUTPUT_DIRECTORY = ./doc/
|
||||
OUTPUT_LANGUAGE = English
|
||||
TAB_SIZE = 2
|
||||
EXTRACT_ALL = YES
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
TYPEDEF_HIDES_STRUCT = YES
|
||||
|
||||
# Warning and progress messages
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
|
||||
# Input files
|
||||
INPUT =
|
||||
EXCLUDE = ./tests
|
||||
FILE_PATTERNS = *.h *.c
|
||||
RECURSIVE = YES
|
||||
|
||||
# Output files
|
||||
GENERATE_HTML = YES
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_RTF = NO
|
||||
GENERATE_XML = NO
|
||||
|
||||
SOURCE_BROWSER = YES
|
64
Makefile
64
Makefile
|
@ -4,10 +4,21 @@ include config.mk
|
|||
include common.mk
|
||||
|
||||
PROJECT = zathura
|
||||
SOURCE = $(shell find . -iname "*.c")
|
||||
SOURCE = $(shell find . -iname "*.c" -a ! -iname "database-*" ! -path "*tests*")
|
||||
HEADER = $(shell find . -iname "*.h")
|
||||
OBJECTS = $(patsubst %.c, %.o, $(SOURCE))
|
||||
DOBJECTS = $(patsubst %.c, %.do, $(SOURCE))
|
||||
|
||||
ifeq (${DATABASE}, sqlite)
|
||||
INCS += $(SQLITE_INC)
|
||||
LIBS += $(SQLITE_LIB)
|
||||
SOURCE += database-sqlite.c
|
||||
else
|
||||
ifeq (${DATABASE}, plain)
|
||||
SOURCE += database-plain.c
|
||||
endif
|
||||
endif
|
||||
|
||||
all: options ${PROJECT}
|
||||
|
||||
options:
|
||||
|
@ -20,12 +31,15 @@ options:
|
|||
%.o: %.c
|
||||
$(ECHO) CC $<
|
||||
@mkdir -p .depend
|
||||
$(QUIET)${CC} -c ${CFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
|
||||
$(QUIET)${CC} -c ${CPPFLAGS} ${CFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
|
||||
|
||||
%.do: %.c
|
||||
$(ECHO) CC $<
|
||||
@mkdir -p .depend
|
||||
$(QUIET)${CC} -c ${CFLAGS} ${DFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
|
||||
$(QUIET)${CC} -c ${CPPFLAGS} ${CFLAGS} ${DFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
|
||||
|
||||
# force recompilation of database.o if DATABASE has changed
|
||||
database.o: database-${DATABASE}.o
|
||||
|
||||
${OBJECTS}: config.mk
|
||||
${DOBJECTS}: config.mk
|
||||
|
@ -36,7 +50,8 @@ ${PROJECT}: ${OBJECTS}
|
|||
|
||||
clean:
|
||||
$(QUIET)rm -rf ${PROJECT} ${OBJECTS} ${PROJECT}-${VERSION}.tar.gz \
|
||||
${DOBJECTS} ${PROJECT}-debug .depend ${PROJECT}.pc
|
||||
${DOBJECTS} ${PROJECT}-debug .depend ${PROJECT}.pc doc *gcda *gcno $(PROJECT).info gcov
|
||||
$(QUIET)make -C tests clean
|
||||
|
||||
${PROJECT}-debug: ${DOBJECTS}
|
||||
$(ECHO) CC -o $@
|
||||
|
@ -57,26 +72,45 @@ valgrind: debug
|
|||
gdb: debug
|
||||
cgdb ${PROJECT}-debug
|
||||
|
||||
tests: ${OBJECTS}
|
||||
$(QUIET)make -C tests
|
||||
|
||||
dist: clean
|
||||
$(QUIET)mkdir -p ${PROJECT}-${VERSION}
|
||||
$(QUIET)cp -R LICENSE Makefile config.mk README \
|
||||
${PROJECT}.1 ${SOURCE} ${PROJECT}.pc.in \
|
||||
$(QUIET)cp -R LICENSE Makefile config.mk common.mk README Doxyfile \
|
||||
${PROJECT}.1 ${SOURCE} ${HEADER} ${PROJECT}.pc.in tests \
|
||||
${PROJECT}-${VERSION}
|
||||
$(QUIET)tar -cf ${PROJECT}-${VERSION}.tar ${PROJECT}-${VERSION}
|
||||
$(QUIET)gzip ${PROJECT}-${VERSION}.tar
|
||||
$(QUIET)rm -rf ${PROJECT}-${VERSION}
|
||||
|
||||
doc: clean
|
||||
$(QUIET)doxygen Doxyfile
|
||||
|
||||
gcov: clean
|
||||
$(QUIET)CFLAGS="${CFLAGS}-fprofile-arcs -ftest-coverage" LDFLAGS="${LDFLAGS} -fprofile-arcs" ${MAKE} $(PROJECT)
|
||||
$(QUIET)${MAKE} -C tests
|
||||
$(QUIET)lcov --directory . --capture --output-file $(PROJECT).info
|
||||
$(QUIET)genhtml --output-directory gcov $(PROJECT).info
|
||||
|
||||
install: all ${PROJECT}.pc
|
||||
$(ECHO) installing executable file
|
||||
$(QUIET)mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
$(QUIET)install -m 755 ${PROJECT} ${DESTDIR}${PREFIX}/bin
|
||||
$(ECHO) installing header file
|
||||
$(ECHO) installing header files
|
||||
$(QUIET)mkdir -p ${DESTDIR}${PREFIX}/include/${PROJECT}
|
||||
$(QUIET)cp -f document.h ${DESTDIR}${PREFIX}/include/${PROJECT}
|
||||
$(QUIET)cp -f zathura.h ${DESTDIR}${PREFIX}/include/${PROJECT}
|
||||
$(ECHO) installing manual page
|
||||
$(ECHO) installing manual pages
|
||||
$(QUIET)mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
$(QUIET)sed "s/VERSION/${VERSION}/g" < ${PROJECT}.1 > ${DESTDIR}${MANPREFIX}/man1/${PROJECT}.1
|
||||
$(QUIET)if which rst2man > /dev/null ; then \
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man5 ; \
|
||||
rst2man ${PROJECT}rc.5.rst > ${DESTDIR}${MANPREFIX}/man5/${PROJECT}rc.5 ; \
|
||||
fi
|
||||
$(QUIET)mkdir -p ${DESTDIR}${DESKTOPPREFIX}
|
||||
$(ECHO) installing desktop file
|
||||
$(QUIET)install -m 644 ${PROJECT}.desktop ${DESTDIR}${DESKTOPPREFIX}
|
||||
$(QUIET)chmod 644 ${DESTDIR}${MANPREFIX}/man1/${PROJECT}.1
|
||||
$(ECHO) installing pkgconfig file
|
||||
$(QUIET)mkdir -p ${DESTDIR}${PREFIX}/lib/pkgconfig
|
||||
|
@ -85,14 +119,16 @@ install: all ${PROJECT}.pc
|
|||
uninstall:
|
||||
$(ECHO) removing executable file
|
||||
$(QUIET)rm -f ${DESTDIR}${PREFIX}/bin/${PROJECT}
|
||||
$(ECHO) removing header file
|
||||
$(QUIET)rm -f ${DESTDIR}${PREFIX}/include/${PROJECT}/document.h
|
||||
$(QUIET)rm -f ${DESTDIR}${PREFIX}/include/${PROJECT}/zathura.h
|
||||
$(ECHO) removing manual page
|
||||
$(ECHO) removing header files
|
||||
$(QUIET)rm -rf ${DESTDIR}${PREFIX}/include/${PROJECT}
|
||||
$(ECHO) removing manual pages
|
||||
$(QUIET)rm -f ${DESTDIR}${MANPREFIX}/man1/${PROJECT}.1
|
||||
$(QUIET)rm -f ${DESTDIR}${MANPREFIX}/man5/${PROJECT}rc.5
|
||||
$(ECHO) removing desktop file
|
||||
$(QUIET)rm -f ${DESTDIR}${DESKTOPPREFIX}/${PROJECT}.desktop
|
||||
$(ECHO) removing pkgconfig file
|
||||
$(QUIET)rm -f ${DESTDIR}${PREFIX}/lib/pkgconfig
|
||||
$(QUIET)rm -f ${DESTDIR}${PREFIX}/lib/pkgconfig/${PROJECT}.pc
|
||||
|
||||
-include $(wildcard .depend/*.dep)
|
||||
|
||||
.PHONY: all options clean debug valgrind gdb dist install uninstall
|
||||
.PHONY: all options clean doc debug valgrind gdb dist doc install uninstall tests
|
||||
|
|
11
README
11
README
|
@ -7,9 +7,16 @@ Requirements
|
|||
------------
|
||||
gtk2 (>= 2.18.6)
|
||||
girara
|
||||
sqlite3
|
||||
check (for tests)
|
||||
|
||||
Please note that you need to have a working pkg-config installation
|
||||
and that the Makefile is only compatible with GNU make.
|
||||
Please note that you need to have a working pkg-config installation and that the
|
||||
Makefile is only compatible with GNU make. If you don't have a working
|
||||
pkg-config installation please set the GTK_INC, GTK_LIB, GIRARA_INC, GIRARA_LIB,
|
||||
SQLITE_INC and SQLITE_LIB variables accordingly.
|
||||
|
||||
And also note that rst2man from python-docutils is needed to build zathurarc.5.
|
||||
If it is not installed, zathurarc.5 won't be built.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
|
51
bookmarks.c
51
bookmarks.c
|
@ -5,18 +5,28 @@
|
|||
#include "database.h"
|
||||
#include "document.h"
|
||||
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/utils.h>
|
||||
|
||||
static int
|
||||
bookmark_compare_find(const void* item, const void* data)
|
||||
{
|
||||
const zathura_bookmark_t* bookmark = item;
|
||||
const char* id = data;
|
||||
|
||||
return g_strcmp0(bookmark->id, id);
|
||||
}
|
||||
|
||||
zathura_bookmark_t*
|
||||
zathura_bookmark_add(zathura_t* zathura, const gchar* id, unsigned int page)
|
||||
{
|
||||
g_return_val_if_fail(zathura && zathura->document && zathura->bookmarks.bookmarks, NULL);
|
||||
g_return_val_if_fail(id, NULL);
|
||||
|
||||
GIRARA_LIST_FOREACH(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark)
|
||||
if (strcmp(bookmark->id, id) == 0) {
|
||||
girara_list_iterator_free(iter);
|
||||
return NULL;
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark)
|
||||
zathura_bookmark_t* old = girara_list_find(zathura->bookmarks.bookmarks, bookmark_compare_find, id);
|
||||
if (old != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zathura_bookmark_t* bookmark = g_malloc0(sizeof(zathura_bookmark_t));
|
||||
bookmark->id = g_strdup(id);
|
||||
|
@ -58,14 +68,7 @@ zathura_bookmark_get(zathura_t* zathura, const gchar* id)
|
|||
g_return_val_if_fail(zathura && zathura->bookmarks.bookmarks, NULL);
|
||||
g_return_val_if_fail(id, NULL);
|
||||
|
||||
GIRARA_LIST_FOREACH(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark)
|
||||
if (strcmp(bookmark->id, id) == 0) {
|
||||
girara_list_iterator_free(iter);
|
||||
return bookmark;
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark)
|
||||
|
||||
return NULL;
|
||||
return girara_list_find(zathura->bookmarks.bookmarks, bookmark_compare_find, id);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -81,8 +84,11 @@ zathura_bookmark_free(zathura_bookmark_t* bookmark)
|
|||
|
||||
bool
|
||||
zathura_bookmarks_load(zathura_t* zathura, const gchar* file) {
|
||||
g_return_val_if_fail(zathura && zathura->database, false);
|
||||
g_return_val_if_fail(zathura, false);
|
||||
g_return_val_if_fail(file, false);
|
||||
if (zathura->database == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
girara_list_t* bookmarks = zathura_db_load_bookmarks(zathura->database, file);
|
||||
if (!bookmarks) {
|
||||
|
@ -94,3 +100,18 @@ zathura_bookmarks_load(zathura_t* zathura, const gchar* file) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
zathura_bookmarks_compare(zathura_bookmark_t* lhs, zathura_bookmark_t* rhs)
|
||||
{
|
||||
if (lhs == NULL && rhs == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (lhs == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (rhs == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return g_strcmp0(lhs->id, rhs->id);
|
||||
}
|
||||
|
|
10
bookmarks.h
10
bookmarks.h
|
@ -49,8 +49,16 @@ void zathura_bookmark_free(zathura_bookmark_t* bookmark);
|
|||
* Load bookmarks for a specific file.
|
||||
* @param zathura The zathura instance.
|
||||
* @param file The file.
|
||||
* @param true on success, false otherwise
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool zathura_bookmarks_load(zathura_t* zathura, const gchar* file);
|
||||
|
||||
/**
|
||||
* Compare two bookmarks.
|
||||
* @param lhs a bookmark
|
||||
* @param rhs a bookmark
|
||||
* @returns g_strcmp0(lhs->id, rhs->id)
|
||||
*/
|
||||
int zathura_bookmarks_compare(zathura_bookmark_t* lhs, zathura_bookmark_t* rhs);
|
||||
|
||||
#endif // BOOKMARKS_H
|
||||
|
|
259
callbacks.c
259
callbacks.c
|
@ -1,23 +1,30 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <girara.h>
|
||||
#include <girara/statusbar.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/settings.h>
|
||||
#include <girara/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "zathura.h"
|
||||
#include "render.h"
|
||||
#include "document.h"
|
||||
#include "utils.h"
|
||||
#include "shortcuts.h"
|
||||
#include "page_widget.h"
|
||||
|
||||
gboolean
|
||||
cb_destroy(GtkWidget* UNUSED(widget), gpointer UNUSED(data))
|
||||
{
|
||||
gtk_main_quit();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
buffer_changed(girara_session_t* session)
|
||||
cb_buffer_changed(girara_session_t* session)
|
||||
{
|
||||
g_return_if_fail(session != NULL);
|
||||
g_return_if_fail(session->global.data != NULL);
|
||||
|
@ -35,57 +42,255 @@ buffer_changed(girara_session_t* session)
|
|||
}
|
||||
|
||||
void
|
||||
cb_view_vadjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
|
||||
cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data)
|
||||
{
|
||||
zathura_t* zathura = data;
|
||||
if (!zathura || !zathura->document || !zathura->document->pages || !zathura->ui.page_view) {
|
||||
if (!zathura || !zathura->document || !zathura->document->pages || !zathura->ui.page_widget) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get current adjustment values */
|
||||
gdouble lower = gtk_adjustment_get_value(adjustment);
|
||||
gdouble upper = lower + gtk_adjustment_get_page_size(adjustment);
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
|
||||
GdkRectangle view_rect;
|
||||
/* get current adjustment values */
|
||||
view_rect.y = gtk_adjustment_get_value(view_vadjustment);
|
||||
view_rect.height = gtk_adjustment_get_page_size(view_vadjustment);
|
||||
view_rect.x = gtk_adjustment_get_value(view_hadjustment);
|
||||
view_rect.width = gtk_adjustment_get_page_size(view_hadjustment);
|
||||
|
||||
int page_padding = 1;
|
||||
girara_setting_get(zathura->ui.session, "page-padding", &page_padding);
|
||||
|
||||
GdkRectangle center;
|
||||
center.x = view_rect.x + (view_rect.width + 1) / 2;
|
||||
center.y = view_rect.y + (view_rect.height + 1) / 2;
|
||||
center.height = center.width = 2*page_padding + 1;
|
||||
|
||||
bool updated = false;
|
||||
/* find page that fits */
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; page_id++)
|
||||
{
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
|
||||
page_offset_t* offset = page_calculate_offset(page);
|
||||
if (offset == NULL) {
|
||||
continue;
|
||||
}
|
||||
page_offset_t offset;
|
||||
page_calculate_offset(page, &offset);
|
||||
|
||||
double begin = offset->y;
|
||||
double end = offset->y + page->height;
|
||||
GdkRectangle page_rect;
|
||||
page_rect.x = offset.x;
|
||||
page_rect.y = offset.y;
|
||||
page_rect.width = page->width * zathura->document->scale;
|
||||
page_rect.height = page->height * zathura->document->scale;
|
||||
|
||||
if ( ( (begin >= lower) && (end <= upper) ) /* [> page is in viewport <]*/
|
||||
|| ( (begin <= lower) && (end >= lower) && (end <= upper) ) /* [> end of the page is in viewport <] */
|
||||
|| ( (begin >= lower) && (end >= upper) && (begin <= upper) ) /* [> begin of the page is in viewport <] */
|
||||
) {
|
||||
if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) {
|
||||
page->visible = true;
|
||||
if (page->surface == NULL) {
|
||||
render_page(zathura->sync.render_thread, page);
|
||||
if (updated == false && gdk_rectangle_intersect(¢er, &page_rect, NULL) == TRUE) {
|
||||
zathura->document->current_page_number = page_id;
|
||||
updated = true;
|
||||
}
|
||||
} else {
|
||||
page->visible = false;
|
||||
cairo_surface_destroy(page->surface);
|
||||
page->surface = NULL;
|
||||
}
|
||||
|
||||
free(offset);
|
||||
}
|
||||
|
||||
statusbar_page_number_update(zathura);
|
||||
}
|
||||
|
||||
void
|
||||
cb_pages_per_row_value_changed(girara_session_t* UNUSED(session), girara_setting_t* setting)
|
||||
cb_pages_per_row_value_changed(girara_session_t* UNUSED(session), const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* data)
|
||||
{
|
||||
int pages_per_row = setting->value.i;
|
||||
zathura_t* zathura = setting->data;
|
||||
g_return_if_fail(value != NULL);
|
||||
|
||||
int pages_per_row = *(int*) value;
|
||||
zathura_t* zathura = data;
|
||||
|
||||
if (pages_per_row < 1) {
|
||||
pages_per_row = 1;
|
||||
}
|
||||
|
||||
page_view_set_mode(zathura, pages_per_row);
|
||||
page_widget_set_mode(zathura, pages_per_row);
|
||||
}
|
||||
|
||||
void
|
||||
cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
|
||||
GtkTreeViewColumn* UNUSED(column), void* data)
|
||||
{
|
||||
zathura_t* zathura = data;
|
||||
if (tree_view == NULL || zathura == NULL || zathura->ui.session == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_object_get(tree_view, "model", &model, NULL);
|
||||
|
||||
if(gtk_tree_model_get_iter(model, &iter, path))
|
||||
{
|
||||
zathura_index_element_t* index_element;
|
||||
gtk_tree_model_get(model, &iter, 2, &index_element, -1);
|
||||
|
||||
if (index_element == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index_element->type == ZATHURA_LINK_TO_PAGE) {
|
||||
sc_toggle_index(zathura->ui.session, NULL, NULL, 0);
|
||||
page_set_delayed(zathura, index_element->target.page_number);
|
||||
} else if (index_element->type == ZATHURA_LINK_EXTERNAL) {
|
||||
if (girara_xdg_open(index_element->target.uri) == false) {
|
||||
girara_notify(zathura->ui.session, GIRARA_ERROR, "Failed to run xdg-open.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref(model);
|
||||
}
|
||||
|
||||
bool
|
||||
cb_sc_follow(GtkEntry* entry, girara_session_t* session)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, FALSE);
|
||||
g_return_val_if_fail(session->global.data != NULL, FALSE);
|
||||
|
||||
zathura_t* zathura = session->global.data;
|
||||
bool eval = true;
|
||||
|
||||
char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
|
||||
if (input == NULL || strlen(input) == 0) {
|
||||
eval = false;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
if (eval == true) {
|
||||
index = atoi(input);
|
||||
if (index == 0 && g_strcmp0(input, "0") != 0) {
|
||||
girara_notify(session, GIRARA_WARNING, "Invalid input '%s' given.", input);
|
||||
eval = false;
|
||||
}
|
||||
index = index - 1;
|
||||
}
|
||||
|
||||
/* set pages to draw links */
|
||||
bool invalid_index = true;
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; page_id++) {
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
if (page == NULL || page->visible == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set(page->drawing_area, "draw-links", FALSE, NULL);
|
||||
|
||||
if (eval == true) {
|
||||
zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page->drawing_area), index);
|
||||
if (link != NULL) {
|
||||
switch (link->type) {
|
||||
case ZATHURA_LINK_TO_PAGE:
|
||||
page_set_delayed(zathura, link->target.page_number);
|
||||
break;
|
||||
case ZATHURA_LINK_EXTERNAL:
|
||||
girara_xdg_open(link->target.value);
|
||||
break;
|
||||
}
|
||||
|
||||
invalid_index = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eval == true && invalid_index == true) {
|
||||
girara_notify(session, GIRARA_WARNING, "Invalid index '%s' given.", input);
|
||||
}
|
||||
|
||||
g_free(input);
|
||||
|
||||
return (eval == TRUE) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
cb_file_monitor(GFileMonitor* monitor, GFile* file, GFile* UNUSED(other_file), GFileMonitorEvent event, girara_session_t* session)
|
||||
{
|
||||
g_return_if_fail(monitor != NULL);
|
||||
g_return_if_fail(file != NULL);
|
||||
g_return_if_fail(session != NULL);
|
||||
|
||||
if (event != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
|
||||
return;
|
||||
}
|
||||
|
||||
sc_reload(session, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
password_dialog(gpointer data)
|
||||
{
|
||||
zathura_password_dialog_info_t* dialog = data;
|
||||
if (dialog != NULL) {
|
||||
girara_dialog(dialog->zathura->ui.session, "Incorrect password. Enter password:", true, NULL,
|
||||
(girara_callback_inputbar_activate_t) cb_password_dialog, dialog);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool
|
||||
cb_password_dialog(GtkEntry* entry, zathura_password_dialog_info_t* dialog)
|
||||
{
|
||||
if (entry == NULL || dialog == NULL) {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
if (dialog->path == NULL) {
|
||||
free(dialog);
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
if (dialog->zathura == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
|
||||
|
||||
/* no or empty password: ask again */
|
||||
if (input == NULL || strlen(input) == 0) {
|
||||
if (input != NULL) {
|
||||
g_free(input);
|
||||
}
|
||||
|
||||
g_idle_add(password_dialog, dialog);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* try to open document again */
|
||||
if (document_open(dialog->zathura, dialog->path, input) == false) {
|
||||
g_idle_add(password_dialog, dialog);
|
||||
} else {
|
||||
g_free(dialog->path);
|
||||
free(dialog);
|
||||
}
|
||||
|
||||
g_free(input);
|
||||
|
||||
return true;
|
||||
|
||||
error_free:
|
||||
|
||||
g_free(dialog->path);
|
||||
free(dialog);
|
||||
|
||||
error_ret:
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
cb_view_resized(GtkWidget* UNUSED(widget), GtkAllocation* UNUSED(allocation), zathura_t* zathura)
|
||||
{
|
||||
if (zathura == NULL || zathura->document == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
girara_argument_t argument = { zathura->document->adjust_mode, NULL };
|
||||
sc_adjust_window(zathura->ui.session, &argument, NULL, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
68
callbacks.h
68
callbacks.h
|
@ -4,14 +4,17 @@
|
|||
#define CALLBACKS_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
#include <girara/macros.h>
|
||||
|
||||
#include "document.h"
|
||||
|
||||
/**
|
||||
* Quits the current zathura session
|
||||
*
|
||||
* @param widget The gtk window of zathura
|
||||
* @param data NULL
|
||||
* @return TRUE
|
||||
* @return true if no error occured and the event has been handled
|
||||
*/
|
||||
gboolean cb_destroy(GtkWidget* widget, gpointer data);
|
||||
|
||||
|
@ -20,7 +23,7 @@ gboolean cb_destroy(GtkWidget* widget, gpointer data);
|
|||
*
|
||||
* @param session The girara session
|
||||
*/
|
||||
void buffer_changed(girara_session_t* session);
|
||||
void cb_buffer_changed(girara_session_t* session);
|
||||
|
||||
/**
|
||||
* This function gets called when the value of the vertical scrollbars
|
||||
|
@ -35,8 +38,63 @@ void cb_view_vadjustment_value_changed(GtkAdjustment *adjustment, gpointer data)
|
|||
* variable changes
|
||||
*
|
||||
* @param session The current girara session
|
||||
* @param setting The "pages-per-row" setting
|
||||
* @param name The name of the row
|
||||
* @param type The settings type
|
||||
* @param value The value
|
||||
* @param data Custom data
|
||||
*/
|
||||
void cb_pages_per_row_value_changed(girara_session_t* session, girara_setting_t* setting);
|
||||
void cb_pages_per_row_value_changed(girara_session_t* session, const char* name,
|
||||
girara_setting_type_t type, void* value, void* data);
|
||||
|
||||
/**
|
||||
* Called when an index element is activated (e.g.: double click)
|
||||
*
|
||||
* @param tree_view Tree view
|
||||
* @param path Path
|
||||
* @param column Column
|
||||
* @param zathura Zathura session
|
||||
*/
|
||||
void cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
|
||||
GtkTreeViewColumn* column, void* zathura);
|
||||
|
||||
/**
|
||||
* Called when input has been passed to the sc_follow dialog
|
||||
*
|
||||
* @param entry The dialog inputbar
|
||||
* @param session The girara session
|
||||
* @return true if no error occured and the event has been handled
|
||||
*/
|
||||
bool cb_sc_follow(GtkEntry* entry, girara_session_t* session);
|
||||
|
||||
/**
|
||||
* Emitted when file has been changed
|
||||
*
|
||||
* @param monitor The file monitor
|
||||
* @param file The file
|
||||
* @param other_file A file or NULL
|
||||
* @param event The monitor event
|
||||
* @param session The girara session
|
||||
*/
|
||||
void cb_file_monitor(GFileMonitor* monitor, GFile* file, GFile* other_file,
|
||||
GFileMonitorEvent event, girara_session_t* session);
|
||||
|
||||
/**
|
||||
* Callback to read new password for file that should be opened
|
||||
*
|
||||
* @param entry The password entry
|
||||
* @param dialog The dialog information
|
||||
* @return true if input has been handled
|
||||
*/
|
||||
bool cb_password_dialog(GtkEntry* entry, zathura_password_dialog_info_t* dialog);
|
||||
|
||||
/**
|
||||
* Emitted when the view has been resized
|
||||
*
|
||||
* @param widget View
|
||||
* @param allocation Allocation
|
||||
* @param zathura Zathura session
|
||||
* @return true if signal has been handled successfully
|
||||
*/
|
||||
bool cb_view_resized(GtkWidget* widget, GtkAllocation* allocation, zathura_t* zathura);
|
||||
|
||||
#endif // CALLBACKS_H
|
||||
|
|
210
commands.c
210
commands.c
|
@ -1,16 +1,54 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "bookmarks.h"
|
||||
#include "database.h"
|
||||
#include "document.h"
|
||||
#include "zathura.h"
|
||||
#include "print.h"
|
||||
#include "document.h"
|
||||
#include "utils.h"
|
||||
#include "page_widget.h"
|
||||
|
||||
|
||||
#include <girara/session.h>
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/utils.h>
|
||||
|
||||
bool
|
||||
cmd_bookmark_create(girara_session_t* UNUSED(session), girara_list_t*
|
||||
UNUSED(argument_list))
|
||||
cmd_bookmark_create(girara_session_t* session, girara_list_t* argument_list)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
if (zathura->document == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "No document opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned int argc = girara_list_size(argument_list);
|
||||
if (argc != 1) {
|
||||
girara_notify(session, GIRARA_ERROR, "Invalid number of arguments given.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* bookmark_name = girara_list_nth(argument_list, 0);
|
||||
zathura_bookmark_t* bookmark = zathura_bookmark_get(zathura, bookmark_name);
|
||||
if (bookmark != NULL) {
|
||||
bookmark->page = zathura->document->current_page_number + 1;
|
||||
girara_notify(session, GIRARA_INFO, "Bookmark successfuly updated: %s", bookmark_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bookmark = zathura_bookmark_add(zathura, bookmark_name, zathura->document->current_page_number + 1);
|
||||
if (bookmark == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "Could not create bookmark: %s", bookmark_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
girara_notify(session, GIRARA_INFO, "Bookmark successfuly created: %s", bookmark_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -42,10 +80,30 @@ cmd_bookmark_delete(girara_session_t* session, girara_list_t* argument_list)
|
|||
}
|
||||
|
||||
bool
|
||||
cmd_bookmark_open(girara_session_t* UNUSED(session), girara_list_t*
|
||||
UNUSED(argument_list))
|
||||
cmd_bookmark_open(girara_session_t* session, girara_list_t* argument_list)
|
||||
{
|
||||
return true;
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
if (zathura->document == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "No document opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned int argc = girara_list_size(argument_list);
|
||||
if (argc != 1) {
|
||||
girara_notify(session, GIRARA_ERROR, "Invalid number of arguments given.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* bookmark_name = girara_list_nth(argument_list, 0);
|
||||
zathura_bookmark_t* bookmark = zathura_bookmark_get(zathura, bookmark_name);
|
||||
if (bookmark == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "No such bookmark: %s", bookmark_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return page_set(zathura, bookmark->page - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -55,7 +113,6 @@ cmd_close(girara_session_t* session, girara_list_t* UNUSED(argument_list))
|
|||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
if (zathura->document == NULL) {
|
||||
// nothing needs to be done
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -65,10 +122,61 @@ cmd_close(girara_session_t* session, girara_list_t* UNUSED(argument_list))
|
|||
}
|
||||
|
||||
bool
|
||||
cmd_info(girara_session_t* UNUSED(session), girara_list_t*
|
||||
UNUSED(argument_list))
|
||||
cmd_info(girara_session_t* session, girara_list_t* UNUSED(argument_list))
|
||||
{
|
||||
return true;
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
if (zathura->document == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "No document opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
struct meta_field {
|
||||
char* name;
|
||||
zathura_document_meta_t field;
|
||||
};
|
||||
|
||||
struct meta_field meta_fields[] = {
|
||||
{ "Title", ZATHURA_DOCUMENT_TITLE },
|
||||
{ "Author", ZATHURA_DOCUMENT_AUTHOR },
|
||||
{ "Subject", ZATHURA_DOCUMENT_SUBJECT },
|
||||
{ "Keywords", ZATHURA_DOCUMENT_KEYWORDS },
|
||||
{ "Creator", ZATHURA_DOCUMENT_CREATOR },
|
||||
{ "Producer", ZATHURA_DOCUMENT_PRODUCER },
|
||||
{ "Creation date", ZATHURA_DOCUMENT_CREATION_DATE },
|
||||
{ "Modiciation date", ZATHURA_DOCUMENT_MODIFICATION_DATE }
|
||||
};
|
||||
|
||||
GString* string = g_string_new(NULL);
|
||||
if (string == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < LENGTH(meta_fields); i++) {
|
||||
char* tmp = zathura_document_meta_get(zathura->document, meta_fields[i].field, NULL);
|
||||
if (tmp != NULL) {
|
||||
char* text = g_strdup_printf("<b>%s:</b> %s\n", meta_fields[i].name, tmp);
|
||||
if (text == NULL) {
|
||||
g_free(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
g_string_append(string, text);
|
||||
|
||||
g_free(text);
|
||||
g_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(string->str) > 0) {
|
||||
g_string_erase(string, strlen(string->str) - 1, 1);
|
||||
girara_notify(session, GIRARA_INFO, "%s", string->str);
|
||||
}
|
||||
|
||||
g_string_free(string, TRUE);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -89,15 +197,13 @@ cmd_open(girara_session_t* session, girara_list_t* argument_list)
|
|||
if (argc > 2) {
|
||||
girara_notify(session, GIRARA_ERROR, "Too many arguments.");
|
||||
return false;
|
||||
}
|
||||
else if (argc >= 1) {
|
||||
} else if (argc >= 1) {
|
||||
if (zathura->document) {
|
||||
document_close(zathura);
|
||||
}
|
||||
|
||||
document_open(zathura, girara_list_nth(argument_list, 0), (argc == 2) ? girara_list_nth(argument_list, 1) : NULL);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
girara_notify(session, GIRARA_ERROR, "No arguments given.");
|
||||
return false;
|
||||
}
|
||||
|
@ -136,8 +242,7 @@ cmd_save(girara_session_t* session, girara_list_t* argument_list)
|
|||
|
||||
if (girara_list_size(argument_list) == 1) {
|
||||
document_save(zathura, girara_list_nth(argument_list, 0), false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
girara_notify(session, GIRARA_ERROR, "Invalid number of arguments.");
|
||||
return false;
|
||||
}
|
||||
|
@ -159,11 +264,82 @@ cmd_savef(girara_session_t* session, girara_list_t* argument_list)
|
|||
|
||||
if (girara_list_size(argument_list) == 1) {
|
||||
document_save(zathura, girara_list_nth(argument_list, 0), true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
girara_notify(session, GIRARA_ERROR, "Invalid number of arguments.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(input != NULL, false);
|
||||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
if (zathura->document == NULL || strlen(input) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool firsthit = true;
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; ++page_id) {
|
||||
zathura_page_t* page = zathura->document->pages[(page_id + zathura->document->current_page_number) % zathura->document->number_of_pages];
|
||||
if (page == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set(page->drawing_area, "draw-links", FALSE, NULL);
|
||||
|
||||
girara_list_t* result = zathura_page_search_text(page, input, NULL);
|
||||
if (result == NULL || girara_list_size(result) == 0) {
|
||||
girara_list_free(result);
|
||||
g_object_set(page->drawing_area, "search-results", NULL, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set(page->drawing_area, "search-results", result, NULL);
|
||||
if (firsthit == true) {
|
||||
if (page_id != 0) {
|
||||
page_set_delayed(zathura, page->number);
|
||||
}
|
||||
g_object_set(page->drawing_area, "search-current", 0, NULL);
|
||||
firsthit = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
cmd_export(girara_session_t* session, girara_list_t* argument_list)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
if (zathura->document == NULL) {
|
||||
girara_notify(session, GIRARA_ERROR, "No document opened.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned int argc = girara_list_size(argument_list);
|
||||
if (argc != 2) {
|
||||
girara_notify(session, GIRARA_ERROR, "Invalid number of arguments given.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* attachment_name = girara_list_nth(argument_list, 0);
|
||||
const char* file_name = girara_list_nth(argument_list, 1);
|
||||
char* file_name2 = girara_fix_path(file_name);
|
||||
if (!zathura_document_attachment_save(zathura->document, attachment_name, file_name)) {
|
||||
girara_notify(session, GIRARA_ERROR, "Couldn't write attachment '%s' to '%s'.", attachment_name, file_name);
|
||||
} else {
|
||||
girara_notify(session, GIRARA_INFO, "Wrote attachment '%s' to '%s'.", attachment_name, file_name2);
|
||||
}
|
||||
|
||||
g_free(file_name2);
|
||||
return true;
|
||||
}
|
||||
|
|
20
commands.h
20
commands.h
|
@ -4,7 +4,7 @@
|
|||
#define COMMANDS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
/**
|
||||
* Create a bookmark
|
||||
|
@ -96,5 +96,23 @@ bool cmd_save(girara_session_t* session, girara_list_t* argument_list);
|
|||
*/
|
||||
bool cmd_savef(girara_session_t* session, girara_list_t* argument_list);
|
||||
|
||||
/**
|
||||
* Search the current file
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param input The current input
|
||||
* @param argument Passed argument
|
||||
* @return true if no error occured
|
||||
*/
|
||||
bool cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument);
|
||||
|
||||
/**
|
||||
* Save attachment to a file
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument_list List of passed arguments
|
||||
* @return true if no error occured
|
||||
*/
|
||||
bool cmd_export(girara_session_t* session, girara_list_t* argument_list);
|
||||
|
||||
#endif // COMMANDS_H
|
||||
|
|
215
completion.c
215
completion.c
|
@ -6,11 +6,82 @@
|
|||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "bookmarks.h"
|
||||
#include "completion.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <girara/session.h>
|
||||
#include <girara/completion.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/datastructures.h>
|
||||
|
||||
static int
|
||||
compare_case_insensitive(const char* str1, const char* str2)
|
||||
{
|
||||
char* ustr1 = g_utf8_casefold(str1, -1);
|
||||
char* ustr2 = g_utf8_casefold(str2, -1);
|
||||
int res = g_utf8_collate(ustr1, ustr2);
|
||||
g_free(ustr1);
|
||||
g_free(ustr2);
|
||||
return res;
|
||||
}
|
||||
|
||||
static girara_list_t*
|
||||
list_files(zathura_t* zathura, const char* current_path, const char* current_file, int current_file_length, bool is_dir)
|
||||
{
|
||||
/* read directory */
|
||||
GDir* dir = g_dir_open(current_path, 0, NULL);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_list_t* res = girara_sorted_list_new2((girara_compare_function_t)compare_case_insensitive,
|
||||
(girara_free_function_t)g_free);
|
||||
|
||||
/* read files */
|
||||
char* name = NULL;
|
||||
while ((name = (char*) g_dir_read_name(dir)) != NULL) {
|
||||
char* e_name = g_filename_display_name(name);
|
||||
if (e_name == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
int e_length = strlen(e_name);
|
||||
|
||||
if ((current_file_length > e_length) || strncmp(current_file, e_name,
|
||||
current_file_length)) {
|
||||
g_free(e_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
char* full_path = g_strdup_printf("%s%s%s", current_path, is_dir ? "" : "/", e_name);
|
||||
if (full_path == NULL) {
|
||||
g_free(e_name);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (g_file_test(full_path, G_FILE_TEST_IS_DIR) == true) {
|
||||
char* tmp_path = full_path;
|
||||
full_path = g_strdup_printf("%s/", full_path);
|
||||
g_free(tmp_path);
|
||||
girara_list_append(res, full_path);
|
||||
} else if (file_valid_extension(zathura, full_path) == true) {
|
||||
girara_list_append(res, full_path);
|
||||
} else {
|
||||
g_free(full_path);
|
||||
}
|
||||
g_free(e_name);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
return res;
|
||||
|
||||
error_free:
|
||||
girara_list_free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_completion_t*
|
||||
cc_open(girara_session_t* session, char* input)
|
||||
cc_open(girara_session_t* session, const char* input)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, NULL);
|
||||
g_return_val_if_fail(session->global.data != NULL, NULL);
|
||||
|
@ -34,7 +105,7 @@ cc_open(girara_session_t* session, char* input)
|
|||
/* If the path does not begin with a slash we update the path with the current
|
||||
* working directory */
|
||||
if (strlen(path) == 0 || path[0] != '/') {
|
||||
size_t path_max;
|
||||
long path_max;
|
||||
#ifdef PATH_MAX
|
||||
path_max = PATH_MAX;
|
||||
#else
|
||||
|
@ -44,7 +115,9 @@ cc_open(girara_session_t* session, char* input)
|
|||
#endif
|
||||
|
||||
char cwd[path_max];
|
||||
getcwd(cwd, path_max);
|
||||
if (getcwd(cwd, path_max) == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
char* tmp_path = g_strdup_printf("%s/%s", cwd, path);
|
||||
if (tmp_path == NULL) {
|
||||
|
@ -79,50 +152,19 @@ cc_open(girara_session_t* session, char* input)
|
|||
|
||||
/* read directory */
|
||||
if (g_file_test(current_path, G_FILE_TEST_IS_DIR) == TRUE) {
|
||||
GDir* dir = g_dir_open(current_path, 0, NULL);
|
||||
if (dir == NULL) {
|
||||
girara_list_t* names = list_files(zathura, current_path, current_file, current_file_length, is_dir);
|
||||
if (!names) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
/* read files */
|
||||
char* name = NULL;
|
||||
while ((name = (char*) g_dir_read_name(dir)) != NULL) {
|
||||
char* e_name = g_filename_display_name(name);
|
||||
int e_length = strlen(e_name);
|
||||
|
||||
if (e_name == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if ((current_file_length > e_length) || strncmp(current_file, e_name,
|
||||
current_file_length)) {
|
||||
g_free(e_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
char* full_path = g_strdup_printf("%s%s%s", current_path, is_dir ? "" : "/", e_name);
|
||||
if (full_path == NULL) {
|
||||
g_free(e_name);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (g_file_test(full_path, G_FILE_TEST_IS_DIR) == true) {
|
||||
char* tmp_path = full_path;
|
||||
full_path = g_strdup_printf("%s/", full_path);
|
||||
g_free(tmp_path);
|
||||
girara_completion_group_add_element(group, full_path, NULL);
|
||||
} else if (file_valid_extension(zathura, full_path) == true) {
|
||||
girara_completion_group_add_element(group, full_path, NULL);
|
||||
}
|
||||
|
||||
g_free(full_path);
|
||||
g_free(e_name);
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
GIRARA_LIST_FOREACH(names, const char*, iter, file)
|
||||
girara_completion_group_add_element(group, file, NULL);
|
||||
GIRARA_LIST_FOREACH_END(names, const char*, iter, file);
|
||||
girara_list_free(names);
|
||||
}
|
||||
|
||||
g_free(path);
|
||||
g_free(current_path);
|
||||
|
||||
girara_completion_add_group(completion, group);
|
||||
|
||||
|
@ -142,3 +184,94 @@ error_free:
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_completion_t*
|
||||
cc_bookmarks(girara_session_t* session, const char* input)
|
||||
{
|
||||
if (input == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_return_val_if_fail(session != NULL, NULL);
|
||||
g_return_val_if_fail(session->global.data != NULL, NULL);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
girara_completion_t* completion = girara_completion_init();
|
||||
girara_completion_group_t* group = girara_completion_group_create(session, NULL);
|
||||
|
||||
if (completion == NULL || group == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
const size_t input_length = strlen(input);
|
||||
GIRARA_LIST_FOREACH(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark)
|
||||
if (input_length <= strlen(bookmark->id) && !strncmp(input, bookmark->id, input_length)) {
|
||||
gchar* paged = g_strdup_printf("Page %d", bookmark->page);
|
||||
girara_completion_group_add_element(group, bookmark->id, paged);
|
||||
g_free(paged);
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark);
|
||||
|
||||
girara_completion_add_group(completion, group);
|
||||
|
||||
return completion;
|
||||
|
||||
error_free:
|
||||
|
||||
if (completion) {
|
||||
girara_completion_free(completion);
|
||||
}
|
||||
|
||||
if (group) {
|
||||
girara_completion_group_free(group);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_completion_t*
|
||||
cc_export(girara_session_t* session, const char* input)
|
||||
{
|
||||
if (input == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_return_val_if_fail(session != NULL, NULL);
|
||||
g_return_val_if_fail(session->global.data != NULL, NULL);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
girara_completion_t* completion = girara_completion_init();
|
||||
girara_completion_group_t* group = girara_completion_group_create(session, NULL);
|
||||
|
||||
if (completion == NULL || group == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
const size_t input_length = strlen(input);
|
||||
girara_list_t* attachments = zathura_document_attachments_get(zathura->document, NULL);
|
||||
if (attachments == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
GIRARA_LIST_FOREACH(attachments, const char*, iter, attachment)
|
||||
if (input_length <= strlen(attachment) && !strncmp(input, attachment, input_length)) {
|
||||
girara_completion_group_add_element(group, attachment, NULL);
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->bookmarks.bookmarks, zathura_bookmark_t*, iter, bookmark);
|
||||
|
||||
girara_completion_add_group(completion, group);
|
||||
girara_list_free(attachments);
|
||||
return completion;
|
||||
|
||||
error_free:
|
||||
|
||||
if (completion) {
|
||||
girara_completion_free(completion);
|
||||
}
|
||||
|
||||
if (group) {
|
||||
girara_completion_group_free(group);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
23
completion.h
23
completion.h
|
@ -3,7 +3,7 @@
|
|||
#ifndef COMPLETION_H
|
||||
#define COMPLETION_H
|
||||
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
/**
|
||||
* Completion for the open command - Creates a list of accesible directories or
|
||||
|
@ -13,6 +13,25 @@
|
|||
* @param input The current input
|
||||
* @return The completion object or NULL if an error occured
|
||||
*/
|
||||
girara_completion_t* cc_open(girara_session_t* session, char* input);
|
||||
girara_completion_t* cc_open(girara_session_t* session, const char* input);
|
||||
|
||||
/**
|
||||
* Completion for the bmarks command - Creates a list of bookmarks
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param input The current input
|
||||
* @return The completion object or NULL if an error occured
|
||||
*/
|
||||
girara_completion_t* cc_bookmarks(girara_session_t* session, const char* input);
|
||||
|
||||
/**
|
||||
* Completion for the export command - Creates a list of attachments
|
||||
*
|
||||
* @param session the girara session
|
||||
* @param input the current input
|
||||
* @return completion object, NULL on error
|
||||
*/
|
||||
girara_completion_t* cc_export(girara_session_t* session, const char* input);
|
||||
|
||||
|
||||
#endif // COMPLETION_H
|
||||
|
|
218
config.c
218
config.c
|
@ -7,15 +7,23 @@
|
|||
#include "shortcuts.h"
|
||||
#include "zathura.h"
|
||||
|
||||
#include <girara/settings.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/shortcuts.h>
|
||||
#include <girara/config.h>
|
||||
#include <girara/commands.h>
|
||||
|
||||
void
|
||||
config_load_default(zathura_t* zathura)
|
||||
{
|
||||
if (!zathura || !zathura->ui.session) {
|
||||
if (zathura == NULL || zathura->ui.session == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int int_value = 0;
|
||||
float float_value = 0;
|
||||
char* string_value = NULL;
|
||||
bool bool_value = false;
|
||||
girara_session_t* gsession = zathura->ui.session;
|
||||
|
||||
/* mode settings */
|
||||
|
@ -33,90 +41,126 @@ config_load_default(zathura_t* zathura)
|
|||
|
||||
/* zathura settings */
|
||||
int_value = 10;
|
||||
girara_setting_add(gsession, "zoom-step", &int_value, INT, false, "Zoom step", NULL, NULL);
|
||||
girara_setting_add(gsession, "zoom-step", &int_value, INT, false, "Zoom step", NULL, NULL);
|
||||
int_value = 1;
|
||||
girara_setting_add(gsession, "page-padding", &int_value, INT, true, "Padding between pages", NULL, NULL);
|
||||
int_value = 2;
|
||||
girara_setting_add(gsession, "pages-per-row", &int_value, INT, false, "Number of pages per row", cb_pages_per_row_value_changed, zathura);
|
||||
girara_setting_add(gsession, "page-padding", &int_value, INT, true, "Padding between pages", NULL, NULL);
|
||||
int_value = 1;
|
||||
girara_setting_add(gsession, "pages-per-row", &int_value, INT, false, "Number of pages per row", cb_pages_per_row_value_changed, zathura);
|
||||
float_value = 40;
|
||||
girara_setting_add(gsession, "scroll-step", &float_value, FLOAT, false, "Scroll step", NULL, NULL);
|
||||
|
||||
string_value = "#FFFFFF";
|
||||
girara_setting_add(gsession, "recolor-dark-color", string_value, STRING, false, "Recoloring (dark color)", NULL, NULL);
|
||||
girara_setting_add(gsession, "recolor-darkcolor", string_value, STRING, false, "Recoloring (dark color)", NULL, NULL);
|
||||
string_value = "#000000";
|
||||
girara_setting_add(gsession, "recolor-light-color", string_value, STRING, false, "Recoloring (light color)", NULL, NULL);
|
||||
girara_setting_add(gsession, "recolor-lightcolor", string_value, STRING, false, "Recoloring (light color)", NULL, NULL);
|
||||
|
||||
string_value = "#9FBC00";
|
||||
girara_setting_add(gsession, "highlight-color", string_value, STRING, false, "Color for highlighting", NULL, NULL);
|
||||
float_value = 0.5;
|
||||
girara_setting_add(gsession, "highlight-transparency", &float_value, FLOAT, false, "Transparency for highlighting", NULL, NULL);
|
||||
bool_value = true;
|
||||
girara_setting_add(gsession, "render-loading", &bool_value, BOOLEAN, false, "Render 'Loading ...'", NULL, NULL);
|
||||
int_value = ADJUST_BESTFIT;
|
||||
girara_setting_add(gsession, "adjust-open", &int_value, INT, false, "Adjust to when opening file", NULL, NULL);
|
||||
|
||||
/* define default shortcuts */
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_c, NULL, sc_abort, 0, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Escape, NULL, sc_abort, 0, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_a, NULL, sc_adjust_window, NORMAL, ADJUST_BESTFIT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_s, NULL, sc_adjust_window, NORMAL, ADJUST_WIDTH, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_i, NULL, sc_change_mode, NORMAL, INSERT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_m, NULL, sc_change_mode, NORMAL, ADD_MARKER, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_apostrophe, NULL, sc_change_mode, NORMAL, EVAL_MARKER, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_slash, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("/"));
|
||||
girara_shortcut_add(gsession, GDK_SHIFT_MASK, GDK_slash, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("/"));
|
||||
girara_shortcut_add(gsession, 0, GDK_question, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("?"));
|
||||
girara_shortcut_add(gsession, 0, GDK_colon, NULL, girara_sc_focus_inputbar, NORMAL, 0, &(":"));
|
||||
girara_shortcut_add(gsession, 0, GDK_o, NULL, girara_sc_focus_inputbar, NORMAL, 0, &(":open "));
|
||||
girara_shortcut_add(gsession, 0, GDK_O, NULL, girara_sc_focus_inputbar, NORMAL, APPEND_FILEPATH, &(":open "));
|
||||
girara_shortcut_add(gsession, 0, GDK_f, NULL, sc_follow, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "gg", sc_goto, NORMAL | FULLSCREEN, TOP, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "G", sc_goto, NORMAL | FULLSCREEN, BOTTOM, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_J, NULL, sc_navigate, NORMAL, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_K, NULL, sc_navigate, NORMAL, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, GDK_MOD1_MASK, GDK_Right, NULL, sc_navigate, NORMAL, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_MOD1_MASK, GDK_Left, NULL, sc_navigate, NORMAL, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Left, NULL, sc_navigate, FULLSCREEN, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Up, NULL, sc_navigate, FULLSCREEN, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Down, NULL, sc_navigate, FULLSCREEN, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Right, NULL, sc_navigate, FULLSCREEN, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_k, NULL, sc_navigate_index, INDEX, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_j, NULL, sc_navigate_index, INDEX, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_h, NULL, sc_navigate_index, INDEX, COLLAPSE, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_l, NULL, sc_navigate_index, INDEX, EXPAND, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_space, NULL, sc_navigate_index, INDEX, SELECT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Return, NULL, sc_navigate_index, INDEX, SELECT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_i, NULL, sc_recolor, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_R, NULL, sc_reload, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_r, NULL, sc_rotate, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_h, NULL, sc_scroll, NORMAL, LEFT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_j, NULL, sc_scroll, NORMAL, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_k, NULL, sc_scroll, NORMAL, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_l, NULL, sc_scroll, NORMAL, RIGHT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Left, NULL, sc_scroll, NORMAL, LEFT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Up, NULL, sc_scroll, NORMAL, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Down, NULL, sc_scroll, NORMAL, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Right, NULL, sc_scroll, NORMAL, RIGHT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_d, NULL, sc_scroll, NORMAL, HALF_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_u, NULL, sc_scroll, NORMAL, HALF_UP, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_f, NULL, sc_scroll, NORMAL, FULL_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_b, NULL, sc_scroll, NORMAL, FULL_UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_space, NULL, sc_scroll, NORMAL, FULL_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_SHIFT_MASK, GDK_space, NULL, sc_scroll, NORMAL, FULL_UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_n, NULL, sc_search, NORMAL, FORWARD, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_N, NULL, sc_search, NORMAL, BACKWARD, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Tab, NULL, sc_toggle_index, NORMAL | INDEX, 0, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_m, NULL, girara_sc_toggle_inputbar, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_F5, NULL, sc_toggle_fullscreen, NORMAL | FULLSCREEN, 0, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_n, NULL, girara_sc_toggle_statusbar, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_q, NULL, sc_quit, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_plus, NULL, sc_zoom, NORMAL | FULLSCREEN, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_minus, NULL, sc_zoom, NORMAL | FULLSCREEN, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_equal, NULL, sc_zoom, NORMAL | FULLSCREEN, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zI", sc_zoom, NORMAL | FULLSCREEN, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zO", sc_zoom, NORMAL | FULLSCREEN, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "z0", sc_zoom, NORMAL | FULLSCREEN, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_c, NULL, sc_abort, 0, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Escape, NULL, sc_abort, 0, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_a, NULL, sc_adjust_window, NORMAL, ADJUST_BESTFIT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_s, NULL, sc_adjust_window, NORMAL, ADJUST_WIDTH, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_i, NULL, sc_change_mode, NORMAL, INSERT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_m, NULL, sc_change_mode, NORMAL, ADD_MARKER, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_apostrophe, NULL, sc_change_mode, NORMAL, EVAL_MARKER, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_slash, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("/"));
|
||||
girara_shortcut_add(gsession, GDK_SHIFT_MASK, GDK_slash, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("/"));
|
||||
girara_shortcut_add(gsession, 0, GDK_question, NULL, girara_sc_focus_inputbar, NORMAL, 0, &("?"));
|
||||
girara_shortcut_add(gsession, 0, GDK_colon, NULL, girara_sc_focus_inputbar, NORMAL, 0, &(":"));
|
||||
girara_shortcut_add(gsession, 0, GDK_o, NULL, girara_sc_focus_inputbar, NORMAL, 0, &(":open "));
|
||||
girara_shortcut_add(gsession, 0, GDK_O, NULL, girara_sc_focus_inputbar, NORMAL, APPEND_FILEPATH, &(":open "));
|
||||
girara_shortcut_add(gsession, 0, GDK_f, NULL, sc_follow, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "gg", sc_goto, NORMAL, TOP, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "gg", sc_goto, FULLSCREEN, TOP, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "G", sc_goto, NORMAL, BOTTOM, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "G", sc_goto, FULLSCREEN, BOTTOM, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_J, NULL, sc_navigate, NORMAL, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_K, NULL, sc_navigate, NORMAL, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, GDK_MOD1_MASK, GDK_Right, NULL, sc_navigate, NORMAL, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_MOD1_MASK, GDK_Left, NULL, sc_navigate, NORMAL, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Left, NULL, sc_navigate, FULLSCREEN, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Up, NULL, sc_navigate, FULLSCREEN, PREVIOUS, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Down, NULL, sc_navigate, FULLSCREEN, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Right, NULL, sc_navigate, FULLSCREEN, NEXT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_k, NULL, sc_navigate_index, INDEX, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_j, NULL, sc_navigate_index, INDEX, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_h, NULL, sc_navigate_index, INDEX, COLLAPSE, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_l, NULL, sc_navigate_index, INDEX, EXPAND, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_space, NULL, sc_navigate_index, INDEX, SELECT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Return, NULL, sc_navigate_index, INDEX, SELECT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_i, NULL, sc_recolor, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_R, NULL, sc_reload, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_r, NULL, sc_rotate, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_h, NULL, sc_scroll, NORMAL, LEFT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_j, NULL, sc_scroll, NORMAL, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_k, NULL, sc_scroll, NORMAL, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_l, NULL, sc_scroll, NORMAL, RIGHT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Left, NULL, sc_scroll, NORMAL, LEFT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Up, NULL, sc_scroll, NORMAL, UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Down, NULL, sc_scroll, NORMAL, DOWN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Right, NULL, sc_scroll, NORMAL, RIGHT, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_d, NULL, sc_scroll, NORMAL, HALF_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_u, NULL, sc_scroll, NORMAL, HALF_UP, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_f, NULL, sc_scroll, NORMAL, FULL_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_b, NULL, sc_scroll, NORMAL, FULL_UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_space, NULL, sc_scroll, NORMAL, FULL_DOWN, NULL);
|
||||
girara_shortcut_add(gsession, GDK_SHIFT_MASK, GDK_space, NULL, sc_scroll, NORMAL, FULL_UP, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_n, NULL, sc_search, NORMAL, FORWARD, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_N, NULL, sc_search, NORMAL, BACKWARD, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Tab, NULL, sc_toggle_index, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_Tab, NULL, sc_toggle_index, INDEX, 0, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_m, NULL, girara_sc_toggle_inputbar, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_F5, NULL, sc_toggle_fullscreen, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_F5, NULL, sc_toggle_fullscreen, FULLSCREEN, 0, NULL);
|
||||
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_n, NULL, girara_sc_toggle_statusbar, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_q, NULL, sc_quit, NORMAL, 0, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_plus, NULL, sc_zoom, NORMAL, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_plus, NULL, sc_zoom, FULLSCREEN, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_minus, NULL, sc_zoom, NORMAL, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_minus, NULL, sc_zoom, FULLSCREEN, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_equal, NULL, sc_zoom, NORMAL, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_equal, NULL, sc_zoom, FULLSCREEN, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zI", sc_zoom, NORMAL, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zI", sc_zoom, FULLSCREEN, ZOOM_IN, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zO", sc_zoom, NORMAL, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "zO", sc_zoom, FULLSCREEN, ZOOM_OUT, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "z0", sc_zoom, NORMAL, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, 0, 0, "z0", sc_zoom, FULLSCREEN, ZOOM_ORIGINAL, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_equal, NULL, sc_zoom, NORMAL, ZOOM_SPECIFIC, NULL);
|
||||
girara_shortcut_add(gsession, 0, GDK_equal, NULL, sc_zoom, FULLSCREEN, ZOOM_SPECIFIC, NULL);
|
||||
|
||||
/* mouse events */
|
||||
girara_mouse_event_add(gsession, 0, 0, sc_mouse_scroll, NORMAL, GIRARA_EVENT_SCROLL, 0, NULL);
|
||||
girara_mouse_event_add(gsession, 0, 0, sc_mouse_scroll, FULLSCREEN, GIRARA_EVENT_SCROLL, 0, NULL);
|
||||
girara_mouse_event_add(gsession, GDK_CONTROL_MASK, 0, sc_mouse_zoom, NORMAL, GIRARA_EVENT_SCROLL, 0, NULL);
|
||||
girara_mouse_event_add(gsession, GDK_CONTROL_MASK, 0, sc_mouse_zoom, FULLSCREEN, GIRARA_EVENT_SCROLL, 0, NULL);
|
||||
girara_mouse_event_add(gsession, 0, GIRARA_MOUSE_BUTTON2, sc_mouse_scroll, NORMAL, GIRARA_EVENT_BUTTON_PRESS, 0, NULL);
|
||||
girara_mouse_event_add(gsession, GDK_BUTTON2_MASK, GIRARA_MOUSE_BUTTON2, sc_mouse_scroll, NORMAL, GIRARA_EVENT_BUTTON_RELEASE, 0, NULL);
|
||||
girara_mouse_event_add(gsession, GDK_BUTTON2_MASK, 0, sc_mouse_scroll, NORMAL, GIRARA_EVENT_MOTION_NOTIFY, 0, NULL);
|
||||
|
||||
/* define default inputbar commands */
|
||||
girara_inputbar_command_add(gsession, "bmark", NULL, cmd_bookmark_create, NULL, "Add a bookmark");
|
||||
girara_inputbar_command_add(gsession, "bdelete", NULL, cmd_bookmark_delete, NULL, "Delete a bookmark");
|
||||
girara_inputbar_command_add(gsession, "blist", NULL, cmd_bookmark_open, NULL, "List all bookmarks");
|
||||
girara_inputbar_command_add(gsession, "close", NULL, cmd_close, NULL, "Close current file");
|
||||
girara_inputbar_command_add(gsession, "info", NULL, cmd_info, NULL, "Show file information");
|
||||
girara_inputbar_command_add(gsession, "help", NULL, cmd_help, NULL, "Show help");
|
||||
girara_inputbar_command_add(gsession, "open", "o", cmd_open, cc_open, "Open document");
|
||||
girara_inputbar_command_add(gsession, "print", NULL, cmd_print, NULL, "Print document");
|
||||
girara_inputbar_command_add(gsession, "write", NULL, cmd_save, NULL, "Save document");
|
||||
girara_inputbar_command_add(gsession, "write!", NULL, cmd_savef, NULL, "Save document (and force overwriting)");
|
||||
girara_inputbar_command_add(gsession, "bmark", NULL, cmd_bookmark_create, NULL, "Add a bookmark");
|
||||
girara_inputbar_command_add(gsession, "bdelete", NULL, cmd_bookmark_delete, cc_bookmarks, "Delete a bookmark");
|
||||
girara_inputbar_command_add(gsession, "blist", NULL, cmd_bookmark_open, cc_bookmarks, "List all bookmarks");
|
||||
girara_inputbar_command_add(gsession, "close", NULL, cmd_close, NULL, "Close current file");
|
||||
girara_inputbar_command_add(gsession, "info", NULL, cmd_info, NULL, "Show file information");
|
||||
girara_inputbar_command_add(gsession, "help", NULL, cmd_help, NULL, "Show help");
|
||||
girara_inputbar_command_add(gsession, "open", "o", cmd_open, cc_open, "Open document");
|
||||
girara_inputbar_command_add(gsession, "print", NULL, cmd_print, NULL, "Print document");
|
||||
girara_inputbar_command_add(gsession, "write", NULL, cmd_save, NULL, "Save document");
|
||||
girara_inputbar_command_add(gsession, "write!", NULL, cmd_savef, NULL, "Save document (and force overwriting)");
|
||||
girara_inputbar_command_add(gsession, "export", NULL, cmd_export, cc_export, "Save attachments");
|
||||
|
||||
girara_special_command_add(gsession, '/', cmd_search, true, FORWARD, NULL);
|
||||
girara_special_command_add(gsession, '?', cmd_search, true, BACKWARD, NULL);
|
||||
|
||||
/* add shortcut mappings */
|
||||
girara_shortcut_mapping_add(gsession, "abort", sc_abort);
|
||||
|
@ -137,6 +181,26 @@ config_load_default(zathura_t* zathura)
|
|||
girara_shortcut_mapping_add(gsession, "toggle_inputbar", girara_sc_toggle_inputbar);
|
||||
girara_shortcut_mapping_add(gsession, "toggle_statusbar", girara_sc_toggle_statusbar);
|
||||
girara_shortcut_mapping_add(gsession, "zoom", sc_zoom);
|
||||
|
||||
/* add argument mappings */
|
||||
girara_argument_mapping_add(gsession, "bottom", BOTTOM);
|
||||
girara_argument_mapping_add(gsession, "default", DEFAULT);
|
||||
girara_argument_mapping_add(gsession, "down", DOWN);
|
||||
girara_argument_mapping_add(gsession, "full-down", FULL_DOWN);
|
||||
girara_argument_mapping_add(gsession, "full-up", FULL_UP);
|
||||
girara_argument_mapping_add(gsession, "half-down", HALF_DOWN);
|
||||
girara_argument_mapping_add(gsession, "half-up", HALF_UP);
|
||||
girara_argument_mapping_add(gsession, "in", ZOOM_IN);
|
||||
girara_argument_mapping_add(gsession, "left", LEFT);
|
||||
girara_argument_mapping_add(gsession, "next", NEXT);
|
||||
girara_argument_mapping_add(gsession, "out", ZOOM_OUT);
|
||||
girara_argument_mapping_add(gsession, "previous", PREVIOUS);
|
||||
girara_argument_mapping_add(gsession, "right", RIGHT);
|
||||
girara_argument_mapping_add(gsession, "specific", ZOOM_SPECIFIC);
|
||||
girara_argument_mapping_add(gsession, "top", TOP);
|
||||
girara_argument_mapping_add(gsession, "up", UP);
|
||||
girara_argument_mapping_add(gsession, "best-fit", ADJUST_BESTFIT);
|
||||
girara_argument_mapping_add(gsession, "width", ADJUST_WIDTH);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
3
config.h
3
config.h
|
@ -11,13 +11,14 @@
|
|||
/**
|
||||
* This function loads the default values of the configuration
|
||||
*
|
||||
* @param zathura the zathura session
|
||||
* @param zathura The zathura session
|
||||
*/
|
||||
void config_load_default(zathura_t* zathura);
|
||||
|
||||
/**
|
||||
* Loads and evaluates a configuration file
|
||||
*
|
||||
* @param zathura The zathura session
|
||||
* @param path Path to the configuration file
|
||||
*/
|
||||
void config_load_file(zathura_t* zathura, char* path);
|
||||
|
|
13
config.mk
13
config.mk
|
@ -6,6 +6,9 @@ VERSION = 0.0.8.1
|
|||
# paths
|
||||
PREFIX ?= /usr
|
||||
MANPREFIX ?= ${PREFIX}/share/man
|
||||
DESKTOPPREFIX ?= ${PREFIX}/share/applications
|
||||
# list of : seperated values
|
||||
PLUGINDIR ?= ${PREFIX}/lib/zathura
|
||||
|
||||
# libs
|
||||
|
||||
|
@ -19,13 +22,15 @@ GIRARA_LIB ?= $(shell pkg-config --libs girara-gtk2)
|
|||
SQLITE_INC ?= $(shell pkg-config --cflags sqlite3)
|
||||
SQLITE_LIB ?= $(shell pkg-config --libs sqlite3)
|
||||
|
||||
#set it to an empty value if you don't need to link against ld for dlopen and friends
|
||||
DL_LIB ?= -ldl
|
||||
|
||||
INCS = ${GIRARA_INC} ${GTK_INC} $(SQLITE_INC)
|
||||
LIBS = ${GIRARA_LIB} ${GTK_LIB} $(SQLITE_LIB) $(DL_LIB) -lpthread -lm
|
||||
INCS = ${GIRARA_INC} ${GTK_INC}
|
||||
LIBS = ${GIRARA_LIB} ${GTK_LIB} $(DL_LIB) -lpthread -lm
|
||||
|
||||
# flags
|
||||
CFLAGS += -std=c99 -pedantic -Wall -Wno-format-zero-length -Wextra $(INCS)
|
||||
CPPFLAGS += -DZATHURA_PLUGINDIR=\"${PLUGINDIR}\"
|
||||
|
||||
# debug
|
||||
DFLAGS ?= -g
|
||||
|
@ -41,3 +46,7 @@ SFLAGS ?= -s
|
|||
|
||||
# set to something != 0 if you want verbose build output
|
||||
VERBOSE ?= 0
|
||||
|
||||
# database
|
||||
# possible values are sqlite and plain
|
||||
DATABASE ?= plain
|
||||
|
|
403
database-plain.c
Normal file
403
database-plain.c
Normal file
|
@ -0,0 +1,403 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#define _POSIX_SOURCE
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/datastructures.h>
|
||||
|
||||
#include "database.h"
|
||||
|
||||
#define BOOKMARKS "bookmarks"
|
||||
#define HISTORY "history"
|
||||
|
||||
#define KEY_PAGE "page"
|
||||
#define KEY_OFFSET "offset"
|
||||
#define KEY_SCALE "scale"
|
||||
#define KEY_ROTATE "rotate"
|
||||
|
||||
#define file_lock_set(fd, cmd) \
|
||||
{ \
|
||||
struct flock lock = { .l_type = cmd, .l_start = 0, .l_whence = SEEK_SET, .l_len = 0}; \
|
||||
fcntl(fd, F_SETLK, lock); \
|
||||
}
|
||||
|
||||
/* forward declaration */
|
||||
static bool zathura_db_check_file(const char* path);
|
||||
static GKeyFile* zathura_db_read_key_file_from_file(const char* path);
|
||||
static void zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file);
|
||||
static void cb_zathura_db_watch_file(GFileMonitor* monitor, GFile* file, GFile*
|
||||
other_file, GFileMonitorEvent event, zathura_database_t* database);
|
||||
|
||||
struct zathura_database_s
|
||||
{
|
||||
char* bookmark_path;
|
||||
GKeyFile* bookmarks;
|
||||
GFileMonitor* bookmark_monitor;
|
||||
|
||||
char* history_path;
|
||||
GKeyFile* history;
|
||||
GFileMonitor* history_monitor;
|
||||
};
|
||||
|
||||
zathura_database_t*
|
||||
zathura_db_init(const char* dir)
|
||||
{
|
||||
if (dir == NULL) {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
zathura_database_t* db = calloc(1, sizeof(zathura_database_t));
|
||||
if (db == NULL) {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* bookmarks */
|
||||
db->bookmark_path = g_build_filename(dir, BOOKMARKS, NULL);
|
||||
if (db->bookmark_path == NULL ||
|
||||
zathura_db_check_file(db->bookmark_path) == false) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
GFile* bookmark_file = g_file_new_for_path(db->bookmark_path);
|
||||
if (bookmark_file != NULL) {
|
||||
db->bookmark_monitor = g_file_monitor(bookmark_file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
} else {
|
||||
goto error_free;
|
||||
}
|
||||
g_object_unref(bookmark_file);
|
||||
|
||||
g_signal_connect(
|
||||
G_OBJECT(db->bookmark_monitor),
|
||||
"changed",
|
||||
G_CALLBACK(cb_zathura_db_watch_file),
|
||||
db
|
||||
);
|
||||
|
||||
db->bookmarks = zathura_db_read_key_file_from_file(db->bookmark_path);
|
||||
if (db->bookmarks == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
/* history */
|
||||
db->history_path = g_build_filename(dir, HISTORY, NULL);
|
||||
if (db->history_path == NULL ||
|
||||
zathura_db_check_file(db->history_path) == false) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
GFile* history_file = g_file_new_for_path(db->history_path);
|
||||
if (history_file != NULL) {
|
||||
db->history_monitor = g_file_monitor(history_file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
} else {
|
||||
goto error_free;
|
||||
}
|
||||
g_object_unref(history_file);
|
||||
|
||||
g_signal_connect(
|
||||
G_OBJECT(db->history_monitor),
|
||||
"changed",
|
||||
G_CALLBACK(cb_zathura_db_watch_file),
|
||||
db
|
||||
);
|
||||
|
||||
db->history = zathura_db_read_key_file_from_file(db->history_path);
|
||||
if (db->history == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
return db;
|
||||
|
||||
error_free:
|
||||
|
||||
zathura_db_free(db);
|
||||
|
||||
error_ret:
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
zathura_db_free(zathura_database_t* db)
|
||||
{
|
||||
if (db == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* bookmarks */
|
||||
g_free(db->bookmark_path);
|
||||
|
||||
if (db->bookmark_monitor != NULL) {
|
||||
g_object_unref(db->bookmark_monitor);
|
||||
}
|
||||
|
||||
if (db->bookmarks != NULL) {
|
||||
g_key_file_free(db->bookmarks);
|
||||
}
|
||||
|
||||
/* history */
|
||||
g_free(db->history_path);
|
||||
|
||||
if (db->history_monitor != NULL) {
|
||||
g_object_unref(db->history_monitor);
|
||||
}
|
||||
|
||||
/* database */
|
||||
free(db);
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_add_bookmark(zathura_database_t* db, const char* file,
|
||||
zathura_bookmark_t* bookmark)
|
||||
{
|
||||
if (db == NULL || db->bookmarks == NULL || db->bookmark_path == NULL || file
|
||||
== NULL || bookmark == NULL || bookmark->id == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_key_file_set_integer(db->bookmarks, file, bookmark->id, bookmark->page);
|
||||
|
||||
zathura_db_write_key_file_to_file(db->bookmark_path, db->bookmarks);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const char*
|
||||
id)
|
||||
{
|
||||
if (db == NULL || db->bookmarks == NULL || db->bookmark_path == NULL || file
|
||||
== NULL || id == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_key_file_has_group(db->bookmarks, file) == TRUE) {
|
||||
g_key_file_remove_group(db->bookmarks, file, NULL);
|
||||
|
||||
zathura_db_write_key_file_to_file(db->bookmark_path, db->bookmarks);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
girara_list_t*
|
||||
zathura_db_load_bookmarks(zathura_database_t* db, const char* file)
|
||||
{
|
||||
if (db == NULL || db->bookmarks == NULL || file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (g_key_file_has_group(db->bookmarks, file) == FALSE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_list_t* result = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
|
||||
(girara_free_function_t) zathura_bookmark_free);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
girara_list_set_free_function(result, (girara_free_function_t) zathura_bookmark_free);
|
||||
|
||||
gsize length;
|
||||
char** keys = g_key_file_get_keys(db->bookmarks, file, &length, NULL);
|
||||
if (keys == NULL) {
|
||||
girara_list_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (gsize i = 0; i < length; i++) {
|
||||
zathura_bookmark_t* bookmark = g_malloc0(sizeof(zathura_bookmark_t));
|
||||
|
||||
bookmark->id = g_strdup(keys[i]);
|
||||
bookmark->page = g_key_file_get_integer(db->bookmarks, file, keys[i], NULL);
|
||||
|
||||
girara_list_append(result, bookmark);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int
|
||||
page, int offset, double scale, int rotation)
|
||||
{
|
||||
if (db == NULL || db->history == NULL || file == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* tmp = g_strdup_printf("%f", scale);
|
||||
if (tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_key_file_set_integer(db->history, file, KEY_PAGE, page);
|
||||
g_key_file_set_integer(db->history, file, KEY_OFFSET, offset);
|
||||
g_key_file_set_string (db->history, file, KEY_SCALE, tmp);
|
||||
g_key_file_set_integer(db->history, file, KEY_ROTATE, rotation);
|
||||
|
||||
g_free(tmp);
|
||||
|
||||
zathura_db_write_key_file_to_file(db->history_path, db->history);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned int*
|
||||
page, int* offset, double* scale, int* rotation)
|
||||
{
|
||||
if (db == NULL || db->history == NULL || file == NULL || page == NULL ||
|
||||
offset == NULL || scale == NULL || rotation == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_key_file_has_group(db->history, file) == FALSE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*page = g_key_file_get_integer(db->history, file, KEY_PAGE, NULL);
|
||||
*offset = g_key_file_get_integer(db->history, file, KEY_OFFSET, NULL);
|
||||
*scale = strtod(g_key_file_get_string(db->history, file, KEY_SCALE, NULL), NULL);
|
||||
*rotation = g_key_file_get_integer(db->history, file, KEY_ROTATE, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
zathura_db_check_file(const char* path)
|
||||
{
|
||||
if (path == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_file_test(path, G_FILE_TEST_EXISTS) == false) {
|
||||
FILE* file = fopen(path, "w");
|
||||
if (file != NULL) {
|
||||
fclose(file);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static GKeyFile*
|
||||
zathura_db_read_key_file_from_file(const char* path)
|
||||
{
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* open file */
|
||||
FILE* file = fopen(path, "r");
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GKeyFile* key_file = g_key_file_new();
|
||||
if (key_file == NULL) {
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read config file */
|
||||
file_lock_set(fileno(file), F_WRLCK);
|
||||
char* content = girara_file_read2(file);
|
||||
file_lock_set(fileno(file), F_UNLCK);
|
||||
fclose(file);
|
||||
if (content == NULL) {
|
||||
g_key_file_free(key_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* parse config file */
|
||||
size_t contentlen = strlen(content);
|
||||
if (contentlen == 0) {
|
||||
static const char dummy_content[] = "# nothing";
|
||||
static const size_t dummy_len = sizeof(dummy_content) - 1;
|
||||
|
||||
free(content);
|
||||
content = malloc(sizeof(char) * (dummy_len + 1));
|
||||
content = memcpy(content, dummy_content, dummy_len + 1);
|
||||
contentlen = dummy_len;
|
||||
}
|
||||
|
||||
GError* error = NULL;
|
||||
if (g_key_file_load_from_data(key_file, content, contentlen,
|
||||
G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error) ==
|
||||
FALSE) {
|
||||
if (error->code != 1) /* ignore empty file */ {
|
||||
free(content);
|
||||
g_key_file_free(key_file);
|
||||
g_error_free(error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
free(content);
|
||||
|
||||
return key_file;
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file)
|
||||
{
|
||||
if (file == NULL || key_file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar* content = g_key_file_to_data(key_file, NULL, NULL);
|
||||
if (content == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* open file */
|
||||
int fd = open(file, O_RDWR);
|
||||
if (fd == -1) {
|
||||
g_free(content);
|
||||
return;
|
||||
}
|
||||
|
||||
file_lock_set(fd, F_WRLCK);
|
||||
if (write(fd, content, strlen(content)) == 0) {
|
||||
girara_error("Failed to write to %s", file);
|
||||
}
|
||||
file_lock_set(fd, F_UNLCK);
|
||||
|
||||
close(fd);
|
||||
|
||||
g_free(content);
|
||||
}
|
||||
|
||||
static void
|
||||
cb_zathura_db_watch_file(GFileMonitor* UNUSED(monitor), GFile* file, GFile* UNUSED(other_file),
|
||||
GFileMonitorEvent event, zathura_database_t* database)
|
||||
{
|
||||
if (event != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT || database == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
char* path = g_file_get_path(file);
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (database->bookmark_path && strcmp(database->bookmark_path, path) == 0) {
|
||||
database->bookmarks = zathura_db_read_key_file_from_file(database->bookmark_path);
|
||||
} else if (database->history_path && strcmp(database->history_path, path) == 0) {
|
||||
database->history = zathura_db_read_key_file_from_file(database->history_path);
|
||||
}
|
||||
}
|
|
@ -2,18 +2,30 @@
|
|||
|
||||
#include <glib.h>
|
||||
#include <sqlite3.h>
|
||||
#include <girara.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/datastructures.h>
|
||||
|
||||
#include "database.h"
|
||||
|
||||
#define DATABASE "bookmarks.sqlite"
|
||||
|
||||
struct zathura_database_s
|
||||
{
|
||||
sqlite3* session;
|
||||
};
|
||||
|
||||
zathura_database_t*
|
||||
zathura_db_init(const char* path)
|
||||
zathura_db_init(const char* dir)
|
||||
{
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* path = g_build_filename(dir, DATABASE, NULL);
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zathura_database_t* db = g_malloc0(sizeof(zathura_database_t));
|
||||
|
||||
/* create bookmarks database */
|
||||
|
@ -29,27 +41,32 @@ zathura_db_init(const char* path)
|
|||
"file TEXT PRIMARY KEY,"
|
||||
"page INTEGER,"
|
||||
"offset INTEGER,"
|
||||
"scale FLOAT);";
|
||||
"scale FLOAT,"
|
||||
"rotation INTEGER);";
|
||||
|
||||
if (sqlite3_open(path, &(db->session)) != SQLITE_OK) {
|
||||
girara_error("Could not open database: %s\n", path);
|
||||
zathura_db_free(db);
|
||||
return NULL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db->session, SQL_BOOKMARK_INIT, NULL, 0, NULL) != SQLITE_OK) {
|
||||
girara_error("Failed to initialize database: %s\n", path);
|
||||
zathura_db_free(db);
|
||||
return NULL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
if (sqlite3_exec(db->session, SQL_FILEINFO_INIT, NULL, 0, NULL) != SQLITE_OK) {
|
||||
girara_error("Failed to initialize database: %s\n", path);
|
||||
zathura_db_free(db);
|
||||
return NULL;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
return db;
|
||||
|
||||
error_free:
|
||||
|
||||
zathura_db_free(db);
|
||||
g_free(path);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -59,7 +76,10 @@ zathura_db_free(zathura_database_t* db)
|
|||
return;
|
||||
}
|
||||
|
||||
sqlite3_close(db->session);
|
||||
if (db->session != NULL) {
|
||||
sqlite3_close(db->session);
|
||||
}
|
||||
|
||||
g_free(db);
|
||||
}
|
||||
|
||||
|
@ -73,7 +93,7 @@ prepare_statement(sqlite3* session, const char* statement)
|
|||
const char* pz_tail = NULL;
|
||||
sqlite3_stmt* pp_stmt = NULL;
|
||||
|
||||
if (sqlite3_prepare(session, statement, -1, &pp_stmt, &pz_tail) != SQLITE_OK) {
|
||||
if (sqlite3_prepare_v2(session, statement, -1, &pp_stmt, &pz_tail) != SQLITE_OK) {
|
||||
girara_error("Failed to prepare query: %s", statement);
|
||||
sqlite3_finalize(pp_stmt);
|
||||
return NULL;
|
||||
|
@ -87,7 +107,8 @@ prepare_statement(sqlite3* session, const char* statement)
|
|||
}
|
||||
|
||||
bool
|
||||
zathura_db_add_bookmark(zathura_database_t* db, const char* file, zathura_bookmark_t* bookmark)
|
||||
zathura_db_add_bookmark(zathura_database_t* db, const char* file,
|
||||
zathura_bookmark_t* bookmark)
|
||||
{
|
||||
g_return_val_if_fail(db && file && bookmark, false);
|
||||
|
||||
|
@ -109,16 +130,17 @@ zathura_db_add_bookmark(zathura_database_t* db, const char* file, zathura_bookma
|
|||
|
||||
int res = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
return res == SQLITE_OK;
|
||||
return res == SQLITE_DONE;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const char* id)
|
||||
zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const char*
|
||||
id)
|
||||
{
|
||||
g_return_val_if_fail(db && file && id, false);
|
||||
|
||||
static const char SQL_BOOKMARK_ADD[] =
|
||||
"DELETE FROM bookmarks WHERE file = ? && id = ?;";
|
||||
"DELETE FROM bookmarks WHERE file = ? AND id = ?;";
|
||||
|
||||
sqlite3_stmt* stmt = prepare_statement(db->session, SQL_BOOKMARK_ADD);
|
||||
if (stmt == NULL) {
|
||||
|
@ -134,7 +156,7 @@ zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const char*
|
|||
|
||||
int res = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
return res == SQLITE_OK;
|
||||
return res == SQLITE_DONE;
|
||||
}
|
||||
|
||||
girara_list_t*
|
||||
|
@ -156,16 +178,17 @@ zathura_db_load_bookmarks(zathura_database_t* db, const char* file)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
girara_list_t* result = girara_list_new();
|
||||
girara_list_t* result = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
|
||||
(girara_free_function_t) zathura_bookmark_free);
|
||||
if (result == NULL) {
|
||||
sqlite3_finalize(stmt);
|
||||
return NULL;
|
||||
}
|
||||
girara_list_set_free_function(result, (girara_free_function_t) zathura_bookmark_free);
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
zathura_bookmark_t* bookmark = g_malloc0(sizeof(zathura_bookmark_t));
|
||||
bookmark->id = g_strdup((const char*) sqlite3_column_text(stmt, 0));
|
||||
|
||||
bookmark->id = g_strdup((const char*) sqlite3_column_text(stmt, 0));
|
||||
bookmark->page = sqlite3_column_int(stmt, 1);
|
||||
|
||||
girara_list_append(result, bookmark);
|
||||
|
@ -175,12 +198,13 @@ zathura_db_load_bookmarks(zathura_database_t* db, const char* file)
|
|||
}
|
||||
|
||||
bool
|
||||
zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int page, int offset, float scale)
|
||||
zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int
|
||||
page, int offset, double scale, int rotation)
|
||||
{
|
||||
g_return_val_if_fail(db && file, false);
|
||||
|
||||
static const char SQL_FILEINFO_SET[] =
|
||||
"REPLACE INTO fileinfo (file, page, offset, scale) VALUES (?, ?, ?);";
|
||||
"REPLACE INTO fileinfo (file, page, offset, scale, rotation) VALUES (?, ?, ?, ?, ?);";
|
||||
|
||||
sqlite3_stmt* stmt = prepare_statement(db->session, SQL_FILEINFO_SET);
|
||||
if (stmt == NULL) {
|
||||
|
@ -190,7 +214,8 @@ zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int p
|
|||
if (sqlite3_bind_text(stmt, 1, file, -1, NULL) != SQLITE_OK ||
|
||||
sqlite3_bind_int(stmt, 2, page) != SQLITE_OK ||
|
||||
sqlite3_bind_int(stmt, 3, offset) != SQLITE_OK ||
|
||||
sqlite3_bind_double(stmt, 4, scale) != SQLITE_OK) {
|
||||
sqlite3_bind_double(stmt, 4, scale) != SQLITE_OK ||
|
||||
sqlite3_bind_int(stmt, 5, rotation) != SQLITE_OK) {
|
||||
sqlite3_finalize(stmt);
|
||||
girara_error("Failed to bind arguments.");
|
||||
return false;
|
||||
|
@ -198,16 +223,17 @@ zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int p
|
|||
|
||||
int res = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
return res == SQLITE_OK;
|
||||
return res == SQLITE_DONE;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned int* page, int* offset, float* scale)
|
||||
zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned int*
|
||||
page, int* offset, double* scale, int* rotation)
|
||||
{
|
||||
g_return_val_if_fail(db && file && page && offset && scale, false);
|
||||
g_return_val_if_fail(db && file && page && offset && scale && rotation, false);
|
||||
|
||||
static const char SQL_FILEINFO_GET[] =
|
||||
"SELECT page, offset, scale FROM fileinfo WHERE file = ?;";
|
||||
"SELECT page, offset, scale, rotation FROM fileinfo WHERE file = ?;";
|
||||
|
||||
sqlite3_stmt* stmt = prepare_statement(db->session, SQL_FILEINFO_GET);
|
||||
if (stmt == NULL) {
|
||||
|
@ -229,6 +255,8 @@ zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned int*
|
|||
*page = sqlite3_column_int(stmt, 0);
|
||||
*offset = sqlite3_column_int(stmt, 1);
|
||||
*scale = sqlite3_column_double(stmt, 2);
|
||||
*rotation = sqlite3_column_int(stmt, 3);
|
||||
sqlite3_finalize(stmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
34
database.h
34
database.h
|
@ -4,69 +4,83 @@
|
|||
#define DATABASE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
#include "zathura.h"
|
||||
#include "bookmarks.h"
|
||||
|
||||
/**
|
||||
* Initialize database system.
|
||||
* @param path Path to the database file.
|
||||
*
|
||||
* @param dir Path to the directory where the database file should be located.
|
||||
* @return A valid zathura_database_t instance or NULL on failure
|
||||
*/
|
||||
zathura_database_t* zathura_db_init(const char* path);
|
||||
zathura_database_t* zathura_db_init(const char* dir);
|
||||
|
||||
/**
|
||||
* Free database instance.
|
||||
* @param The database instance to free.
|
||||
*
|
||||
* @param db The database instance to free.
|
||||
*/
|
||||
void zathura_db_free(zathura_database_t* db);
|
||||
|
||||
/**
|
||||
* Add or update bookmark in the database.
|
||||
*
|
||||
* @param db The database instance
|
||||
* @param file The file to which the bookmark belongs to.
|
||||
* @param bookmark The bookmark instance.
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool zathura_db_add_bookmark(zathura_database_t* db, const char* file, zathura_bookmark_t* bookmark);
|
||||
bool zathura_db_add_bookmark(zathura_database_t* db, const char* file,
|
||||
zathura_bookmark_t* bookmark);
|
||||
|
||||
/**
|
||||
* Add or update bookmark in the database.
|
||||
*
|
||||
* @param db The database instance
|
||||
* @param file The file to which the bookmark belongs to.
|
||||
* @param bookmark The bookmark instance.
|
||||
* @param id The id of the bookmark
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const char* id);
|
||||
bool zathura_db_remove_bookmark(zathura_database_t* db, const char* file, const
|
||||
char* id);
|
||||
|
||||
/**
|
||||
* Loads all bookmarks from the database belonging to a specific file.
|
||||
*
|
||||
* @param db The database instance.
|
||||
* @param file The file for which the bookmarks should be loaded.
|
||||
* @return List of zathura_bookmark_t* or NULL on failure.
|
||||
*/
|
||||
girara_list_t* zathura_db_load_bookmarks(zathura_database_t* db, const char* file);
|
||||
girara_list_t* zathura_db_load_bookmarks(zathura_database_t* db, const char*
|
||||
file);
|
||||
|
||||
/**
|
||||
* Set file info (last site, ...) in the database.
|
||||
*
|
||||
* @param db The database instance
|
||||
* @param file The file to which the file info belongs to.
|
||||
* @param page The last page.
|
||||
* @param offset The last offset.
|
||||
* @param scale The last scale.
|
||||
* @param rotation The last rotation.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned int page, int offset, float scale);
|
||||
bool zathura_db_set_fileinfo(zathura_database_t* db, const char* file, unsigned
|
||||
int page, int offset, double scale, int rotation);
|
||||
|
||||
/* Get file info (last site, ...) from the database.
|
||||
*
|
||||
* @param db The database instance
|
||||
* @param file The file to which the file info belongs to.
|
||||
* @param page The last page.
|
||||
* @param offset The last offset.
|
||||
* @param scale The last scale.
|
||||
* @param rotation The rotation.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned int* page, int* offset, float* scale);
|
||||
bool zathura_db_get_fileinfo(zathura_database_t* db, const char* file, unsigned
|
||||
int* page, int* offset, double* scale, int* rotation);
|
||||
|
||||
#endif // DATABASE_H
|
||||
|
|
428
document.c
428
document.c
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -15,36 +16,46 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "document.h"
|
||||
#include "utils.h"
|
||||
#include "zathura.h"
|
||||
#include "render.h"
|
||||
#include "database.h"
|
||||
#include "page_widget.h"
|
||||
|
||||
#define LENGTH(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/statusbar.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/settings.h>
|
||||
|
||||
/**
|
||||
* Register document plugin
|
||||
*/
|
||||
static bool zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin);
|
||||
|
||||
void
|
||||
zathura_document_plugins_load(zathura_t* zathura)
|
||||
{
|
||||
girara_list_iterator_t* iter = girara_list_iterator(zathura->plugins.path);
|
||||
if (iter == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
char* plugindir = girara_list_iterator_data(iter);
|
||||
|
||||
GIRARA_LIST_FOREACH(zathura->plugins.path, char*, iter, plugindir)
|
||||
/* TODO: rewrite with GDir */
|
||||
/* read all files in the plugin directory */
|
||||
DIR* dir = opendir(plugindir);
|
||||
if (dir == NULL) {
|
||||
girara_error("could not open plugin directory: %s", plugindir);
|
||||
girara_list_iterator_next(iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
int fddir = dirfd(dir);
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
if (fstatat(fddir, entry->d_name, &statbuf, 0) != 0) {
|
||||
girara_error("failed to fstatat %s/%s; errno is %d.", plugindir, entry->d_name, errno);
|
||||
|
@ -87,27 +98,18 @@ zathura_document_plugins_load(zathura_t* zathura)
|
|||
continue;
|
||||
}
|
||||
|
||||
plugin = malloc(sizeof(zathura_document_plugin_t));
|
||||
|
||||
if (plugin == NULL) {
|
||||
g_error("failed to allocate memory!");
|
||||
break;
|
||||
}
|
||||
|
||||
plugin->open_function = NULL;
|
||||
plugin->content_types = girara_list_new();
|
||||
girara_list_set_free_function(plugin->content_types, g_free);
|
||||
plugin = g_malloc0(sizeof(zathura_document_plugin_t));
|
||||
plugin->content_types = girara_list_new2(g_free);
|
||||
plugin->handle = handle;
|
||||
|
||||
register_plugin(plugin);
|
||||
|
||||
bool r = zathura_document_plugin_register(zathura, plugin, handle);
|
||||
bool r = zathura_document_plugin_register(zathura, plugin);
|
||||
|
||||
if (r == false) {
|
||||
girara_error("could not register plugin %s", path);
|
||||
free(plugin);
|
||||
dlclose(handle);
|
||||
}
|
||||
else {
|
||||
zathura_document_plugin_free(plugin);
|
||||
} else {
|
||||
girara_info("successfully loaded plugin %s", path);
|
||||
}
|
||||
|
||||
|
@ -117,8 +119,7 @@ zathura_document_plugins_load(zathura_t* zathura)
|
|||
if (closedir(dir) == -1) {
|
||||
girara_error("could not close plugin directory %s", plugindir);
|
||||
}
|
||||
} while (girara_list_iterator_next(iter));
|
||||
girara_list_iterator_free(iter);
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -128,15 +129,15 @@ zathura_document_plugin_free(zathura_document_plugin_t* plugin)
|
|||
return;
|
||||
}
|
||||
|
||||
dlclose(plugin->handle);
|
||||
girara_list_free(plugin->content_types);
|
||||
free(plugin);
|
||||
g_free(plugin);
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin, void* handle)
|
||||
static bool
|
||||
zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin)
|
||||
{
|
||||
if( (new_plugin == NULL) || (new_plugin->content_types == NULL) || (new_plugin->open_function == NULL)
|
||||
|| (handle == NULL) ) {
|
||||
if (new_plugin == NULL || new_plugin->content_types == NULL || new_plugin->open_function == NULL) {
|
||||
girara_error("plugin: could not register\n");
|
||||
return false;
|
||||
}
|
||||
|
@ -145,9 +146,10 @@ zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t*
|
|||
GIRARA_LIST_FOREACH(new_plugin->content_types, gchar*, iter, type)
|
||||
if (!zathura_type_plugin_mapping_new(zathura, type, new_plugin)) {
|
||||
girara_error("plugin: already registered for filetype %s\n", type);
|
||||
} else {
|
||||
atleastone = true;
|
||||
}
|
||||
atleastone = true;
|
||||
GIRARA_LIST_FOREACH_END(new_plugin->content_types, gchar*, iter, type)
|
||||
GIRARA_LIST_FOREACH_END(new_plugin->content_types, gchar*, iter, type);
|
||||
|
||||
if (atleastone) {
|
||||
girara_list_append(zathura->plugins.plugins, new_plugin);
|
||||
|
@ -155,6 +157,47 @@ zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t*
|
|||
return atleastone;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
guess_type(const char* path)
|
||||
{
|
||||
gboolean uncertain;
|
||||
const gchar* content_type = g_content_type_guess(path, NULL, 0, &uncertain);
|
||||
if (content_type == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE* f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int fd = fileno(f);
|
||||
guchar* content = NULL;
|
||||
size_t length = 0u;
|
||||
while (uncertain == TRUE) {
|
||||
g_free((void*)content_type);
|
||||
content_type = NULL;
|
||||
|
||||
content = g_realloc(content, length + BUFSIZ);
|
||||
const ssize_t r = read(fd, content + length, BUFSIZ);
|
||||
if (r == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
length += r;
|
||||
content_type = g_content_type_guess(NULL, content, length, &uncertain);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
if (uncertain == TRUE) {
|
||||
g_free((void*)content_type);
|
||||
content_type = NULL;
|
||||
}
|
||||
|
||||
g_free(content);
|
||||
return content_type;
|
||||
}
|
||||
|
||||
zathura_document_t*
|
||||
zathura_document_open(zathura_t* zathura, const char* path, const char* password)
|
||||
{
|
||||
|
@ -163,18 +206,20 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* password
|
|||
}
|
||||
|
||||
if (file_exists(path) == false) {
|
||||
girara_error("File does not exist");
|
||||
girara_error("File '%s' does not exist", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const gchar* content_type = g_content_type_guess(path, NULL, 0, NULL);
|
||||
const gchar* content_type = guess_type(path);
|
||||
if (content_type == NULL) {
|
||||
girara_error("Could not determine file type");
|
||||
girara_error("Could not determine file type.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* file_uri = NULL;
|
||||
|
||||
/* determine real path */
|
||||
size_t path_max;
|
||||
long path_max;
|
||||
#ifdef PATH_MAX
|
||||
path_max = PATH_MAX;
|
||||
#else
|
||||
|
@ -204,52 +249,118 @@ zathura_document_open(zathura_t* zathura, const char* path, const char* password
|
|||
plugin = mapping->plugin;
|
||||
break;
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping)
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping);
|
||||
g_free((void*)content_type);
|
||||
|
||||
if (plugin == NULL) {
|
||||
girara_error("unknown file type\n");
|
||||
free(real_path);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document = g_malloc0(sizeof(zathura_document_t));
|
||||
if (document == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document->file_path = real_path;
|
||||
document->password = password;
|
||||
document->scale = 1.0;
|
||||
document->zathura = zathura;
|
||||
|
||||
if (plugin->open_function != NULL) {
|
||||
if (plugin->open_function(document) == true) {
|
||||
/* update statusbar */
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, real_path);
|
||||
|
||||
/* read all pages */
|
||||
document->pages = calloc(document->number_of_pages, sizeof(zathura_page_t*));
|
||||
if (document->pages == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
|
||||
zathura_page_t* page = zathura_page_get(document, page_id);
|
||||
if (page == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document->pages[page_id] = page;
|
||||
}
|
||||
|
||||
return document;
|
||||
}
|
||||
/* open document */
|
||||
if (plugin->open_function == NULL) {
|
||||
girara_error("plugin has no open function\n");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
girara_error("could not open file\n");
|
||||
zathura_plugin_error_t error = plugin->open_function(document);
|
||||
if (error != ZATHURA_PLUGIN_ERROR_OK) {
|
||||
if (error == ZATHURA_PLUGIN_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->path = g_strdup(path);
|
||||
password_dialog_info->zathura = zathura;
|
||||
|
||||
if (path != NULL) {
|
||||
girara_dialog(zathura->ui.session, "Enter password:", true, NULL,
|
||||
(girara_callback_inputbar_activate_t) cb_password_dialog, password_dialog_info);
|
||||
goto error_free;
|
||||
} else {
|
||||
free(password_dialog_info);
|
||||
}
|
||||
}
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
girara_error("could not open document\n");
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
/* read history file */
|
||||
int offset = 0;
|
||||
zathura_db_get_fileinfo(zathura->database, document->file_path,
|
||||
&document->current_page_number, &offset, &document->scale, &document->rotate);
|
||||
|
||||
/* check for valid scale value */
|
||||
if (document->scale <= FLT_EPSILON) {
|
||||
girara_warning("document info: '%s' has non positive scale", document->file_path);
|
||||
document->scale = 1;
|
||||
}
|
||||
|
||||
/* check current page number */
|
||||
if (document->current_page_number > document->number_of_pages) {
|
||||
girara_warning("document info: '%s' has an invalid page number", document->file_path);
|
||||
document->current_page_number = 0;
|
||||
}
|
||||
|
||||
/* update statusbar */
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, real_path);
|
||||
|
||||
/* read all pages */
|
||||
document->pages = calloc(document->number_of_pages, sizeof(zathura_page_t*));
|
||||
if (document->pages == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
|
||||
zathura_page_t* page = zathura_page_get(document, page_id, NULL);
|
||||
if (page == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document->pages[page_id] = page;
|
||||
}
|
||||
|
||||
/* install file monitor */
|
||||
file_uri = g_filename_to_uri(real_path, NULL, NULL);
|
||||
if (file_uri == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document->file_monitor.file = g_file_new_for_uri(file_uri);
|
||||
if (document->file_monitor.file == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document->file_monitor.monitor = g_file_monitor_file(document->file_monitor.file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
if (document->file_monitor.monitor == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
g_signal_connect(G_OBJECT(document->file_monitor.monitor), "changed", G_CALLBACK(cb_file_monitor), zathura->ui.session);
|
||||
|
||||
|
||||
/* apply open adjustment */
|
||||
int adjust_open = ADJUST_BESTFIT;
|
||||
girara_setting_get(zathura->ui.session, "adjust-open", &adjust_open);
|
||||
|
||||
g_free(file_uri);
|
||||
|
||||
return document;
|
||||
|
||||
error_free:
|
||||
|
||||
if (file_uri != NULL) {
|
||||
g_free(file_uri);
|
||||
}
|
||||
|
||||
free(real_path);
|
||||
|
||||
if (document != NULL && document->pages != NULL) {
|
||||
|
@ -264,7 +375,7 @@ error_free:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_plugin_error_t
|
||||
zathura_document_free(zathura_document_t* document)
|
||||
{
|
||||
if (document == NULL) {
|
||||
|
@ -280,19 +391,13 @@ zathura_document_free(zathura_document_t* document)
|
|||
free(document->pages);
|
||||
|
||||
/* free document */
|
||||
bool r = true;
|
||||
if (document->functions.document_free == NULL) {
|
||||
girara_error("%s not implemented", __FUNCTION__);
|
||||
|
||||
if (document->file_path != NULL) {
|
||||
free(document->file_path);
|
||||
}
|
||||
|
||||
g_free(document);
|
||||
return true;
|
||||
} else {
|
||||
r = document->functions.document_free(document);
|
||||
}
|
||||
|
||||
bool r = document->functions.document_free(document);
|
||||
|
||||
if (document->file_path != NULL) {
|
||||
free(document->file_path);
|
||||
}
|
||||
|
@ -302,7 +407,7 @@ zathura_document_free(zathura_document_t* document)
|
|||
return r;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_plugin_error_t
|
||||
zathura_document_save_as(zathura_document_t* document, const char* path)
|
||||
{
|
||||
if (document == NULL || path == NULL) {
|
||||
|
@ -318,7 +423,7 @@ zathura_document_save_as(zathura_document_t* document, const char* path)
|
|||
}
|
||||
|
||||
girara_tree_node_t*
|
||||
zathura_document_index_generate(zathura_document_t* document)
|
||||
zathura_document_index_generate(zathura_document_t* document, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (document == NULL) {
|
||||
return NULL;
|
||||
|
@ -329,11 +434,11 @@ zathura_document_index_generate(zathura_document_t* document)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return document->functions.document_index_generate(document);
|
||||
return document->functions.document_index_generate(document, error);
|
||||
}
|
||||
|
||||
zathura_list_t*
|
||||
zathura_document_attachments_get(zathura_document_t* document)
|
||||
girara_list_t*
|
||||
zathura_document_attachments_get(zathura_document_t* document, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (document == NULL) {
|
||||
return NULL;
|
||||
|
@ -344,17 +449,45 @@ zathura_document_attachments_get(zathura_document_t* document)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return document->functions.document_attachments_get(document);
|
||||
return document->functions.document_attachments_get(document, error);
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_document_attachments_free(zathura_list_t* UNUSED(list))
|
||||
zathura_plugin_error_t
|
||||
zathura_document_attachment_save(zathura_document_t* document, const char* attachment, const char* file)
|
||||
{
|
||||
return false;
|
||||
if (document == NULL) {
|
||||
return ZATHURA_PLUGIN_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (document->functions.document_attachment_save == NULL) {
|
||||
return ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return document->functions.document_attachment_save(document, attachment, file);
|
||||
}
|
||||
|
||||
char*
|
||||
zathura_document_meta_get(zathura_document_t* document, zathura_document_meta_t meta, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (document == NULL) {
|
||||
if (error != NULL) {
|
||||
*error = ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (document->functions.document_meta_get == NULL) {
|
||||
if (error != NULL) {
|
||||
*error = ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return document->functions.document_meta_get(document, meta, error);
|
||||
}
|
||||
|
||||
zathura_page_t*
|
||||
zathura_page_get(zathura_document_t* document, unsigned int page_id)
|
||||
zathura_page_get(zathura_document_t* document, unsigned int page_id, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (document == NULL) {
|
||||
return NULL;
|
||||
|
@ -365,27 +498,25 @@ zathura_page_get(zathura_document_t* document, unsigned int page_id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
zathura_page_t* page = document->functions.page_get(document, page_id);
|
||||
zathura_page_t* page = document->functions.page_get(document, page_id, error);
|
||||
|
||||
if (page != NULL) {
|
||||
page->number = page_id;
|
||||
page->visible = false;
|
||||
page->event_box = gtk_event_box_new();
|
||||
page->drawing_area = gtk_drawing_area_new();
|
||||
page->surface = NULL;
|
||||
page->drawing_area = zathura_page_widget_new(page);
|
||||
page->document = document;
|
||||
g_signal_connect(page->drawing_area, "expose-event", G_CALLBACK(page_expose_event), page);
|
||||
|
||||
gtk_widget_set_size_request(page->drawing_area, page->width * document->scale, page->height * document->scale);
|
||||
gtk_container_add(GTK_CONTAINER(page->event_box), page->drawing_area);
|
||||
unsigned int page_height = 0;
|
||||
unsigned int page_width = 0;
|
||||
page_calc_height_width(page, &page_height, &page_width, true);
|
||||
|
||||
g_static_mutex_init(&(page->lock));
|
||||
gtk_widget_set_size_request(page->drawing_area, page_width, page_height);
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_plugin_error_t
|
||||
zathura_page_free(zathura_page_t* page)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
|
@ -397,13 +528,11 @@ zathura_page_free(zathura_page_t* page)
|
|||
return false;
|
||||
}
|
||||
|
||||
g_static_mutex_free(&(page->lock));
|
||||
|
||||
return page->document->functions.page_free(page);
|
||||
}
|
||||
|
||||
zathura_list_t*
|
||||
zathura_page_search_text(zathura_page_t* page, const char* text)
|
||||
girara_list_t*
|
||||
zathura_page_search_text(zathura_page_t* page, const char* text, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (page == NULL || page->document == NULL || text == NULL) {
|
||||
return NULL;
|
||||
|
@ -414,11 +543,11 @@ zathura_page_search_text(zathura_page_t* page, const char* text)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return page->document->functions.page_search_text(page, text);
|
||||
return page->document->functions.page_search_text(page, text, error);
|
||||
}
|
||||
|
||||
zathura_list_t*
|
||||
zathura_page_links_get(zathura_page_t* page)
|
||||
girara_list_t*
|
||||
zathura_page_links_get(zathura_page_t* page, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
return NULL;
|
||||
|
@ -429,17 +558,17 @@ zathura_page_links_get(zathura_page_t* page)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return page->document->functions.page_links_get(page);
|
||||
return page->document->functions.page_links_get(page, error);
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_page_links_free(zathura_list_t* UNUSED(list))
|
||||
zathura_plugin_error_t
|
||||
zathura_page_links_free(girara_list_t* UNUSED(list))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
zathura_list_t*
|
||||
zathura_page_form_fields_get(zathura_page_t* page)
|
||||
girara_list_t*
|
||||
zathura_page_form_fields_get(zathura_page_t* page, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
return NULL;
|
||||
|
@ -450,28 +579,78 @@ zathura_page_form_fields_get(zathura_page_t* page)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return page->document->functions.page_form_fields_get(page);
|
||||
return page->document->functions.page_form_fields_get(page, error);
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_page_form_fields_free(zathura_list_t* UNUSED(list))
|
||||
zathura_plugin_error_t
|
||||
zathura_page_form_fields_free(girara_list_t* UNUSED(list))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
zathura_page_render(zathura_page_t* page, cairo_t* cairo)
|
||||
girara_list_t*
|
||||
zathura_page_images_get(zathura_page_t* page, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (page->document->functions.page_images_get == NULL) {
|
||||
girara_error("%s not implemented", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return page->document->functions.page_images_get(page, error);
|
||||
}
|
||||
|
||||
zathura_plugin_error_t
|
||||
zathura_page_image_save(zathura_page_t* page, zathura_image_t* image, const char* file)
|
||||
{
|
||||
if (page == NULL || page->document == NULL || image == NULL || file == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (page->document->functions.page_image_save == NULL) {
|
||||
girara_error("%s not implemented", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return page->document->functions.page_image_save(page, image, file);
|
||||
}
|
||||
|
||||
char* zathura_page_get_text(zathura_page_t* page, zathura_rectangle_t rectangle, zathura_plugin_error_t* error)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
if (error) {
|
||||
*error = ZATHURA_PLUGIN_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (page->document->functions.page_get_text == NULL) {
|
||||
girara_error("%s not implemented", __FUNCTION__);
|
||||
if (error) {
|
||||
*error = ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return page->document->functions.page_get_text(page, rectangle, error);
|
||||
}
|
||||
|
||||
zathura_plugin_error_t
|
||||
zathura_page_render(zathura_page_t* page, cairo_t* cairo, bool printing)
|
||||
{
|
||||
if (page == NULL || page->document == NULL || cairo == NULL) {
|
||||
return NULL;
|
||||
return ZATHURA_PLUGIN_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (page->document->functions.page_render_cairo == NULL) {
|
||||
girara_error("%s not implemented", __FUNCTION__);
|
||||
return NULL;
|
||||
return ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return page->document->functions.page_render_cairo(page, cairo);
|
||||
return page->document->functions.page_render_cairo(page, cairo, printing);
|
||||
}
|
||||
|
||||
zathura_index_element_t*
|
||||
|
@ -483,10 +662,6 @@ zathura_index_element_new(const char* title)
|
|||
|
||||
zathura_index_element_t* res = g_malloc0(sizeof(zathura_index_element_t));
|
||||
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res->title = g_strdup(title);
|
||||
|
||||
return res;
|
||||
|
@ -552,7 +727,7 @@ zathura_type_plugin_mapping_new(zathura_t* zathura, const gchar* type, zathura_d
|
|||
girara_list_iterator_free(iter);
|
||||
return false;
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping)
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping);
|
||||
|
||||
zathura_type_plugin_mapping_t* mapping = g_malloc(sizeof(zathura_type_plugin_mapping_t));
|
||||
mapping->type = g_strdup(type);
|
||||
|
@ -571,3 +746,16 @@ zathura_type_plugin_mapping_free(zathura_type_plugin_mapping_t* mapping)
|
|||
g_free((void*)mapping->type);
|
||||
g_free(mapping);
|
||||
}
|
||||
|
||||
void
|
||||
zathura_link_free(zathura_link_t* link)
|
||||
{
|
||||
if (link == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (link->type == ZATHURA_LINK_EXTERNAL) {
|
||||
g_free(link->target.value);
|
||||
}
|
||||
g_free(link);
|
||||
}
|
||||
|
|
339
document.h
339
document.h
|
@ -7,32 +7,72 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <girara-datastructures.h>
|
||||
#include <girara/types.h>
|
||||
#include "zathura.h"
|
||||
|
||||
#define PLUGIN_REGISTER_FUNCTION "plugin_register"
|
||||
|
||||
typedef struct zathura_list_s zathura_list_t;
|
||||
// typedef struct zathura_document_s zathura_document_t;
|
||||
/**
|
||||
* Error types for plugins
|
||||
*/
|
||||
typedef enum zathura_plugin_error_e
|
||||
{
|
||||
ZATHURA_PLUGIN_ERROR_OK, /**< No error occured */
|
||||
ZATHURA_PLUGIN_ERROR_UNKNOWN, /**< An unknown error occured */
|
||||
ZATHURA_PLUGIN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
|
||||
ZATHURA_PLUGIN_ERROR_NOT_IMPLEMENTED, /**< The called function has not been implemented */
|
||||
ZATHURA_PLUGIN_ERROR_INVALID_ARGUMENTS, /**< Invalid arguments have been passed */
|
||||
ZATHURA_PLUGIN_ERROR_INVALID_PASSWORD /**< The provided password is invalid */
|
||||
} zathura_plugin_error_t;
|
||||
|
||||
typedef bool (*zathura_document_open_t)(zathura_document_t* document);
|
||||
/**
|
||||
* Document open function
|
||||
*
|
||||
* @param document The document
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
typedef zathura_plugin_error_t (*zathura_document_open_t)(zathura_document_t* document);
|
||||
|
||||
/**
|
||||
* Document plugin structure
|
||||
*/
|
||||
typedef struct zathura_document_plugin_s
|
||||
{
|
||||
girara_list_t* content_types; /**> List of supported content types */
|
||||
zathura_document_open_t open_function; /**> Document open function */
|
||||
void* handle; /**> DLL handle */
|
||||
girara_list_t* content_types; /**< List of supported content types */
|
||||
zathura_document_open_t open_function; /**< Document open function */
|
||||
void* handle; /**< DLL handle */
|
||||
} zathura_document_plugin_t;
|
||||
|
||||
/**
|
||||
* Plugin mapping
|
||||
*/
|
||||
typedef struct zathura_type_plugin_mapping_s
|
||||
{
|
||||
const gchar* type;
|
||||
zathura_document_plugin_t* plugin;
|
||||
const gchar* type; /**< Plugin type */
|
||||
zathura_document_plugin_t* plugin; /**< Mapped plugin */
|
||||
} zathura_type_plugin_mapping_t;
|
||||
|
||||
/**
|
||||
* Meta data entries
|
||||
*/
|
||||
typedef enum zathura_document_meta_e
|
||||
{
|
||||
ZATHURA_DOCUMENT_TITLE, /**< Title of the document */
|
||||
ZATHURA_DOCUMENT_AUTHOR, /**< Author of the document */
|
||||
ZATHURA_DOCUMENT_SUBJECT, /**< Subject of the document */
|
||||
ZATHURA_DOCUMENT_KEYWORDS, /**< Keywords of the document */
|
||||
ZATHURA_DOCUMENT_CREATOR, /**< Creator of the document */
|
||||
ZATHURA_DOCUMENT_PRODUCER, /**< Producer of the document */
|
||||
ZATHURA_DOCUMENT_CREATION_DATE, /**< Creation data */
|
||||
ZATHURA_DOCUMENT_MODIFICATION_DATE /**< Modification data */
|
||||
} zathura_document_meta_t;
|
||||
|
||||
typedef struct zathura_password_dialog_info_s
|
||||
{
|
||||
char* path; /**< Path to the file */
|
||||
zathura_t* zathura; /**< Zathura session */
|
||||
} zathura_password_dialog_info_t;
|
||||
|
||||
/**
|
||||
* Function prototype that is called to register a document plugin
|
||||
*
|
||||
|
@ -40,24 +80,15 @@ typedef struct zathura_type_plugin_mapping_s
|
|||
*/
|
||||
typedef void (*zathura_plugin_register_service_t)(zathura_document_plugin_t*);
|
||||
|
||||
/**
|
||||
* Structure for a list
|
||||
*/
|
||||
struct zathura_list_s
|
||||
{
|
||||
void* data; /**> Data value */
|
||||
struct zathura_list_s* next; /**> Next element in the list */
|
||||
};
|
||||
|
||||
/**
|
||||
* Image buffer
|
||||
*/
|
||||
typedef struct zathura_image_buffer_s
|
||||
{
|
||||
unsigned char* data; /**> Image buffer data */
|
||||
unsigned int height; /**> Height of the image */
|
||||
unsigned int width; /**> Width of the image */
|
||||
unsigned int rowstride; /**> Rowstride of the image */
|
||||
unsigned char* data; /**< Image buffer data */
|
||||
unsigned int height; /**< Height of the image */
|
||||
unsigned int width; /**< Width of the image */
|
||||
unsigned int rowstride; /**< Rowstride of the image */
|
||||
} zathura_image_buffer_t;
|
||||
|
||||
/**
|
||||
|
@ -72,28 +103,39 @@ zathura_image_buffer_t* zathura_image_buffer_create(unsigned int width, unsigned
|
|||
/**
|
||||
* Frees the image buffer
|
||||
*
|
||||
* @param zathura_image_buffer_t
|
||||
* @param buffer The image buffer
|
||||
*/
|
||||
void zathura_image_buffer_free(zathura_image_buffer_t*);
|
||||
void zathura_image_buffer_free(zathura_image_buffer_t* buffer);
|
||||
|
||||
/**
|
||||
* Rectangle structure
|
||||
* Rectangle structure.
|
||||
* The coordinate system has its origin in the left upper corner. The x axes
|
||||
* goes to the right, the y access goes down.
|
||||
*/
|
||||
typedef struct zathura_rectangle_s
|
||||
{
|
||||
double x1; /**> X coordinate of point 1 */
|
||||
double y1; /**> Y coordinate of point 1 */
|
||||
double x2; /**> X coordinate of point 2 */
|
||||
double y2; /**> Y coordinate of point 2 */
|
||||
double x1; /**< X coordinate of point 1 */
|
||||
double y1; /**< Y coordinate of point 1 */
|
||||
double x2; /**< X coordinate of point 2 */
|
||||
double y2; /**< Y coordinate of point 2 */
|
||||
} zathura_rectangle_t;
|
||||
|
||||
/**
|
||||
* Image structure
|
||||
*/
|
||||
typedef struct zathura_image_s
|
||||
{
|
||||
zathura_rectangle_t position; /**< Coordinates of the image */
|
||||
void* data; /**< Custom data of the plugin */
|
||||
} zathura_image_t;
|
||||
|
||||
/**
|
||||
* Possible link types
|
||||
*/
|
||||
typedef enum zathura_link_type_e
|
||||
{
|
||||
ZATHURA_LINK_TO_PAGE, /**> Links to a page */
|
||||
ZATHURA_LINK_EXTERNAL, /**> Links to an external source */
|
||||
ZATHURA_LINK_TO_PAGE, /**< Links to a page */
|
||||
ZATHURA_LINK_EXTERNAL, /**< Links to an external source */
|
||||
} zathura_link_type_t;
|
||||
|
||||
/**
|
||||
|
@ -101,12 +143,12 @@ typedef enum zathura_link_type_e
|
|||
*/
|
||||
typedef struct zathura_link_s
|
||||
{
|
||||
zathura_rectangle_t position; /**> Position of the link */
|
||||
zathura_link_type_t type; /**> Link type */
|
||||
zathura_rectangle_t position; /**< Position of the link */
|
||||
zathura_link_type_t type; /**< Link type */
|
||||
union
|
||||
{
|
||||
unsigned int page_number; /**> Page number */
|
||||
char* value; /**> Value */
|
||||
unsigned int page_number; /**< Page number */
|
||||
char* value; /**< Value */
|
||||
} target;
|
||||
} zathura_link_t;
|
||||
|
||||
|
@ -115,12 +157,12 @@ typedef struct zathura_link_s
|
|||
*/
|
||||
typedef struct zathura_index_element_s
|
||||
{
|
||||
char* title; /**> Title of the element */
|
||||
zathura_link_type_t type; /**> Type */
|
||||
char* title; /**< Title of the element */
|
||||
zathura_link_type_t type; /**< Type */
|
||||
union
|
||||
{
|
||||
unsigned int page_number; /**> Page number */
|
||||
char* uri; /**> Uri */
|
||||
unsigned int page_number; /**< Page number */
|
||||
char* uri; /**< Uri */
|
||||
} target;
|
||||
} zathura_index_element_t;
|
||||
|
||||
|
@ -129,8 +171,8 @@ typedef struct zathura_index_element_s
|
|||
*/
|
||||
typedef enum zathura_form_type_e
|
||||
{
|
||||
ZATHURA_FORM_CHECKBOX, /**> Checkbox */
|
||||
ZATHURA_FORM_TEXTFIELD /**> Textfield */
|
||||
ZATHURA_FORM_CHECKBOX, /**< Checkbox */
|
||||
ZATHURA_FORM_TEXTFIELD /**< Textfield */
|
||||
} zathura_form_type_t;
|
||||
|
||||
/**
|
||||
|
@ -138,8 +180,8 @@ typedef enum zathura_form_type_e
|
|||
*/
|
||||
typedef struct zathura_form_s
|
||||
{
|
||||
zathura_rectangle_t position; /**> Position */
|
||||
zathura_form_type_t type; /**> Type */
|
||||
zathura_rectangle_t position; /**< Position */
|
||||
zathura_form_type_t type; /**< Type */
|
||||
} zathura_form_t;
|
||||
|
||||
/**
|
||||
|
@ -147,16 +189,13 @@ typedef struct zathura_form_s
|
|||
*/
|
||||
struct zathura_page_s
|
||||
{
|
||||
double height; /**> Page height */
|
||||
double width; /**> Page width */
|
||||
unsigned int number; /**> Page number */
|
||||
zathura_document_t* document; /**> Document */
|
||||
void* data; /**> Custom data */
|
||||
bool visible; /**> Page is visible */
|
||||
GtkWidget* event_box; /**> Widget wrapper for mouse events */
|
||||
GtkWidget* drawing_area; /**> Drawing area */
|
||||
GStaticMutex lock; /**> Lock */
|
||||
cairo_surface_t* surface; /** Cairo surface */
|
||||
double height; /**< Page height */
|
||||
double width; /**< Page width */
|
||||
unsigned int number; /**< Page number */
|
||||
zathura_document_t* document; /**< Document */
|
||||
void* data; /**< Custom data */
|
||||
bool visible; /**< Page is visible */
|
||||
GtkWidget* drawing_area; /**< Drawing area */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,77 +203,111 @@ struct zathura_page_s
|
|||
*/
|
||||
struct zathura_document_s
|
||||
{
|
||||
char* file_path; /**> File path of the document */
|
||||
const char* password; /**> Password of the document */
|
||||
unsigned int current_page_number; /**> Current page number */
|
||||
unsigned int number_of_pages; /**> Number of pages */
|
||||
double scale; /**> Scale value */
|
||||
int rotate; /**> Rotation */
|
||||
void* data; /**> Custom data */
|
||||
char* file_path; /**< File path of the document */
|
||||
const char* password; /**< Password of the document */
|
||||
unsigned int current_page_number; /**< Current page number */
|
||||
unsigned int number_of_pages; /**< Number of pages */
|
||||
double scale; /**< Scale value */
|
||||
int rotate; /**< Rotation */
|
||||
void* data; /**< Custom data */
|
||||
zathura_t* zathura; /** Zathura object */
|
||||
int adjust_mode; /**< Adjust mode (best-fit, width) */
|
||||
|
||||
struct
|
||||
{
|
||||
/**
|
||||
* Frees the document
|
||||
*/
|
||||
bool (*document_free)(zathura_document_t* document);
|
||||
zathura_plugin_error_t (*document_free)(zathura_document_t* document);
|
||||
|
||||
/**
|
||||
* Generates the document index
|
||||
*/
|
||||
girara_tree_node_t* (*document_index_generate)(zathura_document_t* document);
|
||||
girara_tree_node_t* (*document_index_generate)(zathura_document_t* document, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Save the document
|
||||
*/
|
||||
bool (*document_save_as)(zathura_document_t* document, const char* path);
|
||||
zathura_plugin_error_t (*document_save_as)(zathura_document_t* document, const char* path);
|
||||
|
||||
/**
|
||||
* Get list of attachments
|
||||
*/
|
||||
zathura_list_t* (*document_attachments_get)(zathura_document_t* document);
|
||||
girara_list_t* (*document_attachments_get)(zathura_document_t* document, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Save attachment to a file
|
||||
*/
|
||||
zathura_plugin_error_t (*document_attachment_save)(zathura_document_t* document, const char* attachment, const char* file);
|
||||
|
||||
/**
|
||||
* Get document information
|
||||
*/
|
||||
char* (*document_meta_get)(zathura_document_t* document, zathura_document_meta_t info, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Gets the page object
|
||||
*/
|
||||
zathura_page_t* (*page_get)(zathura_document_t* document, unsigned int page_id);
|
||||
zathura_page_t* (*page_get)(zathura_document_t* document, unsigned int page_id, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Search text
|
||||
*/
|
||||
zathura_list_t* (*page_search_text)(zathura_page_t* page, const char* text);
|
||||
girara_list_t* (*page_search_text)(zathura_page_t* page, const char* text, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get links on a page
|
||||
*/
|
||||
zathura_list_t* (*page_links_get)(zathura_page_t* page);
|
||||
girara_list_t* (*page_links_get)(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get form fields
|
||||
*/
|
||||
zathura_list_t* (*page_form_fields_get)(zathura_page_t* page);
|
||||
girara_list_t* (*page_form_fields_get)(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get list of images
|
||||
*/
|
||||
girara_list_t* (*page_images_get)(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Save image to a file
|
||||
*/
|
||||
zathura_plugin_error_t (*page_image_save)(zathura_page_t* page, zathura_image_t* image, const char* file);
|
||||
|
||||
/**
|
||||
* Get text for selection
|
||||
*/
|
||||
char* (*page_get_text)(zathura_page_t* page, zathura_rectangle_t rectangle, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Renders the page
|
||||
*/
|
||||
zathura_image_buffer_t* (*page_render)(zathura_page_t* page);
|
||||
zathura_image_buffer_t* (*page_render)(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Renders the page
|
||||
*/
|
||||
bool (*page_render_cairo)(zathura_page_t* page, cairo_t* cairo);
|
||||
zathura_plugin_error_t (*page_render_cairo)(zathura_page_t* page, cairo_t* cairo, bool printing);
|
||||
|
||||
/**
|
||||
* Free page
|
||||
*/
|
||||
bool (*page_free)(zathura_page_t* page);
|
||||
zathura_plugin_error_t (*page_free)(zathura_page_t* page);
|
||||
} functions;
|
||||
|
||||
/**
|
||||
* Document pages
|
||||
*/
|
||||
zathura_page_t** pages;
|
||||
|
||||
/**
|
||||
* File monitor
|
||||
*/
|
||||
struct {
|
||||
GFileMonitor* monitor; /**< File monitor */
|
||||
GFile* file; /**< File for file monitor */
|
||||
} file_monitor;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -251,128 +324,189 @@ void zathura_document_plugins_load(zathura_t* zathura);
|
|||
*/
|
||||
void zathura_document_plugin_free(zathura_document_plugin_t* plugin);
|
||||
|
||||
/**
|
||||
* Register document plugin
|
||||
*/
|
||||
bool zathura_document_plugin_register(zathura_t* zathura, zathura_document_plugin_t* new_plugin, void* handle);
|
||||
|
||||
/**
|
||||
* Open the document
|
||||
*
|
||||
* @param zathura Zathura object
|
||||
* @param path Path to the document
|
||||
* @param password Password of the document or NULL
|
||||
* @return The document object
|
||||
*/
|
||||
zathura_document_t* zathura_document_open(zathura_t* zathura, const char* path, const char* password);
|
||||
zathura_document_t* zathura_document_open(zathura_t* zathura, const char* path,
|
||||
const char* password);
|
||||
|
||||
/**
|
||||
* Free the document
|
||||
*
|
||||
* @param document
|
||||
* @return true if no error occured, otherwise false
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_document_free(zathura_document_t* document);
|
||||
zathura_plugin_error_t zathura_document_free(zathura_document_t* document);
|
||||
|
||||
/**
|
||||
* Save the document
|
||||
*
|
||||
* @param document The document object
|
||||
* @param path Path for the saved file
|
||||
* @return true if no error occured, otherwise false
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_document_save_as(zathura_document_t* document, const char* path);
|
||||
zathura_plugin_error_t zathura_document_save_as(zathura_document_t* document, const char* path);
|
||||
|
||||
/**
|
||||
* Generate the document index
|
||||
*
|
||||
* @param document The document object
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return Generated index
|
||||
*/
|
||||
|
||||
girara_tree_node_t* zathura_document_index_generate(zathura_document_t* document);
|
||||
girara_tree_node_t* zathura_document_index_generate(zathura_document_t* document, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get list of attachments
|
||||
*
|
||||
* @param document The document object
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return List of attachments
|
||||
*/
|
||||
zathura_list_t* zathura_document_attachments_get(zathura_document_t* document);
|
||||
girara_list_t* zathura_document_attachments_get(zathura_document_t* document, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Free document attachments
|
||||
* Save document attachment
|
||||
*
|
||||
* @param list list of document attachments
|
||||
* @return
|
||||
* @param document The document objects
|
||||
* @param attachment name of the attachment
|
||||
* @param file the target filename
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_document_attachments_free(zathura_list_t* list);
|
||||
zathura_plugin_error_t zathura_document_attachment_save(zathura_document_t* document, const char* attachment, const char* file);
|
||||
|
||||
/**
|
||||
* Returns a string of the requested information
|
||||
*
|
||||
* @param document The zathura document
|
||||
* @param meta The information field
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return String or NULL if information could not be retreived
|
||||
*/
|
||||
char* zathura_document_meta_get(zathura_document_t* document, zathura_document_meta_t meta, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get the page object
|
||||
*
|
||||
* @param document The document
|
||||
* @param page_id Page number
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return Page object or NULL if an error occured
|
||||
*/
|
||||
zathura_page_t* zathura_page_get(zathura_document_t* document, unsigned int page_id);
|
||||
zathura_page_t* zathura_page_get(zathura_document_t* document, unsigned int page_id, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Frees the page object
|
||||
*
|
||||
* @param page The page object
|
||||
* @return true if no error occured, otherwise false
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_page_free(zathura_page_t* page);
|
||||
zathura_plugin_error_t zathura_page_free(zathura_page_t* page);
|
||||
|
||||
/**
|
||||
* Search page
|
||||
*
|
||||
* @param page The page object
|
||||
* @param text Search item
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return List of results
|
||||
*/
|
||||
zathura_list_t* zathura_page_search_text(zathura_page_t* page, const char* text);
|
||||
girara_list_t* zathura_page_search_text(zathura_page_t* page, const char* text, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Get page links
|
||||
*
|
||||
* @param page The page object
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return List of links
|
||||
*/
|
||||
zathura_list_t* zathura_page_links_get(zathura_page_t* page);
|
||||
girara_list_t* zathura_page_links_get(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Free page links
|
||||
*
|
||||
* @param list List of links
|
||||
* @return true if no error occured, otherwise false
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_page_links_free(zathura_list_t* list);
|
||||
zathura_plugin_error_t zathura_page_links_free(girara_list_t* list);
|
||||
|
||||
/**
|
||||
* Get list of form fields
|
||||
*
|
||||
* @param page The page object
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return List of form fields
|
||||
*/
|
||||
zathura_list_t* zathura_page_form_fields_get(zathura_page_t* page);
|
||||
girara_list_t* zathura_page_form_fields_get(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Free list of form fields
|
||||
*
|
||||
* @param list List of form fields
|
||||
* @return true if no error occured, otherwise false
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_page_form_fields_free(zathura_list_t* list);
|
||||
zathura_plugin_error_t zathura_page_form_fields_free(girara_list_t* list);
|
||||
|
||||
/**
|
||||
* Get list of images
|
||||
*
|
||||
* @param page Page
|
||||
* @param error Set to an error value (see \ref zathura_plugin_error_t) if an
|
||||
* error occured
|
||||
* @return List of images or NULL if an error occured
|
||||
*/
|
||||
girara_list_t* zathura_page_images_get(zathura_page_t* page, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Save image
|
||||
*
|
||||
* @param page Page
|
||||
* @param image The image
|
||||
* @param file Path to the file
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
zathura_plugin_error_t zathura_page_image_save(zathura_page_t* page, zathura_image_t* image, const char* file);
|
||||
|
||||
/**
|
||||
* Get text for selection
|
||||
* @param page Page
|
||||
* @param rectangle Selection
|
||||
* @error Set to an error value (see \ref zathura_plugin_error_t) if an error
|
||||
* occured
|
||||
* @return The selected text (needs to be deallocated with g_free)
|
||||
*/
|
||||
char* zathura_page_get_text(zathura_page_t* page, zathura_rectangle_t rectangle, zathura_plugin_error_t* error);
|
||||
|
||||
/**
|
||||
* Render page
|
||||
*
|
||||
* @param page The page object
|
||||
* @param cairo Cairo object
|
||||
* @return True if no error occured, otherwise false
|
||||
* @param printing render for printing
|
||||
* @return ZATHURA_PLUGIN_ERROR_OK when no error occured, otherwise see
|
||||
* zathura_plugin_error_t
|
||||
*/
|
||||
bool zathura_page_render(zathura_page_t* page, cairo_t* cairo);
|
||||
zathura_plugin_error_t zathura_page_render(zathura_page_t* page, cairo_t* cairo, bool printing);
|
||||
|
||||
/**
|
||||
* Create new index element
|
||||
|
@ -389,6 +523,13 @@ zathura_index_element_t* zathura_index_element_new(const char* title);
|
|||
*/
|
||||
void zathura_index_element_free(zathura_index_element_t* index);
|
||||
|
||||
/**
|
||||
* Free link
|
||||
*
|
||||
* @param link The link
|
||||
*/
|
||||
void zathura_link_free(zathura_link_t* link);
|
||||
|
||||
/**
|
||||
* Add type -> plugin mapping
|
||||
* @param zathura zathura instance
|
||||
|
|
29
main.c
Normal file
29
main.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "zathura.h"
|
||||
|
||||
/* main function */
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_thread_init(NULL);
|
||||
gdk_threads_init();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
zathura_t* zathura = zathura_init(argc, argv);
|
||||
if (zathura == NULL) {
|
||||
fprintf(stderr, "error: could not initialize zathura\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_main();
|
||||
gdk_threads_leave();
|
||||
|
||||
zathura_free(zathura);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
535
page_widget.c
Normal file
535
page_widget.c
Normal file
|
@ -0,0 +1,535 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <girara/utils.h>
|
||||
#include <girara/settings.h>
|
||||
#include <girara/datastructures.h>
|
||||
|
||||
#include "page_widget.h"
|
||||
#include "render.h"
|
||||
#include "utils.h"
|
||||
#include "shortcuts.h"
|
||||
|
||||
G_DEFINE_TYPE(ZathuraPage, zathura_page_widget, GTK_TYPE_DRAWING_AREA)
|
||||
|
||||
typedef struct zathura_page_widget_private_s {
|
||||
zathura_page_t* page;
|
||||
zathura_t* zathura;
|
||||
cairo_surface_t* surface; /** Cairo surface */
|
||||
GStaticMutex lock; /**< Lock */
|
||||
girara_list_t* links; /**< List of links on the page */
|
||||
bool links_got; /**< True if we already tried to retrieve the list of links */
|
||||
bool draw_links; /**< True if links should be drawn */
|
||||
unsigned int link_offset; /**< Offset to the links */
|
||||
unsigned int number_of_links; /**< Offset to the links */
|
||||
girara_list_t* search_results; /** A list if there are search results that should be drawn */
|
||||
int search_current; /** The index of the current search result */
|
||||
zathura_rectangle_t selection; /** Region selected with the mouse */
|
||||
} zathura_page_widget_private_t;
|
||||
|
||||
#define ZATHURA_PAGE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), ZATHURA_TYPE_PAGE, zathura_page_widget_private_t))
|
||||
|
||||
static gboolean zathura_page_widget_expose(GtkWidget* widget, GdkEventExpose* event);
|
||||
static void zathura_page_widget_finalize(GObject* object);
|
||||
static void zathura_page_widget_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
|
||||
static void zathura_page_widget_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec);
|
||||
static void zathura_page_widget_size_allocate(GtkWidget* widget, GdkRectangle* allocation);
|
||||
static void redraw_rect(ZathuraPage* widget, zathura_rectangle_t* rectangle);
|
||||
static void redraw_all_rects(ZathuraPage* widget, girara_list_t* rectangles);
|
||||
static gboolean cb_zathura_page_widget_button_press_event(GtkWidget* widget, GdkEventButton* button);
|
||||
static gboolean cb_zathura_page_widget_button_release_event(GtkWidget* widget, GdkEventButton* button);
|
||||
static gboolean cb_zathura_page_widget_motion_notify(GtkWidget* widget, GdkEventMotion* event);
|
||||
|
||||
enum properties_e
|
||||
{
|
||||
PROP_0,
|
||||
PROP_PAGE,
|
||||
PROP_DRAW_LINKS,
|
||||
PROP_LINKS_OFFSET,
|
||||
PROP_LINKS_NUMBER,
|
||||
PROP_SEARCH_RESULT,
|
||||
PROP_SEARCH_RESULTS,
|
||||
PROP_SEARCH_RESULTS_LENGTH,
|
||||
PROP_SEARCH_RESULTS_CURRENT
|
||||
};
|
||||
|
||||
static void
|
||||
zathura_page_widget_class_init(ZathuraPageClass* class)
|
||||
{
|
||||
/* add private members */
|
||||
g_type_class_add_private(class, sizeof(zathura_page_widget_private_t));
|
||||
|
||||
/* overwrite methods */
|
||||
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(class);
|
||||
widget_class->expose_event = zathura_page_widget_expose;
|
||||
widget_class->size_allocate = zathura_page_widget_size_allocate;
|
||||
widget_class->button_press_event = cb_zathura_page_widget_button_press_event;
|
||||
widget_class->button_release_event = cb_zathura_page_widget_button_release_event;
|
||||
widget_class->motion_notify_event = cb_zathura_page_widget_motion_notify;
|
||||
|
||||
GObjectClass* object_class = G_OBJECT_CLASS(class);
|
||||
object_class->finalize = zathura_page_widget_finalize;
|
||||
object_class->set_property = zathura_page_widget_set_property;
|
||||
object_class->get_property = zathura_page_widget_get_property;
|
||||
|
||||
/* add properties */
|
||||
g_object_class_install_property(object_class, PROP_PAGE,
|
||||
g_param_spec_pointer("page", "page", "the page to draw", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property(object_class, PROP_DRAW_LINKS,
|
||||
g_param_spec_boolean("draw-links", "draw-links", "Set to true if links should be drawn", FALSE, G_PARAM_WRITABLE));
|
||||
g_object_class_install_property(object_class, PROP_LINKS_OFFSET,
|
||||
g_param_spec_int("offset-links", "offset-links", "Offset for the link numbers", 0, INT_MAX, 0, G_PARAM_WRITABLE));
|
||||
g_object_class_install_property(object_class, PROP_LINKS_NUMBER,
|
||||
g_param_spec_int("number-of-links", "number-of-links", "Number of links", 0, INT_MAX, 0, G_PARAM_READABLE));
|
||||
g_object_class_install_property(object_class, PROP_SEARCH_RESULTS,
|
||||
g_param_spec_pointer("search-results", "search-results", "Set to the list of search results", G_PARAM_WRITABLE | G_PARAM_READABLE));
|
||||
g_object_class_install_property(object_class, PROP_SEARCH_RESULTS_CURRENT,
|
||||
g_param_spec_int("search-current", "search-current", "The current search result", -1, INT_MAX, 0, G_PARAM_WRITABLE | G_PARAM_READABLE));
|
||||
g_object_class_install_property(object_class, PROP_SEARCH_RESULTS_LENGTH,
|
||||
g_param_spec_int("search-length", "search-length", "The number of search results", -1, INT_MAX, 0, G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_init(ZathuraPage* widget)
|
||||
{
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
priv->page = NULL;
|
||||
priv->surface = NULL;
|
||||
priv->links = NULL;
|
||||
priv->links_got = false;
|
||||
priv->link_offset = 0;
|
||||
priv->search_results = NULL;
|
||||
priv->search_current = INT_MAX;
|
||||
priv->selection.x1 = -1;
|
||||
g_static_mutex_init(&(priv->lock));
|
||||
|
||||
/* we want mouse events */
|
||||
gtk_widget_add_events(GTK_WIDGET(widget),
|
||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
zathura_page_widget_new(zathura_page_t* page)
|
||||
{
|
||||
g_return_val_if_fail(page != NULL, NULL);
|
||||
|
||||
return g_object_new(ZATHURA_TYPE_PAGE, "page", page, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_finalize(GObject* object)
|
||||
{
|
||||
ZathuraPage* widget = ZATHURA_PAGE(object);
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
if (priv->surface) {
|
||||
cairo_surface_destroy(priv->surface);
|
||||
}
|
||||
g_static_mutex_free(&(priv->lock));
|
||||
girara_list_free(priv->links);
|
||||
|
||||
G_OBJECT_CLASS(zathura_page_widget_parent_class)->finalize(object);
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
|
||||
{
|
||||
ZathuraPage* pageview = ZATHURA_PAGE(object);
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(pageview);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PAGE:
|
||||
priv->page = g_value_get_pointer(value);
|
||||
priv->zathura = priv->page->document->zathura;
|
||||
break;
|
||||
case PROP_DRAW_LINKS:
|
||||
priv->draw_links = g_value_get_boolean(value);
|
||||
/* get links */
|
||||
if (priv->draw_links == true && priv->links_got == false) {
|
||||
priv->links = zathura_page_links_get(priv->page, NULL);
|
||||
priv->links_got = true;
|
||||
priv->number_of_links = (priv->links == NULL) ? 0 : girara_list_size(priv->links);
|
||||
}
|
||||
|
||||
if (priv->links_got == true && priv->links != NULL) {
|
||||
GIRARA_LIST_FOREACH(priv->links, zathura_link_t*, iter, link)
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, link->position);
|
||||
redraw_rect(pageview, &rectangle);
|
||||
GIRARA_LIST_FOREACH_END(priv->links, zathura_link_t*, iter, link);
|
||||
}
|
||||
break;
|
||||
case PROP_LINKS_OFFSET:
|
||||
priv->link_offset = g_value_get_int(value);
|
||||
break;
|
||||
case PROP_SEARCH_RESULTS:
|
||||
if (priv->search_results != NULL) {
|
||||
redraw_all_rects(pageview, priv->search_results);
|
||||
girara_list_free(priv->search_results);
|
||||
}
|
||||
priv->search_results = g_value_get_pointer(value);
|
||||
if (priv->search_results != NULL) {
|
||||
priv->draw_links = false;
|
||||
redraw_all_rects(pageview, priv->search_results);
|
||||
}
|
||||
priv->search_current = -1;
|
||||
break;
|
||||
case PROP_SEARCH_RESULTS_CURRENT: {
|
||||
g_return_if_fail(priv->search_results != NULL);
|
||||
if (priv->search_current >= 0 && priv->search_current < (signed) girara_list_size(priv->search_results)) {
|
||||
zathura_rectangle_t* rect = girara_list_nth(priv->search_results, priv->search_current);
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, *rect);
|
||||
redraw_rect(pageview, &rectangle);
|
||||
}
|
||||
int val = g_value_get_int(value);
|
||||
if (val < 0) {
|
||||
priv->search_current = girara_list_size(priv->search_results);
|
||||
} else {
|
||||
priv->search_current = val;
|
||||
zathura_rectangle_t* rect = girara_list_nth(priv->search_results, priv->search_current);
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, *rect);
|
||||
redraw_rect(pageview, &rectangle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
|
||||
{
|
||||
ZathuraPage* pageview = ZATHURA_PAGE(object);
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(pageview);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LINKS_NUMBER:
|
||||
g_value_set_int(value, priv->number_of_links);
|
||||
break;
|
||||
case PROP_SEARCH_RESULTS_LENGTH:
|
||||
g_value_set_int(value, priv->search_results == NULL ? 0 : girara_list_size(priv->search_results));
|
||||
break;
|
||||
case PROP_SEARCH_RESULTS_CURRENT:
|
||||
g_value_set_int(value, priv->search_results == NULL ? -1 : priv->search_current);
|
||||
break;
|
||||
case PROP_SEARCH_RESULTS:
|
||||
g_value_set_pointer(value, priv->search_results);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zathura_page_widget_expose(GtkWidget* widget, GdkEventExpose* event)
|
||||
{
|
||||
cairo_t* cairo = gdk_cairo_create(widget->window);
|
||||
if (cairo == NULL) {
|
||||
girara_error("Could not retreive cairo object");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* set clip region */
|
||||
cairo_rectangle(cairo, event->area.x, event->area.y, event->area.width, event->area.height);
|
||||
cairo_clip(cairo);
|
||||
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
g_static_mutex_lock(&(priv->lock));
|
||||
if (priv->surface != NULL) {
|
||||
cairo_save(cairo);
|
||||
|
||||
unsigned int page_height = widget->allocation.height;
|
||||
unsigned int page_width = widget->allocation.width;
|
||||
|
||||
switch (priv->page->document->rotate) {
|
||||
case 90:
|
||||
cairo_translate(cairo, page_width, 0);
|
||||
break;
|
||||
case 180:
|
||||
cairo_translate(cairo, page_width, page_height);
|
||||
break;
|
||||
case 270:
|
||||
cairo_translate(cairo, 0, page_height);
|
||||
break;
|
||||
}
|
||||
|
||||
if (priv->page->document->rotate != 0) {
|
||||
cairo_rotate(cairo, priv->page->document->rotate * G_PI / 180.0);
|
||||
}
|
||||
|
||||
cairo_set_source_surface(cairo, priv->surface, 0, 0);
|
||||
cairo_paint(cairo);
|
||||
cairo_restore(cairo);
|
||||
|
||||
/* draw rectangles */
|
||||
char* font = NULL;
|
||||
girara_setting_get(priv->zathura->ui.session, "font", &font);
|
||||
|
||||
float transparency = 0.5;
|
||||
girara_setting_get(priv->zathura->ui.session, "highlight-transparency", &transparency);
|
||||
|
||||
if (font != NULL) {
|
||||
cairo_select_font_face(cairo, font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
||||
}
|
||||
g_free(font);
|
||||
|
||||
/* draw links */
|
||||
if (priv->draw_links == true && priv->number_of_links != 0) {
|
||||
unsigned int link_counter = 0;
|
||||
GIRARA_LIST_FOREACH(priv->links, zathura_link_t*, iter, link)
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, link->position);
|
||||
|
||||
/* draw position */
|
||||
GdkColor color = priv->zathura->ui.colors.highlight_color;
|
||||
cairo_set_source_rgba(cairo, color.red, color.green, color.blue, transparency);
|
||||
cairo_rectangle(cairo, rectangle.x1, rectangle.y1,
|
||||
(rectangle.x2 - rectangle.x1), (rectangle.y2 - rectangle.y1));
|
||||
cairo_fill(cairo);
|
||||
|
||||
/* draw text */
|
||||
cairo_set_source_rgba(cairo, 0, 0, 0, 1);
|
||||
cairo_set_font_size(cairo, 10);
|
||||
cairo_move_to(cairo, rectangle.x1 + 1, rectangle.y2 - 1);
|
||||
char* link_number = g_strdup_printf("%i", priv->link_offset + ++link_counter);
|
||||
cairo_show_text(cairo, link_number);
|
||||
g_free(link_number);
|
||||
GIRARA_LIST_FOREACH_END(priv->links, zathura_link_t*, iter, link);
|
||||
}
|
||||
|
||||
/* draw search results */
|
||||
if (priv->search_results != NULL) {
|
||||
int idx = 0;
|
||||
GIRARA_LIST_FOREACH(priv->search_results, zathura_rectangle_t*, iter, rect)
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, *rect);
|
||||
|
||||
/* draw position */
|
||||
GdkColor color = priv->zathura->ui.colors.highlight_color;
|
||||
if (idx == priv->search_current) {
|
||||
cairo_set_source_rgba(cairo, 0, color.green, color.blue, transparency);
|
||||
} else {
|
||||
cairo_set_source_rgba(cairo, color.red, color.green, color.blue, transparency);
|
||||
}
|
||||
cairo_rectangle(cairo, rectangle.x1, rectangle.y1,
|
||||
(rectangle.x2 - rectangle.x1), (rectangle.y2 - rectangle.y1));
|
||||
cairo_fill(cairo);
|
||||
++idx;
|
||||
GIRARA_LIST_FOREACH_END(priv->search_results, zathura_rectangle_t*, iter, rect);
|
||||
}
|
||||
/* draw selection */
|
||||
if (priv->selection.y2 != -1 && priv->selection.x2 != -1) {
|
||||
GdkColor color = priv->zathura->ui.colors.highlight_color;
|
||||
cairo_set_source_rgba(cairo, color.red, color.green, color.blue, transparency);
|
||||
cairo_rectangle(cairo, priv->selection.x1, priv->selection.y1,
|
||||
(priv->selection.x2 - priv->selection.x1), (priv->selection.y2 - priv->selection.y1));
|
||||
cairo_fill(cairo);
|
||||
}
|
||||
} else {
|
||||
/* set background color */
|
||||
cairo_set_source_rgb(cairo, 255, 255, 255);
|
||||
cairo_rectangle(cairo, 0, 0, widget->allocation.width, widget->allocation.height);
|
||||
cairo_fill(cairo);
|
||||
|
||||
bool render_loading = true;
|
||||
girara_setting_get(priv->zathura->ui.session, "render-loading", &render_loading);
|
||||
|
||||
/* write text */
|
||||
if (render_loading == true) {
|
||||
cairo_set_source_rgb(cairo, 0, 0, 0);
|
||||
const char* text = "Loading...";
|
||||
cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(cairo, 16.0);
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents(cairo, text, &extents);
|
||||
double x = widget->allocation.width * 0.5 - (extents.width * 0.5 + extents.x_bearing);
|
||||
double y = widget->allocation.height * 0.5 - (extents.height * 0.5 + extents.y_bearing);
|
||||
cairo_move_to(cairo, x, y);
|
||||
cairo_show_text(cairo, text);
|
||||
}
|
||||
|
||||
/* render real page */
|
||||
render_page(priv->zathura->sync.render_thread, priv->page);
|
||||
}
|
||||
cairo_destroy(cairo);
|
||||
|
||||
g_static_mutex_unlock(&(priv->lock));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_redraw_canvas(ZathuraPage* pageview)
|
||||
{
|
||||
GtkWidget* widget = GTK_WIDGET(pageview);
|
||||
gtk_widget_queue_draw(widget);
|
||||
}
|
||||
|
||||
void
|
||||
zathura_page_widget_update_surface(ZathuraPage* widget, cairo_surface_t* surface)
|
||||
{
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
g_static_mutex_lock(&(priv->lock));
|
||||
if (priv->surface != NULL) {
|
||||
cairo_surface_destroy(priv->surface);
|
||||
}
|
||||
priv->surface = surface;
|
||||
g_static_mutex_unlock(&(priv->lock));
|
||||
/* force a redraw here */
|
||||
zathura_page_widget_redraw_canvas(widget);
|
||||
}
|
||||
|
||||
static void
|
||||
zathura_page_widget_size_allocate(GtkWidget* widget, GdkRectangle* allocation)
|
||||
{
|
||||
GTK_WIDGET_CLASS(zathura_page_widget_parent_class)->size_allocate(widget, allocation);
|
||||
zathura_page_widget_update_surface(ZATHURA_PAGE(widget), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_rect(ZathuraPage* widget, zathura_rectangle_t* rectangle)
|
||||
{
|
||||
/* cause the rect to be drawn */
|
||||
GdkRectangle grect;
|
||||
grect.x = rectangle->x1;
|
||||
grect.y = rectangle->y1;
|
||||
grect.width = rectangle->x2 - rectangle->x1;
|
||||
grect.height = rectangle->y2 - rectangle->y1;
|
||||
gdk_window_invalidate_rect(GTK_WIDGET(widget)->window, &grect, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_all_rects(ZathuraPage* widget, girara_list_t* rectangles)
|
||||
{
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
|
||||
GIRARA_LIST_FOREACH(rectangles, zathura_rectangle_t*, iter, rect)
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(priv->page, *rect);
|
||||
redraw_rect(widget, &rectangle);
|
||||
GIRARA_LIST_FOREACH_END(rectangles, zathura_recantgle_t*, iter, rect);
|
||||
}
|
||||
|
||||
zathura_link_t*
|
||||
zathura_page_widget_link_get(ZathuraPage* widget, unsigned int index)
|
||||
{
|
||||
g_return_val_if_fail(widget != NULL, NULL);
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
g_return_val_if_fail(priv != NULL, NULL);
|
||||
|
||||
if (priv->links != NULL && index >= priv->link_offset &&
|
||||
girara_list_size(priv->links) >= index - priv->link_offset) {
|
||||
return girara_list_nth(priv->links, index - priv->link_offset);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cb_zathura_page_widget_button_press_event(GtkWidget* widget, GdkEventButton* button)
|
||||
{
|
||||
g_return_val_if_fail(widget != NULL, false);
|
||||
g_return_val_if_fail(button != NULL, false);
|
||||
if (button->button != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
|
||||
if (button->type == GDK_BUTTON_PRESS) {
|
||||
/* start the selection */
|
||||
priv->selection.x1 = button->x;
|
||||
priv->selection.y1 = button->y;
|
||||
priv->selection.x2 = -1;
|
||||
priv->selection.y2 = -1;
|
||||
} else if (button->type == GDK_2BUTTON_PRESS || button->type == GDK_3BUTTON_PRESS) {
|
||||
/* abort the selection */
|
||||
priv->selection.x1 = -1;
|
||||
priv->selection.y1 = -1;
|
||||
priv->selection.x2 = -1;
|
||||
priv->selection.y2 = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cb_zathura_page_widget_button_release_event(GtkWidget* widget, GdkEventButton* button)
|
||||
{
|
||||
g_return_val_if_fail(widget != NULL, false);
|
||||
g_return_val_if_fail(button != NULL, false);
|
||||
if (button->type != GDK_BUTTON_RELEASE || button->button != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
|
||||
if (priv->selection.y2 == -1 && priv->selection.x2 == -1 ) {
|
||||
/* simple single click */
|
||||
/* get links */
|
||||
if (priv->links_got == false) {
|
||||
priv->links = zathura_page_links_get(priv->page, NULL);
|
||||
priv->links_got = true;
|
||||
priv->number_of_links = (priv->links == NULL) ? 0 : girara_list_size(priv->links);
|
||||
}
|
||||
|
||||
if (priv->links != NULL && priv->number_of_links > 0) {
|
||||
GIRARA_LIST_FOREACH(priv->links, zathura_link_t*, iter, link)
|
||||
zathura_rectangle_t rect = recalc_rectangle(priv->page, link->position);
|
||||
if (rect.x1 <= button->x && rect.x2 >= button->x
|
||||
&& rect.y1 <= button->y && rect.y2 >= button->y) {
|
||||
switch (link->type) {
|
||||
case ZATHURA_LINK_TO_PAGE:
|
||||
page_set_delayed(priv->page->document->zathura, link->target.page_number);
|
||||
return false;
|
||||
case ZATHURA_LINK_EXTERNAL:
|
||||
girara_xdg_open(link->target.value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(priv->links, zathura_link_t*, iter, link);
|
||||
}
|
||||
} else {
|
||||
redraw_rect(ZATHURA_PAGE(widget), &priv->selection);
|
||||
zathura_rectangle_t tmp = priv->selection;
|
||||
tmp.x1 /= priv->page->document->scale;
|
||||
tmp.x2 /= priv->page->document->scale;
|
||||
tmp.y1 /= priv->page->document->scale;
|
||||
tmp.y2 /= priv->page->document->scale;
|
||||
|
||||
char* text = zathura_page_get_text(priv->page, tmp, NULL);
|
||||
if (text != NULL) {
|
||||
gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), text, -1);
|
||||
g_free(text);
|
||||
}
|
||||
}
|
||||
priv->selection.x1 = -1;
|
||||
priv->selection.y1 = -1;
|
||||
priv->selection.x2 = -1;
|
||||
priv->selection.y2 = -1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cb_zathura_page_widget_motion_notify(GtkWidget* widget, GdkEventMotion* event)
|
||||
{
|
||||
g_return_val_if_fail(widget != NULL, false);
|
||||
g_return_val_if_fail(event != NULL, false);
|
||||
if ((event->state & GDK_BUTTON1_MASK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
zathura_page_widget_private_t* priv = ZATHURA_PAGE_GET_PRIVATE(widget);
|
||||
zathura_rectangle_t tmp = priv->selection;
|
||||
if (event->x < priv->selection.x1) {
|
||||
tmp.x1 = event->x;
|
||||
} else {
|
||||
tmp.x2 = event->x;
|
||||
}
|
||||
if (event->y < priv->selection.y1) {
|
||||
tmp.y1 = event->y;
|
||||
} else {
|
||||
tmp.y2 = event->y;
|
||||
}
|
||||
|
||||
redraw_rect(ZATHURA_PAGE(widget), &priv->selection);
|
||||
redraw_rect(ZATHURA_PAGE(widget), &tmp);
|
||||
priv->selection = tmp;
|
||||
|
||||
return false;
|
||||
}
|
81
page_widget.h
Normal file
81
page_widget.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#ifndef PAGE_WIDGET_H
|
||||
#define PAGE_WIDGET_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "document.h"
|
||||
|
||||
/**
|
||||
* The page view widget. The widget handles all the rendering on its own. It
|
||||
* only has to be resized. The widget also manages and handles all the
|
||||
* rectangles for highlighting.
|
||||
*
|
||||
* Before the properties contain the correct values, 'draw-links' has to be set
|
||||
* to TRUE at least one time.
|
||||
* */
|
||||
typedef struct zathura_page_widget_s ZathuraPage;
|
||||
typedef struct zathura_page_widget_class_s ZathuraPageClass;
|
||||
|
||||
struct zathura_page_widget_s {
|
||||
GtkDrawingArea parent;
|
||||
};
|
||||
|
||||
struct zathura_page_widget_class_s {
|
||||
GtkDrawingAreaClass parent_class;
|
||||
};
|
||||
|
||||
#define ZATHURA_TYPE_PAGE \
|
||||
(zathura_page_widget_get_type ())
|
||||
#define ZATHURA_PAGE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), ZATHURA_TYPE_PAGE, ZathuraPage))
|
||||
#define ZATHURA_PAGE_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((obj), ZATHURA_PAGE, ZathuraPageClass))
|
||||
#define ZATHURA_IS_PAGE(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), ZATHURA_PAGE))
|
||||
#define ZATHURA_IS_PAGE_WDIGET_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((obj), ZATHURA_TYPE_PAGE))
|
||||
#define ZATHURA_PAGE_GET_CLASS \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), ZATHURA_TYPE_PAGE, ZathuraPageclass))
|
||||
|
||||
/**
|
||||
* Returns the type of the page view widget.
|
||||
* @return the type
|
||||
*/
|
||||
GType zathura_page_widget_get_type(void);
|
||||
/**
|
||||
* Create a page view widget.
|
||||
* @param page the page to be displayed
|
||||
* @return a page view widget
|
||||
*/
|
||||
GtkWidget* zathura_page_widget_new(zathura_page_t* page);
|
||||
/**
|
||||
* Update the widget's surface. This should only be called from the render
|
||||
* thread.
|
||||
* @param widget the widget
|
||||
* @param surface the new surface
|
||||
*/
|
||||
void zathura_page_widget_update_surface(ZathuraPage* widget, cairo_surface_t* surface);
|
||||
/**
|
||||
* Draw a rectangle to mark links or search results
|
||||
* @param widget the widget
|
||||
* @param rectangle the rectangle
|
||||
* @param linkid the link id if it's a link, -1 otherwise
|
||||
*/
|
||||
void zathura_page_widget_draw_rectangle(ZathuraPage* widget, zathura_rectangle_t* rectangle, int linkid);
|
||||
/**
|
||||
* Clear all rectangles.
|
||||
* @param widget the widget
|
||||
*/
|
||||
void zathura_page_widget_clear_rectangles(ZathuraPage* widget);
|
||||
|
||||
/**
|
||||
* Returns the zathura link object at the given index
|
||||
*
|
||||
* @param widget the widget
|
||||
* @param index Index of the link
|
||||
* @return Link object or NULL if an error occured
|
||||
*/
|
||||
zathura_link_t* zathura_page_widget_link_get(ZathuraPage* widget, unsigned int index);
|
||||
|
||||
#endif
|
70
print.c
70
print.c
|
@ -1,5 +1,11 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include "print.h"
|
||||
#include "document.h"
|
||||
#include "render.h"
|
||||
|
||||
#include <girara/utils.h>
|
||||
#include <girara/statusbar.h>
|
||||
|
||||
void
|
||||
print(zathura_t* zathura)
|
||||
|
@ -24,15 +30,23 @@ print(zathura_t* zathura)
|
|||
|
||||
/* print operation signals */
|
||||
g_signal_connect(print_operation, "draw-page", G_CALLBACK(cb_print_draw_page), zathura);
|
||||
g_signal_connect(print_operation, "end-print", G_CALLBACK(cb_print_end), zathura);
|
||||
|
||||
/* print */
|
||||
GtkPrintOperationResult result = gtk_print_operation_run(print_operation,
|
||||
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, NULL, NULL);
|
||||
|
||||
if (result == GTK_PRINT_OPERATION_RESULT_APPLY) {
|
||||
if (zathura->print.settings != NULL) {
|
||||
g_object_unref(zathura->print.settings);
|
||||
}
|
||||
if (zathura->print.page_setup != NULL) {
|
||||
g_object_unref(zathura->print.page_setup);
|
||||
}
|
||||
|
||||
/* save previous settings */
|
||||
zathura->print.settings = gtk_print_operation_get_print_settings(print_operation);
|
||||
zathura->print.page_setup = gtk_print_operation_get_default_page_setup(print_operation);
|
||||
zathura->print.settings = g_object_ref(gtk_print_operation_get_print_settings(print_operation));
|
||||
zathura->print.page_setup = g_object_ref(gtk_print_operation_get_default_page_setup(print_operation));
|
||||
} else if (result == GTK_PRINT_OPERATION_RESULT_ERROR) {
|
||||
girara_error("Error occured while printing progress");
|
||||
}
|
||||
|
@ -41,43 +55,39 @@ print(zathura_t* zathura)
|
|||
}
|
||||
|
||||
void
|
||||
cb_print_begin(GtkPrintOperation* UNUSED(print_operation), GtkPrintContext*
|
||||
UNUSED(context), zathura_t* UNUSED(zathura))
|
||||
cb_print_end(GtkPrintOperation* UNUSED(print_operation), GtkPrintContext*
|
||||
UNUSED(context), zathura_t* zathura)
|
||||
{
|
||||
if (zathura == NULL || zathura->ui.session == NULL || zathura->document == NULL
|
||||
|| zathura->document->file_path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
girara_statusbar_item_set_text(zathura->ui.session,
|
||||
zathura->ui.statusbar.file, zathura->document->file_path);
|
||||
}
|
||||
|
||||
void
|
||||
cb_print_draw_page(GtkPrintOperation* UNUSED(print_operation), GtkPrintContext*
|
||||
context, gint page_number, zathura_t* zathura)
|
||||
{
|
||||
/* TODO: Implement with cairo */
|
||||
/*cairo_t* cairo = gtk_print_context_get_cairo_context(context);*/
|
||||
if (context == NULL || zathura == NULL || zathura->document->pages == NULL ||
|
||||
zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*girara_info("Printing page %d", page_number);*/
|
||||
/* update statusbar */
|
||||
char* tmp = g_strdup_printf("Printing %d...", page_number);
|
||||
girara_statusbar_item_set_text(zathura->ui.session,
|
||||
zathura->ui.statusbar.file, tmp);
|
||||
g_free(tmp);
|
||||
|
||||
/*zathura_page_t* page = zathura->document->pages[page_number];*/
|
||||
/* render page */
|
||||
cairo_t* cairo = gtk_print_context_get_cairo_context(context);
|
||||
zathura_page_t* page = zathura->document->pages[page_number];
|
||||
if (cairo == NULL || page == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*double requested_with = gtk_print_context_get_width(context);*/
|
||||
/*double tmp_scale = zathura->document->scale;*/
|
||||
/*zathura->document->scale = requested_with / page->width;*/
|
||||
|
||||
/*g_static_mutex_lock(&(page->lock));*/
|
||||
/*zathura_image_buffer_t* image_buffer = zathura_page_render(page);*/
|
||||
/*g_static_mutex_unlock(&(page->lock));*/
|
||||
|
||||
/*for (unsigned int y = 0; y < image_buffer->height; y++) {*/
|
||||
/*unsigned char* src = image_buffer->data + y * image_buffer->rowstride;*/
|
||||
/*for (unsigned int x = 0; x < image_buffer->width; x++) {*/
|
||||
/*if (src[0] != 255 && src[1] != 255 && src[2] != 255) {*/
|
||||
/*cairo_set_source_rgb(cairo, src[0], src[1], src[2]);*/
|
||||
/*cairo_rectangle(cairo, x, y, 1, 1);*/
|
||||
/*cairo_fill(cairo);*/
|
||||
/*}*/
|
||||
|
||||
/*src += 3;*/
|
||||
/*}*/
|
||||
/*}*/
|
||||
|
||||
/*zathura->document->scale = tmp_scale;*/
|
||||
zathura_page_render(page, cairo, true);
|
||||
}
|
||||
|
|
10
print.h
10
print.h
|
@ -23,4 +23,14 @@ void print(zathura_t* zathura);
|
|||
void cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext*
|
||||
context, gint page_number, zathura_t* zathura);
|
||||
|
||||
/**
|
||||
* Emitted after all pages have been rendered
|
||||
*
|
||||
* @param print_operation Print operation
|
||||
* @param context Print context
|
||||
* @param zathura Zathura object
|
||||
*/
|
||||
void cb_print_end(GtkPrintOperation* print_operation, GtkPrintContext* context,
|
||||
zathura_t* zathura);
|
||||
|
||||
#endif // PRINT_H
|
||||
|
|
136
render.c
136
render.c
|
@ -1,6 +1,16 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <math.h>
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/settings.h>
|
||||
|
||||
#include "render.h"
|
||||
#include "zathura.h"
|
||||
#include "document.h"
|
||||
#include "page_widget.h"
|
||||
#include "utils.h"
|
||||
|
||||
void* render_job(void* data);
|
||||
bool render(zathura_t* zathura, zathura_page_t* page);
|
||||
|
@ -13,11 +23,11 @@ render_job(void* data)
|
|||
while (true) {
|
||||
g_mutex_lock(render_thread->lock);
|
||||
|
||||
if (girara_list_size(render_thread->list) <= 0) {
|
||||
if (girara_list_size(render_thread->list) == 0) {
|
||||
g_cond_wait(render_thread->cond, render_thread->lock);
|
||||
}
|
||||
|
||||
if (girara_list_size(render_thread->list) <= 0) {
|
||||
if (girara_list_size(render_thread->list) == 0) {
|
||||
/*
|
||||
* We've been signaled with g_cond_signal(), but the list
|
||||
* is still empty. This means that the signal came from
|
||||
|
@ -43,16 +53,9 @@ render_job(void* data)
|
|||
render_thread_t*
|
||||
render_init(zathura_t* zathura)
|
||||
{
|
||||
render_thread_t* render_thread = malloc(sizeof(render_thread_t));
|
||||
|
||||
if (!render_thread) {
|
||||
goto error_ret;
|
||||
}
|
||||
render_thread_t* render_thread = g_malloc0(sizeof(render_thread_t));
|
||||
|
||||
/* init */
|
||||
render_thread->list = NULL;
|
||||
render_thread->thread = NULL;
|
||||
render_thread->cond = NULL;
|
||||
render_thread->zathura = zathura;
|
||||
|
||||
/* setup */
|
||||
|
@ -96,9 +99,7 @@ error_free:
|
|||
g_mutex_free(render_thread->lock);
|
||||
}
|
||||
|
||||
free(render_thread);
|
||||
|
||||
error_ret:
|
||||
g_free(render_thread);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ render_free(render_thread_t* render_thread)
|
|||
bool
|
||||
render_page(render_thread_t* render_thread, zathura_page_t* page)
|
||||
{
|
||||
if (!render_thread || !page || !render_thread->list || page->surface) {
|
||||
if (!render_thread || !page || !render_thread->list) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,24 +151,15 @@ render(zathura_t* zathura, zathura_page_t* page)
|
|||
}
|
||||
|
||||
gdk_threads_enter();
|
||||
g_static_mutex_lock(&(page->lock));
|
||||
|
||||
/* create cairo surface */
|
||||
unsigned int page_width = 0;
|
||||
unsigned int page_height = 0;
|
||||
|
||||
if (page->document->rotate == 0 || page->document->rotate == 180) {
|
||||
page_width = page->width * zathura->document->scale;
|
||||
page_height = page->height * zathura->document->scale;
|
||||
} else {
|
||||
page_width = page->height * zathura->document->scale;
|
||||
page_height = page->width * zathura->document->scale;
|
||||
}
|
||||
page_calc_height_width(page, &page_height, &page_width, false);
|
||||
|
||||
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height);
|
||||
|
||||
if (surface == NULL) {
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
gdk_threads_leave();
|
||||
return false;
|
||||
}
|
||||
|
@ -176,7 +168,6 @@ render(zathura_t* zathura, zathura_page_t* page)
|
|||
|
||||
if (cairo == NULL) {
|
||||
cairo_surface_destroy(surface);
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
gdk_threads_leave();
|
||||
return false;
|
||||
}
|
||||
|
@ -188,26 +179,13 @@ render(zathura_t* zathura, zathura_page_t* page)
|
|||
cairo_restore(cairo);
|
||||
cairo_save(cairo);
|
||||
|
||||
switch(page->document->rotate) {
|
||||
case 90:
|
||||
cairo_translate(cairo, page_width, 0);
|
||||
break;
|
||||
case 180:
|
||||
cairo_translate(cairo, page_width, page_height);
|
||||
break;
|
||||
case 270:
|
||||
cairo_translate(cairo, 0, page_height);
|
||||
break;
|
||||
if (fabs(zathura->document->scale - 1.0f) > FLT_EPSILON) {
|
||||
cairo_scale(cairo, zathura->document->scale, zathura->document->scale);
|
||||
}
|
||||
|
||||
if (page->document->rotate != 0) {
|
||||
cairo_rotate(cairo, page->document->rotate * G_PI / 180.0);
|
||||
}
|
||||
|
||||
if (zathura_page_render(page, cairo) == false) {
|
||||
if (zathura_page_render(page, cairo, false) != ZATHURA_PLUGIN_ERROR_OK) {
|
||||
cairo_destroy(cairo);
|
||||
cairo_surface_destroy(surface);
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
gdk_threads_leave();
|
||||
return false;
|
||||
}
|
||||
|
@ -215,7 +193,7 @@ render(zathura_t* zathura, zathura_page_t* page)
|
|||
cairo_restore(cairo);
|
||||
cairo_destroy(cairo);
|
||||
|
||||
int rowstride = cairo_image_surface_get_stride(surface);
|
||||
const int rowstride = cairo_image_surface_get_stride(surface);
|
||||
unsigned char* image = cairo_image_surface_get_data(surface);
|
||||
|
||||
/* recolor */
|
||||
|
@ -251,12 +229,9 @@ render(zathura_t* zathura, zathura_page_t* page)
|
|||
}
|
||||
}
|
||||
|
||||
/* draw to gtk widget */
|
||||
page->surface = surface;
|
||||
gtk_widget_set_size_request(page->drawing_area, page_width, page_height);
|
||||
gtk_widget_queue_draw(page->drawing_area);
|
||||
/* update the widget */
|
||||
zathura_page_widget_update_surface(ZATHURA_PAGE(page->drawing_area), surface);
|
||||
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
gdk_threads_leave();
|
||||
|
||||
return true;
|
||||
|
@ -271,66 +246,11 @@ render_all(zathura_t* zathura)
|
|||
|
||||
/* unmark all pages */
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; page_id++) {
|
||||
cairo_surface_destroy(zathura->document->pages[page_id]->surface);
|
||||
zathura->document->pages[page_id]->surface = NULL;
|
||||
}
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
unsigned int page_height = 0, page_width = 0;
|
||||
page_calc_height_width(page, &page_height, &page_width, true);
|
||||
|
||||
/* redraw current page */
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
cb_view_vadjustment_value_changed(view_vadjustment, zathura);
|
||||
}
|
||||
|
||||
gboolean
|
||||
page_expose_event(GtkWidget* UNUSED(widget), GdkEventExpose* UNUSED(event),
|
||||
gpointer data)
|
||||
{
|
||||
zathura_page_t* page = data;
|
||||
if (page == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_static_mutex_lock(&(page->lock));
|
||||
|
||||
cairo_t* cairo = gdk_cairo_create(page->drawing_area->window);
|
||||
|
||||
if (cairo == NULL) {
|
||||
girara_error("Could not retreive cairo object");
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (page->surface != NULL) {
|
||||
cairo_set_source_surface(cairo, page->surface, 0, 0);
|
||||
cairo_paint(cairo);
|
||||
} else {
|
||||
/* set background color */
|
||||
cairo_set_source_rgb(cairo, 255, 255, 255);
|
||||
cairo_rectangle(cairo, 0, 0, page->width * page->document->scale, page->height * page->document->scale);
|
||||
cairo_fill(cairo);
|
||||
|
||||
/* write text */
|
||||
cairo_set_source_rgb(cairo, 0, 0, 0);
|
||||
const char* text = "Loading...";
|
||||
cairo_select_font_face(cairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(cairo, 16.0);
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents(cairo, text, &extents);
|
||||
double x = (page->width * page->document->scale) / 2 - (extents.width / 2 + extents.x_bearing);
|
||||
double y = (page->height * page->document->scale) / 2 - (extents.height / 2 + extents.y_bearing);
|
||||
cairo_move_to(cairo, x, y);
|
||||
cairo_show_text(cairo, text);
|
||||
|
||||
/* render real page */
|
||||
render_page(page->document->zathura->sync.render_thread, page);
|
||||
|
||||
/* update statusbar */
|
||||
}
|
||||
cairo_destroy(cairo);
|
||||
|
||||
page->document->current_page_number = page->number;
|
||||
statusbar_page_number_update(page->document->zathura);
|
||||
|
||||
g_static_mutex_unlock(&(page->lock));
|
||||
|
||||
return TRUE;
|
||||
gtk_widget_set_size_request(page->drawing_area, page_width, page_height);
|
||||
gtk_widget_queue_resize(page->drawing_area);
|
||||
}
|
||||
}
|
||||
|
|
14
render.h
14
render.h
|
@ -5,24 +5,24 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <girara-datastructures.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
#include "zathura.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
struct render_thread_s
|
||||
{
|
||||
girara_list_t* list; /**> The list of pages */
|
||||
GThread* thread; /**> The thread object */
|
||||
GMutex* lock; /**> Lock */
|
||||
GCond* cond; /**> Condition */
|
||||
zathura_t* zathura; /**> Zathura object */
|
||||
girara_list_t* list; /**< The list of pages */
|
||||
GThread* thread; /**< The thread object */
|
||||
GMutex* lock; /**< Lock */
|
||||
GCond* cond; /**< Condition */
|
||||
zathura_t* zathura; /**< Zathura object */
|
||||
};
|
||||
|
||||
/**
|
||||
* This function initializes a render thread
|
||||
*
|
||||
* @param Zathura object
|
||||
* @param zathura object
|
||||
* @return The render thread object or NULL if an error occured
|
||||
*/
|
||||
render_thread_t* render_init(zathura_t* zathura);
|
||||
|
|
564
shortcuts.c
564
shortcuts.c
|
@ -1,6 +1,10 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <girara.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/settings.h>
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/shortcuts.h>
|
||||
#include <girara/utils.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
|
@ -9,30 +13,97 @@
|
|||
#include "zathura.h"
|
||||
#include "render.h"
|
||||
#include "utils.h"
|
||||
#include "page_widget.h"
|
||||
|
||||
bool
|
||||
sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
if (zathura->document != NULL) {
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; ++page_id) {
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
if (page == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set(page->drawing_area, "draw-links", FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
girara_mode_set(session, session->modes.normal);
|
||||
girara_sc_abort(session, NULL, NULL, 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_adjust_window(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
sc_adjust_window(girara_session_t* session, girara_argument_t* argument,
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
g_return_val_if_fail(argument != NULL, false);
|
||||
|
||||
unsigned int pages_per_row = 1;
|
||||
girara_setting_get(session, "pages-per-row", &pages_per_row);
|
||||
|
||||
if (zathura->ui.page_widget == NULL || zathura->document == NULL) {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
zathura->document->adjust_mode = argument->n;
|
||||
|
||||
/* get window size */
|
||||
GtkAllocation allocation;
|
||||
gtk_widget_get_allocation(session->gtk.view, &allocation);
|
||||
gint width = allocation.width;
|
||||
gint height = allocation.height;
|
||||
|
||||
/* calculate total width and max-height */
|
||||
double total_width = 0;
|
||||
double max_height = 0;
|
||||
|
||||
for (unsigned int page_id = 0; page_id < pages_per_row; page_id++) {
|
||||
if (page_id == zathura->document->number_of_pages) {
|
||||
break;
|
||||
}
|
||||
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
if (page == NULL) {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
if (page->height > max_height) {
|
||||
max_height = page->height;
|
||||
}
|
||||
|
||||
total_width += page->width;
|
||||
}
|
||||
|
||||
if (argument->n == ADJUST_WIDTH) {
|
||||
zathura->document->scale = width / total_width;
|
||||
} else if (argument->n == ADJUST_BESTFIT) {
|
||||
zathura->document->scale = height / max_height;
|
||||
} else {
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
/* re-render all pages */
|
||||
render_all(zathura);
|
||||
|
||||
error_ret:
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_change_mode(girara_session_t* session, girara_argument_t* argument, unsigned
|
||||
int UNUSED(t))
|
||||
sc_change_mode(girara_session_t* session, girara_argument_t* argument,
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
|
||||
|
@ -43,15 +114,51 @@ sc_change_mode(girara_session_t* session, girara_argument_t* argument, unsigned
|
|||
|
||||
bool
|
||||
sc_follow(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
if (zathura->document == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set pages to draw links */
|
||||
bool show_links = false;
|
||||
unsigned int page_offset = 0;
|
||||
for (unsigned int page_id = 0; page_id < zathura->document->number_of_pages; page_id++) {
|
||||
zathura_page_t* page = zathura->document->pages[page_id];
|
||||
if (page == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set(page->drawing_area, "search-results", NULL, NULL);
|
||||
if (page->visible == true) {
|
||||
g_object_set(page->drawing_area, "draw-links", TRUE, NULL);
|
||||
|
||||
int number_of_links = 0;
|
||||
g_object_get(page->drawing_area, "number-of-links", &number_of_links, NULL);
|
||||
if (number_of_links != 0) {
|
||||
show_links = true;
|
||||
}
|
||||
g_object_set(page->drawing_area, "offset-links", page_offset, NULL);
|
||||
page_offset += number_of_links;
|
||||
} else {
|
||||
g_object_set(page->drawing_area, "draw-links", FALSE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* ask for input */
|
||||
if (show_links == true) {
|
||||
girara_dialog(zathura->ui.session, "Follow link:", FALSE, NULL, (girara_callback_inputbar_activate_t) cb_sc_follow, NULL);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_goto(girara_session_t* session, girara_argument_t* argument, unsigned int t)
|
||||
sc_goto(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -60,27 +167,113 @@ sc_goto(girara_session_t* session, girara_argument_t* argument, unsigned int t)
|
|||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
|
||||
if (argument->n == TOP) {
|
||||
girara_argument_t arg = { TOP, NULL };
|
||||
sc_scroll(session, &arg, 0);
|
||||
|
||||
return false;
|
||||
page_set(zathura, 0);
|
||||
} else {
|
||||
if (t == 0) {
|
||||
girara_argument_t arg = { BOTTOM, NULL };
|
||||
sc_scroll(session, &arg, 0);
|
||||
|
||||
return true;
|
||||
page_set(zathura, zathura->document->number_of_pages - 1);
|
||||
} else {
|
||||
page_set(zathura, t - 1);
|
||||
}
|
||||
|
||||
page_set(zathura, t - 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_navigate(girara_session_t* session, girara_argument_t* argument, unsigned int
|
||||
UNUSED(t))
|
||||
sc_mouse_scroll(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(event != NULL, false);
|
||||
|
||||
static int x = 0;
|
||||
static int y = 0;
|
||||
|
||||
if (zathura->document == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* scroll event */
|
||||
if (event->type == GIRARA_EVENT_SCROLL) {
|
||||
switch (event->direction) {
|
||||
case GIRARA_SCROLL_UP:
|
||||
argument->n = UP;
|
||||
break;
|
||||
case GIRARA_SCROLL_DOWN:
|
||||
argument->n = DOWN;
|
||||
break;
|
||||
case GIRARA_SCROLL_LEFT:
|
||||
argument->n = LEFT;
|
||||
break;
|
||||
case GIRARA_SCROLL_RIGHT:
|
||||
argument->n = RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
return sc_scroll(session, argument, NULL, t);
|
||||
} else if (event->type == GIRARA_EVENT_BUTTON_PRESS) {
|
||||
x = event->x;
|
||||
y = event->y;
|
||||
} else if (event->type == GIRARA_EVENT_BUTTON_RELEASE) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else if (event->type == GIRARA_EVENT_MOTION_NOTIFY) {
|
||||
GtkAdjustment* x_adj =
|
||||
gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
|
||||
GtkAdjustment* y_adj =
|
||||
gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
|
||||
|
||||
if (x_adj == NULL || y_adj == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_adjustment(x_adj, gtk_adjustment_get_value(x_adj) - (event->x - x));
|
||||
set_adjustment(y_adj, gtk_adjustment_get_value(y_adj) - (event->y - y));
|
||||
|
||||
x = event->x;
|
||||
y = event->y;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_mouse_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(event != NULL, false);
|
||||
|
||||
if (zathura->document == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* scroll event */
|
||||
if (event->type == GIRARA_EVENT_SCROLL) {
|
||||
switch (event->direction) {
|
||||
case GIRARA_SCROLL_UP:
|
||||
argument->n = ZOOM_IN;
|
||||
break;
|
||||
case GIRARA_SCROLL_DOWN:
|
||||
argument->n = ZOOM_OUT;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return sc_zoom(session, argument, NULL, t);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_navigate(girara_session_t* session, girara_argument_t* argument,
|
||||
girara_event_t* UNUSED(event), unsigned int t)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -91,10 +284,11 @@ sc_navigate(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
unsigned int number_of_pages = zathura->document->number_of_pages;
|
||||
unsigned int new_page = zathura->document->current_page_number;
|
||||
|
||||
t = (t == 0) ? 1 : t;
|
||||
if (argument->n == NEXT) {
|
||||
new_page = (new_page + 1) % number_of_pages;
|
||||
new_page = (new_page + t) % number_of_pages;
|
||||
} else if (argument->n == PREVIOUS) {
|
||||
new_page = (new_page + number_of_pages - 1) % number_of_pages;
|
||||
new_page = (new_page + number_of_pages - t) % number_of_pages;
|
||||
}
|
||||
|
||||
page_set(zathura, new_page);
|
||||
|
@ -104,7 +298,7 @@ sc_navigate(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
|
||||
bool
|
||||
sc_recolor(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -118,34 +312,58 @@ sc_recolor(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
|||
|
||||
bool
|
||||
sc_reload(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
if (zathura->document == NULL || zathura->document->file_path == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* save current document path and password */
|
||||
char* path = g_strdup(zathura->document->file_path);
|
||||
char* password = zathura->document->password ? g_strdup(zathura->document->password) : NULL;
|
||||
|
||||
/* close current document */
|
||||
document_close(zathura);
|
||||
|
||||
/* reopen document */
|
||||
document_open(zathura, path, password);
|
||||
|
||||
/* clean up */
|
||||
g_free(path);
|
||||
g_free(password);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_rotate(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
|
||||
unsigned int page_number = zathura->document->current_page_number;
|
||||
|
||||
/* update rotate value */
|
||||
zathura->document->rotate = (zathura->document->rotate + 90) % 360;
|
||||
|
||||
/* render all pages again */
|
||||
render_all(zathura);
|
||||
|
||||
page_set_delayed(zathura, page_number);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_scroll(girara_session_t* session, girara_argument_t* argument, unsigned int
|
||||
UNUSED(t))
|
||||
sc_scroll(girara_session_t* session, girara_argument_t* argument,
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -156,38 +374,39 @@ sc_scroll(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
}
|
||||
|
||||
GtkAdjustment* adjustment = NULL;
|
||||
if ( (argument->n == LEFT) || (argument->n == RIGHT) )
|
||||
adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
else
|
||||
adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
|
||||
gdouble view_size = gtk_adjustment_get_page_size(adjustment);
|
||||
gdouble value = gtk_adjustment_get_value(adjustment);
|
||||
gdouble max = gtk_adjustment_get_upper(adjustment) - view_size;
|
||||
gdouble scroll_step = 40;
|
||||
if ( (argument->n == LEFT) || (argument->n == RIGHT) ) {
|
||||
adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
|
||||
} else {
|
||||
adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
|
||||
}
|
||||
|
||||
gdouble view_size = gtk_adjustment_get_page_size(adjustment);
|
||||
gdouble value = gtk_adjustment_get_value(adjustment);
|
||||
gdouble max = gtk_adjustment_get_upper(adjustment) - view_size;
|
||||
float scroll_step = 40;
|
||||
girara_setting_get(session, "scroll-step", &scroll_step);
|
||||
gdouble new_value;
|
||||
switch(argument->n)
|
||||
{
|
||||
|
||||
switch(argument->n) {
|
||||
case FULL_UP:
|
||||
new_value = (value - view_size) < 0 ? 0 : (value - view_size);
|
||||
new_value = value - view_size;
|
||||
break;
|
||||
case FULL_DOWN:
|
||||
new_value = (value + view_size) > max ? max : (value + view_size);
|
||||
new_value = value + view_size;
|
||||
break;
|
||||
case HALF_UP:
|
||||
new_value = (value - (view_size / 2)) < 0 ? 0 : (value - (view_size / 2));
|
||||
new_value = value - (view_size / 2);
|
||||
break;
|
||||
case HALF_DOWN:
|
||||
new_value = (value + (view_size / 2)) > max ? max : (value + (view_size / 2));
|
||||
new_value = value + (view_size / 2);
|
||||
break;
|
||||
case LEFT:
|
||||
case UP:
|
||||
new_value = (value - scroll_step) < 0 ? 0 : (value - scroll_step);
|
||||
new_value = value - scroll_step;
|
||||
break;
|
||||
case RIGHT:
|
||||
case DOWN:
|
||||
new_value = (value + scroll_step) > max ? max : (value + scroll_step);
|
||||
new_value = value + scroll_step;
|
||||
break;
|
||||
case TOP:
|
||||
new_value = 0;
|
||||
|
@ -196,17 +415,17 @@ sc_scroll(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
new_value = max;
|
||||
break;
|
||||
default:
|
||||
new_value = 0;
|
||||
new_value = value;
|
||||
}
|
||||
|
||||
gtk_adjustment_set_value(adjustment, new_value);
|
||||
set_adjustment(adjustment, new_value);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_search(girara_session_t* session, girara_argument_t* argument, unsigned int
|
||||
UNUSED(t))
|
||||
sc_search(girara_session_t* session, girara_argument_t* argument,
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -214,12 +433,79 @@ sc_search(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
|
||||
const int num_pages = zathura->document->number_of_pages;
|
||||
const int cur_page = zathura->document->current_page_number;
|
||||
int diff = argument->n == FORWARD ? 1 : -1;
|
||||
|
||||
zathura_page_t* target_page = NULL;
|
||||
int target_idx = 0;
|
||||
|
||||
for (int page_id = 0; page_id < num_pages; ++page_id) {
|
||||
int tmp = cur_page + diff * page_id;
|
||||
zathura_page_t* page = zathura->document->pages[(tmp + num_pages) % num_pages];
|
||||
if (page == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int num_search_results = 0, current = -1;
|
||||
g_object_get(page->drawing_area, "search-current", ¤t,
|
||||
"search-length", &num_search_results, NULL);
|
||||
if (num_search_results == 0 || current == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (diff == 1 && current < num_search_results - 1) {
|
||||
/* the next result is on the same page */
|
||||
target_page = page;
|
||||
target_idx = current + 1;
|
||||
// g_object_set(page->drawing_area, "search-current", current + 1, NULL);
|
||||
} else if (diff == -1 && current >= 1) {
|
||||
// g_object_set(page->drawing_area, "search-current", current - 1, NULL);
|
||||
target_page = page;
|
||||
target_idx = current - 1;
|
||||
} else {
|
||||
/* the next result is on a different page */
|
||||
g_object_set(page->drawing_area, "search-current", -1, NULL);
|
||||
|
||||
for (int npage_id = 1; page_id < num_pages; ++npage_id) {
|
||||
int ntmp = cur_page + diff * (page_id + npage_id);
|
||||
zathura_page_t* npage = zathura->document->pages[(ntmp + 2*num_pages) % num_pages];
|
||||
g_object_get(npage->drawing_area, "search-length", &num_search_results, NULL);
|
||||
if (num_search_results != 0) {
|
||||
target_page = npage;
|
||||
target_idx = diff == 1 ? 0 : num_search_results - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (target_page != NULL) {
|
||||
girara_list_t* results = NULL;
|
||||
g_object_set(target_page->drawing_area, "search-current", target_idx, NULL);
|
||||
g_object_get(target_page->drawing_area, "search-results", &results, NULL);
|
||||
|
||||
zathura_rectangle_t* rect = girara_list_nth(results, target_idx);
|
||||
zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect);
|
||||
page_offset_t offset;
|
||||
page_calculate_offset(target_page, &offset);
|
||||
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
|
||||
int x = offset.x - gtk_adjustment_get_page_size(view_hadjustment) / 2 + rectangle.x1;
|
||||
int y = offset.y - gtk_adjustment_get_page_size(view_vadjustment) / 2 + rectangle.y1;
|
||||
set_adjustment(view_hadjustment, x);
|
||||
set_adjustment(view_vadjustment, y);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_navigate_index(girara_session_t* session, girara_argument_t* argument,
|
||||
unsigned int UNUSED(t))
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -227,23 +513,95 @@ sc_navigate_index(girara_session_t* session, girara_argument_t* argument,
|
|||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
|
||||
if(zathura->ui.index == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GtkTreeView *tree_view = gtk_container_get_children(GTK_CONTAINER(zathura->ui.index))->data;
|
||||
GtkTreePath *path;
|
||||
|
||||
gtk_tree_view_get_cursor(tree_view, &path, NULL);
|
||||
if (path == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter child_iter;
|
||||
|
||||
gboolean is_valid_path = TRUE;
|
||||
|
||||
switch(argument->n) {
|
||||
case UP:
|
||||
if(gtk_tree_path_prev(path) == FALSE) {
|
||||
is_valid_path = gtk_tree_path_up(path);
|
||||
} else { /* row above */
|
||||
while(gtk_tree_view_row_expanded(tree_view, path)) {
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
/* select last child */
|
||||
gtk_tree_model_iter_nth_child(model, &child_iter, &iter,
|
||||
gtk_tree_model_iter_n_children(model, &iter)-1);
|
||||
gtk_tree_path_free(path);
|
||||
path = gtk_tree_model_get_path(model, &child_iter);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case COLLAPSE:
|
||||
if(!gtk_tree_view_collapse_row(tree_view, path)
|
||||
&& gtk_tree_path_get_depth(path) > 1) {
|
||||
gtk_tree_path_up(path);
|
||||
gtk_tree_view_collapse_row(tree_view, path);
|
||||
}
|
||||
break;
|
||||
case DOWN:
|
||||
if(gtk_tree_view_row_expanded(tree_view, path)) {
|
||||
gtk_tree_path_down(path);
|
||||
} else {
|
||||
do {
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
if (gtk_tree_model_iter_next(model, &iter)) {
|
||||
path = gtk_tree_model_get_path(model, &iter);
|
||||
break;
|
||||
}
|
||||
} while((is_valid_path = (gtk_tree_path_get_depth(path) > 1))
|
||||
&& gtk_tree_path_up(path));
|
||||
}
|
||||
break;
|
||||
case EXPAND:
|
||||
if(gtk_tree_view_expand_row(tree_view, path, FALSE)) {
|
||||
gtk_tree_path_down(path);
|
||||
}
|
||||
break;
|
||||
case SELECT:
|
||||
cb_index_row_activated(tree_view, path, NULL, zathura);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_valid_path) {
|
||||
gtk_tree_view_set_cursor(tree_view, path, NULL, FALSE);
|
||||
}
|
||||
|
||||
gtk_tree_path_free(path);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_toggle_index(girara_session_t* session, girara_argument_t* argument, unsigned
|
||||
int UNUSED(t))
|
||||
sc_toggle_index(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
if (zathura->document == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
girara_tree_node_t* document_index = NULL;
|
||||
GtkWidget* treeview = NULL;
|
||||
GtkTreeModel* model = NULL;
|
||||
GtkCellRenderer* renderer = NULL;
|
||||
GtkCellRenderer* renderer2 = NULL;
|
||||
|
||||
if (zathura->ui.index == NULL) {
|
||||
/* create new index widget */
|
||||
|
@ -257,13 +615,13 @@ sc_toggle_index(girara_session_t* session, girara_argument_t* argument, unsigned
|
|||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
/* create index */
|
||||
document_index = zathura_document_index_generate(zathura->document);
|
||||
document_index = zathura_document_index_generate(zathura->document, NULL);
|
||||
if (document_index == NULL) {
|
||||
// TODO: Error message
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
model = GTK_TREE_MODEL(gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER));
|
||||
model = GTK_TREE_MODEL(gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
|
||||
if (model == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
@ -280,27 +638,37 @@ sc_toggle_index(girara_session_t* session, girara_argument_t* argument, unsigned
|
|||
goto error_free;
|
||||
}
|
||||
|
||||
renderer2 = gtk_cell_renderer_text_new();
|
||||
if (renderer2 == NULL) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
document_index_build(model, NULL, document_index);
|
||||
girara_node_free(document_index);
|
||||
|
||||
/* setup widget */
|
||||
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (treeview), 0, "Title", renderer, "markup", 0, NULL);
|
||||
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW (treeview), 1, "Target", renderer2, "text", 1, NULL);
|
||||
|
||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
|
||||
g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
g_object_set(G_OBJECT(gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), 0)), "expand", TRUE, NULL);
|
||||
gtk_tree_view_column_set_alignment(gtk_tree_view_get_column(GTK_TREE_VIEW(treeview), 1), 1.0f);
|
||||
gtk_tree_view_set_cursor(GTK_TREE_VIEW(treeview), gtk_tree_path_new_first(), NULL, FALSE);
|
||||
/*g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(cb_index_row_activated), NULL); TODO*/
|
||||
g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(cb_index_row_activated), zathura);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(zathura->ui.index), treeview);
|
||||
gtk_widget_show(treeview);
|
||||
}
|
||||
|
||||
if (gtk_widget_get_visible(GTK_WIDGET(zathura->ui.index))) {
|
||||
girara_set_view(session, zathura->ui.page_view);
|
||||
girara_set_view(session, zathura->ui.page_widget_alignment);
|
||||
gtk_widget_hide(GTK_WIDGET(zathura->ui.index));
|
||||
girara_mode_set(zathura->ui.session, zathura->modes.normal);
|
||||
} else {
|
||||
girara_set_view(session, zathura->ui.index);
|
||||
gtk_widget_show(GTK_WIDGET(zathura->ui.index));
|
||||
girara_mode_set(zathura->ui.session, zathura->modes.index);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -323,15 +691,49 @@ error_ret:
|
|||
|
||||
bool
|
||||
sc_toggle_fullscreen(girara_session_t* session, girara_argument_t*
|
||||
UNUSED(argument), unsigned int UNUSED(t))
|
||||
UNUSED(argument), girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
zathura_t* zathura = session->global.data;
|
||||
|
||||
static bool fullscreen = false;
|
||||
static bool fullscreen = false;
|
||||
static int pages_per_row = 1;
|
||||
static double zoom = 1.0;
|
||||
|
||||
if (fullscreen) {
|
||||
if (fullscreen == true) {
|
||||
/* reset pages per row */
|
||||
girara_setting_set(session, "pages-per-row", &pages_per_row);
|
||||
|
||||
/* show status bar */
|
||||
gtk_widget_show(GTK_WIDGET(session->gtk.statusbar));
|
||||
|
||||
/* set full screen */
|
||||
gtk_window_unfullscreen(GTK_WINDOW(session->gtk.window));
|
||||
|
||||
/* reset scale */
|
||||
zathura->document->scale = zoom;
|
||||
render_all(zathura);
|
||||
} else {
|
||||
/* backup pages per row */
|
||||
girara_setting_get(session, "pages-per-row", &pages_per_row);
|
||||
|
||||
/* set single view */
|
||||
int int_value = 1;
|
||||
girara_setting_set(session, "pages-per-row", &int_value);
|
||||
|
||||
/* back up zoom */
|
||||
zoom = zathura->document->scale;
|
||||
|
||||
/* adjust window */
|
||||
girara_argument_t argument = { ADJUST_BESTFIT, NULL };
|
||||
sc_adjust_window(session, &argument, NULL, 0);
|
||||
|
||||
/* hide status and inputbar */
|
||||
gtk_widget_hide(GTK_WIDGET(session->gtk.inputbar));
|
||||
gtk_widget_hide(GTK_WIDGET(session->gtk.statusbar));
|
||||
|
||||
/* set full screen */
|
||||
gtk_window_fullscreen(GTK_WINDOW(session->gtk.window));
|
||||
}
|
||||
|
||||
|
@ -341,24 +743,22 @@ sc_toggle_fullscreen(girara_session_t* session, girara_argument_t*
|
|||
}
|
||||
|
||||
bool
|
||||
sc_quit(girara_session_t* session, girara_argument_t* UNUSED(argument), unsigned
|
||||
int UNUSED(t))
|
||||
sc_quit(girara_session_t* session, girara_argument_t* UNUSED(argument),
|
||||
girara_event_t* UNUSED(event), unsigned int UNUSED(t))
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
|
||||
girara_argument_t arg = { GIRARA_HIDE, NULL };
|
||||
girara_isc_completion(session, &arg, 0);
|
||||
girara_isc_completion(session, &arg, NULL, 0);
|
||||
|
||||
cb_destroy(NULL, NULL);
|
||||
|
||||
gtk_main_quit();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_zoom(girara_session_t* session, girara_argument_t* argument, unsigned int
|
||||
UNUSED(t))
|
||||
sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t*
|
||||
UNUSED(event), unsigned int t)
|
||||
{
|
||||
g_return_val_if_fail(session != NULL, false);
|
||||
g_return_val_if_fail(session->global.data != NULL, false);
|
||||
|
@ -366,23 +766,43 @@ sc_zoom(girara_session_t* session, girara_argument_t* argument, unsigned int
|
|||
g_return_val_if_fail(argument != NULL, false);
|
||||
g_return_val_if_fail(zathura->document != NULL, false);
|
||||
|
||||
zathura->document->adjust_mode = ADJUST_NONE;
|
||||
|
||||
/* retreive zoom step value */
|
||||
int* value = girara_setting_get(zathura->ui.session, "zoom-step");
|
||||
if (value == NULL) {
|
||||
return false;
|
||||
}
|
||||
int value = 1;
|
||||
girara_setting_get(zathura->ui.session, "zoom-step", &value);
|
||||
|
||||
float zoom_step = *value / 100.0f;
|
||||
float zoom_step = value / 100.0f;
|
||||
float oldzoom = zathura->document->scale;
|
||||
|
||||
/* specify new zoom value */
|
||||
if (argument->n == ZOOM_IN) {
|
||||
zathura->document->scale += zoom_step;
|
||||
} else if (argument->n == ZOOM_OUT) {
|
||||
zathura->document->scale -= zoom_step;
|
||||
} else if (argument->n == ZOOM_SPECIFIC) {
|
||||
zathura->document->scale = t / 100.0f;
|
||||
} else {
|
||||
zathura->document->scale = 1.0;
|
||||
}
|
||||
|
||||
/* zoom limitations */
|
||||
if (zathura->document->scale < 0.1f) {
|
||||
zathura->document->scale = 0.1f;
|
||||
} else if (zathura->document->scale > 10.0f) {
|
||||
zathura->document->scale = 10.0f;
|
||||
}
|
||||
|
||||
/* keep position */
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
gdouble valx = gtk_adjustment_get_value(view_hadjustment) / oldzoom * zathura->document->scale;
|
||||
gdouble valy = gtk_adjustment_get_value(view_vadjustment) / oldzoom * zathura->document->scale;
|
||||
set_adjustment(view_hadjustment, valx);
|
||||
set_adjustment(view_vadjustment, valy);
|
||||
|
||||
render_all(zathura);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
72
shortcuts.h
72
shortcuts.h
|
@ -3,166 +3,204 @@
|
|||
#ifndef SHORTCUTS_H
|
||||
#define SHORTCUTS_H
|
||||
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
/**
|
||||
* Abort the current action and return to normal mode
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_abort(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_abort(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Adjust the rendered pages to the window
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_adjust_window(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_adjust_window(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Change the current mode
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_change_mode(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_change_mode(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Follow a link
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_follow(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_follow(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Go to a specific page or position
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_goto(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_goto(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Handle mouse events
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_mouse_scroll(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Handle mouse zoom events
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_mouse_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Navigate through the document
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_navigate(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_navigate(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Recolor the pages
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_recolor(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_recolor(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Reload the current document
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_reload(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_reload(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Rotate the pages
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_rotate(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_rotate(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Scroll through the pages
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_scroll(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_scroll(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Search through the document for the latest search item
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_search(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_search(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Navigate through the index of the document
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_navigate_index(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_navigate_index(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Show/Hide the index of the document
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_toggle_index(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_toggle_index(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Toggle fullscreen mode
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_toggle_fullscreen(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_toggle_fullscreen(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Quit zathura
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_quit(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_quit(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
/**
|
||||
* Change the zoom level
|
||||
*
|
||||
* @param session The used girara session
|
||||
* @param argument The used argument
|
||||
* @param event Girara event
|
||||
* @param t Number of executions
|
||||
* @return true if no error occured otherwise false
|
||||
*/
|
||||
bool sc_zoom(girara_session_t* session, girara_argument_t* argument, unsigned int t);
|
||||
bool sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
|
||||
|
||||
#endif // SHORTCUTS_H
|
||||
|
|
1
tests/.gitignore
vendored
Normal file
1
tests/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
tests
|
53
tests/Makefile
Normal file
53
tests/Makefile
Normal file
|
@ -0,0 +1,53 @@
|
|||
# See LICENSE file for license and copyright information
|
||||
|
||||
include ../config.mk
|
||||
include ../common.mk
|
||||
include config.mk
|
||||
|
||||
PROJECT = tests
|
||||
SOURCE = tests.c $(wildcard test_*.c)
|
||||
OBJECTS = ${SOURCE:.c=.o}
|
||||
|
||||
ZSOURCE = $(shell find ../ -iname "*.c" -a ! -iname "database-*" ! -iname "main.c" ! -path "*tests*")
|
||||
ZOBJECTS = ${ZSOURCE:.c=.o}
|
||||
|
||||
ifeq (${DATABASE}, sqlite)
|
||||
INCS += $(SQLITE_INC)
|
||||
LIBS += $(SQLITE_LIB)
|
||||
ZSOURCE += ../database-sqlite.c
|
||||
else
|
||||
ifeq (${DATABASE}, plain)
|
||||
ZSOURCE += ../database-plain.c
|
||||
endif
|
||||
endif
|
||||
|
||||
all: ${PROJECT} run
|
||||
|
||||
run: ${PROJECT}
|
||||
$(QUIET)./${PROJECT}
|
||||
|
||||
options:
|
||||
@echo ${PROJECT} build options:
|
||||
@echo "CFLAGS = ${CFLAGS}"
|
||||
@echo "LDFLAGS = ${LDFLAGS}"
|
||||
@echo "DFLAGS = ${DFLAGS}"
|
||||
@echo "CC = ${CC}"
|
||||
|
||||
%.o: %.c
|
||||
$(ECHO) CC $<
|
||||
@mkdir -p .depend
|
||||
$(QUIET)${CC} -c -I.. ${CPPFLAGS} ${CFLAGS} -o $@ $< -MMD -MF .depend/$@.dep
|
||||
|
||||
${PROJECT}: options ${OBJECTS}
|
||||
$(QUIET)make -C ..
|
||||
$(ECHO) CC -o $@
|
||||
$(QUIET)${CC} ${SFLAGS} ${LDFLAGS} -o $@ ${OBJECTS} ${ZOBJECTS} ${LIBS}
|
||||
|
||||
${OBJECTS}: ../config.mk
|
||||
|
||||
clean:
|
||||
$(QUIET)rm -rf ${OBJECTS} ${PROJECT}
|
||||
|
||||
.PHONY: all options clean debug
|
||||
|
||||
-include $(wildcard .depend/*.dep)
|
9
tests/config.mk
Normal file
9
tests/config.mk
Normal file
|
@ -0,0 +1,9 @@
|
|||
# See LICENSE file for license and copyright information
|
||||
|
||||
CHECK_INC ?= $(shell pkg-config --cflags check)
|
||||
CHECK_LIB ?= $(shell pkg-config --libs check)
|
||||
|
||||
LIBS += ${CHECK_LIB}
|
||||
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
LDFLAGS += -fprofile-arcs
|
44
tests/test_utils.c
Normal file
44
tests/test_utils.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <check.h>
|
||||
|
||||
#include "../utils.h"
|
||||
|
||||
START_TEST(test_file_exists_null) {
|
||||
fail_unless(file_exists(NULL) == false);
|
||||
} END_TEST
|
||||
|
||||
START_TEST(test_file_get_extension_null) {
|
||||
fail_unless(file_get_extension(NULL) == NULL);
|
||||
} END_TEST
|
||||
|
||||
START_TEST(test_file_get_extension_none) {
|
||||
const char* path = "test";
|
||||
fail_unless(file_get_extension(path) == NULL);
|
||||
} END_TEST
|
||||
|
||||
START_TEST(test_file_get_extension_single) {
|
||||
const char* path = "test.pdf";
|
||||
const char* extension = file_get_extension(path);
|
||||
fail_unless(strcmp(extension, "pdf") == 0);
|
||||
} END_TEST
|
||||
|
||||
Suite* suite_utils()
|
||||
{
|
||||
TCase* tcase = NULL;
|
||||
Suite* suite = suite_create("Utils");
|
||||
|
||||
/* file exists */
|
||||
tcase = tcase_create("file_exists");
|
||||
tcase_add_test(tcase, test_file_exists_null);
|
||||
suite_add_tcase(suite, tcase);
|
||||
|
||||
/* file exists */
|
||||
tcase = tcase_create("file_get_extension");
|
||||
tcase_add_test(tcase, test_file_get_extension_null);
|
||||
tcase_add_test(tcase, test_file_get_extension_none);
|
||||
tcase_add_test(tcase, test_file_get_extension_single);
|
||||
suite_add_tcase(suite, tcase);
|
||||
|
||||
return suite;
|
||||
}
|
22
tests/tests.c
Normal file
22
tests/tests.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <check.h>
|
||||
#include <girara/macros.h>
|
||||
|
||||
#define UNUSED(x) GIRARA_UNUSED(x)
|
||||
|
||||
Suite* suite_utils();
|
||||
|
||||
int main(int UNUSED(argc), char *UNUSED(argv[]))
|
||||
{
|
||||
Suite* suite = NULL;
|
||||
SRunner* suite_runner = NULL;
|
||||
|
||||
/* test utils */
|
||||
suite = suite_utils();
|
||||
suite_runner = srunner_create(suite);
|
||||
srunner_run_all(suite_runner, CK_NORMAL);
|
||||
srunner_free(suite_runner);
|
||||
|
||||
return 0;
|
||||
}
|
205
utils.c
205
utils.c
|
@ -7,11 +7,14 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include "math.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "zathura.h"
|
||||
#include "document.h"
|
||||
|
||||
#include <girara/datastructures.h>
|
||||
|
||||
#define BLOCK_SIZE 64
|
||||
|
||||
bool
|
||||
|
@ -66,9 +69,9 @@ file_valid_extension(zathura_t* zathura, const char* path)
|
|||
result = true;
|
||||
break;
|
||||
}
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping)
|
||||
GIRARA_LIST_FOREACH_END(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_t*, iter, mapping);
|
||||
|
||||
g_free(content_type);
|
||||
g_free((void*)content_type);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -149,96 +152,130 @@ execute_command(char* const argv[], char** output)
|
|||
}
|
||||
|
||||
void
|
||||
document_index_build(GtkTreeModel* UNUSED(model), GtkTreeIter* UNUSED(parent),
|
||||
girara_tree_node_t* UNUSED(tree))
|
||||
document_index_build(GtkTreeModel* model, GtkTreeIter* parent,
|
||||
girara_tree_node_t* tree)
|
||||
{
|
||||
/*girara_list_t* list = girara_node_get_children(tree);*/
|
||||
/*girara_list_iterator_t* it = girara_list_iterator(list);*/
|
||||
girara_list_t* list = girara_node_get_children(tree);
|
||||
GIRARA_LIST_FOREACH(list, girara_tree_node_t*, iter, node)
|
||||
zathura_index_element_t* index_element = (zathura_index_element_t*)girara_node_get_data(node);
|
||||
|
||||
/*do {*/
|
||||
/*zathura_index_element_t* index_element = (zathura_index_element_t*) girara_list_iterator_data(it);*/
|
||||
/*} while ((it = girara_list_iterator_next(it)));*/
|
||||
gchar* description = NULL;
|
||||
if (index_element->type == ZATHURA_LINK_TO_PAGE) {
|
||||
description = g_strdup_printf("Page %d", index_element->target.page_number);
|
||||
} else {
|
||||
description = g_strdup(index_element->target.uri);
|
||||
}
|
||||
|
||||
GtkTreeIter tree_iter;
|
||||
gtk_tree_store_append(GTK_TREE_STORE(model), &tree_iter, parent);
|
||||
gtk_tree_store_set(GTK_TREE_STORE(model), &tree_iter, 0, index_element->title, 1, description, 2, index_element, -1);
|
||||
g_object_weak_ref(G_OBJECT(model), (GWeakNotify) zathura_index_element_free, index_element);
|
||||
g_free(description);
|
||||
|
||||
if (girara_node_get_num_children(node) > 0) {
|
||||
document_index_build(model, &tree_iter, node);
|
||||
}
|
||||
|
||||
GIRARA_LIST_FOREACH_END(list, gchar*, iter, name);
|
||||
}
|
||||
|
||||
char*
|
||||
string_concat(const char* string1, ...)
|
||||
void
|
||||
page_calculate_offset(zathura_page_t* page, page_offset_t* offset)
|
||||
{
|
||||
if(!string1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
char* s;
|
||||
int l = strlen(string1) + 1;
|
||||
|
||||
/* calculate length */
|
||||
va_start(args, string1);
|
||||
|
||||
s = va_arg(args, char*);
|
||||
|
||||
while(s) {
|
||||
l += strlen(s);
|
||||
s = va_arg(args, char*);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
/* prepare */
|
||||
char* c = malloc(sizeof(char) * l);
|
||||
char* p = c;
|
||||
|
||||
/* copy */
|
||||
char* d = p;
|
||||
char* x = (char*) string1;
|
||||
|
||||
do {
|
||||
*d++ = *x;
|
||||
} while (*x++ != '\0');
|
||||
|
||||
p = d - 1;
|
||||
|
||||
va_start(args, string1);
|
||||
|
||||
s = va_arg(args, char*);
|
||||
|
||||
while(s) {
|
||||
d = p;
|
||||
x = s;
|
||||
|
||||
do {
|
||||
*d++ = *x;
|
||||
} while (*x++ != '\0');
|
||||
|
||||
p = d - 1;
|
||||
s = va_arg(args, char*);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
page_offset_t*
|
||||
page_calculate_offset(zathura_page_t* page)
|
||||
{
|
||||
if (page == NULL || page->document == NULL || page->document->zathura == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
page_offset_t* offset = malloc(sizeof(page_offset_t));
|
||||
|
||||
if (offset == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_return_if_fail(page != NULL && page->document != NULL && page->document->zathura != NULL && offset != NULL);
|
||||
zathura_document_t* document = page->document;
|
||||
zathura_t* zathura = document->zathura;
|
||||
|
||||
if (gtk_widget_translate_coordinates(page->event_box, zathura->ui.page_view, 0, 0, &(offset->x), &(offset->y)) == false) {
|
||||
free(offset);
|
||||
return NULL;
|
||||
g_return_if_fail(gtk_widget_translate_coordinates(page->drawing_area,
|
||||
zathura->ui.page_widget, 0, 0, &(offset->x), &(offset->y)) == true);
|
||||
}
|
||||
|
||||
zathura_rectangle_t rotate_rectangle(zathura_rectangle_t rectangle, unsigned int degree, int height, int width)
|
||||
{
|
||||
zathura_rectangle_t tmp;
|
||||
switch (degree) {
|
||||
case 90:
|
||||
tmp.x1 = height - rectangle.y2;
|
||||
tmp.x2 = height - rectangle.y1;
|
||||
tmp.y1 = rectangle.x1;
|
||||
tmp.y2 = rectangle.x2;
|
||||
break;
|
||||
case 180:
|
||||
tmp.x1 = width - rectangle.x2;
|
||||
tmp.x2 = width - rectangle.x1;
|
||||
tmp.y1 = height - rectangle.y2;
|
||||
tmp.y2 = height - rectangle.y1;
|
||||
break;
|
||||
case 270:
|
||||
tmp.x1 = rectangle.y1;
|
||||
tmp.x2 = rectangle.y2;
|
||||
tmp.y1 = width - rectangle.x2;
|
||||
tmp.y2 = width - rectangle.x1;
|
||||
break;
|
||||
default:
|
||||
tmp.x1 = rectangle.x1;
|
||||
tmp.x2 = rectangle.x2;
|
||||
tmp.y1 = rectangle.y1;
|
||||
tmp.y2 = rectangle.y2;
|
||||
}
|
||||
|
||||
return offset;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
zathura_rectangle_t
|
||||
recalc_rectangle(zathura_page_t* page, zathura_rectangle_t rectangle)
|
||||
{
|
||||
if (page == NULL || page->document == NULL) {
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
zathura_rectangle_t tmp;
|
||||
|
||||
switch (page->document->rotate) {
|
||||
case 90:
|
||||
tmp.x1 = (page->height - rectangle.y2) * page->document->scale;
|
||||
tmp.x2 = (page->height - rectangle.y1) * page->document->scale;
|
||||
tmp.y1 = rectangle.x1 * page->document->scale;
|
||||
tmp.y2 = rectangle.x2 * page->document->scale;
|
||||
break;
|
||||
case 180:
|
||||
tmp.x1 = (page->width - rectangle.x2) * page->document->scale;
|
||||
tmp.x2 = (page->width - rectangle.x1) * page->document->scale;
|
||||
tmp.y1 = (page->height - rectangle.y2) * page->document->scale;
|
||||
tmp.y2 = (page->height - rectangle.y1) * page->document->scale;
|
||||
break;
|
||||
case 270:
|
||||
tmp.x1 = rectangle.y1 * page->document->scale;
|
||||
tmp.x2 = rectangle.y2 * page->document->scale;
|
||||
tmp.y1 = (page->width - rectangle.x2) * page->document->scale;
|
||||
tmp.y2 = (page->width - rectangle.x1) * page->document->scale;
|
||||
break;
|
||||
default:
|
||||
tmp.x1 = rectangle.x1 * page->document->scale;
|
||||
tmp.x2 = rectangle.x2 * page->document->scale;
|
||||
tmp.y1 = rectangle.y1 * page->document->scale;
|
||||
tmp.y2 = rectangle.y2 * page->document->scale;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void
|
||||
set_adjustment(GtkAdjustment* adjustment, gdouble value)
|
||||
{
|
||||
gtk_adjustment_set_value(adjustment, MAX(adjustment->lower, MIN(adjustment->upper - adjustment->page_size, value)));
|
||||
}
|
||||
|
||||
void
|
||||
page_calc_height_width(zathura_page_t* page, unsigned int* page_height, unsigned int* page_width, bool rotate)
|
||||
{
|
||||
g_return_if_fail(page != NULL && page_height != NULL && page_width != NULL);
|
||||
|
||||
if (rotate && page->document->rotate % 180) {
|
||||
*page_width = ceil(page->height * page->document->scale);
|
||||
*page_height = ceil(page->width * page->document->scale);
|
||||
} else {
|
||||
*page_width = ceil(page->width * page->document->scale);
|
||||
*page_height = ceil(page->height * page->document->scale);
|
||||
}
|
||||
}
|
||||
|
|
60
utils.h
60
utils.h
|
@ -5,10 +5,12 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
|
||||
#include "document.h"
|
||||
|
||||
#define LENGTH(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
typedef struct page_offset_s
|
||||
{
|
||||
int x;
|
||||
|
@ -55,28 +57,58 @@ bool execute_command(char* const argv[], char** output);
|
|||
* object.
|
||||
*
|
||||
* @param model The tree model
|
||||
* @param tree_it The Tree iterator
|
||||
* @param list_it The index list iterator
|
||||
* @param parent The tree iterator parent
|
||||
* @param tree The Tree iterator
|
||||
*/
|
||||
void document_index_build(GtkTreeModel* model, GtkTreeIter* parent, girara_tree_node_t* tree);
|
||||
|
||||
/**
|
||||
* This function is used to concatenate multiple strings. Argument list has to
|
||||
* be ended with NULL. Returned string has to be freed with free().
|
||||
*
|
||||
* @param string1 First string
|
||||
* @param ... Additional strings
|
||||
* @return Concatenated string or NULL if an error occured
|
||||
*/
|
||||
char* string_concat(const char* string1, ...);
|
||||
|
||||
/**
|
||||
* Calculates the offset of the page to the top of the viewing area as
|
||||
* well as to the left side of it. The result has to be freed.
|
||||
*
|
||||
* @param page The Page
|
||||
* @param offset Applied offset
|
||||
* @return The calculated offset or NULL if an error occured
|
||||
*/
|
||||
page_offset_t* page_calculate_offset(zathura_page_t* page);
|
||||
void page_calculate_offset(zathura_page_t* page, page_offset_t* offset);
|
||||
|
||||
/**
|
||||
* Rotate a rectangle by 0, 90, 180 or 270 degree
|
||||
* @param rect the rectangle to rotate
|
||||
* @param degree rotation degree
|
||||
* @param height the height of the enclosing rectangle
|
||||
* @param width the width of the enclosing rectangle
|
||||
* @return the rotated rectangle
|
||||
*/
|
||||
zathura_rectangle_t rotate_rectangle(zathura_rectangle_t rectangle, unsigned int degree, int height, int width);
|
||||
|
||||
/**
|
||||
* Calculates the new coordinates based on the rotation and scale level of the
|
||||
* document for the given rectangle
|
||||
*
|
||||
* @param page Page where the rectangle should be
|
||||
* @param rectangle The rectangle
|
||||
* @return New rectangle
|
||||
*/
|
||||
zathura_rectangle_t recalc_rectangle(zathura_page_t* page, zathura_rectangle_t rectangle);
|
||||
|
||||
/**
|
||||
* Set adjustment of a GtkAdjustment respecting its limits.
|
||||
* @param adjust the GtkAdkustment instance
|
||||
* @param value the new adjustment
|
||||
*/
|
||||
void set_adjustment(GtkAdjustment* adjust, gdouble value);
|
||||
|
||||
/**
|
||||
* Calculate the page size according to the corrent scaling and rotation if
|
||||
* desired.
|
||||
* @param page the page
|
||||
* @param page_height the resulting page height
|
||||
* @param page_width the resultung page width
|
||||
* @param rotate honor page's rotation
|
||||
*/
|
||||
void
|
||||
page_calc_height_width(zathura_page_t* page, unsigned int* page_height, unsigned int* page_width, bool rotate);
|
||||
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
373
zathura.c
373
zathura.c
|
@ -1,8 +1,18 @@
|
|||
/* See LICENSE file for license and copyright information */
|
||||
|
||||
#include <stdlib.h>
|
||||
#define _BSD_SOURCE
|
||||
#define _XOPEN_SOURCE 700
|
||||
|
||||
#include <girara.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <girara/datastructures.h>
|
||||
#include <girara/utils.h>
|
||||
#include <girara/session.h>
|
||||
#include <girara/statusbar.h>
|
||||
#include <girara/settings.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "bookmarks.h"
|
||||
#include "callbacks.h"
|
||||
|
@ -21,7 +31,7 @@ typedef struct zathura_document_info_s
|
|||
const char* password;
|
||||
} zathura_document_info_t;
|
||||
|
||||
gboolean document_info_open(gpointer data);
|
||||
static gboolean document_info_open(gpointer data);
|
||||
|
||||
/* function implementation */
|
||||
zathura_t*
|
||||
|
@ -30,12 +40,14 @@ zathura_init(int argc, char* argv[])
|
|||
/* parse command line options */
|
||||
GdkNativeWindow embed = 0;
|
||||
gchar* config_dir = NULL, *data_dir = NULL, *plugin_path = NULL;
|
||||
bool forkback = false;
|
||||
GOptionEntry entries[] =
|
||||
{
|
||||
{ "reparent", 'e', 0, G_OPTION_ARG_INT, &embed, "Reparents to window specified by xid", "xid" },
|
||||
{ "config-dir", 'c', 0, G_OPTION_ARG_FILENAME, &config_dir, "Path to the config directory", "path" },
|
||||
{ "data-dir", 'd', 0, G_OPTION_ARG_FILENAME, &data_dir, "Path to the data directory", "path" },
|
||||
{ "plugins-dir", 'p', 0, G_OPTION_ARG_STRING, &plugin_path, "Path to the directories containing plugins", "path" },
|
||||
{ "fork", '\0', 0, G_OPTION_ARG_NONE, &forkback, "Fork into the background" , NULL },
|
||||
{ NULL, '\0', 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -48,26 +60,31 @@ zathura_init(int argc, char* argv[])
|
|||
printf("Error parsing command line arguments: %s\n", error->message);
|
||||
g_option_context_free(context);
|
||||
g_error_free(error);
|
||||
goto error_free;
|
||||
return NULL;
|
||||
}
|
||||
g_option_context_free(context);
|
||||
|
||||
zathura_t* zathura = malloc(sizeof(zathura_t));
|
||||
/* Fork into the background if the user really wants to ... */
|
||||
if (forkback == true)
|
||||
{
|
||||
int pid = fork();
|
||||
if (pid > 0) { /* parent */
|
||||
exit(0);
|
||||
} else if (pid < 0) { /* error */
|
||||
printf("Error: couldn't fork.");
|
||||
}
|
||||
|
||||
if (zathura == NULL) {
|
||||
return NULL;
|
||||
setsid();
|
||||
}
|
||||
|
||||
/* general */
|
||||
zathura->document = NULL;
|
||||
zathura_t* zathura = g_malloc0(sizeof(zathura_t));
|
||||
|
||||
/* plugins */
|
||||
zathura->plugins.plugins = girara_list_new();
|
||||
girara_list_set_free_function(zathura->plugins.plugins, zathura_document_plugin_free);
|
||||
zathura->plugins.path = girara_list_new();
|
||||
girara_list_set_free_function(zathura->plugins.path, g_free);
|
||||
zathura->plugins.type_plugin_mapping = girara_list_new();
|
||||
girara_list_set_free_function(zathura->plugins.type_plugin_mapping, zathura_type_plugin_mapping_free);
|
||||
zathura->plugins.plugins = girara_list_new2(
|
||||
(girara_free_function_t)zathura_document_plugin_free);
|
||||
zathura->plugins.path = girara_list_new2(g_free);
|
||||
zathura->plugins.type_plugin_mapping = girara_list_new2(
|
||||
(girara_free_function_t)zathura_type_plugin_mapping_free);
|
||||
|
||||
if (config_dir) {
|
||||
zathura->config.config_dir = g_strdup(config_dir);
|
||||
|
@ -85,16 +102,20 @@ zathura_init(int argc, char* argv[])
|
|||
g_free(path);
|
||||
}
|
||||
|
||||
/* create zathura (config/data) directory */
|
||||
g_mkdir_with_parents(zathura->config.config_dir, 0771);
|
||||
g_mkdir_with_parents(zathura->config.data_dir, 0771);
|
||||
|
||||
if (plugin_path) {
|
||||
gchar** paths = g_strsplit(plugin_path, ":", 0);
|
||||
for (unsigned int i = 0; paths[i] != '\0'; ++i) {
|
||||
girara_list_append(zathura->plugins.path, g_strdup(paths[i]));
|
||||
}
|
||||
g_strfreev(paths);
|
||||
girara_list_t* paths = girara_split_path_array(plugin_path);
|
||||
girara_list_merge(zathura->plugins.path, paths);
|
||||
girara_list_free(paths);
|
||||
} else {
|
||||
/* XXX: this shouldn't be hard coded! */
|
||||
girara_list_append(zathura->plugins.path, g_strdup("/usr/local/lib/zathura"));
|
||||
girara_list_append(zathura->plugins.path, g_strdup("/usr/lib/zathura"));
|
||||
#ifdef ZATHURA_PLUGINDIR
|
||||
girara_list_t* paths = girara_split_path_array(ZATHURA_PLUGINDIR);
|
||||
girara_list_merge(zathura->plugins.path, paths);
|
||||
girara_list_free(paths);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* UI */
|
||||
|
@ -106,7 +127,7 @@ zathura_init(int argc, char* argv[])
|
|||
zathura->ui.statusbar.file = NULL;
|
||||
zathura->ui.statusbar.buffer = NULL;
|
||||
zathura->ui.statusbar.page_number = NULL;
|
||||
zathura->ui.page_view = NULL;
|
||||
zathura->ui.page_widget = NULL;
|
||||
zathura->ui.index = NULL;
|
||||
|
||||
/* print settings */
|
||||
|
@ -123,35 +144,54 @@ zathura_init(int argc, char* argv[])
|
|||
config_load_default(zathura);
|
||||
|
||||
/* load global configuration files */
|
||||
girara_list_t* config_dirs = girara_split_path_array(girara_get_xdg_path(XDG_CONFIG_DIRS));
|
||||
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);
|
||||
|
||||
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);
|
||||
free(configuration_file);
|
||||
g_free(configuration_file);
|
||||
|
||||
/* initialize girara */
|
||||
zathura->ui.session->gtk.embed = embed;
|
||||
if (girara_session_init(zathura->ui.session) == false) {
|
||||
if (girara_session_init(zathura->ui.session, "zathura") == false) {
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* girara events */
|
||||
zathura->ui.session->events.buffer_changed = buffer_changed;
|
||||
zathura->ui.session->events.buffer_changed = cb_buffer_changed;
|
||||
|
||||
/* page view */
|
||||
zathura->ui.page_view = gtk_table_new(0, 0, TRUE);
|
||||
if (!zathura->ui.page_view) {
|
||||
zathura->ui.page_widget = gtk_table_new(0, 0, TRUE);
|
||||
if (!zathura->ui.page_widget) {
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "size-allocate", G_CALLBACK(cb_view_resized), zathura);
|
||||
|
||||
/* callbacks */
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
g_signal_connect(G_OBJECT(view_vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
|
||||
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
g_signal_connect(G_OBJECT(view_hadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
|
||||
|
||||
gtk_widget_show(zathura->ui.page_view);
|
||||
/* page view alignment */
|
||||
zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
|
||||
if (!zathura->ui.page_widget_alignment) {
|
||||
goto error_free;
|
||||
}
|
||||
gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget);
|
||||
|
||||
gtk_widget_show(zathura->ui.page_widget);
|
||||
|
||||
/* statusbar */
|
||||
zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
|
||||
|
@ -175,64 +215,69 @@ zathura_init(int argc, char* argv[])
|
|||
g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), NULL);
|
||||
|
||||
/* save page padding */
|
||||
int* page_padding = girara_setting_get(zathura->ui.session, "page-padding");
|
||||
zathura->global.page_padding = (page_padding) ? *page_padding : 1;
|
||||
zathura->global.page_padding = 1;
|
||||
girara_setting_get(zathura->ui.session, "page-padding", &zathura->global.page_padding);
|
||||
|
||||
gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_view), zathura->global.page_padding);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_view), zathura->global.page_padding);
|
||||
gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), zathura->global.page_padding);
|
||||
gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), zathura->global.page_padding);
|
||||
|
||||
/* parse colors */
|
||||
char* string_value = girara_setting_get(zathura->ui.session, "recolor-dark-color");
|
||||
char* string_value = NULL;
|
||||
girara_setting_get(zathura->ui.session, "recolor-darkcolor", &string_value);
|
||||
if (string_value != NULL) {
|
||||
gdk_color_parse(string_value, &(zathura->ui.colors.recolor_dark_color));
|
||||
free(string_value);
|
||||
g_free(string_value);
|
||||
}
|
||||
|
||||
string_value = girara_setting_get(zathura->ui.session, "recolor-light-color");
|
||||
string_value = NULL;
|
||||
girara_setting_get(zathura->ui.session, "recolor-lightcolor", &string_value);
|
||||
if (string_value != NULL) {
|
||||
gdk_color_parse(string_value, &(zathura->ui.colors.recolor_light_color));
|
||||
free(string_value);
|
||||
g_free(string_value);
|
||||
}
|
||||
|
||||
string_value = NULL;
|
||||
girara_setting_get(zathura->ui.session, "highlight-color", &string_value);
|
||||
if (string_value != NULL) {
|
||||
gdk_color_parse(string_value, &(zathura->ui.colors.highlight_color));
|
||||
g_free(string_value);
|
||||
}
|
||||
|
||||
/* database */
|
||||
char* database_path = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
|
||||
zathura->database = zathura_db_init(database_path);
|
||||
zathura->database = zathura_db_init(zathura->config.data_dir);
|
||||
if (zathura->database == NULL) {
|
||||
girara_error("Unable to inizialize database. Bookmarks won't be available.");
|
||||
girara_error("Unable to initialize database. Bookmarks won't be available.");
|
||||
}
|
||||
g_free(database_path);
|
||||
|
||||
/* bookmarks */
|
||||
zathura->bookmarks.bookmarks = girara_list_new();
|
||||
girara_list_set_free_function(zathura->bookmarks.bookmarks, (girara_free_function_t) zathura_bookmark_free);
|
||||
zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
|
||||
(girara_free_function_t) zathura_bookmark_free);
|
||||
|
||||
/* open document if passed */
|
||||
if (argc > 1) {
|
||||
zathura_document_info_t* document_info = malloc(sizeof(zathura_document_info_t));
|
||||
zathura_document_info_t* document_info = g_malloc0(sizeof(zathura_document_info_t));
|
||||
|
||||
if (document_info != NULL) {
|
||||
document_info->zathura = zathura;
|
||||
document_info->path = argv[1];
|
||||
document_info->password = (argc >= 2) ? argv[2] : NULL;
|
||||
g_idle_add(document_info_open, document_info);
|
||||
}
|
||||
document_info->zathura = zathura;
|
||||
document_info->path = argv[1];
|
||||
document_info->password = (argc >= 2) ? argv[2] : NULL;
|
||||
g_idle_add(document_info_open, document_info);
|
||||
}
|
||||
|
||||
return zathura;
|
||||
|
||||
error_free:
|
||||
|
||||
if (zathura->ui.page_view) {
|
||||
g_object_unref(zathura->ui.page_view);
|
||||
if (zathura->ui.page_widget) {
|
||||
g_object_unref(zathura->ui.page_widget);
|
||||
}
|
||||
|
||||
girara_session_destroy(zathura->ui.session);
|
||||
girara_list_free(zathura->bookmarks.bookmarks);
|
||||
zathura_db_free(zathura->database);
|
||||
if (zathura->ui.page_widget_alignment) {
|
||||
g_object_unref(zathura->ui.page_widget_alignment);
|
||||
}
|
||||
|
||||
error_out:
|
||||
|
||||
free(zathura);
|
||||
zathura_free(zathura);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -244,11 +289,17 @@ zathura_free(zathura_t* zathura)
|
|||
return;
|
||||
}
|
||||
|
||||
document_close(zathura);
|
||||
|
||||
if (zathura->ui.session != NULL) {
|
||||
girara_session_destroy(zathura->ui.session);
|
||||
}
|
||||
|
||||
document_close(zathura);
|
||||
/* stdin support */
|
||||
if (zathura->stdin_support.file != NULL) {
|
||||
g_unlink(zathura->stdin_support.file);
|
||||
g_free(zathura->stdin_support.file);
|
||||
}
|
||||
|
||||
/* bookmarks */
|
||||
girara_list_free(zathura->bookmarks.bookmarks);
|
||||
|
@ -272,22 +323,91 @@ zathura_free(zathura_t* zathura)
|
|||
/* free config variables */
|
||||
g_free(zathura->config.config_dir);
|
||||
g_free(zathura->config.data_dir);
|
||||
|
||||
g_free(zathura);
|
||||
}
|
||||
|
||||
gboolean
|
||||
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);
|
||||
if (handle == -1)
|
||||
{
|
||||
if (error != NULL) {
|
||||
girara_error("Can not create temporary file: %s", error->message);
|
||||
g_error_free(error);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// read from stdin and dump to temporary file
|
||||
int stdinfno = fileno(stdin);
|
||||
if (stdinfno == -1)
|
||||
{
|
||||
girara_error("Can not read from stdin.");
|
||||
close(handle);
|
||||
g_unlink(file);
|
||||
g_free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char buffer[BUFSIZ];
|
||||
ssize_t count = 0;
|
||||
while ((count = read(stdinfno, buffer, BUFSIZ)) > 0)
|
||||
{
|
||||
if (write(handle, buffer, count) != count)
|
||||
{
|
||||
girara_error("Can not write to temporary file: %s", file);
|
||||
close(handle);
|
||||
g_unlink(file);
|
||||
g_free(file);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
close(handle);
|
||||
|
||||
if (count != 0)
|
||||
{
|
||||
girara_error("Can not read from stdin.");
|
||||
g_unlink(file);
|
||||
g_free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
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) {
|
||||
free(document_info);
|
||||
return FALSE;
|
||||
if (document_info->zathura != NULL && document_info->path != NULL) {
|
||||
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,
|
||||
"Could not read file from stdin and write it to a temporary file.");
|
||||
} else {
|
||||
document_info->zathura->stdin_support.file = g_strdup(file);
|
||||
}
|
||||
} else {
|
||||
file = g_strdup(document_info->path);
|
||||
}
|
||||
|
||||
if (file != NULL) {
|
||||
document_open(document_info->zathura, file, document_info->password);
|
||||
g_free(file);
|
||||
}
|
||||
}
|
||||
|
||||
document_open(document_info->zathura, document_info->path, document_info->password);
|
||||
free(document_info);
|
||||
|
||||
g_free(document_info);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -307,12 +427,11 @@ document_open(zathura_t* zathura, const char* path, const char* password)
|
|||
zathura->document = document;
|
||||
|
||||
/* view mode */
|
||||
int* value = girara_setting_get(zathura->ui.session, "pages-per-row");
|
||||
int pages_per_row = (value) ? *value : 1;
|
||||
free(value);
|
||||
page_view_set_mode(zathura, pages_per_row);
|
||||
int pages_per_row = 1;
|
||||
girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row);
|
||||
page_widget_set_mode(zathura, pages_per_row);
|
||||
|
||||
girara_set_view(zathura->ui.session, zathura->ui.page_view);
|
||||
girara_set_view(zathura->ui.session, zathura->ui.page_widget_alignment);
|
||||
|
||||
/* threads */
|
||||
zathura->sync.render_thread = render_init(zathura);
|
||||
|
@ -324,7 +443,7 @@ document_open(zathura_t* zathura, const char* path, const char* password)
|
|||
/* create blank pages */
|
||||
for (unsigned int page_id = 0; page_id < document->number_of_pages; page_id++) {
|
||||
zathura_page_t* page = document->pages[page_id];
|
||||
gtk_widget_realize(page->event_box);
|
||||
gtk_widget_realize(page->drawing_area);
|
||||
}
|
||||
|
||||
/* bookmarks */
|
||||
|
@ -332,6 +451,9 @@ document_open(zathura_t* zathura, const char* path, const char* password)
|
|||
girara_warning("Failed to load bookmarks for %s.\n", zathura->document->file_path);
|
||||
}
|
||||
|
||||
page_set_delayed(zathura, document->current_page_number - 1);
|
||||
cb_view_vadjustment_value_changed(NULL, zathura);
|
||||
|
||||
return true;
|
||||
|
||||
error_free:
|
||||
|
@ -353,9 +475,8 @@ document_save(zathura_t* zathura, const char* path, bool overwrite)
|
|||
gchar* file_path = girara_fix_path(path);
|
||||
if (!overwrite && g_file_test(file_path, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
gchar* message = g_strdup_printf("File already exists: %s. Use :write! to overwrite it.", file_path);
|
||||
girara_error(message);
|
||||
g_free(message);
|
||||
girara_error("File already exists: %s. Use :write! to overwrite it.", file_path);
|
||||
g_free(file_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -381,23 +502,65 @@ document_close(zathura_t* zathura)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* store last seen page */
|
||||
zathura_db_set_fileinfo(zathura->database, zathura->document->file_path, zathura->document->current_page_number,
|
||||
/* zathura->document->offset TODO */ 0, zathura->document->scale,
|
||||
zathura->document->rotate);
|
||||
|
||||
render_free(zathura->sync.render_thread);
|
||||
zathura->sync.render_thread = NULL;
|
||||
|
||||
gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_view), remove_page_from_table, (gpointer)1);
|
||||
gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), remove_page_from_table, (gpointer)1);
|
||||
|
||||
zathura_document_free(zathura->document);
|
||||
zathura->document = NULL;
|
||||
|
||||
gtk_widget_hide_all(zathura->ui.page_view);
|
||||
gtk_widget_hide(zathura->ui.page_widget);
|
||||
|
||||
statusbar_page_number_update(zathura);
|
||||
|
||||
if (zathura->ui.session != NULL && zathura->ui.statusbar.file != NULL) {
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, "[No name]");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct page_set_delayed_s
|
||||
{
|
||||
zathura_t* zathura;
|
||||
unsigned int page;
|
||||
} page_set_delayed_t;
|
||||
|
||||
static gboolean
|
||||
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 || zathura->document->pages == NULL ||
|
||||
page_id >= zathura->document->number_of_pages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
page_set_delayed_t* p = g_malloc(sizeof(page_set_delayed_t));
|
||||
p->zathura = zathura;
|
||||
p->page = page_id;
|
||||
g_idle_add(page_set_delayed_impl, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
page_set(zathura_t* zathura, unsigned int page_id)
|
||||
{
|
||||
if (!zathura->document || !zathura->document->pages) {
|
||||
if (zathura == NULL || zathura->document == NULL || zathura->document->pages == NULL) {
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
@ -412,19 +575,13 @@ page_set(zathura_t* zathura, unsigned int page_id)
|
|||
goto error_out;
|
||||
}
|
||||
|
||||
page_offset_t* offset = page_calculate_offset(page);
|
||||
if (offset == NULL) {
|
||||
goto error_out;
|
||||
}
|
||||
page_offset_t offset;
|
||||
page_calculate_offset(page, &offset);
|
||||
|
||||
GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
|
||||
gtk_adjustment_set_value(view_hadjustment, offset->x);
|
||||
gtk_adjustment_set_value(view_vadjustment, offset->y);
|
||||
|
||||
/* update page number */
|
||||
zathura->document->current_page_number = page_id;
|
||||
statusbar_page_number_update(zathura);
|
||||
set_adjustment(view_hadjustment, offset.x);
|
||||
set_adjustment(view_vadjustment, offset.y);
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -440,13 +597,17 @@ statusbar_page_number_update(zathura_t* zathura)
|
|||
return;
|
||||
}
|
||||
|
||||
char* page_number_text = g_strdup_printf("[%d/%d]", zathura->document->current_page_number + 1, zathura->document->number_of_pages);
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.page_number, page_number_text);
|
||||
g_free(page_number_text);
|
||||
if (zathura->document != NULL) {
|
||||
char* page_number_text = g_strdup_printf("[%d/%d]", zathura->document->current_page_number + 1, zathura->document->number_of_pages);
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.page_number, page_number_text);
|
||||
g_free(page_number_text);
|
||||
} else {
|
||||
girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.page_number, "");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
page_view_set_mode(zathura_t* zathura, unsigned int pages_per_row)
|
||||
page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row)
|
||||
{
|
||||
/* show at least one page */
|
||||
if (pages_per_row == 0) {
|
||||
|
@ -457,37 +618,15 @@ page_view_set_mode(zathura_t* zathura, unsigned int pages_per_row)
|
|||
return;
|
||||
}
|
||||
|
||||
gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_view), remove_page_from_table, (gpointer)0);
|
||||
gtk_container_foreach(GTK_CONTAINER(zathura->ui.page_widget), remove_page_from_table, (gpointer)0);
|
||||
|
||||
gtk_table_resize(GTK_TABLE(zathura->ui.page_view), zathura->document->number_of_pages / pages_per_row + 1, pages_per_row);
|
||||
gtk_table_resize(GTK_TABLE(zathura->ui.page_widget), ceil(zathura->document->number_of_pages / pages_per_row), pages_per_row);
|
||||
for (unsigned int i = 0; i < zathura->document->number_of_pages; i++)
|
||||
{
|
||||
int x = i % pages_per_row;
|
||||
int y = i / pages_per_row;
|
||||
gtk_table_attach(GTK_TABLE(zathura->ui.page_view), zathura->document->pages[i]->event_box, x, x + 1, y, y + 1, GTK_EXPAND, GTK_EXPAND, 0, 0);
|
||||
gtk_table_attach(GTK_TABLE(zathura->ui.page_widget), zathura->document->pages[i]->drawing_area, x, x + 1, y, y + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
|
||||
}
|
||||
|
||||
gtk_widget_show_all(zathura->ui.page_view);
|
||||
}
|
||||
|
||||
/* main function */
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
g_thread_init(NULL);
|
||||
gdk_threads_init();
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
zathura_t* zathura = zathura_init(argc, argv);
|
||||
if (zathura == NULL) {
|
||||
printf("error: coult not initialize zathura\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gdk_threads_enter();
|
||||
gtk_main();
|
||||
gdk_threads_leave();
|
||||
|
||||
zathura_free(zathura);
|
||||
|
||||
return 0;
|
||||
gtk_widget_show_all(zathura->ui.page_widget);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
Version=1.0
|
||||
Type=Application
|
||||
Name=Zathura
|
||||
Comment=A minimalistic PDF viewer
|
||||
Comment[de]=Ein minimalistischer PDF-Betrachter
|
||||
Comment=A minimalistic document viewer
|
||||
Comment[de]=Ein minimalistischer Dokumenten-Betrachter
|
||||
Exec=zathura %f
|
||||
Terminal=false
|
||||
Categories=Office;Viewer;
|
||||
MimeType=application/pdf;
|
||||
MimeType=application/pdf;application/postscript;image/vnd.djvu;
|
||||
|
|
84
zathura.h
84
zathura.h
|
@ -4,16 +4,11 @@
|
|||
#define ZATHURA_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <girara.h>
|
||||
#include <girara/types.h>
|
||||
#include <girara/macros.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef UNUSED
|
||||
#elif defined(__GNUC__)
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
|
||||
#elif defined(__LCINT__)
|
||||
# define UNUSED(x) /*@unused@*/ x
|
||||
#else
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
#define UNUSED(x) GIRARA_UNUSED(x)
|
||||
|
||||
enum { NEXT, PREVIOUS, LEFT, RIGHT, UP, DOWN, BOTTOM, TOP, HIDE, HIGHLIGHT,
|
||||
DELETE_LAST_WORD, DELETE_LAST_CHAR, DEFAULT, ERROR, WARNING, NEXT_GROUP,
|
||||
|
@ -41,71 +36,78 @@ typedef struct zathura_s
|
|||
{
|
||||
struct
|
||||
{
|
||||
girara_session_t* session; /**> girara interface session */
|
||||
girara_session_t* session; /**< girara interface session */
|
||||
|
||||
struct
|
||||
{
|
||||
girara_statusbar_item_t* buffer; /**> buffer statusbar entry */
|
||||
girara_statusbar_item_t* file; /**> file statusbar entry */
|
||||
girara_statusbar_item_t* page_number; /**> page number statusbar entry */
|
||||
girara_statusbar_item_t* buffer; /**< buffer statusbar entry */
|
||||
girara_statusbar_item_t* file; /**< file statusbar entry */
|
||||
girara_statusbar_item_t* page_number; /**< page number statusbar entry */
|
||||
} statusbar;
|
||||
|
||||
struct
|
||||
{
|
||||
GdkColor recolor_dark_color; /**> Dark color for recoloring */
|
||||
GdkColor recolor_light_color; /**> Light color for recoloring */
|
||||
GdkColor recolor_dark_color; /**< Dark color for recoloring */
|
||||
GdkColor recolor_light_color; /**< Light color for recoloring */
|
||||
GdkColor highlight_color; /**< Color for highlighting */
|
||||
} colors;
|
||||
|
||||
GtkWidget *page_view; /**> Widget that contains all rendered pages */
|
||||
GtkWidget *index; /**> Widget to show the index of the document */
|
||||
GtkWidget *page_widget_alignment;
|
||||
GtkWidget *page_widget; /**< Widget that contains all rendered pages */
|
||||
GtkWidget *index; /**< Widget to show the index of the document */
|
||||
} ui;
|
||||
|
||||
struct
|
||||
{
|
||||
render_thread_t* render_thread; /**> The thread responsible for rendering the pages */
|
||||
render_thread_t* render_thread; /**< The thread responsible for rendering the pages */
|
||||
} sync;
|
||||
|
||||
struct
|
||||
{
|
||||
girara_list_t* plugins; /**> List of plugins */
|
||||
girara_list_t* path; /**> List of plugin paths */
|
||||
girara_list_t* type_plugin_mapping; /**> List of type -> plugin mappings */
|
||||
girara_list_t* plugins; /**< List of plugins */
|
||||
girara_list_t* path; /**< List of plugin paths */
|
||||
girara_list_t* type_plugin_mapping; /**< List of type -> plugin mappings */
|
||||
} plugins;
|
||||
|
||||
struct
|
||||
{
|
||||
gchar* config_dir; /**> Path to the configuration directory */
|
||||
gchar* data_dir; /**> Path to the data directory */
|
||||
gchar* config_dir; /**< Path to the configuration directory */
|
||||
gchar* data_dir; /**< Path to the data directory */
|
||||
} config;
|
||||
|
||||
struct
|
||||
{
|
||||
GtkPrintSettings* settings; /**> Print settings */
|
||||
GtkPageSetup* page_setup; /**> Saved page setup */
|
||||
GtkPrintSettings* settings; /**< Print settings */
|
||||
GtkPageSetup* page_setup; /**< Saved page setup */
|
||||
} print;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int page_padding; /**> Padding between the pages */
|
||||
bool recolor; /**> Recoloring mode switch */
|
||||
unsigned int page_padding; /**< Padding between the pages */
|
||||
bool recolor; /**< Recoloring mode switch */
|
||||
} global;
|
||||
|
||||
struct
|
||||
{
|
||||
girara_mode_t normal; /**> Normal mode */
|
||||
girara_mode_t fullscreen; /**> Fullscreen mode */
|
||||
girara_mode_t index; /**> Index mode */
|
||||
girara_mode_t insert; /**> Insert mode */
|
||||
girara_mode_t normal; /**< Normal mode */
|
||||
girara_mode_t fullscreen; /**< Fullscreen mode */
|
||||
girara_mode_t index; /**< Index mode */
|
||||
girara_mode_t insert; /**< Insert mode */
|
||||
} modes;
|
||||
|
||||
struct
|
||||
{
|
||||
gchar* file; /**> bookmarks file */
|
||||
girara_list_t* bookmarks; /**> bookmarks */
|
||||
gchar* file; /**< bookmarks file */
|
||||
girara_list_t* bookmarks; /**< bookmarks */
|
||||
} bookmarks;
|
||||
|
||||
zathura_document_t* document; /**> The current document */
|
||||
zathura_database_t* database; /**> The database */
|
||||
struct
|
||||
{
|
||||
gchar* file;
|
||||
} stdin_support;
|
||||
|
||||
zathura_document_t* document; /**< The current document */
|
||||
zathura_database_t* database; /**< The database */
|
||||
} zathura_t;
|
||||
|
||||
/**
|
||||
|
@ -158,17 +160,27 @@ bool document_close(zathura_t* zathura);
|
|||
* Opens the page with the given number
|
||||
*
|
||||
* @param zathura The zathura session
|
||||
* @param page_id The id of the page that should be set
|
||||
* @return If no error occured true, otherwise false, is returned.
|
||||
*/
|
||||
bool page_set(zathura_t* zathura, unsigned int page_id);
|
||||
|
||||
/**
|
||||
* Opens the page with the given number (delayed)
|
||||
*
|
||||
* @param zathura The zathura session
|
||||
* @param page_id The id of the page that should be set
|
||||
* @return If no error occured true, otherwise false, is returned.
|
||||
*/
|
||||
bool page_set_delayed(zathura_t* zathura, unsigned int page_id);
|
||||
|
||||
/**
|
||||
* Builds the box structure to show the rendered pages
|
||||
*
|
||||
* @param zathura The zathura session
|
||||
* @param pages_per_row Number of shown pages per row
|
||||
*/
|
||||
void page_view_set_mode(zathura_t* zathura, unsigned int pages_per_row);
|
||||
void page_widget_set_mode(zathura_t* zathura, unsigned int pages_per_row);
|
||||
|
||||
/**
|
||||
* Updates the page number in the statusbar. Note that 1 will be added to the
|
||||
|
|
360
zathurarc.5.rst
360
zathurarc.5.rst
|
@ -6,188 +6,268 @@
|
|||
zathura configuration file
|
||||
--------------------------
|
||||
|
||||
:Author: Sebastian Ramacher <s.ramacher@gmx.at>
|
||||
:Date: 19.8.2010
|
||||
:Author: pwmt.org
|
||||
:Date: 02.02.2012
|
||||
:Manual section: 5
|
||||
|
||||
SYNOPOSIS
|
||||
=========
|
||||
|
||||
/etc/zathurarc, ~/.config/zathura/zathurarc
|
||||
/etc/zathurarc, $XDG_CONFIG_HOME/zathura/zathurarc
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
The zathurarc contains various options controlling the behavior of zathura. One
|
||||
can use the ``set`` and ``map`` commands:
|
||||
The zathurarc file is a simple plain text file that can be populated with
|
||||
various commands to change the behaviour and the look of zathura which we are
|
||||
going to describe in the following subsections. Each line (besides empty lines
|
||||
and comments (which start with a prepended #)) is evaluated on its own, so it is
|
||||
not possible to write multiple commands in one single line.
|
||||
|
||||
* ``set`` [id] [value]
|
||||
* ``map`` [key] [function] [argument] [mode]
|
||||
The following commands can be used:
|
||||
|
||||
They behave the same as the ``set`` and ``map`` commands in zathura. Any line
|
||||
not starting with ``set`` or ``map`` will be ignored.
|
||||
set - Changing the options
|
||||
--------------------------
|
||||
|
||||
set
|
||||
---
|
||||
In addition to the build-in :set command zathura offers more options to be
|
||||
changed and makes those changes permanent. To overwrite an option you just have
|
||||
to add a line structured like the following:
|
||||
|
||||
[id] and the corresponding [value] can be one of
|
||||
::
|
||||
set <option> <new value>
|
||||
|
||||
* adjust_open [bestfit|width|noadjust] - adjust mode.
|
||||
The option field has to be replaced with the name of the option that should be
|
||||
changed and the new value field has to be replaced with the new value the option
|
||||
should get. The type of the value can be one of the following:
|
||||
|
||||
- bestfit: adjust to best fit
|
||||
- width: adjust to width
|
||||
- noadjust: don't adjust
|
||||
* INT - An integer number
|
||||
* FLOAT - A floating point number
|
||||
* STRING - A character string
|
||||
* BOOL - A boolean value (“true” for true, “false” for false)
|
||||
|
||||
* browser,
|
||||
uri_command [string] - command to open external URIs.
|
||||
|
||||
The string has to include a ``%s`` which will be replaced with the URI.
|
||||
In addition we advice you to check the List of options to get a more detailed
|
||||
view of the options that can be changed and which values they should be set to.
|
||||
|
||||
* completion_bgcolor,
|
||||
completion_fgcolor,
|
||||
completion_g_bgcolor,
|
||||
completion_g_fgcolor,
|
||||
completion_hl_bgcolor,
|
||||
completion_hl_fgcolor,
|
||||
default_bgcolor,
|
||||
default_fgcolor,
|
||||
inputbar_bgcolor,
|
||||
inputbar_fgcolor,
|
||||
notification_e_bgcolor,
|
||||
notification_e_fgcolor,
|
||||
notification_w_bgcolor,
|
||||
notification_w_fgcolor,
|
||||
recolor_darkcolor,
|
||||
recoler_lightcolor,
|
||||
statusbar_bgcolor,
|
||||
statusbar_fgcolor,
|
||||
search_highlight,
|
||||
select_text [color] -
|
||||
colors settings.
|
||||
|
||||
The color can be given as hex triplet (#rrggbb) or any color
|
||||
string understood by GTK+ (e.g. red, green, blue, black, ...).
|
||||
The following example should give some deeper insight of how the set command can
|
||||
be used:
|
||||
|
||||
* default_text [string] - text displayed in the statusbar if no file is opened.
|
||||
::
|
||||
set option1 5
|
||||
set option2 2.0
|
||||
set option3 hello
|
||||
set option4 hello\ world
|
||||
set option5 "hello world"
|
||||
|
||||
* font [string] - the used font.
|
||||
Possible options are:
|
||||
|
||||
* height,
|
||||
width [int] - default height and width of the zathura window.
|
||||
page-padding
|
||||
^^^^^^^^^^^^
|
||||
The page padding defines the gap in pixels between each rendered page and can
|
||||
not be changed during runtime.
|
||||
|
||||
* labels [bool] - allow label mode.
|
||||
* Value-type: Integer
|
||||
* Default value: 1
|
||||
|
||||
* list_printer_command [string] - command to list all available printers.
|
||||
pages-per-row
|
||||
^^^^^^^^^^^^^
|
||||
Defines the number of pages that are rendered next to each other in a row.
|
||||
|
||||
* n_completion_items [int] - number of completion items to display.
|
||||
* Value-type: Integer
|
||||
* Default value: 1
|
||||
|
||||
* offset - page offset.
|
||||
recolor-dark-color
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Defines the color value that is used to represent dark colors in recoloring mode
|
||||
|
||||
* print_command [string] - command to print the file.
|
||||
|
||||
The string has to include
|
||||
``%s`` four times. The first occurence of ``%s`` will be replaced with the
|
||||
printer, the second with additional options given on the command line, the
|
||||
third with the pages to print and the fourth with the filename.
|
||||
* Value-type: String
|
||||
* Default value: #FFFFFF
|
||||
|
||||
* recolor [bool] - invert the image.
|
||||
recolor-light-color
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
Defines the color value that is used to represent light colors in recoloring mode
|
||||
|
||||
* save_position, save_zoom_level [bool] - save current page and zoom level in
|
||||
bookmarks file.
|
||||
* Value-type: String
|
||||
* Default value: #000000
|
||||
|
||||
* scroll_step [float] - scroll step.
|
||||
zoom-step
|
||||
^^^^^^^^^
|
||||
Defines the amount of percent that is zoomed in or out on each comand.
|
||||
|
||||
* scroll_wrap [bool] - wrap scrolling at the end and beginning of the document.
|
||||
* Value-type: Integer
|
||||
* Default value: 10
|
||||
|
||||
* scrollbars,
|
||||
show_statusbar,
|
||||
show_inputbar [bool] -
|
||||
show statusbar, inputbar and scrollbars.
|
||||
map - Mapping a shortcut
|
||||
------------------------
|
||||
It is possible to map or remap new key bindings to shortcut functions which
|
||||
allows a high level of customization. The *:map* command can also be used in
|
||||
the *zathurarc* file to make those changes permanent::
|
||||
|
||||
* smooth_scrolling [float] - smooth scrolling.
|
||||
map [mode] <binding> <shortcut function> <argument>
|
||||
|
||||
* transparency [float] - transparency of rectangles.
|
||||
Mode
|
||||
^^^^
|
||||
The *map* command expects several arguments where only the *binding* as well as
|
||||
the *shortcut-function* argument is required. Since zathura uses several odes it
|
||||
is possible to map bindings only for a specific mode by passing the *mode*
|
||||
argument which can take one of the following values:
|
||||
|
||||
* zoom_max,
|
||||
zoom_min,
|
||||
zoom_step [float] - maximal and minimal zoom level and zoom step.
|
||||
|
||||
map
|
||||
---
|
||||
|
||||
[key] can be a single character, ``<C-?>`` for ``Ctrl + ?`` like shortcuts,
|
||||
where ``?`` stands for some key (e.g. ``<C-q>``). Also it can be ``<S-?>`` for
|
||||
uppercase shortcuts or one of
|
||||
|
||||
``<BackSpace>, <CapsLock>, <Down>, <Esc>, <F[1-12]>, <Left>, <PageDown>,
|
||||
<PageUp>, <Return>, <Right>, <Space>, <Super>, <Tab>, <Up>``.
|
||||
|
||||
[function] and the corresponding [argument] can be one of
|
||||
|
||||
* abort - clear command line and buffer.
|
||||
* adjust_window
|
||||
* change_buffer [delete_last]: change buffer.
|
||||
|
||||
- delete_last: delete last character
|
||||
|
||||
* change_mode [mode] - change mode.
|
||||
|
||||
For the possible modes see the list of modes below.
|
||||
|
||||
* focus_inputbar - focus the inputbar.
|
||||
* follow - follow a URI.
|
||||
* navigate [next|previous|left|right] - navigate the document.
|
||||
* navigate_index [up|down|expand|collapse|select] - nagivate the index.
|
||||
* quit - quit zathura.
|
||||
* recolor - toogle recolor setting.
|
||||
* reload - reload the file.
|
||||
* rotate - rotate by 90 degrees clockwise.
|
||||
* scroll [up|down|half_up|half_down|full_up|full_down|left|right] - scroll.
|
||||
* search [string] - search for the specified string.
|
||||
* switch_goto_mode - toogle goto mode.
|
||||
* toggle_fullscreen - toogle fullscreen mode.
|
||||
* toggle_index - toogle index mode.
|
||||
* toggle_inputbar - toogle inputbar display setting.
|
||||
* toogle_statusbar - toogle statusbar display setting.
|
||||
* zoom [in|out|float] - zoom in, out or to a specific zooming level.
|
||||
|
||||
[mode] can be one of
|
||||
|
||||
* all
|
||||
* fullscreen
|
||||
* index
|
||||
* normal
|
||||
* insert
|
||||
* normal (default)
|
||||
* visual
|
||||
* insert
|
||||
* index
|
||||
|
||||
If [mode] is omitted, all will be used.
|
||||
The brackets around the value are mandatory.
|
||||
|
||||
Single key binding
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
The (possible) second argument defines the used key binding that should be
|
||||
mapped to the shortcut function and is structured like the following. On the one
|
||||
hand it is possible to just assign single letters, numbers or signs to it::
|
||||
|
||||
map a shortcut_function
|
||||
map b shortcut_function
|
||||
map c shortcut_function
|
||||
map 1 shortcut_function
|
||||
map 2 shortcut_function
|
||||
map 3 shortcut_function
|
||||
map ! shortcut_function
|
||||
map ? shortcut_function
|
||||
|
||||
Using modifiers
|
||||
^^^^^^^^^^^^^^^
|
||||
It is also possible to use modifiers like the *Control* or *Alt* button on the
|
||||
keyboard. It is possible to use the following modifiers:
|
||||
|
||||
* A - *Alt*
|
||||
* C - *Control*
|
||||
* S - *Shift*
|
||||
|
||||
Now it is required to define the *binding* with the following structure::
|
||||
|
||||
map <A-a> shortcut_function
|
||||
map <C-a> shortcut_function
|
||||
|
||||
Special keys
|
||||
^^^^^^^^^^^^
|
||||
zathura allows it also to assign keys like the space bar or the tab button which
|
||||
also have to be written in between angle brackets. The following special keys
|
||||
are currently available:
|
||||
|
||||
========== =================
|
||||
Identifier Description
|
||||
========== =================
|
||||
BackSpace *Back space*
|
||||
CapsLock *Caps lock*
|
||||
Esc *Escape*
|
||||
Down *Arrow down*
|
||||
Up *Arrow up*
|
||||
Left *Arrow left*
|
||||
Right *A7row right*
|
||||
F1 *F1*
|
||||
F2 *F2*
|
||||
F3 *F3*
|
||||
F4 *F4*
|
||||
F5 *F5*
|
||||
F6 *F6*
|
||||
F7 *F7*
|
||||
F8 *F8*
|
||||
F9 *F9*
|
||||
F10 *F10*
|
||||
F11 *F11*
|
||||
F12 *F12*
|
||||
PageDown *Page Down*
|
||||
PageUp *Page Up*
|
||||
Return *Return*
|
||||
Space *Space*
|
||||
Super *Windows button*
|
||||
Tab *Tab*
|
||||
========== =================
|
||||
|
||||
Of course it is possible to combine those special keys with a modifier. The
|
||||
usage of those keys should be explained by the following examples::
|
||||
|
||||
map <Space> shortcut_function
|
||||
map <C-Space> shortcut_function
|
||||
|
||||
Mouse buttons
|
||||
^^^^^^^^^^^^^
|
||||
It is also possible to map mouse buttons to shortcuts by using the following
|
||||
special keys:
|
||||
|
||||
========== ================
|
||||
Identifier Description
|
||||
========== ================
|
||||
Button1 *Mouse button 1*
|
||||
Button2 *Mouse button 2*
|
||||
Button3 *Mouse button 3*
|
||||
Button4 *Mouse button 4*
|
||||
Button5 *Mouse button 5*
|
||||
========== ================
|
||||
|
||||
They can also be combined with modifiers::
|
||||
|
||||
map <Button1> shortcut_function
|
||||
map <C-Button1> shortcut_function
|
||||
|
||||
Buffer commands
|
||||
^^^^^^^^^^^^^^^
|
||||
If a mapping does not match one of the previous definition but is still a valid
|
||||
mapping it will be mapped as a buffer command::
|
||||
|
||||
map abc quit
|
||||
map test quit
|
||||
|
||||
Shortcut functions
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
The following shortcut functions can be mapped:
|
||||
|
||||
================= ====================================
|
||||
Function Description
|
||||
================= ====================================
|
||||
abort *Switch back to normal mode*
|
||||
adjust *Adjust page width*
|
||||
change_mode *Change current mode*
|
||||
focus_inputbar *Focus inputbar*
|
||||
follow *Follow a link*
|
||||
goto *Go to a certain page*
|
||||
index_navigate *Navigate through the index*
|
||||
naviate *Navigate to the next/previous page*
|
||||
quit *Quit zathura*
|
||||
recolor *Recolor the pages*
|
||||
reload *Reload the document*
|
||||
rotate *Rotate the page*
|
||||
scroll *Scroll*
|
||||
search *Search next/previous item*
|
||||
toggle_fullscreen *Toggle fullscreen*
|
||||
toggle_index *Show or hide index*
|
||||
toggle_inputbar *Show or hide inputbar*
|
||||
toggle_statusbar *Show or hide statusbar*
|
||||
zoom *Zoom in or out*
|
||||
================= ====================================
|
||||
|
||||
Pass arguments
|
||||
^^^^^^^^^^^^^^
|
||||
Some shortcut function require or have optional arguments which influence the
|
||||
behaviour of them. Those can be passed as the last argument::
|
||||
|
||||
map <C-i> zoom in
|
||||
map <C-o> zoom out
|
||||
|
||||
unmap - Removing a shortcut
|
||||
---------------------------
|
||||
In addition to mapping or remaping custom key bindings it is possible to remove
|
||||
existing ones by using the *:unmap* command. The command is used in the
|
||||
following way (the explanation of the parameters is described in the *map*
|
||||
section of this document::
|
||||
|
||||
unmap [mode] <binding>
|
||||
|
||||
EXAMPLE
|
||||
=======
|
||||
|
||||
::
|
||||
|
||||
# zathurarc
|
||||
|
||||
# colors
|
||||
set statusbar_bgcolor #00FF00
|
||||
set statusbar_fgcolor red
|
||||
|
||||
# settings
|
||||
set height 1024
|
||||
set width 768
|
||||
set adjust_open width
|
||||
|
||||
# key bindings
|
||||
map <PageUp> navigate previous
|
||||
map <PageDown> navigate next
|
||||
|
||||
map + zoom in
|
||||
map - zoom out
|
||||
|
||||
map <C-q> quit
|
||||
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
|
|
Loading…
Reference in a new issue