diff options
author | RichardHitt <rbh00@netcom.com> | 2013-01-02 14:50:26 -0800 |
---|---|---|
committer | RichardHitt <rbh00@netcom.com> | 2013-01-02 14:50:26 -0800 |
commit | 4af624627eafdd5db9e0200bfd05c59aa60292b9 (patch) | |
tree | 602d296c8e34a36396979ea0b82cb7bb471af7da /src/fe-gtk | |
parent | 7f2846a5bddbfaf78e99b303db4c9152460bb4d3 (diff) |
overhauling of URL detection, including channel, nick, etc 'words'
Diffstat (limited to 'src/fe-gtk')
-rw-r--r-- | src/fe-gtk/fe-gtk.c | 2 | ||||
-rw-r--r-- | src/fe-gtk/maingui.c | 67 | ||||
-rw-r--r-- | src/fe-gtk/xtext.c | 125 | ||||
-rw-r--r-- | src/fe-gtk/xtext.h | 4 |
4 files changed, 119 insertions, 79 deletions
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index 57ffa2f6..204b7570 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -1058,7 +1058,7 @@ static void fe_open_url_locale (const char *url) { /* the http:// part's missing, prepend it, otherwise it won't always work */ - if (strchr (url, ':') == NULL && url_check_word (url, strlen (url)) != WORD_PATH) + if (strchr (url, ':') == NULL && url_check_word (url) != WORD_PATH) { url = g_strdup_printf ("http://%s", url); fe_open_url_inner (url); diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index a52aa9d4..b6fdbdfa 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -2242,20 +2242,14 @@ mg_create_topicbar (session *sess, GtkWidget *box) /* check if a word is clickable */ static int -mg_word_check (GtkWidget * xtext, char *word, int len) +mg_word_check (GtkWidget * xtext, char *word) { session *sess = current_sess; int ret; - ret = url_check_word (word, len); /* common/url.c */ - if (ret == 0) - { - if (( (word[0]=='@' || word[0]=='+' || word[0]=='%') && userlist_find (sess, word+1)) || userlist_find (sess, word)) - return WORD_NICK; - - if (sess->type == SESS_DIALOG) - return WORD_DIALOG; - } + ret = url_check_word (word); + if (ret == 0 && sess->type == SESS_DIALOG) + return WORD_DIALOG; return ret; } @@ -2266,23 +2260,28 @@ static void mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even) { session *sess = current_sess; + int word_type, start, end; + char *tmp; - if (even->button == 1) /* left button */ + if (word == NULL) { - if (word == NULL) - { + if (even->button == 1) /* left button */ mg_focus (sess); - return; - } + return; + } + + word_type = mg_word_check (xtext, word); + url_last (&start, &end); - if ((even->state & 13) == prefs.hex_gui_url_mod) + if (even->button == 1 && (even->state & 13) == prefs.hex_gui_url_mod) + { + switch (word_type) { - switch (mg_word_check (xtext, word, strlen (word))) - { - case WORD_URL: - case WORD_HOST: - fe_open_url (word); - } + case WORD_URL: + case WORD_HOST: + word[end] = 0; + word += start; + fe_open_url (word); } return; } @@ -2296,7 +2295,7 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even) return; } - switch (mg_word_check (xtext, word, strlen (word))) + switch (word_type) { case 0: case WORD_PATH: @@ -2304,26 +2303,22 @@ mg_word_clicked (GtkWidget *xtext, char *word, GdkEventButton *even) break; case WORD_URL: case WORD_HOST: + word[end] = 0; + word += start; menu_urlmenu (even, word); break; case WORD_NICK: - menu_nickmenu (sess, even, (word[0]=='@' || word[0]=='+' || word[0]=='%') ? - word+1 : word, FALSE); + menu_nickmenu (sess, even, word + (ispunct (*word)? 1: 0), FALSE); break; case WORD_CHANNEL: - if (*word == '@' || *word == '+' || *word=='^' || *word=='%' || *word=='*') - word++; - menu_chanmenu (sess, even, word); + menu_chanmenu (sess, even, word + (ispunct (*word)? 1: 0)); break; case WORD_EMAIL: - { - char *newword = malloc (strlen (word) + 10); - if (*word == '~') - word++; - sprintf (newword, "mailto:%s", word); - menu_urlmenu (even, newword); - free (newword); - } + word[end] = 0; + word += start; + tmp = g_strdup_printf("mailto:%s", word + (ispunct (*word)? 1: 0)); + menu_urlmenu (even, tmp); + g_free (tmp); break; case WORD_DIALOG: menu_nickmenu (sess, even, sess->channel, FALSE); diff --git a/src/fe-gtk/xtext.c b/src/fe-gtk/xtext.c index e8419b5a..4d2a8a69 100644 --- a/src/fe-gtk/xtext.c +++ b/src/fe-gtk/xtext.c @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * ========================================================================= * * xtext, the text widget used by X-Chat. @@ -73,6 +73,7 @@ #include "../common/fe.h" #include "../common/util.h" #include "../common/hexchatc.h" +#include "../common/url.h" #include "fe-gtk.h" #include "xtext.h" #include "fkeys.h" @@ -1901,7 +1902,7 @@ gtk_xtext_selection_update (GtkXText * xtext, GdkEventMotion * event, int p_y, g static char * gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, - int *ret_off, int *ret_len) + int *ret_off, int *ret_len, GSList **slp) { textentry *ent; int offset; @@ -1950,9 +1951,9 @@ gtk_xtext_get_word (GtkXText * xtext, int x, int y, textentry ** ret_ent, if (ret_off) *ret_off = word - ent->str; if (ret_len) - *ret_len = str - word; + *ret_len = len; /* Length before stripping */ - return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, NULL, FALSE); + return gtk_xtext_strip_color (word, len, xtext->scratch_buffer, NULL, NULL, slp, FALSE); } #ifdef MOTION_MONITOR @@ -2028,14 +2029,62 @@ gtk_xtext_check_mark_stamp (GtkXText *xtext, GdkModifierType mask) return redraw; } +static int +gtk_xtext_get_word_adjust (GtkXText *xtext, int x, int y, textentry **word_ent, int *offset, int *len) +{ + GSList *slp = NULL; + unsigned char *word; + int word_type = 0; + + word = gtk_xtext_get_word (xtext, x, y, word_ent, offset, len, &slp); + if (word) + { + int laststart, lastend; + + word_type = xtext->urlcheck_function (GTK_WIDGET (xtext), word); + if (word_type > 0) + { + if (url_last (&laststart, &lastend)) + { + int cumlen, startadj = 0, endadj = 0; + offlen_t o; + GSList *sl; + + for (sl = slp, cumlen = 0; sl; sl = g_slist_next (sl)) + { + o.u = GPOINTER_TO_UINT (sl->data); + startadj = o.o.off - cumlen; + cumlen += o.o.len; + if (laststart < cumlen) + break; + } + for (sl = slp, cumlen = 0; sl; sl = g_slist_next (sl)) + { + o.u = GPOINTER_TO_UINT (sl->data); + endadj = o.o.off - cumlen; + cumlen += o.o.len; + if (lastend < cumlen) + break; + } + laststart += startadj; + *offset += laststart; + *len = lastend + endadj - laststart; + } + } + } + g_slist_free (slp); + + return word_type; +} + static gboolean gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event) { GtkXText *xtext = GTK_XTEXT (widget); GdkModifierType mask; int redraw, tmp, x, y, offset, len, line_x; - unsigned char *word; textentry *word_ent; + int word_type; gdk_window_get_pointer (widget->window, &x, &y, &mask); @@ -2104,43 +2153,40 @@ gtk_xtext_motion_notify (GtkWidget * widget, GdkEventMotion * event) if (xtext->urlcheck_function == NULL) return FALSE; - word = gtk_xtext_get_word (xtext, x, y, &word_ent, &offset, &len); - if (word) + word_type = gtk_xtext_get_word_adjust (xtext, x, y, &word_ent, &offset, &len); + if (word_type > 0) { - if (xtext->urlcheck_function (GTK_WIDGET (xtext), word, len) > 0) + if (!xtext->cursor_hand || + xtext->hilight_ent != word_ent || + xtext->hilight_start != offset || + xtext->hilight_end != offset + len) { - if (!xtext->cursor_hand || - xtext->hilight_ent != word_ent || - xtext->hilight_start != offset || - xtext->hilight_end != offset + len) + if (!xtext->cursor_hand) { - if (!xtext->cursor_hand) - { - gdk_window_set_cursor (GTK_WIDGET (xtext)->window, - xtext->hand_cursor); - xtext->cursor_hand = TRUE; - } + gdk_window_set_cursor (GTK_WIDGET (xtext)->window, + xtext->hand_cursor); + xtext->cursor_hand = TRUE; + } - /* un-render the old hilight */ - if (xtext->hilight_ent) - gtk_xtext_unrender_hilight (xtext); + /* un-render the old hilight */ + if (xtext->hilight_ent) + gtk_xtext_unrender_hilight (xtext); - xtext->hilight_ent = word_ent; - xtext->hilight_start = offset; - xtext->hilight_end = offset + len; + xtext->hilight_ent = word_ent; + xtext->hilight_start = offset; + xtext->hilight_end = offset + len; - xtext->skip_border_fills = TRUE; - xtext->render_hilights_only = TRUE; - xtext->skip_stamp = TRUE; + xtext->skip_border_fills = TRUE; + xtext->render_hilights_only = TRUE; + xtext->skip_stamp = TRUE; - gtk_xtext_render_ents (xtext, word_ent, NULL); + gtk_xtext_render_ents (xtext, word_ent, NULL); - xtext->skip_border_fills = FALSE; - xtext->render_hilights_only = FALSE; - xtext->skip_stamp = FALSE; - } - return FALSE; + xtext->skip_border_fills = FALSE; + xtext->render_hilights_only = FALSE; + xtext->skip_stamp = FALSE; } + return FALSE; } gtk_xtext_leave_notify (widget, NULL); @@ -2280,7 +2326,7 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event) if (!xtext->hilighting) { - word = gtk_xtext_get_word (xtext, event->x, event->y, 0, 0, 0); + word = gtk_xtext_get_word (xtext, event->x, event->y, 0, 0, 0, 0); g_signal_emit (G_OBJECT (xtext), xtext_signals[WORD_CLICK], 0, word ? word : NULL, event); } else { @@ -2288,7 +2334,6 @@ gtk_xtext_button_release (GtkWidget * widget, GdkEventButton * event) } } - return FALSE; } @@ -2305,7 +2350,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event) if (event->button == 3 || event->button == 2) /* right/middle click */ { - word = gtk_xtext_get_word (xtext, x, y, 0, 0, 0); + word = gtk_xtext_get_word (xtext, x, y, 0, 0, 0, 0); if (word) { g_signal_emit (G_OBJECT (xtext), xtext_signals[WORD_CLICK], 0, @@ -2322,7 +2367,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event) if (event->type == GDK_2BUTTON_PRESS) /* WORD select */ { gtk_xtext_check_mark_stamp (xtext, mask); - if (gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len)) + if (gtk_xtext_get_word (xtext, x, y, &ent, &offset, &len, 0)) { if (len == 0) return FALSE; @@ -2343,7 +2388,7 @@ gtk_xtext_button_press (GtkWidget * widget, GdkEventButton * event) if (event->type == GDK_3BUTTON_PRESS) /* LINE select */ { gtk_xtext_check_mark_stamp (xtext, mask); - if (gtk_xtext_get_word (xtext, x, y, &ent, 0, 0)) + if (gtk_xtext_get_word (xtext, x, y, &ent, 0, 0, 0)) { gtk_xtext_selection_clear (xtext->buffer); ent->mark_start = 0; @@ -2852,7 +2897,7 @@ gtk_xtext_render_flush (GtkXText * xtext, int x, int y, unsigned char *str, { int str_width, dofill; GdkDrawable *pix = NULL; - int dest_x, dest_y; + int dest_x = 0, dest_y = 0; if (xtext->dont_render || len < 1 || xtext->hidden) return 0; @@ -5904,7 +5949,7 @@ gtk_xtext_set_tint (GtkXText *xtext, int tint_red, int tint_green, int tint_blue } void -gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *, int)) +gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *)) { xtext->urlcheck_function = urlcheck_function; } diff --git a/src/fe-gtk/xtext.h b/src/fe-gtk/xtext.h index 48c71d0c..cc6bbebb 100644 --- a/src/fe-gtk/xtext.h +++ b/src/fe-gtk/xtext.h @@ -179,7 +179,7 @@ struct _GtkXText unsigned char scratch_buffer[4096]; void (*error_function) (int type); - int (*urlcheck_function) (GtkWidget * xtext, char *word, int len); + int (*urlcheck_function) (GtkWidget * xtext, char *word); int jump_out_offset; /* point at which to stop rendering */ int jump_in_offset; /* "" start rendering */ @@ -274,7 +274,7 @@ void gtk_xtext_set_show_separator (GtkXText *xtext, gboolean show_separator); void gtk_xtext_set_thin_separator (GtkXText *xtext, gboolean thin_separator); void gtk_xtext_set_time_stamp (xtext_buffer *buf, gboolean timestamp); void gtk_xtext_set_tint (GtkXText *xtext, int tint_red, int tint_green, int tint_blue); -void gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *, int)); +void gtk_xtext_set_urlcheck_function (GtkXText *xtext, int (*urlcheck_function) (GtkWidget *, char *)); void gtk_xtext_set_wordwrap (GtkXText *xtext, gboolean word_wrap); xtext_buffer *gtk_xtext_buffer_new (GtkXText *xtext); |