diff --git a/callbacks.c b/callbacks.c index f9a7b05..6ffc884 100644 --- a/callbacks.c +++ b/callbacks.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "callbacks.h" #include "zathura.h" @@ -13,6 +14,7 @@ #include "document.h" #include "utils.h" #include "shortcuts.h" +#include "page_view_widget.h" gboolean cb_destroy(GtkWidget* UNUSED(widget), gpointer UNUSED(data)) @@ -145,4 +147,64 @@ cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path, g_object_unref(model); } -bool +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; + + char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + if (input == NULL) { + goto error_ret; + } else if (strlen(input) == 0) { + goto error_free; + } + + int index = atoi(input); + if (index == 0 && g_strcmp0(input, "0") != 0) { + girara_notify(session, GIRARA_WARNING, "Invalid input '%s' given.", input); + goto error_free; + } + + /* 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; + } + + zathura_link_t* link = zathura_page_view_link_get(ZATHURA_PAGE_VIEW(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; + break; + } + } + + if (invalid_index == true) { + girara_notify(session, GIRARA_WARNING, "Invalid index '%s' given.", input); + } + + g_free(input); + + return TRUE; + +error_free: + + g_free(input); + +error_ret: + + return FALSE; +} diff --git a/callbacks.h b/callbacks.h index 70ad94f..afb9d73 100644 --- a/callbacks.h +++ b/callbacks.h @@ -51,4 +51,13 @@ void cb_pages_per_row_value_changed(girara_session_t* GIRARA_UNUSED(session), co 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 + */ +bool cb_sc_follow(GtkEntry* entry, girara_session_t* session); + #endif // CALLBACKS_H diff --git a/page_view_widget.c b/page_view_widget.c index e88e675..7f64be7 100644 --- a/page_view_widget.c +++ b/page_view_widget.c @@ -18,6 +18,8 @@ typedef struct zathura_page_view_private_s { bool links_got; /**< True if we already tried to retrieve the list of links */ bool draw_links; /**< True if links should be drawn */ girara_list_t* search_results; /** True if search results should be drawn */ + unsigned int link_offset; /**< Offset to the links */ + unsigned int number_of_links; /**< Offset to the links */ } zathura_page_view_private_t; #define ZATHURA_PAGE_VIEW_GET_PRIVATE(obj) \ @@ -26,6 +28,7 @@ typedef struct zathura_page_view_private_s { static gboolean zathura_page_view_expose(GtkWidget* widget, GdkEventExpose* event); static void zathura_page_view_finalize(GObject* object); static void zathura_page_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec); +static void zathura_page_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec); static void zathura_page_view_size_allocate(GtkWidget* widget, GdkRectangle* allocation); static void redraw_rect(ZathuraPageView* widget, zathura_rectangle_t* rectangle); static void redraw_all_rects(ZathuraPageView* widget, girara_list_t* rectangles); @@ -35,6 +38,8 @@ enum properties_e PROP_0, PROP_PAGE, PROP_DRAW_LINKS, + PROP_LINKS_OFFSET, + PROP_LINKS_NUMBER, PROP_SEARCH_RESULTS }; @@ -52,12 +57,17 @@ zathura_page_view_class_init(ZathuraPageViewClass* class) GObjectClass* object_class = G_OBJECT_CLASS(class); object_class->finalize = zathura_page_view_finalize; object_class->set_property = zathura_page_view_set_property; + object_class->get_property = zathura_page_view_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)); } @@ -66,10 +76,11 @@ static void zathura_page_view_init(ZathuraPageView* widget) { zathura_page_view_private_t* priv = ZATHURA_PAGE_VIEW_GET_PRIVATE(widget); - priv->page = NULL; - priv->surface = NULL; - priv->links = NULL; - priv->links_got = false; + priv->page = NULL; + priv->surface = NULL; + priv->links = NULL; + priv->links_got = false; + priv->link_offset = 0; g_static_mutex_init(&(priv->lock)); /* we want mouse events */ @@ -127,6 +138,9 @@ zathura_page_view_set_property(GObject* object, guint prop_id, const GValue* val 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); @@ -137,6 +151,20 @@ zathura_page_view_set_property(GObject* object, guint prop_id, const GValue* val priv->draw_links = false; redraw_all_rects(pageview, priv->search_results); } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + } +} + +static void +zathura_page_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) +{ + ZathuraPageView* pageview = ZATHURA_PAGE_VIEW(object); + zathura_page_view_private_t* priv = ZATHURA_PAGE_VIEW_GET_PRIVATE(pageview); + + switch (prop_id) { + case PROP_LINKS_NUMBER: + g_value_set_int(value, priv->number_of_links); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -202,13 +230,14 @@ zathura_page_view_expose(GtkWidget* widget, GdkEventExpose* event) /* draw links */ if (priv->draw_links == true) { + 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 text */ cairo_set_font_size(cairo, 10); cairo_move_to(cairo, rectangle.x1 + 1, rectangle.y1 - 1); - char* link_number = g_strdup_printf("%i", 0); + char* link_number = g_strdup_printf("%i", priv->link_offset + ++link_counter); cairo_show_text(cairo, link_number); g_free(link_number); @@ -324,5 +353,10 @@ zathura_page_view_link_get(ZathuraPageView* widget, unsigned int index) zathura_page_view_private_t* priv = ZATHURA_PAGE_VIEW_GET_PRIVATE(widget); g_return_val_if_fail(priv != NULL, NULL); - return girara_list_nth(priv->links, index); + 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; + } } diff --git a/shortcuts.c b/shortcuts.c index 5dcec7d..519760e 100644 --- a/shortcuts.c +++ b/shortcuts.c @@ -122,6 +122,7 @@ sc_follow(girara_session_t* session, girara_argument_t* UNUSED(argument), } /* set pages to draw links */ + 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) { @@ -130,14 +131,18 @@ sc_follow(girara_session_t* session, girara_argument_t* UNUSED(argument), g_object_set(page->drawing_area, "search-results", NULL, NULL); if (page->visible == true) { + int number_of_links = 0; + g_object_get(page->drawing_area, "number-of-links", &number_of_links, NULL); g_object_set(page->drawing_area, "draw-links", TRUE, NULL); + 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 */ - girara_dialog(zathura->ui.session, "Follow link:", FALSE, NULL, NULL); + girara_dialog(zathura->ui.session, "Follow link:", FALSE, NULL, (girara_callback_inputbar_activate_t) cb_sc_follow); return false; }