parent
e3faaab83d
commit
dc5c291bb9
139
src/bin/termio.c
139
src/bin/termio.c
|
@ -54,6 +54,7 @@ struct _Termio
|
|||
char *string;
|
||||
int x1, y1, x2, y2;
|
||||
int suspend;
|
||||
uint16_t id;
|
||||
Eina_List *objs;
|
||||
struct {
|
||||
Evas_Object *dndobj;
|
||||
|
@ -1389,8 +1390,133 @@ _remove_links(Termio *sd, Evas_Object *obj)
|
|||
sd->link.y2 = -1;
|
||||
sd->link.suspend = EINA_FALSE;
|
||||
_update_link(obj, sd, same_link, same_geom);
|
||||
sd->link.id = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_hyperlink_end(Termio *sd,
|
||||
Term_Link *hl,
|
||||
Evas_Object *o,
|
||||
Eina_Bool add_tooltip)
|
||||
{
|
||||
Eina_Bool popup_exists;
|
||||
|
||||
sd->link.objs = eina_list_append(sd->link.objs, o);
|
||||
elm_object_cursor_set(o, "hand2");
|
||||
evas_object_show(o);
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
|
||||
_cb_link_down, sd->self);
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP,
|
||||
_cb_link_up, sd->self);
|
||||
evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE,
|
||||
_cb_link_move, sd->self);
|
||||
popup_exists = main_term_popup_exists(sd->term);
|
||||
if (!popup_exists && add_tooltip)
|
||||
{
|
||||
if (link_is_email(hl->url))
|
||||
{
|
||||
gravatar_tooltip(o, sd->config, hl->url);
|
||||
}
|
||||
/* display tooltip */
|
||||
elm_object_tooltip_text_set(o, hl->url);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_hyperlink_mouseover(Evas_Object *obj, Termio *sd,
|
||||
uint16_t link_id)
|
||||
{
|
||||
Evas_Coord ox, oy, ow, oh;
|
||||
Evas_Object *o;
|
||||
int x, y;
|
||||
Term_Link *hl;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(sd);
|
||||
|
||||
/* If it's the same link, consider we already have the correct links
|
||||
* displayed */
|
||||
if (sd->link.id == link_id)
|
||||
return;
|
||||
|
||||
if (sd->link.suspend)
|
||||
return;
|
||||
|
||||
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
|
||||
EINA_LIST_FREE(sd->link.objs, o)
|
||||
{
|
||||
if (sd->link.down.dndobj == o)
|
||||
{
|
||||
sd->link.down.dndobjdel = EINA_TRUE;
|
||||
evas_object_hide(o);
|
||||
}
|
||||
else
|
||||
evas_object_del(o);
|
||||
}
|
||||
hl = &sd->pty->hl.links[link_id];
|
||||
if (!hl->url)
|
||||
return;
|
||||
|
||||
/* Scan the whole screen and display links as needed */
|
||||
termpty_backlog_lock();
|
||||
termpty_backscroll_adjust(sd->pty, &sd->scroll);
|
||||
for (y = 0; y < sd->grid.h; y++)
|
||||
{
|
||||
ssize_t w = 0;
|
||||
Termcell *cells;
|
||||
int start_x = -1;
|
||||
|
||||
o = NULL;
|
||||
|
||||
cells = termpty_cellrow_get(sd->pty, y - sd->scroll, &w);
|
||||
if (!cells)
|
||||
continue;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
Termcell *c = cells + x;
|
||||
if (term_link_eq(sd->pty, hl, c->att.link_id))
|
||||
{
|
||||
if (!o)
|
||||
{
|
||||
o = elm_layout_add(sd->win);
|
||||
evas_object_smart_member_add(o, obj);
|
||||
theme_apply(elm_layout_edje_get(o), sd->config,
|
||||
"terminology/link");
|
||||
evas_object_move(o,
|
||||
ox + (x * sd->font.chw),
|
||||
oy + (y * sd->font.chh));
|
||||
start_x = x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (o)
|
||||
{
|
||||
evas_object_resize(o,
|
||||
(x - start_x) * sd->font.chw,
|
||||
sd->font.chh);
|
||||
_hyperlink_end(sd, hl, o,
|
||||
(y == sd->mouse.cy) &&
|
||||
((start_x <= sd->mouse.cx) &&
|
||||
(sd->mouse.cx <= x)));
|
||||
o = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o)
|
||||
{
|
||||
evas_object_resize(o,
|
||||
(x - start_x + 1) * sd->font.chw,
|
||||
sd->font.chh);
|
||||
_hyperlink_end(sd, hl, o,
|
||||
(y == sd->mouse.cy) &&
|
||||
((start_x <= sd->mouse.cx) &&
|
||||
(sd->mouse.cx <= x)));
|
||||
}
|
||||
}
|
||||
termpty_backlog_unlock();
|
||||
}
|
||||
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Blocks */
|
||||
|
||||
|
@ -3573,6 +3699,7 @@ _smart_mouseover_apply(Evas_Object *obj)
|
|||
Eina_Bool same_link = EINA_FALSE, same_geom = EINA_FALSE;
|
||||
Termio *sd = evas_object_smart_data_get(obj);
|
||||
Config *config;
|
||||
Termcell *cell = NULL;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(sd);
|
||||
config = sd->config;
|
||||
|
@ -3584,6 +3711,18 @@ _smart_mouseover_apply(Evas_Object *obj)
|
|||
_remove_links(sd, obj);
|
||||
return;
|
||||
}
|
||||
cell = termpty_cell_get(sd->pty, sd->mouse.cy - sd->scroll, sd->mouse.cx);
|
||||
if (!cell)
|
||||
{
|
||||
_remove_links(sd, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cell->att.link_id)
|
||||
{
|
||||
_hyperlink_mouseover(obj, sd, cell->att.link_id);
|
||||
return;
|
||||
}
|
||||
|
||||
s = termio_link_find(obj, sd->mouse.cx, sd->mouse.cy,
|
||||
&x1, &y1, &x2, &y2);
|
||||
|
|
|
@ -85,7 +85,7 @@ _txt_at(Termpty *ty, int *x, int *y, char *txt, int *txtlenp)
|
|||
cell = cells[*x];
|
||||
}
|
||||
|
||||
if (cell.codepoint == 0)
|
||||
if ((cell.codepoint == 0) || (cell.att.link_id))
|
||||
goto empty;
|
||||
|
||||
*txtlenp = codepoint_to_utf8(cell.codepoint, txt);
|
||||
|
@ -146,7 +146,7 @@ _txt_prev_at(Termpty *ty, int *x, int *y, char *txt, int *txtlenp)
|
|||
cell = cells[*x];
|
||||
}
|
||||
|
||||
if (cell.codepoint == 0)
|
||||
if ((cell.codepoint == 0) || (cell.att.link_id))
|
||||
goto empty;
|
||||
|
||||
*txtlenp = codepoint_to_utf8(cell.codepoint, txt);
|
||||
|
@ -210,7 +210,7 @@ _txt_next_at(Termpty *ty, int *x, int *y, char *txt, int *txtlenp)
|
|||
}
|
||||
|
||||
cell = cells[*x];
|
||||
if (cell.codepoint == 0)
|
||||
if ((cell.codepoint == 0) || (cell.att.link_id))
|
||||
goto empty;
|
||||
|
||||
*txtlenp = codepoint_to_utf8(cell.codepoint, txt);
|
||||
|
@ -235,7 +235,9 @@ termio_link_find(const Evas_Object *obj, int cx, int cy,
|
|||
char *s = NULL;
|
||||
char endmatch = 0;
|
||||
int x1, x2, y1, y2, w = 0, h = 0, sc;
|
||||
Eina_Bool goback = EINA_TRUE, goforward = EINA_FALSE, escaped = EINA_FALSE;
|
||||
Eina_Bool goback = EINA_TRUE,
|
||||
goforward = EINA_FALSE,
|
||||
escaped = EINA_FALSE;
|
||||
struct ty_sb sb = {.buf = NULL, .gap = 0, .len = 0, .alloc = 0};
|
||||
Termpty *ty = termio_pty_get(obj);
|
||||
int res;
|
||||
|
@ -525,9 +527,9 @@ term_link_free(Termpty *ty, Term_Link *link)
|
|||
return;
|
||||
uint16_t id = (link - ty->hl.links);
|
||||
|
||||
free(link->key);
|
||||
eina_stringshare_del(link->key);
|
||||
link->key = NULL;
|
||||
free(link->url);
|
||||
eina_stringshare_del(link->url);
|
||||
link->url = NULL;
|
||||
|
||||
/* Remove from bitmap */
|
||||
|
|
|
@ -817,7 +817,7 @@ termpty_free(Termpty *ty)
|
|||
size_t i;
|
||||
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
termpty_save_free(ty, &ty->back[i]);
|
||||
free(ty->back);
|
||||
}
|
||||
free(ty->screen);
|
||||
|
@ -962,7 +962,7 @@ _backlog_remove_latest_nolock(Termpty *ty)
|
|||
ty->backlog_beacon.backlog_y = 0;
|
||||
verify_beacon(ty, 0);
|
||||
|
||||
termpty_save_free(ts);
|
||||
termpty_save_free(ty, ts);
|
||||
}
|
||||
|
||||
|
||||
|
@ -993,7 +993,7 @@ termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
|
|||
if (ts->w && ts->cells[ts->w - 1].att.autowrapped)
|
||||
{
|
||||
int old_len = ts->w;
|
||||
termpty_save_expand(ts, cells, w);
|
||||
termpty_save_expand(ty, ts, cells, w);
|
||||
ty->backlog_beacon.screen_y += (ts->w + ty->w - 1) / ty->w
|
||||
- (old_len + ty->w - 1) / ty->w;
|
||||
verify_beacon(ty, 0);
|
||||
|
@ -1003,7 +1003,7 @@ termpty_text_save_top(Termpty *ty, Termcell *cells, ssize_t w_max)
|
|||
|
||||
add_new_ts:
|
||||
ts = BACKLOG_ROW_GET(ty, 0);
|
||||
ts = termpty_save_new(ts, w);
|
||||
ts = termpty_save_new(ty, ts, w);
|
||||
if (!ts)
|
||||
return;
|
||||
TERMPTY_CELL_COPY(ty, cells, ts->cells, w);
|
||||
|
@ -1485,7 +1485,7 @@ termpty_backlog_size_set(Termpty *ty, size_t size)
|
|||
size_t i;
|
||||
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
termpty_save_free(ty, &ty->back[i]);
|
||||
free(ty->back);
|
||||
}
|
||||
if (size > 0)
|
||||
|
@ -1677,6 +1677,9 @@ termpty_cells_att_fill_preserve_colors(Termpty *ty, Termcell *cells,
|
|||
int i;
|
||||
Termcell local = { .codepoint = codepoint, .att = ty->termstate.att};
|
||||
|
||||
if (EINA_UNLIKELY(local.att.link_id))
|
||||
term_link_refcount_inc(ty, local.att.link_id, count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
Termatt att = cells[i].att;
|
||||
|
@ -1696,8 +1699,6 @@ termpty_cells_att_fill_preserve_colors(Termpty *ty, Termcell *cells,
|
|||
cells[i].att.bgintense = att.bgintense;
|
||||
}
|
||||
}
|
||||
if (EINA_UNLIKELY(local.att.link_id))
|
||||
term_link_refcount_inc(ty, local.att.link_id, count);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1708,6 +1709,9 @@ termpty_cell_codepoint_att_fill(Termpty *ty, Eina_Unicode codepoint,
|
|||
Termcell local = { .codepoint = codepoint, .att = att };
|
||||
int i;
|
||||
|
||||
if (EINA_UNLIKELY(local.att.link_id))
|
||||
term_link_refcount_inc(ty, local.att.link_id, n);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, codepoint);
|
||||
|
@ -1716,8 +1720,6 @@ termpty_cell_codepoint_att_fill(Termpty *ty, Eina_Unicode codepoint,
|
|||
|
||||
dst[i] = local;
|
||||
}
|
||||
if (EINA_UNLIKELY(local.att.link_id))
|
||||
term_link_refcount_inc(ty, local.att.link_id, n);
|
||||
}
|
||||
|
||||
Config *
|
||||
|
|
|
@ -311,10 +311,10 @@ do { \
|
|||
HANDLE_BLOCK_CODEPOINT_OVERWRITE(Tpty, \
|
||||
(Tdst)[__i].codepoint, \
|
||||
(Tsrc)[__i].codepoint); \
|
||||
if (EINA_UNLIKELY((Tsrc)[__i].att.link_id)) \
|
||||
term_link_refcount_dec(ty, (Tsrc)[__i].att.link_id, 1); \
|
||||
if (EINA_UNLIKELY((Tdst)[__i].att.link_id)) \
|
||||
term_link_refcount_inc(ty, (Tdst)[__i].att.link_id, 1); \
|
||||
term_link_refcount_dec(ty, (Tdst)[__i].att.link_id, 1); \
|
||||
if (EINA_UNLIKELY((Tsrc)[__i].att.link_id)) \
|
||||
term_link_refcount_inc(ty, (Tsrc)[__i].att.link_id, 1); \
|
||||
} \
|
||||
memcpy(Tdst, Tsrc, N * sizeof(Termcell)); \
|
||||
} while (0)
|
||||
|
@ -340,6 +340,25 @@ term_link_refcount_dec(Termpty *ty, uint16_t link_id, uint16_t count)
|
|||
term_link_free(ty, link);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
term_link_eq(Termpty *ty, Term_Link *hl, uint16_t link_id)
|
||||
{
|
||||
Term_Link *hl2;
|
||||
uint16_t hl_id;
|
||||
|
||||
if (link_id == 0)
|
||||
return EINA_FALSE;
|
||||
|
||||
hl_id = hl - ty->hl.links;
|
||||
if (hl_id == link_id)
|
||||
return EINA_TRUE;
|
||||
hl2 = &ty->hl.links[link_id];
|
||||
if (!hl->key || !hl2->key ||
|
||||
strcmp(hl->key, hl2->key) != 0)
|
||||
return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n)
|
||||
{
|
||||
|
@ -356,7 +375,7 @@ termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n)
|
|||
dst[i] = src[0];
|
||||
}
|
||||
if (src[0].att.link_id)
|
||||
term_link_refcount_inc(ty, dst[i].att.link_id, n);
|
||||
term_link_refcount_inc(ty, src[0].att.link_id, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1852,7 +1852,7 @@ _handle_hyperlink(Termpty *ty,
|
|||
|
||||
s += 3;
|
||||
len -= 3;
|
||||
key = strndup(s, end_param - s);
|
||||
key = eina_stringshare_add_length(s, end_param - s);
|
||||
}
|
||||
len -= end_param - s;
|
||||
s = end_param;
|
||||
|
@ -1868,7 +1868,7 @@ _handle_hyperlink(Termpty *ty,
|
|||
s++;
|
||||
len--;
|
||||
|
||||
url = strndup(s, len);
|
||||
url = eina_stringshare_add_length(s, len);
|
||||
if (!url)
|
||||
goto end;
|
||||
|
||||
|
@ -1885,8 +1885,8 @@ _handle_hyperlink(Termpty *ty,
|
|||
|
||||
end:
|
||||
term_link_free(ty, hl);
|
||||
free(url);
|
||||
free(key);
|
||||
eina_stringshare_del(url);
|
||||
eina_stringshare_del(key);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -319,7 +319,7 @@ termpty_clear_backlog(Termpty *ty)
|
|||
{
|
||||
size_t i;
|
||||
for (i = 0; i < ty->backsize; i++)
|
||||
termpty_save_free(&ty->back[i]);
|
||||
termpty_save_free(ty, &ty->back[i]);
|
||||
free(ty->back);
|
||||
ty->back = NULL;
|
||||
}
|
||||
|
@ -421,7 +421,6 @@ termpty_reset_att(Termatt *att)
|
|||
att->framed = 0;
|
||||
att->encircled = 0;
|
||||
att->overlined = 0;
|
||||
att->link_id = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -442,6 +441,7 @@ termpty_soft_reset_state(Termpty *ty)
|
|||
ty->termstate.had_cr_y = 0;
|
||||
ty->termstate.restrict_cursor = 0;
|
||||
termpty_reset_att(&(ty->termstate.att));
|
||||
ty->termstate.att.link_id = 0;
|
||||
ty->termstate.charset = 0;
|
||||
ty->termstate.charsetch = 'B';
|
||||
ty->termstate.chset[0] = 'B';
|
||||
|
|
|
@ -3,11 +3,6 @@
|
|||
#include "termpty.h"
|
||||
#include "termptysave.h"
|
||||
|
||||
static void
|
||||
_ts_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static int ts_comp = 0;
|
||||
static int ts_uncomp = 0;
|
||||
|
@ -38,9 +33,9 @@ termpty_save_extract(Termsave *ts)
|
|||
}
|
||||
|
||||
Termsave *
|
||||
termpty_save_new(Termsave *ts, int w)
|
||||
termpty_save_new(Termpty *ty, Termsave *ts, int w)
|
||||
{
|
||||
termpty_save_free(ts);
|
||||
termpty_save_free(ty, ts);
|
||||
|
||||
Termcell *cells = calloc(1, w * sizeof(Termcell));
|
||||
if (!cells ) return NULL;
|
||||
|
@ -50,7 +45,7 @@ termpty_save_new(Termsave *ts, int w)
|
|||
}
|
||||
|
||||
Termsave *
|
||||
termpty_save_expand(Termsave *ts, Termcell *cells, size_t delta)
|
||||
termpty_save_expand(Termpty *ty, Termsave *ts, Termcell *cells, size_t delta)
|
||||
{
|
||||
Termcell *newcells;
|
||||
|
||||
|
@ -58,20 +53,29 @@ termpty_save_expand(Termsave *ts, Termcell *cells, size_t delta)
|
|||
if (!newcells)
|
||||
return NULL;
|
||||
|
||||
memcpy(&newcells[ts->w], cells, delta * sizeof(Termcell));
|
||||
memset(newcells + ts->w,
|
||||
0, delta * sizeof(Termcell));
|
||||
TERMPTY_CELL_COPY(ty, cells, &newcells[ts->w], (int)delta);
|
||||
|
||||
ts->w += delta;
|
||||
ts->cells = newcells;
|
||||
return ts;
|
||||
}
|
||||
|
||||
void
|
||||
termpty_save_free(Termsave *ts)
|
||||
termpty_save_free(Termpty *ty, Termsave *ts)
|
||||
{
|
||||
unsigned int i;
|
||||
if (!ts) return;
|
||||
if (ts->comp) ts_comp--;
|
||||
else ts_uncomp--;
|
||||
ts_freeops++;
|
||||
_ts_free(ts->cells);
|
||||
for (i = 0; i < ts->w; i++)
|
||||
{
|
||||
if (EINA_UNLIKELY(ts->cells[i].att.link_id))
|
||||
term_link_refcount_dec(ty, ts->cells[i].att.link_id, 1);
|
||||
}
|
||||
free(ts->cells);
|
||||
ts->cells = NULL;
|
||||
ts->w = 0;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
void termpty_save_register(Termpty *ty);
|
||||
void termpty_save_unregister(Termpty *ty);
|
||||
Termsave *termpty_save_extract(Termsave *ts);
|
||||
Termsave *termpty_save_new(Termsave *ts, int w);
|
||||
void termpty_save_free(Termsave *ts);
|
||||
Termsave *termpty_save_expand(Termsave *ts, Termcell *cells, size_t delta);
|
||||
Termsave *termpty_save_new(Termpty *ty, Termsave *ts, int w);
|
||||
void termpty_save_free(Termpty *ty, Termsave *ts);
|
||||
Termsave *termpty_save_expand(Termpty *ty, Termsave *ts,
|
||||
Termcell *cells, size_t delta);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue