diff --git a/src/bin/termiolink.c b/src/bin/termiolink.c index 99ebfa2c..bbb818e1 100644 --- a/src/bin/termiolink.c +++ b/src/bin/termiolink.c @@ -519,11 +519,16 @@ term_link_new(Termpty *ty) } void -term_link_free(Term_Link *link, Termpty *ty) +term_link_free(Termpty *ty, Term_Link *link) { - if (!link) - return; - uint16_t id = (link - ty->hl.links); + if (!link || !ty) + return; + uint16_t id = (link - ty->hl.links); + + free(link->key); + link->key = NULL; + free(link->url); + link->url = NULL; /* Remove from bitmap */ hl_bitmap_clear_bit(ty, id); diff --git a/src/bin/termiolink.h b/src/bin/termiolink.h index f09d03ab..25b5a8f1 100644 --- a/src/bin/termiolink.h +++ b/src/bin/termiolink.h @@ -12,7 +12,12 @@ struct _Termlink unsigned int refcount; }; +typedef struct _Termpty Termpty; + char *termio_link_find(const Evas_Object *obj, int cx, int cy, int *x1r, int *y1r, int *x2r, int *y2r); +Term_Link * term_link_new(Termpty *ty); +void term_link_free(Termpty *ty, Term_Link *link); + #endif diff --git a/src/bin/termpty.c b/src/bin/termpty.c index 6f4f1941..74c8caee 100644 --- a/src/bin/termpty.c +++ b/src/bin/termpty.c @@ -830,8 +830,7 @@ termpty_free(Termpty *ty) { Term_Link *l = ty->hl.links + i; - free(l->key); - free(l->url); + term_link_free(ty, l); } free(ty->hl.links); } @@ -1635,29 +1634,6 @@ termpty_screen_swap(Termpty *ty) ty->cb.cancel_sel.func(ty->cb.cancel_sel.data); } -void -termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n) -{ - int i; - - if (src) - { - for (i = 0; i < n; i++) - { - HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, src[0].codepoint); - dst[i] = src[0]; - } - } - else - { - for (i = 0; i < n; i++) - { - HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, 0); - memset(&(dst[i]), 0, sizeof(*dst)); - } - } -} - void termpty_cells_set_content(Termpty *ty, Termcell *cells, Eina_Unicode codepoint, int count) @@ -1681,6 +1657,9 @@ termpty_cells_att_fill_preserve_colors(Termpty *ty, Termcell *cells, { Termatt att = cells[i].att; HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, cells[i].codepoint, codepoint); + if (EINA_UNLIKELY(cells[i].att.link_id)) + term_link_refcount_dec(ty, cells[i].att.link_id, 1); + cells[i] = local; if (ty->termstate.att.fg == 0 && ty->termstate.att.bg == 0) { @@ -1693,6 +1672,8 @@ 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); } @@ -1706,8 +1687,13 @@ termpty_cell_codepoint_att_fill(Termpty *ty, Eina_Unicode codepoint, for (i = 0; i < n; i++) { HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, codepoint); + if (EINA_UNLIKELY(dst[i].att.link_id)) + term_link_refcount_dec(ty, dst[i].att.link_id, 1); + dst[i] = local; } + if (EINA_UNLIKELY(local.att.link_id)) + term_link_refcount_inc(ty, local.att.link_id, n); } Config * diff --git a/src/bin/termpty.h b/src/bin/termpty.h index c3fe654f..638c0531 100644 --- a/src/bin/termpty.h +++ b/src/bin/termpty.h @@ -5,7 +5,6 @@ #include "media.h" #include "termiolink.h" -typedef struct _Termpty Termpty; typedef struct _Termcell Termcell; typedef struct _Termatt Termatt; typedef struct _Termsave Termsave; @@ -180,7 +179,7 @@ struct _Termpty struct { Term_Link *links; uint8_t *bitmap; - uint16_t size; + uint32_t size; } hl; }; @@ -240,6 +239,7 @@ struct _Termexp int x, y, w, h; }; + void termpty_init(void); void termpty_shutdown(void); @@ -270,7 +270,6 @@ Termblock *termpty_block_get(const Termpty *ty, int id); void termpty_block_chid_update(Termpty *ty, Termblock *blk); Termblock *termpty_block_chid_get(const Termpty *ty, const char *chid); -void termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n); void termpty_cell_codepoint_att_fill(Termpty *ty, Eina_Unicode codepoint, Termatt att, Termcell *dst, int n); void termpty_cells_set_content(Termpty *ty, Termcell *cells, Eina_Unicode codepoint, int count); @@ -311,15 +310,63 @@ 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); \ } \ memcpy(Tdst, Tsrc, N * sizeof(Termcell)); \ } while (0) -Term_Link * -term_link_new(Termpty *ty); +static inline void +term_link_refcount_inc(Termpty *ty, uint16_t link_id, uint16_t count) +{ + Term_Link *link; -void -term_link_free(Term_Link *link, Termpty *ty); + link = &ty->hl.links[link_id]; + link->refcount += count; +} +static inline void +term_link_refcount_dec(Termpty *ty, uint16_t link_id, uint16_t count) +{ + Term_Link *link; + + link = &ty->hl.links[link_id]; + link->refcount -= count; + if (EINA_UNLIKELY(link->refcount == 0)) + term_link_free(ty, link); +} + +static inline void +termpty_cell_fill(Termpty *ty, Termcell *src, Termcell *dst, int n) +{ + int i; + + if (src) + { + for (i = 0; i < n; i++) + { + HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, src[0].codepoint); + if (EINA_UNLIKELY(dst[i].att.link_id)) + term_link_refcount_dec(ty, dst[i].att.link_id, 1); + + dst[i] = src[0]; + } + if (src[0].att.link_id) + term_link_refcount_inc(ty, dst[i].att.link_id, n); + } + else + { + for (i = 0; i < n; i++) + { + HANDLE_BLOCK_CODEPOINT_OVERWRITE(ty, dst[i].codepoint, 0); + if (EINA_UNLIKELY(dst[i].att.link_id)) + term_link_refcount_dec(ty, dst[i].att.link_id, 1); + + memset(&(dst[i]), 0, sizeof(*dst)); + } + } +} #endif diff --git a/src/bin/termptyesc.c b/src/bin/termptyesc.c index 6a9c7aa2..a182a851 100644 --- a/src/bin/termptyesc.c +++ b/src/bin/termptyesc.c @@ -1884,7 +1884,7 @@ _handle_hyperlink(Termpty *ty, hl = NULL; end: - term_link_free(hl, ty); + term_link_free(ty, hl); free(url); free(key); }