From 26aeb7673430af86bfc3b0ee0e574dd0259de013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Kr=C3=A1l?= Date: Thu, 3 Dec 2020 23:25:56 +0000 Subject: [PATCH] Implement copy link (fixes #197) Implement copying the link target into the system clipboard. --- doc/man/zathura.1.rst | 2 ++ zathura/callbacks.c | 11 +++++++++++ zathura/callbacks.h | 9 +++++++++ zathura/config.c | 2 ++ zathura/links.c | 25 +++++++++++++++++++++++++ zathura/links.h | 8 ++++++++ zathura/shortcuts.c | 25 +++++++++++++++++++++++++ zathura/shortcuts.h | 11 +++++++++++ zathura/utils.c | 15 +++++++++++++++ zathura/utils.h | 14 ++++++++++++++ 10 files changed, 122 insertions(+) diff --git a/doc/man/zathura.1.rst b/doc/man/zathura.1.rst index fe2e67d..a5766f4 100644 --- a/doc/man/zathura.1.rst +++ b/doc/man/zathura.1.rst @@ -113,6 +113,8 @@ General Follow links F Display link target + c + Copy link target into the clipboard \: Enter command r diff --git a/zathura/callbacks.c b/zathura/callbacks.c index 9fa18c2..4b7047d 100644 --- a/zathura/callbacks.c +++ b/zathura/callbacks.c @@ -370,6 +370,7 @@ cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path, typedef enum zathura_link_action_e { ZATHURA_LINK_ACTION_FOLLOW, + ZATHURA_LINK_ACTION_COPY, ZATHURA_LINK_ACTION_DISPLAY } zathura_link_action_t; @@ -425,6 +426,9 @@ handle_link(GtkEntry* entry, girara_session_t* session, case ZATHURA_LINK_ACTION_DISPLAY: zathura_link_display(zathura, link); break; + case ZATHURA_LINK_ACTION_COPY: + zathura_link_copy(zathura, link); + break; } } } @@ -452,6 +456,13 @@ cb_sc_display_link(GtkEntry* entry, void* data) return handle_link(entry, session, ZATHURA_LINK_ACTION_DISPLAY); } +gboolean +cb_sc_copy_link(GtkEntry* entry, void* data) +{ + girara_session_t* session = data; + return handle_link(entry, session, ZATHURA_LINK_ACTION_COPY); +} + static gboolean file_monitor_reload(void* data) { diff --git a/zathura/callbacks.h b/zathura/callbacks.h index e614f78..8cbaaf8 100644 --- a/zathura/callbacks.h +++ b/zathura/callbacks.h @@ -174,6 +174,15 @@ gboolean cb_sc_follow(GtkEntry* entry, void* session); */ gboolean cb_sc_display_link(GtkEntry* entry, void* session); +/** + * Called when input has been passed to the sc_copy_link dialog + * + * @param entry The dialog inputbar + * @param session The girara session + * @return true if no error occurred and the event has been handled + */ +gboolean cb_sc_copy_link(GtkEntry* entry, void* session); + /** * Emitted when file has been changed * diff --git a/zathura/config.c b/zathura/config.c index 6b00fb3..567d3d8 100644 --- a/zathura/config.c +++ b/zathura/config.c @@ -298,6 +298,7 @@ config_load_default(zathura_t* zathura) girara_shortcut_add(gsession, 0, GDK_KEY_s, NULL, sc_adjust_window, (mode), ZATHURA_ADJUST_WIDTH, NULL); \ \ girara_shortcut_add(gsession, 0, GDK_KEY_F, NULL, sc_display_link, (mode), 0, NULL); \ + girara_shortcut_add(gsession, 0, GDK_KEY_c, NULL, sc_copy_link, (mode), 0, NULL); \ \ girara_shortcut_add(gsession, 0, GDK_KEY_slash, NULL, sc_focus_inputbar, (mode), 0, &("/")); \ girara_shortcut_add(gsession, GDK_SHIFT_MASK, GDK_KEY_slash, NULL, sc_focus_inputbar, (mode), 0, &("/")); \ @@ -514,6 +515,7 @@ config_load_default(zathura_t* zathura) girara_shortcut_mapping_add(gsession, "bisect", sc_bisect); girara_shortcut_mapping_add(gsession, "change_mode", sc_change_mode); girara_shortcut_mapping_add(gsession, "display_link", sc_display_link); + girara_shortcut_mapping_add(gsession, "copy_link", sc_copy_link); girara_shortcut_mapping_add(gsession, "exec", sc_exec); girara_shortcut_mapping_add(gsession, "focus_inputbar", sc_focus_inputbar); girara_shortcut_mapping_add(gsession, "follow", sc_follow); diff --git a/zathura/links.c b/zathura/links.c index 90b2047..8181744 100644 --- a/zathura/links.c +++ b/zathura/links.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "adjustment.h" #include "links.h" @@ -291,3 +292,27 @@ zathura_link_display(zathura_t* zathura, zathura_link_t* link) girara_notify(zathura->ui.session, GIRARA_ERROR, _("Link: Invalid")); } } + +void +zathura_link_copy(zathura_t* zathura, zathura_link_t* link) +{ + zathura_link_type_t type = zathura_link_get_type(link); + zathura_link_target_t target = zathura_link_get_target(link); + switch (type) { + case ZATHURA_LINK_GOTO_DEST: + copy_int_to_clipboard(target.page_number); + girara_notify(zathura->ui.session, GIRARA_INFO, _("Copied page number: %d"), + target.page_number); + break; + case ZATHURA_LINK_GOTO_REMOTE: + case ZATHURA_LINK_URI: + case ZATHURA_LINK_LAUNCH: + case ZATHURA_LINK_NAMED: + copy_str_to_clipboard(target.value); + girara_notify(zathura->ui.session, GIRARA_INFO, _("Copied link: %s"), + target.value); + break; + default: + girara_notify(zathura->ui.session, GIRARA_ERROR, _("Link: Invalid")); + } +} diff --git a/zathura/links.h b/zathura/links.h index e90cab7..1db52a0 100644 --- a/zathura/links.h +++ b/zathura/links.h @@ -64,4 +64,12 @@ void zathura_link_evaluate(zathura_t* zathura, zathura_link_t* link); */ void zathura_link_display(zathura_t* zathura, zathura_link_t* link); +/** + * Copy a link into the clipboard using and display it using girara_notify + * + * @param zathura Zathura instance + * @param link The link + */ +void zathura_link_copy(zathura_t* zathura, zathura_link_t* link); + #endif // LINK_H diff --git a/zathura/shortcuts.c b/zathura/shortcuts.c index d53dacd..21524cb 100644 --- a/zathura/shortcuts.c +++ b/zathura/shortcuts.c @@ -149,6 +149,31 @@ sc_display_link(girara_session_t* session, girara_argument_t* UNUSED(argument), return false; } +bool +sc_copy_link(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; + + if (zathura->document == NULL || zathura->ui.session == NULL) { + return false; + } + + bool show_links = draw_links(zathura); + + /* ask for input */ + if (show_links) { + zathura_document_set_adjust_mode(zathura->document, ZATHURA_ADJUST_INPUTBAR); + girara_dialog(zathura->ui.session, "Copy link:", FALSE, NULL, + cb_sc_copy_link, + zathura->ui.session); + } + + return false; +} + bool sc_focus_inputbar(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t)) { diff --git a/zathura/shortcuts.h b/zathura/shortcuts.h index f198880..7ffd385 100644 --- a/zathura/shortcuts.h +++ b/zathura/shortcuts.h @@ -49,6 +49,17 @@ bool sc_change_mode(girara_session_t* session, girara_argument_t* argument, gira */ bool sc_display_link(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t); +/** + * Copy 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 occurred otherwise false + */ +bool sc_copy_link(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t); + /** * Shortcut function to focus the inputbar * diff --git a/zathura/utils.c b/zathura/utils.c index b4b058f..e2a5872 100644 --- a/zathura/utils.c +++ b/zathura/utils.c @@ -460,3 +460,18 @@ flatten_rectangles(girara_list_t* rectangles) { girara_list_free(points); return new_rectangles; } + +void copy_str_to_clipboard(const char* text) { + GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); + gtk_clipboard_set_text(clipboard, text, -1); +} + +void copy_int_to_clipboard(int n) { + char* str; + const char fmt[] = "%d"; + const int len = 1 + snprintf(NULL, 0, fmt, n); + str = malloc(len); + snprintf(str, len, fmt, n); + copy_str_to_clipboard(str); + free(str); +} diff --git a/zathura/utils.h b/zathura/utils.h index e1da74b..25c0d4d 100644 --- a/zathura/utils.h +++ b/zathura/utils.h @@ -145,4 +145,18 @@ bool running_under_wsl(void); */ girara_list_t* flatten_rectangles(girara_list_t* rectangles); +/** + * Copy text into the clipboard. + * + * @param str The string to be copied + */ +void copy_str_to_clipboard(const char* text); + +/** + * Copy integer as a string into the clipboard. + * + * @param n The integer to be copied + */ +void copy_int_to_clipboard(int n); + #endif // UTILS_H