/* * $LynxId: LYList.c,v 1.53 2013/10/03 07:46:14 tom Exp $ * * Lynx Document Reference List Support LYList.c * ==================================== * * Author: FM Foteos Macrides (macrides@sci.wfbr.edu) * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DIRED_SUPPORT #include #include #endif /* DIRED_SUPPORT */ #include #include /* showlist - F.Macrides (macrides@sci.wfeb.edu) * -------- * Create a temporary text/html file with a list of links to * HyperText References in the current document. * * On entry * titles Set: if we want titles where available * Clear: we only get addresses. */ int showlist(DocInfo *newdoc, int titles) { int cnt; int refs, hidden_links; int result; static char tempfile[LY_MAXPATH]; static BOOLEAN last_titles = TRUE; FILE *fp0; char *Address = NULL, *Title = NULL, *cp = NULL; char *LinkTitle = NULL; /* Rel stored as property of link, not of dest */ BOOLEAN intern_w_post = FALSE; const char *desc = "unknown field or link"; void *helper; refs = HText_sourceAnchors(HTMainText); hidden_links = HText_HiddenLinkCount(HTMainText); if (refs <= 0 && hidden_links > 0 && LYHiddenLinks != HIDDENLINKS_SEPARATE) { HTUserMsg(NO_VISIBLE_REFS_FROM_DOC); return (-1); } if (refs <= 0 && hidden_links <= 0) { HTUserMsg(NO_REFS_FROM_DOC); return (-1); } if ((fp0 = InternalPageFP(tempfile, titles == last_titles)) == 0) return (-1); LYLocalFileToURL(&(newdoc->address), tempfile); LYRegisterUIPage(newdoc->address, titles ? UIP_LIST_PAGE : UIP_ADDRLIST_PAGE); last_titles = (BOOLEAN) titles; LYforce_HTML_mode = TRUE; /* force this file to be HTML */ LYforce_no_cache = TRUE; /* force this file to be new */ #ifdef USE_ADDRLIST_PAGE if (titles != TRUE) BeginInternalPage(fp0, ADDRLIST_PAGE_TITLE, LIST_PAGE_HELP); else #endif BeginInternalPage(fp0, LIST_PAGE_TITLE, LIST_PAGE_HELP); StrAllocCopy(Address, HTLoadedDocumentURL()); LYEntify(&Address, FALSE); fprintf(fp0, "%s%s

\n", gettext("References in "), (non_empty(Address) ? Address : gettext("this document:"))); FREE(Address); if (refs > 0) { fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ? "ol" : "ul")); if (hidden_links > 0) fprintf(fp0, "%s\n", gettext("Visible links:")); } if (hidden_links > 0) { if (LYHiddenLinks == HIDDENLINKS_IGNORE) hidden_links = 0; } helper = NULL; /* init */ result = 1; for (cnt = 1; cnt <= refs; cnt++) { HTChildAnchor *child = HText_childNextNumber(cnt, &helper); int value = HText_findAnchorNumber(helper); HTAnchor *dest_intl = NULL; HTAnchor *dest; HTParentAnchor *parent; char *address; const char *title; if (child == 0) { /* * child should not be 0 unless form field numbering is on and cnt * is the number of a form input field. HText_FormDescNumber() * will set desc to a description of what type of input field this * is. We'll list it to ensure that the link numbers on the list * page match the numbering in the original document, but won't * create a forward link to the form. - FM && LE * * Changed to create a fake hidden link, to get the numbering right * in connection with always treating this file as * HIDDENLINKS_MERGE in GridText.c - kw */ if (fields_are_numbered()) { HText_FormDescNumber(cnt, &desc); fprintf(fp0, "

  • form field = %s\n", cnt, cnt, desc); } } else if (value >= result) { if (track_internal_links) dest_intl = HTAnchor_followTypedLink(child, HTInternalLink); dest = (dest_intl ? dest_intl : HTAnchor_followLink(child)); parent = HTAnchor_parent(dest); if (!intern_w_post && dest_intl && HTMainAnchor && HTMainAnchor->post_data && parent->post_data && BINEQ(HTMainAnchor->post_data, parent->post_data)) { /* * Set flag to note that we had at least one internal link, if * the document from which we are generating the list has * associated POST data; after an extra check that the link * destination really has the same POST data so that we can * believe it is an internal link. */ intern_w_post = TRUE; } address = HTAnchor_address(dest); title = titles ? HTAnchor_title(parent) : NULL; if (dest_intl) { HTSprintf0(&LinkTitle, "(internal)"); } else if (titles && child->type && dest == child->dest && !StrNCmp(HTAtom_name(child->type), "RelTitle: ", 10)) { HTSprintf0(&LinkTitle, "(%s)", HTAtom_name(child->type) + 10); } else { FREE(LinkTitle); } StrAllocCopy(Address, address); FREE(address); LYEntify(&Address, TRUE); if (non_empty(title)) { LYformTitle(&Title, title); LYEntify(&Title, TRUE); if (*Title) { cp = findPoundSelector(Address); } else { FREE(Title); } } fprintf(fp0, "
  • %s%s%s%s%s\n", Address, dest_intl ? " TYPE=\"internal link\"" : "", NonNull(LinkTitle), ((HTAnchor *) parent != dest) && Title ? "in " : "", (char *) (Title ? Title : Address), (Title && cp) ? " - " : "", (Title && cp) ? (cp + 1) : ""); FREE(Address); FREE(Title); } result = value + 1; } FREE(LinkTitle); if (hidden_links > 0) { if (refs > 0) fprintf(fp0, "\n\n\n

    \n", ((keypad_mode == NUMBERS_AS_ARROWS) ? "ol" : "ul")); fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ? "ol continue" : "ul")); fprintf(fp0, "%s\n", gettext("Hidden links:")); } for (cnt = 0; cnt < hidden_links; cnt++) { StrAllocCopy(Address, HText_HiddenLinkAt(HTMainText, cnt)); LYEntify(&Address, FALSE); if (isEmpty(Address)) { FREE(Address); continue; } fprintf(fp0, "

  • %s\n", Address, Address); FREE(Address); } fprintf(fp0, "\n\n", ((keypad_mode == NUMBERS_AS_ARROWS) ? "ol" : "ul")); EndInternalPage(fp0); LYCloseTempFP(fp0); /* * Make necessary changes to newdoc before returning to caller. If the * intern_w_post flag is set, we keep the POST data in newdoc that have * been passed in. They should be the same as in the loaded document for * which we generated the list. In that case the file we have written will * be associated with the same POST data when it is loaded after we are * done here, so that following one of the links we have marked as * "internal link" can lead back to the underlying document with the right * address+post_data combination. - kw */ if (intern_w_post) { newdoc->internal_link = TRUE; } else { LYFreePostData(newdoc); newdoc->internal_link = FALSE; } newdoc->isHEAD = FALSE; newdoc->safe = FALSE; return (0); } static int print_refs(FILE *fp, int titles, int refs) { int result = 0; int cnt; int value; char *address = NULL; const char *desc = gettext("unknown field or link"); void *helper = NULL; /* init */ for (cnt = 1; cnt <= refs; cnt++) { HTChildAnchor *child = HText_childNextNumber(cnt, &helper); HTAnchor *dest; HTParentAnchor *parent; const char *title; int counter = result + 1; if (child == 0) { /* * child should not be 0 unless form field numbering is on and * cnt is the number of a form input field. * HText_FormDescNumber() will set desc to a description of * what type of input field this is. We'll create a * within-document link to ensure that the link numbers on the * list page match the numbering in the original document, but * won't create a forward link to the form. - FM && LE */ if (fields_are_numbered()) { HText_FormDescNumber(cnt, &desc); fprintf(fp, "%4d. form field = %s\n", counter, desc); } } else { dest = HTAnchor_followLink(child); /* * Ignore if child anchor points to itself, i.e., we had something * like and it is not treated as a hidden * link. Useful if someone 'P'rints the List Page (which isn't a * very useful action to do, but anyway...) - kw */ if (dest != (HTAnchor *) child) { parent = HTAnchor_parent(dest); title = titles ? HTAnchor_title(parent) : NULL; if (links_are_numbered()) { value = HText_findAnchorNumber(helper); if (value <= result) continue; fprintf(fp, "%4d. ", value); } if (((HTAnchor *) parent != dest) && title) { fprintf(fp, "in "); } if (title) { fprintf(fp, "%s\n", title); } else { address = HTAnchor_short_address(dest); if (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) { (void) HTUnEscape(address); } fprintf(fp, "%s\n", address); FREE(address); } } } if (counter > result) result = counter; #ifdef VMS if (HadVMSInterrupt) break; #endif /* VMS */ } return result; } static void print_hidden_refs(FILE *fp, int refs, int hidden_links) { int cnt; char *address = NULL; fprintf(fp, "%s %s\n", ((refs > 0) ? "\n" : ""), gettext("Hidden links:")); for (cnt = 0; cnt < hidden_links; cnt++) { StrAllocCopy(address, HText_HiddenLinkAt(HTMainText, cnt)); if (isEmpty(address)) { FREE(address); continue; } if (links_are_numbered()) fprintf(fp, "%4d. ", ((cnt + 1) + refs)); fprintf(fp, "%s\n", address); FREE(address); #ifdef VMS if (HadVMSInterrupt) break; #endif /* VMS */ } } /* printlist - F.Macrides (macrides@sci.wfeb.edu) * --------- * Print a text/plain list of HyperText References * in the current document. * * On entry * titles Set: if we want titles where available * Clear: we only get addresses. */ void printlist(FILE *fp, int titles) { int refs, hidden_links; refs = HText_sourceAnchors(HTMainText); if (refs > 0 || LYHiddenLinks == HIDDENLINKS_SEPARATE) { hidden_links = HText_HiddenLinkCount(HTMainText); if (refs > 0 || hidden_links > 0) { if (links_are_numbered() || fields_are_numbered()) fprintf(fp, "\n%s\n\n", gettext("References")); if (LYHiddenLinks == HIDDENLINKS_IGNORE) hidden_links = 0; if (hidden_links > 0) { fprintf(fp, " %s\n", gettext("Visible links")); } refs = print_refs(fp, titles, refs) + 1; if (hidden_links > 0) { print_hidden_refs(fp, refs, hidden_links); } } } LYPrintImgMaps(fp); return; }