2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
33 void *url_tree
= NULL
;
37 url_free (char *url
, void *data
)
46 tree_foreach (url_tree
, (tree_traverse_func
*)url_free
, NULL
);
47 tree_destroy (url_tree
);
52 url_save_cb (char *url
, FILE *fd
)
54 fprintf (fd
, "%s\n", url
);
59 url_save (const char *fname
, const char *mode
, gboolean fullpath
)
64 fd
= xchat_fopen_file (fname
, mode
, XOF_FULLPATH
);
66 fd
= xchat_fopen_file (fname
, mode
, 0);
70 tree_foreach (url_tree
, (tree_traverse_func
*)url_save_cb
, fd
);
77 url_save ("url.save", "a", FALSE
);
81 url_find (char *urltext
)
85 if (tree_find (url_tree
, urltext
, (tree_cmp_func
*)strcasecmp
, NULL
, &pos
))
91 url_add (char *urltext
, int len
)
96 if (!prefs
.url_grabber
)
99 data
= malloc (len
+ 1);
102 memcpy (data
, urltext
, len
);
105 if (data
[len
- 1] == '.') /* chop trailing dot */
110 if (data
[len
- 1] == ')') /* chop trailing ) */
120 url_tree
= tree_new ((tree_cmp_func
*)strcasecmp
, NULL
);
122 size
= tree_size (url_tree
);
124 if (prefs
.url_grabber_limit
> 0 && size
>= prefs
.url_grabber_limit
)
126 /* the loop is necessary to handle having the limit lowered while
128 size
-= prefs
.url_grabber_limit
;
129 for(; size
> 0; size
--)
130 tree_remove_at_pos (url_tree
, 0);
133 tree_append (url_tree
, data
);
137 /* check if a word is clickable. This is called on mouse motion events, so
138 keep it FAST! This new version was found to be almost 3x faster than
142 url_check_word (char *word
, int len
)
144 #define D(x) (x), ((sizeof (x)) - 1)
145 static const struct {
171 const char *at
, *dot
;
174 if (len
> 1 && word
[1] == '#' && strchr("@+^%*#", word
[0]))
177 if ((word
[0] == '#' || word
[0] == '&') && word
[1] != '#' && word
[1] != 0)
180 for (i
= 0; i
< G_N_ELEMENTS(prefix
); i
++)
189 /* This is pretty much strncasecmp(). */
190 for (j
= 0; j
< l
; j
++)
192 unsigned char c
= word
[j
];
193 if (tolower(c
) != prefix
[i
].s
[j
])
201 at
= strchr (word
, '@'); /* check for email addy */
202 dot
= strrchr (word
, '.');
207 if (strchr (word
, '*'))
214 /* check if it's an IP number */
216 for (i
= 0; i
< len
; i
++)
218 if (word
[i
] == '.' && i
> 0)
219 dots
++; /* allow 127.0.0.1:80 */
220 else if (!isdigit ((unsigned char) word
[i
]) && word
[i
] != ':')
231 for (i
= 0; i
< G_N_ELEMENTS(suffix
); i
++)
238 const unsigned char *p
= &word
[len
- l
];
241 /* This is pretty much strncasecmp(). */
242 for (j
= 0; j
< l
; j
++)
244 if (tolower(p
[j
]) != suffix
[i
].s
[j
])
252 if (word
[len
- 3] == '.' &&
253 isalpha ((unsigned char) word
[len
- 2]) &&
254 isalpha ((unsigned char) word
[len
- 1]))
262 url_check_line (char *buf
, int len
)
268 if (buf
[0] == ':' && buf
[1] != 0)
273 /* check each "word" (space separated) */
285 /* This is to work around not being able to detect URLs that are at
286 the start of messages. */
292 if (start
[0] == '+' || start
[0] == '-')
298 if (wlen
> 2 && url_check_word (start
, wlen
) == WORD_URL
)
300 url_add (start
, wlen
);