2012-05-28 12:43:22 +02:00
|
|
|
/* See LICENSE file for license and copyright information */
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <girara/utils.h>
|
|
|
|
#include <girara/session.h>
|
2012-08-16 18:41:31 +02:00
|
|
|
#include <girara/settings.h>
|
2012-05-28 12:43:22 +02:00
|
|
|
|
2013-10-23 09:46:00 +02:00
|
|
|
#include "adjustment.h"
|
2012-05-28 12:43:22 +02:00
|
|
|
#include "links.h"
|
|
|
|
#include "zathura.h"
|
|
|
|
#include "document.h"
|
2012-06-06 16:20:12 +02:00
|
|
|
#include "utils.h"
|
2012-05-28 12:43:22 +02:00
|
|
|
|
2012-10-09 01:12:18 +02:00
|
|
|
struct zathura_link_s {
|
2012-05-28 12:43:22 +02:00
|
|
|
zathura_rectangle_t position; /**< Position of the link */
|
|
|
|
zathura_link_type_t type; /**< Link type */
|
|
|
|
zathura_link_target_t target; /**< Link target */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* forward declarations */
|
|
|
|
static void link_remote(zathura_t* zathura, const char* file);
|
|
|
|
static void link_launch(zathura_t* zathura, zathura_link_t* link);
|
|
|
|
|
|
|
|
zathura_link_t*
|
|
|
|
zathura_link_new(zathura_link_type_t type, zathura_rectangle_t position,
|
2012-10-09 01:12:18 +02:00
|
|
|
zathura_link_target_t target)
|
2012-05-28 12:43:22 +02:00
|
|
|
{
|
|
|
|
zathura_link_t* link = g_malloc0(sizeof(zathura_link_t));
|
|
|
|
|
|
|
|
link->type = type;
|
|
|
|
link->position = position;
|
|
|
|
|
|
|
|
switch (type) {
|
2013-02-23 13:54:50 +01:00
|
|
|
case ZATHURA_LINK_NONE:
|
2012-05-28 12:43:22 +02:00
|
|
|
case ZATHURA_LINK_GOTO_DEST:
|
2012-06-06 15:45:20 +02:00
|
|
|
link->target = target;
|
|
|
|
|
|
|
|
if (target.value != NULL) {
|
|
|
|
link->target.value = g_strdup(target.value);
|
|
|
|
}
|
2012-05-28 12:43:22 +02:00
|
|
|
break;
|
|
|
|
case ZATHURA_LINK_GOTO_REMOTE:
|
|
|
|
case ZATHURA_LINK_URI:
|
|
|
|
case ZATHURA_LINK_LAUNCH:
|
2012-06-06 15:45:20 +02:00
|
|
|
case ZATHURA_LINK_NAMED:
|
2012-05-28 12:43:22 +02:00
|
|
|
if (target.value == NULL) {
|
|
|
|
g_free(link);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
link->target.value = g_strdup(target.value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_free(link);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return link;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
zathura_link_free(zathura_link_t* link)
|
|
|
|
{
|
|
|
|
if (link == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (link->type) {
|
2013-02-23 13:54:50 +01:00
|
|
|
case ZATHURA_LINK_NONE:
|
2012-06-06 15:45:20 +02:00
|
|
|
case ZATHURA_LINK_GOTO_DEST:
|
|
|
|
case ZATHURA_LINK_GOTO_REMOTE:
|
2012-05-28 12:43:22 +02:00
|
|
|
case ZATHURA_LINK_URI:
|
|
|
|
case ZATHURA_LINK_LAUNCH:
|
2012-06-06 15:45:20 +02:00
|
|
|
case ZATHURA_LINK_NAMED:
|
2012-05-28 12:43:22 +02:00
|
|
|
if (link->target.value != NULL) {
|
|
|
|
g_free(link->target.value);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(link);
|
|
|
|
}
|
|
|
|
|
|
|
|
zathura_link_type_t
|
|
|
|
zathura_link_get_type(zathura_link_t* link)
|
|
|
|
{
|
|
|
|
if (link == NULL) {
|
|
|
|
return ZATHURA_LINK_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return link->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
zathura_rectangle_t
|
|
|
|
zathura_link_get_position(zathura_link_t* link)
|
|
|
|
{
|
|
|
|
if (link == NULL) {
|
|
|
|
zathura_rectangle_t position = { 0, 0, 0, 0 };
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
return link->position;
|
|
|
|
}
|
|
|
|
|
|
|
|
zathura_link_target_t
|
|
|
|
zathura_link_get_target(zathura_link_t* link)
|
|
|
|
{
|
|
|
|
if (link == NULL) {
|
2013-07-26 09:07:05 +02:00
|
|
|
zathura_link_target_t target = { 0, NULL, 0, 0, 0, 0, 0, 0 };
|
2012-05-28 12:43:22 +02:00
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
|
|
|
return link->target;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
zathura_link_evaluate(zathura_t* zathura, zathura_link_t* link)
|
|
|
|
{
|
2012-06-06 15:45:20 +02:00
|
|
|
if (zathura == NULL || zathura->document == NULL || link == NULL) {
|
2012-05-28 12:43:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-21 18:01:04 +02:00
|
|
|
bool link_zoom = true;
|
|
|
|
girara_setting_get(zathura->ui.session, "link-zoom", &link_zoom);
|
|
|
|
|
2012-05-28 12:43:22 +02:00
|
|
|
switch (link->type) {
|
|
|
|
case ZATHURA_LINK_GOTO_DEST:
|
2012-10-31 07:29:17 +01:00
|
|
|
if (link->target.destination_type != ZATHURA_LINK_DESTINATION_UNKNOWN) {
|
2013-10-21 18:01:04 +02:00
|
|
|
if (link->target.scale != 0 && link_zoom) {
|
2012-10-31 07:29:17 +01:00
|
|
|
zathura_document_set_scale(zathura->document, link->target.scale);
|
|
|
|
}
|
2012-06-06 15:45:20 +02:00
|
|
|
|
2012-10-31 07:29:17 +01:00
|
|
|
/* get page */
|
|
|
|
zathura_page_t* page = zathura_document_get_page(zathura->document,
|
|
|
|
link->target.page_number);
|
|
|
|
if (page == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2012-06-06 16:20:12 +02:00
|
|
|
|
2012-08-16 18:41:31 +02:00
|
|
|
page_offset_t offset;
|
|
|
|
page_calculate_offset(zathura, page, &offset);
|
2012-06-06 16:20:12 +02:00
|
|
|
|
2012-10-31 07:29:17 +01:00
|
|
|
if (link->target.destination_type == ZATHURA_LINK_DESTINATION_XYZ) {
|
2012-06-06 16:20:12 +02:00
|
|
|
if (link->target.left != -1) {
|
|
|
|
offset.x += link->target.left * zathura_document_get_scale(zathura->document);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->target.top != -1) {
|
|
|
|
offset.y += link->target.top * zathura_document_get_scale(zathura->document);
|
|
|
|
}
|
2012-10-09 01:12:18 +02:00
|
|
|
}
|
2012-10-31 07:29:17 +01:00
|
|
|
|
2013-06-21 10:02:19 +02:00
|
|
|
zathura_jumplist_add(zathura);
|
|
|
|
|
2012-08-16 18:41:31 +02:00
|
|
|
/* jump to the page */
|
|
|
|
page_set(zathura, link->target.page_number);
|
|
|
|
|
|
|
|
/* move to the target position */
|
|
|
|
bool link_hadjust = true;
|
|
|
|
girara_setting_get(zathura->ui.session, "link-hadjust", &link_hadjust);
|
|
|
|
|
|
|
|
if (link_hadjust == true) {
|
2013-06-09 05:53:31 +02:00
|
|
|
position_set(zathura, offset.x, offset.y);
|
2012-08-16 18:41:31 +02:00
|
|
|
} else {
|
2013-06-09 05:53:31 +02:00
|
|
|
position_set(zathura, -1, offset.y);
|
2012-08-16 18:41:31 +02:00
|
|
|
}
|
2013-06-21 10:02:19 +02:00
|
|
|
|
|
|
|
zathura_jumplist_add(zathura);
|
2012-06-06 15:45:20 +02:00
|
|
|
}
|
2012-05-28 12:43:22 +02:00
|
|
|
break;
|
|
|
|
case ZATHURA_LINK_GOTO_REMOTE:
|
|
|
|
link_remote(zathura, link->target.value);
|
|
|
|
break;
|
|
|
|
case ZATHURA_LINK_URI:
|
|
|
|
if (girara_xdg_open(link->target.value) == false) {
|
|
|
|
girara_notify(zathura->ui.session, GIRARA_ERROR, _("Failed to run xdg-open."));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZATHURA_LINK_LAUNCH:
|
|
|
|
link_launch(zathura, link);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-07 16:03:43 +01:00
|
|
|
void
|
|
|
|
zathura_link_display(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:
|
|
|
|
girara_notify(zathura->ui.session, GIRARA_INFO, _("Link: page %d"),
|
|
|
|
target.page_number);
|
|
|
|
break;
|
|
|
|
case ZATHURA_LINK_GOTO_REMOTE:
|
|
|
|
case ZATHURA_LINK_URI:
|
|
|
|
case ZATHURA_LINK_LAUNCH:
|
|
|
|
case ZATHURA_LINK_NAMED:
|
|
|
|
girara_notify(zathura->ui.session, GIRARA_INFO, _("Link: %s"),
|
|
|
|
target.value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
girara_notify(zathura->ui.session, GIRARA_ERROR, _("Link: Invalid"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 12:43:22 +02:00
|
|
|
static void
|
|
|
|
link_remote(zathura_t* zathura, const char* file)
|
|
|
|
{
|
|
|
|
if (zathura == NULL || file == NULL || zathura->document == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* path = zathura_document_get_path(zathura->document);
|
|
|
|
char* dir = g_path_get_dirname(path);
|
|
|
|
char* uri = g_build_filename(dir, file, NULL);
|
|
|
|
|
|
|
|
char* argv[] = {
|
|
|
|
*(zathura->global.arguments),
|
|
|
|
uri,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
g_free(uri);
|
|
|
|
g_free(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
link_launch(zathura_t* zathura, zathura_link_t* link)
|
|
|
|
{
|
|
|
|
if (zathura == NULL || link == NULL || zathura->document == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get file path */
|
|
|
|
if (link->target.value == NULL) {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
char* path = NULL;
|
|
|
|
if (g_path_is_absolute(link->target.value) == TRUE) {
|
|
|
|
path = g_strdup(link->target.value);
|
|
|
|
} else {
|
|
|
|
const char* document = zathura_document_get_path(zathura->document);
|
|
|
|
char* dir = g_path_get_dirname(document);
|
|
|
|
path = g_build_filename(dir, link->target.value, NULL);
|
|
|
|
g_free(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (girara_xdg_open(path) == false) {
|
|
|
|
girara_notify(zathura->ui.session, GIRARA_ERROR, _("Failed to run xdg-open."));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(path);
|
|
|
|
}
|