Implement copy link (fixes #197)

Implement copying the link target into the system clipboard.
This commit is contained in:
Karel Král 2020-12-03 23:25:56 +00:00 committed by Sebastian Ramacher
parent fb671c26cd
commit 26aeb76734
10 changed files with 122 additions and 0 deletions

View file

@ -113,6 +113,8 @@ General
Follow links Follow links
F F
Display link target Display link target
c
Copy link target into the clipboard
\: \:
Enter command Enter command
r r

View file

@ -370,6 +370,7 @@ cb_index_row_activated(GtkTreeView* tree_view, GtkTreePath* path,
typedef enum zathura_link_action_e typedef enum zathura_link_action_e
{ {
ZATHURA_LINK_ACTION_FOLLOW, ZATHURA_LINK_ACTION_FOLLOW,
ZATHURA_LINK_ACTION_COPY,
ZATHURA_LINK_ACTION_DISPLAY ZATHURA_LINK_ACTION_DISPLAY
} zathura_link_action_t; } zathura_link_action_t;
@ -425,6 +426,9 @@ handle_link(GtkEntry* entry, girara_session_t* session,
case ZATHURA_LINK_ACTION_DISPLAY: case ZATHURA_LINK_ACTION_DISPLAY:
zathura_link_display(zathura, link); zathura_link_display(zathura, link);
break; 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); 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 static gboolean
file_monitor_reload(void* data) file_monitor_reload(void* data)
{ {

View file

@ -174,6 +174,15 @@ gboolean cb_sc_follow(GtkEntry* entry, void* session);
*/ */
gboolean cb_sc_display_link(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 * Emitted when file has been changed
* *

View file

@ -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_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_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, 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, &("/")); \ 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, "bisect", sc_bisect);
girara_shortcut_mapping_add(gsession, "change_mode", sc_change_mode); 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, "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, "exec", sc_exec);
girara_shortcut_mapping_add(gsession, "focus_inputbar", sc_focus_inputbar); girara_shortcut_mapping_add(gsession, "focus_inputbar", sc_focus_inputbar);
girara_shortcut_mapping_add(gsession, "follow", sc_follow); girara_shortcut_mapping_add(gsession, "follow", sc_follow);

View file

@ -5,6 +5,7 @@
#include <girara/utils.h> #include <girara/utils.h>
#include <girara/session.h> #include <girara/session.h>
#include <girara/settings.h> #include <girara/settings.h>
#include <gtk/gtk.h>
#include "adjustment.h" #include "adjustment.h"
#include "links.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")); 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"));
}
}

View file

@ -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); 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 #endif // LINK_H

View file

@ -149,6 +149,31 @@ sc_display_link(girara_session_t* session, girara_argument_t* UNUSED(argument),
return false; 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 bool
sc_focus_inputbar(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t)) sc_focus_inputbar(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{ {

View file

@ -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); 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 * Shortcut function to focus the inputbar
* *

View file

@ -460,3 +460,18 @@ flatten_rectangles(girara_list_t* rectangles) {
girara_list_free(points); girara_list_free(points);
return new_rectangles; 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);
}

View file

@ -145,4 +145,18 @@ bool running_under_wsl(void);
*/ */
girara_list_t* flatten_rectangles(girara_list_t* rectangles); 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 #endif // UTILS_H