aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Faure <billiob@gmail.com>2018-12-12 21:42:42 +0100
committerBoris Faure <billiob@gmail.com>2018-12-13 16:41:29 +0100
commit64b58bb09452ae9799c477aef2767f9aecb981d9 (patch)
tree2ec3673078f647f8d0296224e02456042093b945
parentMinor manpage improvements (diff)
downloadterminology-64b58bb09452ae9799c477aef2767f9aecb981d9.tar.gz
termio/win: handle hyperlinks on right click
Fix segfault
-rw-r--r--src/bin/termio.c135
-rw-r--r--src/bin/win.c17
2 files changed, 114 insertions, 38 deletions
diff --git a/src/bin/termio.c b/src/bin/termio.c
index f24a0fa..abf6ae6 100644
--- a/src/bin/termio.c
+++ b/src/bin/termio.c
@@ -51,7 +51,7 @@ struct _Termio
int button;
} mouse;
struct {
- char *string;
+ const char *string;
int x1, y1, x2, y2;
int suspend;
uint16_t id;
@@ -819,12 +819,40 @@ _should_inline(const Evas_Object *obj)
return EINA_TRUE;
}
-const char *
+/* Need to be freed */
+const char *
termio_link_get(const Evas_Object *obj)
{
Termio *sd = evas_object_smart_data_get(obj);
EINA_SAFETY_ON_NULL_RETURN_VAL(sd, NULL);
- return sd->link.string;
+ const char *link;
+
+ if (!sd->link.string && !sd->link.id)
+ return NULL;
+ link = sd->link.string;
+ if (sd->link.id)
+ {
+ Term_Link *hl = &sd->pty->hl.links[sd->link.id];
+ if (!hl->url)
+ return NULL;
+ link = hl->url;
+ }
+ if (link_is_url(link))
+ {
+ if (casestartswith(link, "file://"))
+ {
+ // TODO: decode string: %XX -> char
+ link = link + sizeof("file://") - 1;
+ /* Handle cases where / is ommitted: file://HOSTNAME/home/ */
+ if (link[0] != '/')
+ {
+ link = strchr(link, '/');
+ if (!link)
+ return NULL;
+ }
+ }
+ }
+ return strdup(link);
}
static void
@@ -834,33 +862,32 @@ _activate_link(Evas_Object *obj, Eina_Bool may_inline)
Config *config;
char buf[PATH_MAX], *s, *escaped;
const char *path = NULL, *cmd = NULL;
+ const char *link = NULL;
Eina_Bool url = EINA_FALSE, email = EINA_FALSE, handled = EINA_FALSE;
EINA_SAFETY_ON_NULL_RETURN(sd);
config = sd->config;
if (!config) return;
if (!config->active_links) return;
- if (!sd->link.string) return;
- if (link_is_url(sd->link.string))
- {
- if (casestartswith(sd->link.string, "file://"))
- // TODO: decode string: %XX -> char
- path = sd->link.string + sizeof("file://") - 1;
- else
- url = EINA_TRUE;
- }
- else if (sd->link.string[0] == '/')
- path = sd->link.string;
- else if (link_is_email(sd->link.string))
+
+ link = termio_link_get(obj);
+ if (!link)
+ return;
+
+ if (link_is_url(link))
+ url = EINA_TRUE;
+ else if (link[0] == '/')
+ path = link;
+ else if (link_is_email(link))
email = EINA_TRUE;
- if (url && casestartswith(sd->link.string, "mailto:"))
+ if (url && casestartswith(link, "mailto:"))
{
email = EINA_TRUE;
url = EINA_FALSE;
}
- s = eina_str_escape(sd->link.string);
+ s = eina_str_escape(link);
if (!s) return;
if (email)
{
@@ -888,10 +915,10 @@ _activate_link(Evas_Object *obj, Eina_Bool may_inline)
// locally accessible file
cmd = "xdg-open";
- escaped = ecore_file_escape_name(s);
+ escaped = ecore_file_escape_name(path);
if (escaped)
{
- Media_Type type = media_src_type_get(sd->link.string);
+ Media_Type type = media_src_type_get(path);
if (may_inline && _should_inline(obj))
{
if ((type == MEDIA_TYPE_IMG) ||
@@ -942,7 +969,7 @@ _activate_link(Evas_Object *obj, Eina_Bool may_inline)
escaped = ecore_file_escape_name(s);
if (escaped)
{
- Media_Type type = media_src_type_get(sd->link.string);
+ Media_Type type = media_src_type_get(link);
if (may_inline && _should_inline(obj))
{
evas_object_smart_callback_call(obj, "popup", NULL);
@@ -1050,9 +1077,20 @@ _cb_ctxp_link_content_copy(void *data,
size_t len;
EINA_SAFETY_ON_NULL_RETURN(sd);
- raw_link = termio_selection_get(term, sd->link.x1, sd->link.y1, sd->link.x2, sd->link.y2, &len, EINA_FALSE);
+ if (sd->link.id)
+ {
+ Term_Link *hl = &sd->pty->hl.links[sd->link.id];
- _take_selection_text(sd, ELM_SEL_TYPE_CLIPBOARD, raw_link);
+ if (!hl->url)
+ return;
+ _take_selection_text(sd, ELM_SEL_TYPE_CLIPBOARD, hl->url);
+ }
+ else
+ {
+ raw_link = termio_selection_get(term, sd->link.x1, sd->link.y1, sd->link.x2, sd->link.y2, &len, EINA_FALSE);
+
+ _take_selection_text(sd, ELM_SEL_TYPE_CLIPBOARD, raw_link);
+ }
sd->ctxpopup = NULL;
evas_object_del(obj);
@@ -1082,6 +1120,16 @@ _cb_link_down(void *data,
Evas_Event_Mouse_Down *ev = event;
Termio *sd = evas_object_smart_data_get(data);
EINA_SAFETY_ON_NULL_RETURN(sd);
+ Term_Link *hl = NULL;
+
+
+ if (!sd->link.string && sd->link.id)
+ {
+ hl = &sd->pty->hl.links[sd->link.id];
+ if (!hl->url)
+ return;
+ sd->link.string = eina_stringshare_add(hl->url);
+ }
if (ev->button == 1)
{
@@ -1093,7 +1141,7 @@ _cb_link_down(void *data,
{
Evas_Object *ctxp;
Eina_Bool absolut = EINA_FALSE;
- char *raw_link;
+ const char *raw_link;
size_t len;
if (sd->pty->selection.is_active)
@@ -1121,7 +1169,20 @@ _cb_link_down(void *data,
}
elm_ctxpopup_item_append(ctxp, _("Open"), NULL, _cb_ctxp_link_open,
sd->self);
- raw_link = termio_selection_get(sd->self, sd->link.x1, sd->link.y1, sd->link.x2, sd->link.y2, &len, EINA_FALSE);
+ if (hl)
+ {
+ raw_link = hl->url;
+ }
+ else
+ {
+ raw_link = termio_selection_get(sd->self,
+ sd->link.x1,
+ sd->link.y1,
+ sd->link.x2,
+ sd->link.y2,
+ &len,
+ EINA_FALSE);
+ }
if (len > 0 && raw_link[0] == '/')
absolut = EINA_TRUE;
@@ -1145,7 +1206,8 @@ _cb_link_down(void *data,
_cb_ctxp_dismissed, sd);
evas_object_event_callback_add(ctxp, EVAS_CALLBACK_DEL,
_cb_ctxp_del, sd);
- free(raw_link);
+ if (!hl)
+ free((void*)raw_link);
}
}
@@ -1257,7 +1319,8 @@ _cb_link_move(void *data,
Evas_Coord dx, dy;
EINA_SAFETY_ON_NULL_RETURN(sd);
- if (!sd->link.down.down) return;
+ if (!sd->link.down.down)
+ return;
dx = abs(ev->cur.canvas.x - sd->link.down.x);
dy = abs(ev->cur.canvas.y - sd->link.down.y);
if ((sd->config->drag_links) &&
@@ -1384,7 +1447,7 @@ _remove_links(Termio *sd)
if (sd->link.string)
{
- free(sd->link.string);
+ eina_stringshare_del(sd->link.string);
sd->link.string = NULL;
}
sd->link.x1 = -1;
@@ -2511,7 +2574,7 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
{
Termio *sd = evas_object_smart_data_get(obj);
int start_x = 0, start_y = 0, end_x = 0, end_y = 0;
- char *s = NULL;
+ const char *s = NULL;
size_t len = 0;
EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EINA_FALSE);
@@ -2533,7 +2596,7 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
if (sd->link.string)
{
len = strlen(sd->link.string);
- s = strndup(sd->link.string, len);
+ s = eina_stringshare_add_length(sd->link.string, len);
}
goto end;
}
@@ -2560,12 +2623,14 @@ termio_take_selection(Evas_Object *obj, Elm_Sel_Type type)
}
len = eina_strbuf_length_get(sb);
s = eina_strbuf_string_steal(sb);
+ s = eina_stringshare_add_length(s, len);
eina_strbuf_free(sb);
}
else
{
s = termio_selection_get(obj, start_x, start_y, end_x, end_y, &len,
EINA_TRUE);
+ s = eina_stringshare_add_length(s, len);
}
end:
@@ -2573,7 +2638,7 @@ end:
{
if ((sd->win) && (len > 0))
_take_selection_text(sd, type, s);
- free(s);
+ eina_stringshare_del(s);
return EINA_TRUE;
}
return EINA_FALSE;
@@ -3711,7 +3776,8 @@ _smart_mouseover_apply(Evas_Object *obj)
EINA_SAFETY_ON_NULL_RETURN(sd);
config = sd->config;
- if (!config->active_links) return;
+ if (!config->active_links)
+ return;
if ((sd->mouse.cx < 0) || (sd->mouse.cy < 0) ||
(sd->link.suspend) || (!evas_object_focus_get(obj)))
@@ -3741,8 +3807,8 @@ _smart_mouseover_apply(Evas_Object *obj)
}
if (sd->link.string)
- free(sd->link.string);
- sd->link.string = s;
+ eina_stringshare_del(sd->link.string);
+ sd->link.string = eina_stringshare_add(s);
if ((x1 == sd->link.x1) && (y1 == sd->link.y1) &&
(x2 == sd->link.x2) && (y2 == sd->link.y2))
@@ -5531,7 +5597,8 @@ _smart_del(Evas_Object *obj)
if (sd->mouseover_delay) ecore_timer_del(sd->mouseover_delay);
if (sd->font.name) eina_stringshare_del(sd->font.name);
if (sd->pty) termpty_free(sd->pty);
- if (sd->link.string) free(sd->link.string);
+ if (sd->link.string)
+ eina_stringshare_del(sd->link.string);
if (sd->glayer) evas_object_del(sd->glayer);
if (sd->win)
evas_object_event_callback_del_full(sd->win, EVAS_CALLBACK_DEL,
diff --git a/src/bin/win.c b/src/bin/win.c
index d6c4b75..5b3dd01 100644
--- a/src/bin/win.c
+++ b/src/bin/win.c
@@ -4401,9 +4401,13 @@ _cb_popup(void *data,
Term *term = data;
const char *src = event;
- if (!src) src = termio_link_get(term->termio);
- if (!src) return;
+ if (!src)
+ src = termio_link_get(term->termio);
+ if (!src)
+ return;
_popmedia(term, src);
+ if (!event)
+ free((void*)src);
}
static void
@@ -4413,9 +4417,14 @@ _cb_popup_queue(void *data,
{
Term *term = data;
const char *src = event;
- if (!src) src = termio_link_get(term->termio);
- if (!src) return;
+
+ if (!src)
+ src = termio_link_get(term->termio);
+ if (!src)
+ return;
_popmedia_queue_add(term, src);
+ if (!event)
+ free((void*)src);
}
static void