1 /***************************************************************************
2 * Pinfo is a ncurses based lynx style info documentation browser
3 *
4 * Copyright (C) 1999 Przemek Borys <pborys@dione.ids.pl>
5 * Copyright (C) 2005 Bas Zoetekouw <bas@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 ***************************************************************************/
21 #include "common_includes.h"
22
23 #define MENU_DOT 0
24 #define NOTE_DOT 1
25
26 int
compare_hyperlink(const void * a,const void * b)27 compare_hyperlink(const void *a, const void *b)
28 {
29 return ((HyperObject *) a)->col -((HyperObject *) b)->col;
30 }
31
32 void
sort_hyperlinks_from_current_line(long startlink,long endlink)33 sort_hyperlinks_from_current_line(long startlink, long endlink)
34 {
35 qsort(hyperobjects + startlink, endlink - startlink, sizeof(HyperObject), compare_hyperlink);
36 }
37
38 /*
39 * Compares two strings, ignoring whitespaces(tabs, spaces)
40 */
41 int
compare_tag_table_string(char * base,char * compared)42 compare_tag_table_string(char *base, char *compared)
43 {
44 int i, j;
45
46 j = 0;
47
48 for (i = 0; base[i] != 0; i++)
49 {
50 if (base[i] != compared[j])
51 {
52 if ((isspace(compared[j])) &&(isspace(base[i]))); /* OK--two blanks */
53 else if (isspace(compared[j]))
54 i--; /* index of `base' should be unchanged after for's i++ */
55 else if (isspace(base[i]))
56 j--; /* index of `compared' stands in place
57 and waits for base to skip blanks */
58 else
59 return (int) base[i] -(int) compared[j];
60 }
61 j++;
62 }
63 while (compared[j]) /* handle trailing whitespaces of variable `compared' */
64 {
65 if (!isspace(compared[j]))
66 return (int) base[i] -(int) compared[j];
67 j++;
68 }
69 return 0;
70 }
71
72 /*
73 * checks if an item belongs to tag table. returns 1 on success and 0 on
74 * failure. It should be optimised...
75 */
76 int
exists_in_tag_table(char * item)77 exists_in_tag_table(char *item)
78 {
79 if (gettagtablepos(item) != -1)
80 return 1;
81 else
82 return 0;
83 }
84
85
86 void
freelinks()87 freelinks() /* frees space allocated previously by node-links */
88 {
89 if ((hyperobjects)&&(hyperobjectcount))
90 xfree(hyperobjects);
91 hyperobjects = 0;
92 hyperobjectcount = 0;
93 }
94
95 /*
96 * Finds url end. It is recognized by an invalid character.
97 */
98 /* TODO: fix possible string overflow (no bounds checking) */
99 char *
findurlend(char * str)100 findurlend(char *str)
101 {
102 char *end;
103 char *allowedchars = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890-_/~.%=|:@";
104 end = str;
105 while (strchr(allowedchars, *end) != NULL)
106 ++end;
107 if (end > str)
108 {
109 if (*(end - 1) == '.')
110 end--;
111 }
112 assert(end>=str);
113 return end;
114 }
115
116 /*
117 * Searchs for a note/menu delimiter. it may be dot, comma, tab, or newline.
118 */
119 /* TODO: fix possible string overflow (no bounds checking) */
120 char *
finddot(char * str,int mynote)121 finddot(char *str, int mynote)
122 {
123 char *ptr = str;
124 char *end[4] =
125 {
126 0, 0, 0, 0
127 };
128 char *closest = 0;
129 int i;
130 while (isspace(*ptr)) /* if there are only spaces and newline... */
131 {
132 if (*ptr == '\n') /* then it's a `Menu: \n' entry--skip it */
133 return 0;
134 ptr++;
135 }
136 end[0] = strchr(str, '.'); /* nodename entry may end with dot, comma */
137 end[1] = strchr(str, ','); /* tabulation, or newline */
138 if (!mynote)
139 {
140 end[2] = strchr(str, '\t');
141 end[3] = strchr(str, '\n');
142 }
143 else
144 mynote = 2;
145 if (end[0])
146 closest = end[0];
147 else if (end[1])
148 closest = end[1];
149 else if (end[2])
150 closest = end[2];
151 else if (end[3])
152 closest = end[3];
153 for (i = 1; i < mynote; i++) /* find the delimiter, which was found most
154 recently */
155 {
156 if ((end[i] < closest) &&(end[i]))
157 closest = end[i];
158 }
159 assert(closest>=str);
160 return closest;
161 }
162
163 /*
164 * Moves you to the beginning of username in email address. If username has
165 * length=0, NULL is returned.
166 */
167 /* TODO: fix possible string overflow (no bounds checking) */
168 char *
findemailstart(char * str)169 findemailstart(char *str)
170 {
171 char *allowedchars = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890-_/~.%=|:";
172 char *at = strchr(str, '@');
173 if (at)
174 {
175 while (at > str)
176 {
177 at--;
178 if (strchr(allowedchars, *at) == NULL)
179 {
180 if (*(at + 1) != '@')
181 return at + 1;
182 else
183 return 0;
184 }
185 }
186 if (*at != '@')
187 return at;
188 else
189 return 0;
190 }
191 return 0;
192 }
193
194 void
initializelinks(char * line1,char * line2,int line)195 initializelinks(char *line1, char *line2, int line)
196 {
197 char *tmp;
198 char *notestart = 0, *urlstart = 0, *urlend = 0;
199 char *quotestart = 0, *quoteend = 0;
200 char *buf = xmalloc(strlen(line1) + strlen(line2) + 1);
201 /* required to sort properly the hyperlinks from current line only */
202 unsigned long initialhyperobjectcount = hyperobjectcount;
203 int changed;
204 int line1len = strlen(line1);
205
206 strcpy(buf, line1); /* copy two lines into one */
207 if (strlen(line1))
208 buf[strlen(line1) - 1] = ' '; /* replace trailing '\n' with ' ' */
209 strcat(buf, line2);
210 /******************************************************************************
211 * First scan for some highlights ;) -- words enclosed with quotes *
212 ******************************************************************************/
213 quoteend = buf;
214 do
215 {
216 changed = 0;
217 /* find start of quoted text */
218 if ( ((quotestart = strchr(quoteend, '`')) != NULL)
219 /* if it's in the first line of the two glued together */
220 && (quotestart < buf + line1len)
221 /* find the end of quoted text */
222 && ((quoteend = strchr(quotestart, '\'')) != NULL)
223 && (quoteend - quotestart > 1))
224 {
225 /* if this apostrophe is not a part of "haven't",
226 * "wouldn't", etc. */
227 while (!strncmp(quoteend - 1, "n't", 3))
228 {
229 quoteend = strchr(quoteend + 1, '\'');
230 if (!quoteend)
231 break;
232 }
233 if (quoteend)
234 {
235 changed = 1;
236 if (!hyperobjectcount)
237 hyperobjects = xmalloc(sizeof(HyperObject));
238 else
239 {
240 hyperobjects = xrealloc(hyperobjects,
241 sizeof(HyperObject) *(hyperobjectcount + 1));
242 }
243 hyperobjects[hyperobjectcount].line = line;
244 hyperobjects[hyperobjectcount].col =
245 calculate_len(buf, quotestart + 1);
246 hyperobjects[hyperobjectcount].breakpos = -1; /* default */
247 if (quoteend > buf + line1len)
248 {
249 hyperobjects[hyperobjectcount].breakpos =
250 buf + line1len - quotestart - 1;
251 }
252 hyperobjects[hyperobjectcount].type = HIGHLIGHT;
253 strncpy( hyperobjects[hyperobjectcount].node,
254 quotestart + 1, quoteend - quotestart - 1);
255 hyperobjects[hyperobjectcount].node[quoteend - quotestart - 1] = 0;
256 strcpy(hyperobjects[hyperobjectcount].file, "");
257 hyperobjects[hyperobjectcount].nodelen =
258 strlen(hyperobjects[hyperobjectcount].node);
259 hyperobjects[hyperobjectcount].filelen =
260 strlen(hyperobjects[hyperobjectcount].file);
261 hyperobjects[hyperobjectcount].tagtableoffset = -1;
262 hyperobjectcount++;
263 }
264 }
265 }
266 while (changed);
267 /******************************************************************************
268 * Look for e-mail url's *
269 ******************************************************************************/
270 urlend = line1;
271 do
272 {
273 changed = 0;
274 if ((urlstart = findemailstart(urlend)) != NULL)
275 {
276 urlend = findurlend(urlstart); /* always successful */
277 if (!hyperobjectcount)
278 hyperobjects = xmalloc(sizeof(HyperObject));
279 else
280 {
281 hyperobjects = xrealloc(hyperobjects,
282 sizeof(HyperObject) *(hyperobjectcount + 1));
283 }
284 hyperobjects[hyperobjectcount].line = line;
285 hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
286 hyperobjects[hyperobjectcount].breakpos = -1;
287 hyperobjects[hyperobjectcount].type = 6;
288 strncpy(hyperobjects[hyperobjectcount].node,
289 urlstart, urlend - urlstart);
290 hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
291 strcpy(hyperobjects[hyperobjectcount].file, "");
292 hyperobjects[hyperobjectcount].nodelen =
293 strlen(hyperobjects[hyperobjectcount].node);
294 hyperobjects[hyperobjectcount].filelen =
295 strlen(hyperobjects[hyperobjectcount].file);
296 hyperobjects[hyperobjectcount].tagtableoffset = -1;
297 if (strchr(hyperobjects[hyperobjectcount].node, '.') == NULL)
298 {
299 if (!hyperobjectcount)
300 xfree(hyperobjects);
301 }
302 else
303 hyperobjectcount++;
304 changed = 1;
305 }
306
307 }
308 while (changed);
309 /******************************************************************************
310 * First try to scan for menu. Use as many security mechanisms, as possible *
311 ******************************************************************************/
312
313 if ((line1[0] == '*') &&(line1[1] == ' ')) /* menu */
314 {
315 /*************************************************************************
316 * Scan for normal menu of kind "*(infofile)reference:: comment", where *
317 * the infofile parameter is optional, and indicates, that a reference *
318 * matches different info file. *
319 *************************************************************************/
320 tmp = strstr(line1, "::"); /* "* menulink:: comment" */
321 if (tmp != NULL)
322 {
323 if (!hyperobjectcount)
324 hyperobjects = xmalloc(sizeof(HyperObject));
325 else
326 {
327 hyperobjects = xrealloc(hyperobjects,
328 sizeof(HyperObject) *(hyperobjectcount + 1));
329 }
330 if (line1[2] == '(') /* if cross-info link */
331 {
332 char *end = strchr(line1, ')');
333 /* if the ')' char was found, and was before '::' */
334 if ((end != NULL) &&(end < tmp))
335 {
336 long FilenameLen =(long)(end - line1 - 3);
337 long NodenameLen =(long)(tmp - end - 1);
338 strncpy(hyperobjects[hyperobjectcount].file,
339 line1 + 3, FilenameLen);
340 hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
341 strncpy(hyperobjects[hyperobjectcount].node,
342 end + 1, NodenameLen);
343 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
344 hyperobjects[hyperobjectcount].type = 0;
345 hyperobjects[hyperobjectcount].line = line;
346 hyperobjects[hyperobjectcount].col = 2;
347 hyperobjects[hyperobjectcount].breakpos = -1;
348 hyperobjects[hyperobjectcount].nodelen =
349 strlen(hyperobjects[hyperobjectcount].node);
350 hyperobjects[hyperobjectcount].filelen =
351 strlen(hyperobjects[hyperobjectcount].file);
352 hyperobjectcount++;
353 }
354 }
355 else
356 {
357 /* if not cross-info link */
358 long NodenameLen =(long)(tmp - line1 - 2);
359 int goodHit = 0;
360 strcpy(hyperobjects[hyperobjectcount].file, "");
361 strncpy(hyperobjects[hyperobjectcount].node,
362 line1 + 2, NodenameLen);
363 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
364 hyperobjects[hyperobjectcount].type = 0;
365 hyperobjects[hyperobjectcount].line = line;
366 hyperobjects[hyperobjectcount].col = 2;
367 hyperobjects[hyperobjectcount].breakpos = -1;
368 hyperobjects[hyperobjectcount].nodelen =
369 strlen(hyperobjects[hyperobjectcount].node);
370 hyperobjects[hyperobjectcount].filelen =
371 strlen(hyperobjects[hyperobjectcount].file);
372 if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
373 {
374 hyperobjectcount++; /* yep, this was a good hit */
375 goodHit = 1;
376 }
377 if (!goodHit && !hyperobjectcount)
378 {
379 xfree(hyperobjects);
380 hyperobjects = 0;
381 }
382 }
383 }
384 /************************************************************
385 * Scan for menu references of form *
386 * "* Comment:[spaces](infofile)reference." *
387 ******************************************************************************/
388 else if ((tmp = strrchr(line1, ':')) != NULL)
389 {
390 char *start = 0, *end = 0, *dot = 0;
391 /* find the trailing dot */
392 dot = finddot(tmp + 1, MENU_DOT);
393 if (dot != NULL && (dot + 7 < dot + strlen(dot)) )
394 {
395 /* skip possible '.info' filename suffix when
396 * searching for ending dot */
397 if (strncmp(dot, ".info)", 6) == 0)
398 dot = finddot(dot + 1, MENU_DOT);
399 }
400 /* we make use of sequential AND evaluation: start must not be NULL! */
401 if (((start = strchr(tmp, '(')) != NULL) &&(dot != NULL) &&
402 ((end = strchr(start, ')')) != NULL))
403 {
404 if ( (start < dot) && (end < dot) ) /* security mechanism ;) */
405 {
406 long FilenameLen =(long)(end - start - 1);
407 long NodenameLen =(long)(dot - end - 1);
408 if (!hyperobjectcount)
409 hyperobjects = xmalloc(sizeof(HyperObject));
410 else
411 {
412 hyperobjects = xrealloc(hyperobjects,
413 sizeof(HyperObject) *(hyperobjectcount + 1));
414 }
415 strncpy(hyperobjects[hyperobjectcount].file,
416 start + 1, FilenameLen);
417 hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
418 strncpy(hyperobjects[hyperobjectcount].node,
419 end + 1, NodenameLen);
420 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
421 hyperobjects[hyperobjectcount].type = 1;
422 hyperobjects[hyperobjectcount].line = line;
423 hyperobjects[hyperobjectcount].col =
424 calculate_len(line1, start);
425 hyperobjects[hyperobjectcount].breakpos = -1;
426 hyperobjects[hyperobjectcount].nodelen =
427 strlen(hyperobjects[hyperobjectcount].node);
428 hyperobjects[hyperobjectcount].filelen =
429 strlen(hyperobjects[hyperobjectcount].file);
430 hyperobjectcount++;
431 }
432 else
433 {
434 goto handle_no_file_menu_label;
435 }
436 }
437 else if (dot != NULL) /* if not cross-info reference */
438 {
439 handle_no_file_menu_label:
440 {
441 long NodenameLen;
442 int goodHit = 0; /* has val of 1, if it's a good hit */
443 if (!hyperobjectcount)
444 hyperobjects = xmalloc(sizeof(HyperObject));
445 else
446 {
447 hyperobjects = xrealloc(hyperobjects,
448 sizeof(HyperObject) *(hyperobjectcount + 1));
449 }
450
451 start = tmp + 1; /* move after the padding spaces */
452 while (isspace(*start))
453 start++;
454 NodenameLen =(long)(dot - start);
455 strcpy(hyperobjects[hyperobjectcount].file, "");
456 strncpy(hyperobjects[hyperobjectcount].node,
457 start, NodenameLen);
458 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
459 hyperobjects[hyperobjectcount].type = 1;
460 hyperobjects[hyperobjectcount].line = line;
461 hyperobjects[hyperobjectcount].col = calculate_len(line1, start);
462 hyperobjects[hyperobjectcount].breakpos = -1;
463 hyperobjects[hyperobjectcount].nodelen =
464 strlen(hyperobjects[hyperobjectcount].node);
465 hyperobjects[hyperobjectcount].filelen =
466 strlen(hyperobjects[hyperobjectcount].file);
467 if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
468 {
469 hyperobjectcount++; /* yep, this was a good hit */
470 goodHit = 1;
471 }
472 if (!goodHit && !hyperobjectcount)
473 {
474 xfree(hyperobjects);
475 hyperobjects = 0;
476 }
477 }
478 }
479 }
480 }
481 /******************************************************************************
482 * Handle notes. In similar way as above. *
483 ******************************************************************************/
484 else if ( ( (notestart = strstr(buf, "*note")) != NULL )
485 || ( (notestart = strstr(buf, "*Note")) != NULL ) )
486 {
487 handlenote:
488 /*************************************************************************
489 * Scan for normal note of kind "*(infofile)reference:: comment", where *
490 * the infofile parameter is optional, and indicates, that a reference *
491 * matches different info file. *
492 *************************************************************************/
493 /* make sure that we don't handle notes, which fit in the second line */
494 /* Signed-unsigned issues FIXME */
495 if (notestart < buf + strlen(line1))
496 {
497 /* we can handle only those, who are in the first line,
498 * or who are split up into two lines */
499 tmp = strstr(notestart, "::"); /* "*note notelink:: comment" */
500 if (tmp != NULL)
501 {
502 if (!hyperobjectcount)
503 hyperobjects = xmalloc(sizeof(HyperObject));
504 else
505 hyperobjects = xrealloc(hyperobjects, sizeof(HyperObject) *(hyperobjectcount + 1));
506 if (notestart[6] == '(') /* if cross-info link */
507 {
508 char *end = strchr(notestart, ')');
509 /* if the ')' char was found, and was before '::' */
510 if ((end != NULL) &&(end < tmp))
511 {
512 long FilenameLen =(long)(end - notestart - 7);
513 long NodenameLen =(long)(tmp - end - 1);
514 strncpy(hyperobjects[hyperobjectcount].file,
515 notestart + 7, FilenameLen);
516 hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
517 strncpy(hyperobjects[hyperobjectcount].node,
518 end + 1, NodenameLen);
519 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
520 hyperobjects[hyperobjectcount].type = 2;
521 if (notestart + 7 < buf + strlen(line1))
522 {
523 hyperobjects[hyperobjectcount].line = line;
524 hyperobjects[hyperobjectcount].col = calculate_len(buf, notestart + 7);
525 /* if the note highlight fits int first line */
526 if (tmp < buf + strlen(line1))
527 {
528 /* we don't need to break highlighting
529 * into several lines */
530 hyperobjects[hyperobjectcount].breakpos = -1;
531 }
532 else
533 {
534 /* otherwise we need it */
535 hyperobjects[hyperobjectcount].breakpos =
536 strlen(line1) -(long)(notestart + 7 - buf) + 1;
537 }
538 }
539 else
540 {
541 hyperobjects[hyperobjectcount].line = line + 1;
542 hyperobjects[hyperobjectcount].col =
543 calculate_len(buf + strlen(line1), notestart + 7);
544 if (tmp < buf + strlen(line1)) /* as above */
545 hyperobjects[hyperobjectcount].breakpos = -1;
546 else if ((hyperobjects[hyperobjectcount].breakpos =
547 strlen(line1) -
548 (long)(notestart + 7 - buf) + 1) == 0)
549 {
550 hyperobjects[hyperobjectcount].line--;
551 }
552 }
553 hyperobjects[hyperobjectcount].nodelen =
554 strlen(hyperobjects[hyperobjectcount].node);
555 hyperobjects[hyperobjectcount].filelen =
556 strlen(hyperobjects[hyperobjectcount].file);
557 hyperobjectcount++;
558 }
559 }
560 else /* if not cross-info link */
561 {
562 long NodenameLen =(long)(tmp - notestart - 6);
563 int goodHit = 0;
564 strcpy(hyperobjects[hyperobjectcount].file, "");
565 strncpy(hyperobjects[hyperobjectcount].node,
566 notestart + 6, NodenameLen);
567 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
568 hyperobjects[hyperobjectcount].type = 2;
569 hyperobjects[hyperobjectcount].nodelen =
570 strlen(hyperobjects[hyperobjectcount].node);
571 hyperobjects[hyperobjectcount].filelen =
572 strlen(hyperobjects[hyperobjectcount].file);
573 if (notestart + 7 < buf + strlen(line1))
574 {
575 hyperobjects[hyperobjectcount].line = line;
576 hyperobjects[hyperobjectcount].col =
577 calculate_len(buf, notestart + 7) - 1;
578 /* if the note highlight fits int first line */
579 if (tmp < buf + strlen(line1))
580 {
581 /* we don't need to break highlighting into
582 * several lines */
583 hyperobjects[hyperobjectcount].breakpos = -1;
584 }
585 else
586 {
587 /* otherwise we need it */
588 hyperobjects[hyperobjectcount].breakpos =
589 strlen(line1) -(long)(notestart + 7 - buf) + 1;
590 }
591 }
592 else
593 {
594 hyperobjects[hyperobjectcount].line = line + 1;
595 hyperobjects[hyperobjectcount].col =
596 calculate_len(buf + strlen(line1), notestart + 7) - 1;
597 if (tmp < buf + strlen(line1)) /* as above */
598 hyperobjects[hyperobjectcount].breakpos = -1;
599 else if ((hyperobjects[hyperobjectcount].breakpos =
600 strlen(line1)
601 -(long)(notestart + 7 - buf) + 1) == 0)
602 {
603 hyperobjects[hyperobjectcount].line--;
604 }
605 }
606 if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
607 {
608 hyperobjectcount++; /* yep, this was a good hit */
609 goodHit = 1;
610 }
611 if (!goodHit && !hyperobjectcount)
612 {
613 xfree(hyperobjects);
614 hyperobjects = 0;
615 }
616 }
617 }
618 /*****************************************************************
619 * Scan for note references of form *
620 * "* Comment:[spaces](infofile)reference." *
621 *****************************************************************/
622 else if ((tmp = strstr(notestart, ":")) != NULL)
623 {
624 char *start = 0, *end = 0, *dot = 0;
625 dot = finddot(tmp + 1, NOTE_DOT); /* find the trailing dot */
626 if ( (dot != NULL) && ( dot + 7 < dot + strlen(dot)) )
627 {
628 if (strncmp(dot, ".info)", 6) == 0)
629 dot = finddot(dot + 1, NOTE_DOT);
630 }
631 if ( ((start = strchr(tmp, '(')) != NULL)
632 && (dot != NULL)
633 && ((end = strchr(start, ')')) != NULL))
634 /* end may be found only if start is nonNULL!!! */
635 {
636 if ( (start < dot) && (end < dot) ) /* security mechanism ;) */
637 {
638 long FilenameLen =(long)(end - start - 1);
639 long NodenameLen =(long)(dot - end - 1);
640 if (!hyperobjectcount)
641 hyperobjects = xmalloc(sizeof(HyperObject));
642 else
643 {
644 hyperobjects = xrealloc(hyperobjects,
645 sizeof(HyperObject) *(hyperobjectcount + 1));
646 }
647 strncpy(hyperobjects[hyperobjectcount].file,
648 start + 1, FilenameLen);
649 hyperobjects[hyperobjectcount].file[FilenameLen] = 0;
650 strncpy(hyperobjects[hyperobjectcount].node,
651 end + 1, NodenameLen);
652 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
653 hyperobjects[hyperobjectcount].type = 3;
654 if (start < buf + strlen(line1))
655 {
656 hyperobjects[hyperobjectcount].line = line;
657 hyperobjects[hyperobjectcount].col =
658 calculate_len(buf, start);
659 if (dot < buf + strlen(line1))
660 {
661 /* if the note highlight fits in first line
662 * we don't need to break highlighting into
663 * several lines */
664 hyperobjects[hyperobjectcount].breakpos = -1;
665 }
666 else
667 {
668 /* otherwise we need it */
669 hyperobjects[hyperobjectcount].breakpos =
670 strlen(line1) -(long)(start - buf);
671 }
672 }
673 else
674 {
675 hyperobjects[hyperobjectcount].line = line + 1;
676 hyperobjects[hyperobjectcount].col =
677 calculate_len(buf + strlen(line1), start);
678 hyperobjects[hyperobjectcount].breakpos = -1;
679 }
680 hyperobjects[hyperobjectcount].nodelen =
681 strlen(hyperobjects[hyperobjectcount].node);
682 hyperobjects[hyperobjectcount].filelen =
683 strlen(hyperobjects[hyperobjectcount].file);
684 hyperobjectcount++;
685 }
686 else
687 {
688 goto handle_no_file_note_label;
689 }
690 }
691 else if (dot != NULL) /* if not cross-info reference */
692 {
693 handle_no_file_note_label:
694 {
695 long NodenameLen;
696 int goodHit = 0;
697 if (!hyperobjectcount)
698 hyperobjects = xmalloc(sizeof(HyperObject));
699 else
700 {
701 hyperobjects = xrealloc(hyperobjects,
702 sizeof(HyperObject) *(hyperobjectcount + 1));
703 }
704
705 start = tmp + 1; /* move after the padding spaces */
706 while (isspace(*start))
707 start++;
708 NodenameLen =(long)(dot - start);
709 strcpy(hyperobjects[hyperobjectcount].file, "");
710 strncpy(hyperobjects[hyperobjectcount].node,
711 start, NodenameLen);
712 hyperobjects[hyperobjectcount].node[NodenameLen] = 0;
713 hyperobjects[hyperobjectcount].type = 3;
714 hyperobjects[hyperobjectcount].nodelen =
715 strlen(hyperobjects[hyperobjectcount].node);
716 hyperobjects[hyperobjectcount].filelen =
717 strlen(hyperobjects[hyperobjectcount].file);
718 if (start < buf + strlen(line1))
719 {
720 hyperobjects[hyperobjectcount].line = line;
721 hyperobjects[hyperobjectcount].col =
722 calculate_len(buf, start);
723 if (dot < buf + strlen(line1))
724 {
725 /* if the note highlight fits in first line
726 * we don't need to break highlighting into
727 * several lines */
728 hyperobjects[hyperobjectcount].breakpos = -1;
729 }
730 else
731 {
732 /* otherwise we need it */
733 hyperobjects[hyperobjectcount].breakpos =
734 strlen(line1) -(long)(start - buf);
735 }
736 }
737 else
738 {
739 hyperobjects[hyperobjectcount].line = line + 1;
740 hyperobjects[hyperobjectcount].col =
741 calculate_len(strlen(line1) + buf, start);
742 hyperobjects[hyperobjectcount].breakpos = -1;
743 }
744 if (exists_in_tag_table(hyperobjects[hyperobjectcount].node))
745 {
746 hyperobjectcount++; /* yep, this was a good hit */
747 goodHit = 1;
748 }
749 if (!goodHit && !hyperobjectcount)
750 {
751 xfree(hyperobjects);
752 hyperobjects = 0;
753 }
754 }
755 }
756 }
757 }
758 }
759 if (notestart)
760 if (notestart + 6 < buf + strlen(buf) + 1)
761 {
762 tmp = notestart;
763 if ((notestart = strstr(notestart + 6, "*Note")) != NULL)
764 goto handlenote;
765 notestart = tmp;
766 if ((notestart = strstr(notestart + 6, "*note")) != NULL)
767 goto handlenote;
768 }
769 /******************************************************************************
770 * Try to scan for some url-like objects in single line; mainly *
771 * http://[address][space|\n|\t] *
772 * ftp://[address][space|\n|\t] *
773 * username@something.else[space|\n|\t] *
774 *****************************************************************************/
775 /* http:// */
776 urlend = line1;
777 while ((urlstart = strstr(urlend, "http://")) != NULL)
778 {
779 urlend = findurlend(urlstart); /* always successful */
780 if (!hyperobjectcount)
781 hyperobjects = xmalloc(sizeof(HyperObject));
782 else
783 {
784 hyperobjects = xrealloc(hyperobjects,
785 sizeof(HyperObject) *(hyperobjectcount + 1));
786 }
787 hyperobjects[hyperobjectcount].line = line;
788 hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
789 hyperobjects[hyperobjectcount].breakpos = -1;
790 hyperobjects[hyperobjectcount].type = 4;
791 strncpy(hyperobjects[hyperobjectcount].node, urlstart, urlend - urlstart);
792 hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
793 strcpy(hyperobjects[hyperobjectcount].file, "");
794 hyperobjects[hyperobjectcount].tagtableoffset = -1;
795 hyperobjects[hyperobjectcount].nodelen =
796 strlen(hyperobjects[hyperobjectcount].node);
797 hyperobjects[hyperobjectcount].filelen =
798 strlen(hyperobjects[hyperobjectcount].file);
799 hyperobjectcount++;
800 }
801 /* ftp:// */
802 urlend = line1;
803 while ((urlstart = strstr(urlend, "ftp://")) != NULL)
804 {
805 urlend = findurlend(urlstart); /* always successful */
806 if (!hyperobjectcount)
807 hyperobjects = xmalloc(sizeof(HyperObject));
808 else
809 {
810 hyperobjects = xrealloc(hyperobjects,
811 sizeof(HyperObject) *(hyperobjectcount + 1));
812 }
813 hyperobjects[hyperobjectcount].line = line;
814 hyperobjects[hyperobjectcount].col = calculate_len(line1, urlstart);
815 hyperobjects[hyperobjectcount].breakpos = -1;
816 hyperobjects[hyperobjectcount].type = 5;
817 strncpy(hyperobjects[hyperobjectcount].node, urlstart, urlend - urlstart);
818 hyperobjects[hyperobjectcount].node[urlend - urlstart] = 0;
819 strcpy(hyperobjects[hyperobjectcount].file, "");
820 hyperobjects[hyperobjectcount].tagtableoffset = -1;
821 hyperobjects[hyperobjectcount].nodelen =
822 strlen(hyperobjects[hyperobjectcount].node);
823 hyperobjects[hyperobjectcount].filelen =
824 strlen(hyperobjects[hyperobjectcount].file);
825 hyperobjectcount++;
826 }
827 if (initialhyperobjectcount != hyperobjectcount)
828 sort_hyperlinks_from_current_line(initialhyperobjectcount, hyperobjectcount);
829 if (buf)
830 {
831 xfree(buf);
832 buf = 0;
833 }
834 }
835