diff options
Diffstat (limited to 'src/LYList.c')
-rw-r--r-- | src/LYList.c | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/src/LYList.c b/src/LYList.c new file mode 100644 index 0000000..71633fc --- /dev/null +++ b/src/LYList.c @@ -0,0 +1,373 @@ +/* + * $LynxId: LYList.c,v 1.54 2018/06/10 20:27:01 tom Exp $ + * + * Lynx Document Reference List Support LYList.c + * ==================================== + * + * Author: FM Foteos Macrides (macrides@sci.wfbr.edu) + * + */ + +#include <HTUtils.h> +#include <HTAlert.h> +#include <LYUtils.h> +#include <GridText.h> +#include <HTParse.h> +#include <LYList.h> +#include <LYMap.h> +#include <LYClean.h> +#include <LYGlobalDefs.h> +#include <LYCharUtils.h> +#include <LYCharSets.h> +#include <LYStrings.h> +#include <LYHistory.h> + +#ifdef DIRED_SUPPORT +#include <LYUpload.h> +#include <LYLocal.h> +#endif /* DIRED_SUPPORT */ + +#include <LYexit.h> +#include <LYLeaks.h> + +/* 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<p>\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, "<lh><em>%s</em>\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, + "<li><a id=%d href=\"#%d\">form field</a> = <em>%s</em>\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, "<li><a href=\"%s\"%s>%s%s%s%s%s</a>\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</%s>\n\n<p>\n", + ((keypad_mode == NUMBERS_AS_ARROWS) ? + "ol" : "ul")); + fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ? + "ol continue" : "ul")); + fprintf(fp0, "<lh><em>%s</em>\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, "<li><a href=\"%s\">%s</a>\n", Address, Address); + + FREE(Address); + } + + fprintf(fp0, "\n</%s>\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 <A NAME=xyz HREF="#xyz"> 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; +} |