anchor.c (19858B)
1 /* $Id$ */ 2 #include "fm.h" 3 #include "myctype.h" 4 #include "regex.h" 5 6 #define FIRST_ANCHOR_SIZE 30 7 8 AnchorList * 9 putAnchor(AnchorList *al, char *url, char *target, Anchor **anchor_return, 10 char *referer, char *title, unsigned char key, int line, int pos) 11 { 12 int n, i, j; 13 Anchor *a; 14 BufferPoint bp; 15 if (al == NULL) { 16 al = New(AnchorList); 17 al->anchors = NULL; 18 al->nanchor = al->anchormax = 0; 19 al->acache = -1; 20 } 21 if (al->anchormax == 0) { 22 /* first time; allocate anchor buffer */ 23 al->anchors = New_N(Anchor, FIRST_ANCHOR_SIZE); 24 al->anchormax = FIRST_ANCHOR_SIZE; 25 } 26 if (al->nanchor == al->anchormax) { /* need realloc */ 27 al->anchormax *= 2; 28 al->anchors = New_Reuse(Anchor, al->anchors, al->anchormax); 29 } 30 bp.line = line; 31 bp.pos = pos; 32 n = al->nanchor; 33 if (!n || bpcmp(al->anchors[n - 1].start, bp) < 0) 34 i = n; 35 else 36 for (i = 0; i < n; i++) { 37 if (bpcmp(al->anchors[i].start, bp) >= 0) { 38 for (j = n; j > i; j--) 39 al->anchors[j] = al->anchors[j - 1]; 40 break; 41 } 42 } 43 a = &al->anchors[i]; 44 a->url = url; 45 a->target = target; 46 a->referer = referer; 47 a->title = title; 48 a->accesskey = key; 49 a->slave = FALSE; 50 a->start = bp; 51 a->end = bp; 52 al->nanchor++; 53 if (anchor_return) 54 *anchor_return = a; 55 return al; 56 } 57 58 59 Anchor * 60 registerHref(Buffer *buf, char *url, char *target, char *referer, char *title, 61 unsigned char key, int line, int pos) 62 { 63 Anchor *a; 64 buf->href = putAnchor(buf->href, url, target, &a, referer, title, key, 65 line, pos); 66 return a; 67 } 68 69 Anchor * 70 registerName(Buffer *buf, char *url, int line, int pos) 71 { 72 Anchor *a; 73 buf->name = putAnchor(buf->name, url, NULL, &a, NULL, NULL, '\0', line, 74 pos); 75 return a; 76 } 77 78 Anchor * 79 registerImg(Buffer *buf, char *url, char *title, int line, int pos) 80 { 81 Anchor *a; 82 buf->img = putAnchor(buf->img, url, NULL, &a, NULL, title, '\0', line, 83 pos); 84 return a; 85 } 86 87 Anchor * 88 registerForm(Buffer *buf, FormList *flist, struct parsed_tag *tag, int line, 89 int pos) 90 { 91 Anchor *a; 92 FormItemList *fi; 93 94 fi = formList_addInput(flist, tag); 95 if (fi == NULL) 96 return NULL; 97 buf->formitem = putAnchor(buf->formitem, (char *)fi, flist->target, &a, 98 NULL, NULL, '\0', line, pos); 99 return a; 100 } 101 102 int 103 onAnchor(Anchor *a, int line, int pos) 104 { 105 BufferPoint bp; 106 bp.line = line; 107 bp.pos = pos; 108 109 if (bpcmp(bp, a->start) < 0) 110 return -1; 111 if (bpcmp(a->end, bp) <= 0) 112 return 1; 113 return 0; 114 } 115 116 Anchor * 117 retrieveAnchor(AnchorList *al, int line, int pos) 118 { 119 Anchor *a; 120 size_t b, e; 121 int cmp; 122 123 if (al == NULL || al->nanchor == 0) 124 return NULL; 125 126 if (al->acache < 0 || al->acache >= al->nanchor) 127 al->acache = 0; 128 129 for (b = 0, e = al->nanchor - 1; b <= e; al->acache = (b + e) / 2) { 130 a = &al->anchors[al->acache]; 131 cmp = onAnchor(a, line, pos); 132 if (cmp == 0) 133 return a; 134 else if (cmp > 0) 135 b = al->acache + 1; 136 else if (al->acache == 0) 137 return NULL; 138 else 139 e = al->acache - 1; 140 } 141 return NULL; 142 } 143 144 Anchor * 145 retrieveCurrentAnchor(Buffer *buf) 146 { 147 if (buf->currentLine == NULL) 148 return NULL; 149 return retrieveAnchor(buf->href, buf->currentLine->linenumber, buf->pos); 150 } 151 152 Anchor * 153 retrieveCurrentImg(Buffer *buf) 154 { 155 if (buf->currentLine == NULL) 156 return NULL; 157 return retrieveAnchor(buf->img, buf->currentLine->linenumber, buf->pos); 158 } 159 160 Anchor * 161 retrieveCurrentForm(Buffer *buf) 162 { 163 if (buf->currentLine == NULL) 164 return NULL; 165 return retrieveAnchor(buf->formitem, 166 buf->currentLine->linenumber, buf->pos); 167 } 168 169 Anchor * 170 searchAnchor(AnchorList *al, char *str) 171 { 172 int i; 173 Anchor *a; 174 if (al == NULL) 175 return NULL; 176 for (i = 0; i < al->nanchor; i++) { 177 a = &al->anchors[i]; 178 if (a->hseq < 0) 179 continue; 180 if (!strcmp(a->url, str)) 181 return a; 182 } 183 return NULL; 184 } 185 186 Anchor * 187 searchURLLabel(Buffer *buf, char *url) 188 { 189 return searchAnchor(buf->name, url); 190 } 191 192 #ifdef USE_NNTP 193 static Anchor * 194 _put_anchor_news(Buffer *buf, char *p1, char *p2, int line, int pos) 195 { 196 Str tmp; 197 198 if (*p1 == '<') { 199 p1++; 200 if (*(p2 - 1) == '>') 201 p2--; 202 } 203 tmp = wc_Str_conv_strict(Strnew_charp_n(p1, p2 - p1), InnerCharset, 204 buf->document_charset); 205 tmp = Sprintf("news:%s", file_quote(tmp->ptr)); 206 return registerHref(buf, tmp->ptr, NULL, NO_REFERER, NULL, '\0', line, 207 pos); 208 } 209 #endif /* USE_NNTP */ 210 211 static Anchor * 212 _put_anchor_all(Buffer *buf, char *p1, char *p2, int line, int pos) 213 { 214 Str tmp; 215 216 tmp = wc_Str_conv_strict(Strnew_charp_n(p1, p2 - p1), InnerCharset, 217 buf->document_charset); 218 return registerHref(buf, url_quote(tmp->ptr), NULL, NO_REFERER, NULL, 219 '\0', line, pos); 220 } 221 222 static void 223 reseq_anchor0(AnchorList *al, short *seqmap) 224 { 225 int i; 226 Anchor *a; 227 228 if (!al) 229 return; 230 231 for (i = 0; i < al->nanchor; i++) { 232 a = &al->anchors[i]; 233 if (a->hseq >= 0) { 234 a->hseq = seqmap[a->hseq]; 235 } 236 } 237 } 238 239 /* renumber anchor */ 240 static void 241 reseq_anchor(Buffer *buf) 242 { 243 int i, j, n, nmark = (buf->hmarklist) ? buf->hmarklist->nmark : 0; 244 short *seqmap; 245 Anchor *a, *a1; 246 HmarkerList *ml = NULL; 247 248 if (!buf->href) 249 return; 250 251 n = nmark; 252 for (i = 0; i < buf->href->nanchor; i++) { 253 a = &buf->href->anchors[i]; 254 if (a->hseq == -2) 255 n++; 256 } 257 258 if (n == nmark) 259 return; 260 261 seqmap = NewAtom_N(short, n); 262 263 for (i = 0; i < n; i++) 264 seqmap[i] = i; 265 266 n = nmark; 267 for (i = 0; i < buf->href->nanchor; i++) { 268 a = &buf->href->anchors[i]; 269 if (a->hseq == -2) { 270 a->hseq = n; 271 a1 = closest_next_anchor(buf->href, NULL, a->start.pos, 272 a->start.line); 273 a1 = closest_next_anchor(buf->formitem, a1, a->start.pos, 274 a->start.line); 275 if (a1 && a1->hseq >= 0) { 276 seqmap[n] = seqmap[a1->hseq]; 277 for (j = a1->hseq; j < nmark; j++) 278 seqmap[j]++; 279 } 280 ml = putHmarker(ml, a->start.line, a->start.pos, seqmap[n]); 281 n++; 282 } 283 } 284 285 for (i = 0; i < nmark; i++) { 286 ml = putHmarker(ml, buf->hmarklist->marks[i].line, 287 buf->hmarklist->marks[i].pos, seqmap[i]); 288 } 289 buf->hmarklist = ml; 290 291 reseq_anchor0(buf->href, seqmap); 292 reseq_anchor0(buf->formitem, seqmap); 293 } 294 295 static char * 296 reAnchorPos(Buffer *buf, Line *l, char *p1, char *p2, 297 Anchor *(*anchorproc) (Buffer *, char *, char *, int, int)) 298 { 299 Anchor *a; 300 int spos, epos; 301 int i, hseq = -2; 302 303 spos = p1 - l->lineBuf; 304 epos = p2 - l->lineBuf; 305 for (i = spos; i < epos; i++) { 306 if (l->propBuf[i] & (PE_ANCHOR | PE_FORM)) 307 return p2; 308 } 309 for (i = spos; i < epos; i++) 310 l->propBuf[i] |= PE_ANCHOR; 311 while (spos > l->len && l->next && l->next->bpos) { 312 spos -= l->len; 313 epos -= l->len; 314 l = l->next; 315 } 316 while (1) { 317 a = anchorproc(buf, p1, p2, l->linenumber, spos); 318 a->hseq = hseq; 319 if (hseq == -2) { 320 reseq_anchor(buf); 321 hseq = a->hseq; 322 } 323 a->end.line = l->linenumber; 324 if (epos > l->len && l->next && l->next->bpos) { 325 a->end.pos = l->len; 326 spos = 0; 327 epos -= l->len; 328 l = l->next; 329 } 330 else { 331 a->end.pos = epos; 332 break; 333 } 334 } 335 return p2; 336 } 337 338 void 339 reAnchorWord(Buffer *buf, Line *l, int spos, int epos) 340 { 341 reAnchorPos(buf, l, &l->lineBuf[spos], &l->lineBuf[epos], _put_anchor_all); 342 } 343 344 /* search regexp and register them as anchors */ 345 /* returns error message if any */ 346 static char * 347 reAnchorAny(Buffer *buf, char *re, 348 Anchor *(*anchorproc) (Buffer *, char *, char *, int, int)) 349 { 350 Line *l; 351 char *p = NULL, *p1, *p2; 352 353 if (re == NULL || *re == '\0') { 354 return NULL; 355 } 356 if ((re = regexCompile(re, 1)) != NULL) { 357 return re; 358 } 359 for (l = MarkAllPages ? buf->firstLine : buf->topLine; l != NULL && 360 (MarkAllPages || l->linenumber < buf->topLine->linenumber + LASTLINE); 361 l = l->next) { 362 if (p && l->bpos) 363 goto next_line; 364 p = l->lineBuf; 365 for (;;) { 366 if (regexMatch(p, &l->lineBuf[l->size] - p, p == l->lineBuf) == 1) { 367 matchedPosition(&p1, &p2); 368 p = reAnchorPos(buf, l, p1, p2, anchorproc); 369 } 370 else 371 break; 372 } 373 next_line: 374 if (MarkAllPages && l->next == NULL && buf->pagerSource && 375 !(buf->bufferprop & BP_CLOSE)) 376 getNextPage(buf, PagerMax); 377 } 378 return NULL; 379 } 380 381 char * 382 reAnchor(Buffer *buf, char *re) 383 { 384 return reAnchorAny(buf, re, _put_anchor_all); 385 } 386 387 #ifdef USE_NNTP 388 char * 389 reAnchorNews(Buffer *buf, char *re) 390 { 391 return reAnchorAny(buf, re, _put_anchor_news); 392 } 393 394 char * 395 reAnchorNewsheader(Buffer *buf) 396 { 397 Line *l; 398 char *p, *p1, *p2; 399 static char *header_mid[] = { 400 "Message-Id:", "References:", "In-Reply-To:", NULL 401 }; 402 static char *header_group[] = { 403 "Newsgroups:", NULL 404 }; 405 char **header, **q; 406 int i, search = FALSE; 407 408 if (!buf || !buf->firstLine) 409 return NULL; 410 for (i = 0; i <= 1; i++) { 411 if (i == 0) { 412 regexCompile("<[!-;=?-~]+@[a-zA-Z0-9\\.\\-_]+>", 1); 413 header = header_mid; 414 } 415 else { 416 regexCompile("[a-zA-Z0-9\\.\\-_]+", 1); 417 header = header_group; 418 } 419 for (l = buf->firstLine; l != NULL && l->real_linenumber == 0; 420 l = l->next) { 421 if (l->bpos) 422 continue; 423 p = l->lineBuf; 424 if (!IS_SPACE(*p)) { 425 search = FALSE; 426 for (q = header; *q; q++) { 427 if (!strncasecmp(p, *q, strlen(*q))) { 428 search = TRUE; 429 p = strchr(p, ':') + 1; 430 break; 431 } 432 } 433 } 434 if (!search) 435 continue; 436 for (;;) { 437 if (regexMatch(p, &l->lineBuf[l->size] - p, p == l->lineBuf) 438 == 1) { 439 matchedPosition(&p1, &p2); 440 p = reAnchorPos(buf, l, p1, p2, _put_anchor_news); 441 } 442 else 443 break; 444 } 445 } 446 } 447 reseq_anchor(buf); 448 return NULL; 449 } 450 #endif /* USE_NNTP */ 451 452 #define FIRST_MARKER_SIZE 30 453 HmarkerList * 454 putHmarker(HmarkerList *ml, int line, int pos, int seq) 455 { 456 if (ml == NULL) { 457 ml = New(HmarkerList); 458 ml->marks = NULL; 459 ml->nmark = 0; 460 ml->markmax = 0; 461 ml->prevhseq = -1; 462 } 463 if (ml->markmax == 0) { 464 ml->markmax = FIRST_MARKER_SIZE; 465 ml->marks = NewAtom_N(BufferPoint, ml->markmax); 466 bzero(ml->marks, sizeof(BufferPoint) * ml->markmax); 467 } 468 if (seq + 1 > ml->nmark) 469 ml->nmark = seq + 1; 470 if (ml->nmark >= ml->markmax) { 471 ml->markmax = ml->nmark * 2; 472 ml->marks = New_Reuse(BufferPoint, ml->marks, ml->markmax); 473 } 474 ml->marks[seq].line = line; 475 ml->marks[seq].pos = pos; 476 ml->marks[seq].invalid = 0; 477 return ml; 478 } 479 480 Anchor * 481 closest_next_anchor(AnchorList *a, Anchor *an, int x, int y) 482 { 483 int i; 484 485 if (a == NULL || a->nanchor == 0) 486 return an; 487 for (i = 0; i < a->nanchor; i++) { 488 if (a->anchors[i].hseq < 0) 489 continue; 490 if (a->anchors[i].start.line > y || 491 (a->anchors[i].start.line == y && a->anchors[i].start.pos > x)) { 492 if (an == NULL || an->start.line > a->anchors[i].start.line || 493 (an->start.line == a->anchors[i].start.line && 494 an->start.pos > a->anchors[i].start.pos)) 495 an = &a->anchors[i]; 496 } 497 } 498 return an; 499 } 500 501 Anchor * 502 closest_prev_anchor(AnchorList *a, Anchor *an, int x, int y) 503 { 504 int i; 505 506 if (a == NULL || a->nanchor == 0) 507 return an; 508 for (i = 0; i < a->nanchor; i++) { 509 if (a->anchors[i].hseq < 0) 510 continue; 511 if (a->anchors[i].end.line < y || 512 (a->anchors[i].end.line == y && a->anchors[i].end.pos <= x)) { 513 if (an == NULL || an->end.line < a->anchors[i].end.line || 514 (an->end.line == a->anchors[i].end.line && 515 an->end.pos < a->anchors[i].end.pos)) 516 an = &a->anchors[i]; 517 } 518 } 519 return an; 520 } 521 522 void 523 shiftAnchorPosition(AnchorList *al, HmarkerList *hl, int line, int pos, 524 int shift) 525 { 526 Anchor *a; 527 size_t b, e, s = 0; 528 int cmp; 529 530 if (al == NULL || al->nanchor == 0) 531 return; 532 533 s = al->nanchor / 2; 534 for (b = 0, e = al->nanchor - 1; b <= e; s = (b + e + 1) / 2) { 535 a = &al->anchors[s]; 536 cmp = onAnchor(a, line, pos); 537 if (cmp == 0) 538 break; 539 else if (cmp > 0) 540 b = s + 1; 541 else if (s == 0) 542 break; 543 else 544 e = s - 1; 545 } 546 for (; s < al->nanchor; s++) { 547 a = &al->anchors[s]; 548 if (a->start.line > line) 549 break; 550 if (a->start.pos > pos) { 551 a->start.pos += shift; 552 if (hl->marks[a->hseq].line == line) 553 hl->marks[a->hseq].pos = a->start.pos; 554 } 555 if (a->end.pos >= pos) 556 a->end.pos += shift; 557 } 558 } 559 560 #ifdef USE_IMAGE 561 void 562 addMultirowsImg(Buffer *buf, AnchorList *al) 563 { 564 int i, j, k, col, ecol, pos; 565 Image *img; 566 Anchor a_img, a_href, a_form, *a; 567 Line *l, *ls; 568 569 if (al == NULL || al->nanchor == 0) 570 return; 571 for (i = 0; i < al->nanchor; i++) { 572 a_img = al->anchors[i]; 573 img = a_img.image; 574 if (a_img.hseq < 0 || !img || img->rows <= 1) 575 continue; 576 for (l = buf->firstLine; l != NULL; l = l->next) { 577 if (l->linenumber == img->y) 578 break; 579 } 580 if (!l) 581 continue; 582 if (a_img.y == a_img.start.line) 583 ls = l; 584 else { 585 for (ls = l; ls != NULL; 586 ls = (a_img.y < a_img.start.line) ? ls->next : ls->prev) { 587 if (ls->linenumber == a_img.start.line) 588 break; 589 } 590 if (!ls) 591 continue; 592 } 593 a = retrieveAnchor(buf->href, a_img.start.line, a_img.start.pos); 594 if (a) 595 a_href = *a; 596 else 597 a_href.url = NULL; 598 a = retrieveAnchor(buf->formitem, a_img.start.line, a_img.start.pos); 599 if (a) 600 a_form = *a; 601 else 602 a_form.url = NULL; 603 col = COLPOS(ls, a_img.start.pos); 604 ecol = COLPOS(ls, a_img.end.pos); 605 for (j = 0; l && j < img->rows; l = l->next, j++) { 606 if (a_img.start.line == l->linenumber) 607 continue; 608 pos = columnPos(l, col); 609 a = registerImg(buf, a_img.url, a_img.title, l->linenumber, pos); 610 a->hseq = -a_img.hseq; 611 a->slave = TRUE; 612 a->image = img; 613 a->end.pos = pos + ecol - col; 614 for (k = pos; k < a->end.pos; k++) 615 l->propBuf[k] |= PE_IMAGE; 616 if (a_href.url) { 617 a = registerHref(buf, a_href.url, a_href.target, 618 a_href.referer, a_href.title, 619 a_href.accesskey, l->linenumber, pos); 620 a->hseq = a_href.hseq; 621 a->slave = TRUE; 622 a->end.pos = pos + ecol - col; 623 for (k = pos; k < a->end.pos; k++) 624 l->propBuf[k] |= PE_ANCHOR; 625 } 626 if (a_form.url) { 627 buf->formitem = putAnchor(buf->formitem, a_form.url, 628 a_form.target, &a, NULL, NULL, '\0', 629 l->linenumber, pos); 630 a->hseq = a_form.hseq; 631 a->end.pos = pos + ecol - col; 632 } 633 } 634 img->rows = 0; 635 } 636 } 637 #endif 638 639 void 640 addMultirowsForm(Buffer *buf, AnchorList *al) 641 { 642 int i, j, k, col, ecol, pos; 643 Anchor a_form, *a; 644 FormItemList *fi; 645 Line *l, *ls; 646 647 if (al == NULL || al->nanchor == 0) 648 return; 649 for (i = 0; i < al->nanchor; i++) { 650 a_form = al->anchors[i]; 651 al->anchors[i].rows = 1; 652 if (a_form.hseq < 0 || a_form.rows <= 1) 653 continue; 654 for (l = buf->firstLine; l != NULL; l = l->next) { 655 if (l->linenumber == a_form.y) 656 break; 657 } 658 if (!l) 659 continue; 660 if (a_form.y == a_form.start.line) 661 ls = l; 662 else { 663 for (ls = l; ls != NULL; 664 ls = (a_form.y < a_form.start.line) ? ls->next : ls->prev) { 665 if (ls->linenumber == a_form.start.line) 666 break; 667 } 668 if (!ls) 669 continue; 670 } 671 fi = (FormItemList *)a_form.url; 672 col = COLPOS(ls, a_form.start.pos); 673 ecol = COLPOS(ls, a_form.end.pos); 674 for (j = 0; l && j < a_form.rows; l = l->next, j++) { 675 pos = columnPos(l, col); 676 if (j == 0) { 677 buf->hmarklist->marks[a_form.hseq].line = l->linenumber; 678 buf->hmarklist->marks[a_form.hseq].pos = pos; 679 } 680 if (a_form.start.line == l->linenumber) 681 continue; 682 buf->formitem = putAnchor(buf->formitem, a_form.url, 683 a_form.target, &a, NULL, NULL, '\0', 684 l->linenumber, pos); 685 a->hseq = a_form.hseq; 686 a->y = a_form.y; 687 a->end.pos = pos + ecol - col; 688 l->lineBuf[pos - 1] = '['; 689 l->lineBuf[a->end.pos] = ']'; 690 for (k = pos; k < a->end.pos; k++) 691 l->propBuf[k] |= PE_FORM; 692 } 693 } 694 } 695 696 char * 697 getAnchorText(Buffer *buf, AnchorList *al, Anchor *a) 698 { 699 int hseq, i; 700 Line *l; 701 Str tmp = NULL; 702 char *p, *ep; 703 704 if (!a || a->hseq < 0) 705 return NULL; 706 hseq = a->hseq; 707 l = buf->firstLine; 708 for (i = 0; i < al->nanchor; i++) { 709 a = &al->anchors[i]; 710 if (a->hseq != hseq) 711 continue; 712 for (; l; l = l->next) { 713 if (l->linenumber == a->start.line) 714 break; 715 } 716 if (!l) 717 break; 718 p = l->lineBuf + a->start.pos; 719 ep = l->lineBuf + a->end.pos; 720 for (; p < ep && IS_SPACE(*p); p++) ; 721 if (p == ep) 722 continue; 723 if (!tmp) 724 tmp = Strnew_size(ep - p); 725 else 726 Strcat_char(tmp, ' '); 727 Strcat_charp_n(tmp, p, ep - p); 728 } 729 return tmp ? tmp->ptr : NULL; 730 } 731 732 Buffer * 733 link_list_panel(Buffer *buf) 734 { 735 LinkList *l; 736 AnchorList *al; 737 Anchor *a; 738 FormItemList *fi; 739 int i; 740 char *t, *u, *p; 741 ParsedURL pu; 742 /* FIXME: gettextize? */ 743 Str tmp = Strnew_charp("<title>Link List</title>\ 744 <h1 align=center>Link List</h1>\n"); 745 746 if (buf->bufferprop & BP_INTERNAL || 747 (buf->linklist == NULL && buf->href == NULL && buf->img == NULL)) { 748 return NULL; 749 } 750 751 if (buf->linklist) { 752 Strcat_charp(tmp, "<hr><h2>Links</h2>\n<ol>\n"); 753 for (l = buf->linklist; l; l = l->next) { 754 if (l->url) { 755 parseURL2(l->url, &pu, baseURL(buf)); 756 p = parsedURL2Str(&pu)->ptr; 757 u = html_quote(p); 758 if (DecodeURL) 759 p = html_quote(url_unquote_conv(p, buf->document_charset)); 760 else 761 p = u; 762 } 763 else 764 u = p = ""; 765 if (l->type == LINK_TYPE_REL) 766 t = " [Rel]"; 767 else if (l->type == LINK_TYPE_REV) 768 t = " [Rev]"; 769 else 770 t = ""; 771 t = Sprintf("%s%s\n", l->title ? l->title : "", t)->ptr; 772 t = html_quote(t); 773 Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, "</a><br>", p, 774 "\n", NULL); 775 } 776 Strcat_charp(tmp, "</ol>\n"); 777 } 778 779 if (buf->href) { 780 Strcat_charp(tmp, "<hr><h2>Anchors</h2>\n<ol>\n"); 781 al = buf->href; 782 for (i = 0; i < al->nanchor; i++) { 783 a = &al->anchors[i]; 784 if (a->hseq < 0 || a->slave) 785 continue; 786 parseURL2(a->url, &pu, baseURL(buf)); 787 p = parsedURL2Str(&pu)->ptr; 788 u = html_quote(p); 789 if (DecodeURL) 790 p = html_quote(url_unquote_conv(p, buf->document_charset)); 791 else 792 p = u; 793 t = getAnchorText(buf, al, a); 794 t = t ? html_quote(t) : ""; 795 Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, "</a><br>", p, 796 "\n", NULL); 797 } 798 Strcat_charp(tmp, "</ol>\n"); 799 } 800 801 if (buf->img) { 802 Strcat_charp(tmp, "<hr><h2>Images</h2>\n<ol>\n"); 803 al = buf->img; 804 for (i = 0; i < al->nanchor; i++) { 805 a = &al->anchors[i]; 806 if (a->slave) 807 continue; 808 parseURL2(a->url, &pu, baseURL(buf)); 809 p = parsedURL2Str(&pu)->ptr; 810 u = html_quote(p); 811 if (DecodeURL) 812 p = html_quote(url_unquote_conv(p, buf->document_charset)); 813 else 814 p = u; 815 if (a->title && *a->title) 816 t = html_quote(a->title); 817 else if (DecodeURL) 818 t = html_quote(url_unquote_conv 819 (a->url, buf->document_charset)); 820 else 821 t = html_quote(a->url); 822 Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, "</a><br>", p, 823 "\n", NULL); 824 a = retrieveAnchor(buf->formitem, a->start.line, a->start.pos); 825 if (!a) 826 continue; 827 fi = (FormItemList *)a->url; 828 fi = fi->parent->item; 829 if (fi->parent->method == FORM_METHOD_INTERNAL && 830 !Strcmp_charp(fi->parent->action, "map") && fi->value) { 831 MapList *ml = searchMapList(buf, fi->value->ptr); 832 ListItem *mi; 833 MapArea *m; 834 if (!ml) 835 continue; 836 Strcat_charp(tmp, "<br>\n<b>Image map</b>\n<ol>\n"); 837 for (mi = ml->area->first; mi != NULL; mi = mi->next) { 838 m = (MapArea *) mi->ptr; 839 if (!m) 840 continue; 841 parseURL2(m->url, &pu, baseURL(buf)); 842 p = parsedURL2Str(&pu)->ptr; 843 u = html_quote(p); 844 if (DecodeURL) 845 p = html_quote(url_unquote_conv(p, 846 buf-> 847 document_charset)); 848 else 849 p = u; 850 if (m->alt && *m->alt) 851 t = html_quote(m->alt); 852 else if (DecodeURL) 853 t = html_quote(url_unquote_conv(m->url, 854 buf-> 855 document_charset)); 856 else 857 t = html_quote(m->url); 858 Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, 859 "</a><br>", p, "\n", NULL); 860 } 861 Strcat_charp(tmp, "</ol>\n"); 862 } 863 } 864 Strcat_charp(tmp, "</ol>\n"); 865 } 866 867 return loadHTMLString(tmp); 868 }