123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- /* html.c -- html-related utilities.
- $Id: html.c,v 1.43 2011-04-06 21:32:42 gray Exp $
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
- Free Software Foundation, Inc.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "system.h"
- #include "cmds.h"
- #include "files.h"
- #include "html.h"
- #include "lang.h"
- #include "makeinfo.h"
- #include "node.h"
- #include "sectioning.h"
- /* Filename to which to write list of index entries */
- char *internal_links_filename = NULL;
- FILE *internal_links_stream = NULL;
- /* Append CHAR to BUFFER, (re)allocating as necessary. We don't handle
- null characters. */
- typedef struct
- {
- unsigned size; /* allocated */
- unsigned length; /* used */
- char *buffer;
- } buffer_type;
- static buffer_type *
- init_buffer (void)
- {
- buffer_type *buf = xmalloc (sizeof (buffer_type));
- buf->length = 0;
- buf->size = 0;
- buf->buffer = NULL;
- return buf;
- }
- static void
- append_char (buffer_type *buf, int c)
- {
- buf->length++;
- if (buf->length >= buf->size)
- {
- buf->size += 100;
- buf->buffer = xrealloc (buf->buffer, buf->size);
- }
- buf->buffer[buf->length - 1] = c;
- buf->buffer[buf->length] = 0;
- }
- /* Read the cascading style-sheet file FILENAME. Write out any @import
- commands, which must come first, by the definition of css. If the
- file contains any actual css code following the @imports, return it;
- else return NULL. */
- static char *
- process_css_file (char *filename)
- {
- int c;
- int lastchar = 0;
- FILE *f;
- buffer_type *import_text = init_buffer ();
- buffer_type *inline_text = init_buffer ();
- unsigned lineno = 1;
- enum { null_state, comment_state, import_state, inline_state } state
- = null_state, prev_state;
- prev_state = null_state;
- /* read from stdin if `-' is the filename. */
- f = STREQ (filename, "-") ? stdin : fopen (filename, "r");
- if (!f)
- {
- error (_("%s: could not open --css-file: %s"), progname, filename);
- return NULL;
- }
- /* Read the file. The @import statements must come at the beginning,
- with only whitespace and comments allowed before any inline css code. */
- while ((c = getc (f)) >= 0)
- {
- if (c == '\n')
- lineno++;
- switch (state)
- {
- case null_state: /* between things */
- if (c == '@')
- { /* Only @import and @charset should switch into
- import_state, other @-commands, such as @media, should
- put us into inline_state. I don't think any other css
- @-commands start with `i' or `c', although of course
- this will break when such a command is defined. */
- int nextchar = getc (f);
- if (nextchar == 'i' || nextchar == 'c')
- {
- append_char (import_text, c);
- append_char (import_text, nextchar);
- state = import_state;
- }
- else
- {
- ungetc (nextchar, f); /* wasn't an @import */
- state = inline_state;
- }
- }
- else if (c == '/')
- { /* possible start of a comment */
- int nextchar = getc (f);
- if (nextchar == '*')
- state = comment_state;
- else
- {
- ungetc (nextchar, f); /* wasn't a comment */
- state = inline_state;
- }
- }
- else if (isspace (c))
- ; /* skip whitespace; maybe should use c_isspace? */
- else
- /* not an @import, not a comment, not whitespace: we must
- have started the inline text. */
- state = inline_state;
- if (state == inline_state)
- append_char (inline_text, c);
- if (state != null_state)
- prev_state = null_state;
- break;
- case comment_state:
- if (c == '/' && lastchar == '*')
- state = prev_state; /* end of comment */
- break; /* else ignore this comment char */
- case import_state:
- append_char (import_text, c); /* include this import char */
- if (c == ';')
- { /* done with @import */
- append_char (import_text, '\n'); /* make the output nice */
- state = null_state;
- prev_state = import_state;
- }
- break;
- case inline_state:
- /* No harm in writing out comments, so don't bother parsing
- them out, just append everything. */
- append_char (inline_text, c);
- break;
- }
- lastchar = c;
- }
- fclose (f); /* Even closing stdin should be ok, can't read it more
- than once? */
-
- /* Reached the end of the file. We should not be still in a comment. */
- if (state == comment_state)
- warning (_("%s:%d: --css-file ended in comment"), filename, lineno);
- /* Write the @import text, if any. */
- if (import_text->buffer)
- {
- add_word (import_text->buffer);
- free (import_text->buffer);
- free (import_text);
- }
- /* We're wasting the buffer struct memory, but so what. */
- return inline_text->buffer;
- }
- HSTACK *htmlstack = NULL;
- /* See html.h. */
- int html_title_written = 0;
- void
- html_output_head (void)
- {
- static const char *html_title = NULL;
- char *encoding = current_document_encoding ();
- /* The <title> should not have markup, so use text_expansion. */
- if (!html_title)
- html_title = escape_string (title ?
- text_expansion (title) : (char *) gdt("Untitled"));
- /* Make sure this is the very first string of the output document. */
- output_paragraph_offset = 0;
- add_html_block_elt_args ("<html lang=\"%s\">\n<head>\n",
- language_table[language_code].abbrev);
- /* When splitting, add current node's name to title if it's available
- and not Top. */
- if (splitting && current_node && !STREQ (current_node, "Top"))
- add_word_args ("<title>%s - %s</title>\n",
- escape_string (xstrdup (current_node)), html_title);
- else
- add_word_args ("<title>%s</title>\n", html_title);
- add_word ("<meta http-equiv=\"Content-Type\" content=\"text/html");
- if (encoding && *encoding)
- add_word_args ("; charset=%s", encoding);
-
- add_word ("\">\n");
- if (!document_description)
- document_description = html_title;
- add_word_args ("<meta name=\"description\" content=\"%s\">\n",
- document_description);
- add_word_args ("<meta name=\"generator\" content=\"makeinfo %s\">\n",
- VERSION);
- /* Navigation bar links. */
- if (!splitting)
- add_word ("<link title=\"Top\" rel=\"top\" href=\"#Top\">\n");
- else if (tag_table)
- {
- /* Always put a top link. */
- add_word ("<link title=\"Top\" rel=\"start\" href=\"index.html#Top\">\n");
- /* We already have a top link, avoid duplication. */
- if (tag_table->up && !STREQ (tag_table->up, "Top"))
- add_link (tag_table->up, "rel=\"up\"");
- if (tag_table->prev)
- add_link (tag_table->prev, "rel=\"prev\"");
- if (tag_table->next)
- add_link (tag_table->next, "rel=\"next\"");
- /* fixxme: Look for a way to put links to various indices in the
- document. Also possible candidates to be added here are First and
- Last links. */
- }
- else
- {
- /* We are splitting, but we neither have a tag_table. So this must be
- index.html. So put a link to Top. */
- add_word ("<link title=\"Top\" rel=\"start\" href=\"#Top\">\n");
- }
- add_word ("<link href=\"http://www.gnu.org/software/texinfo/\" \
- rel=\"generator-home\" title=\"Texinfo Homepage\">\n");
- if (copying_text)
- { /* It is not ideal that we include the html markup here within
- <head>, so we use text_expansion. */
- insert_string ("<!--\n");
- insert_string (text_expansion (copying_text));
- insert_string ("-->\n");
- }
- /* Put the style definitions in a comment for the sake of browsers
- that don't support <style>. */
- add_word ("<meta http-equiv=\"Content-Style-Type\" content=\"text/css\">\n");
- add_word ("<style type=\"text/css\"><!--\n");
- {
- char *css_inline = NULL;
- if (css_include)
- /* This writes out any @import commands from the --css-file,
- and returns any actual css code following the imports. */
- css_inline = process_css_file (css_include);
- /* This seems cleaner than adding <br>'s at the end of each line for
- these "roman" displays. It's hardly the end of the world if the
- browser doesn't do <style>s, in any case; they'll just come out in
- typewriter. */
- #define CSS_FONT_INHERIT "font-family:inherit"
- add_word_args (" pre.display { %s }\n", CSS_FONT_INHERIT);
- add_word_args (" pre.format { %s }\n", CSS_FONT_INHERIT);
- /* Alternatively, we could do <font size=-1> in insertion.c, but this
- way makes it easier to override. */
- #define CSS_FONT_SMALLER "font-size:smaller"
- add_word_args (" pre.smalldisplay { %s; %s }\n", CSS_FONT_INHERIT,
- CSS_FONT_SMALLER);
- add_word_args (" pre.smallformat { %s; %s }\n", CSS_FONT_INHERIT,
- CSS_FONT_SMALLER);
- add_word_args (" pre.smallexample { %s }\n", CSS_FONT_SMALLER);
- add_word_args (" pre.smalllisp { %s }\n", CSS_FONT_SMALLER);
- /* Since HTML doesn't have a sc element, we use span with a bit of
- CSS spice instead. */
- #define CSS_FONT_SMALL_CAPS "font-variant:small-caps"
- add_word_args (" span.sc { %s }\n", CSS_FONT_SMALL_CAPS);
- /* Roman (default) font class, closest we can come. */
- #define CSS_FONT_ROMAN "font-family:serif; font-weight:normal;"
- add_word_args (" span.roman { %s } \n", CSS_FONT_ROMAN);
- /* Sans serif font class. */
- #define CSS_FONT_SANSSERIF "font-family:sans-serif; font-weight:normal;"
- add_word_args (" span.sansserif { %s } \n", CSS_FONT_SANSSERIF);
- /* Write out any css code from the user's --css-file. */
- if (css_inline)
- insert_string (css_inline);
- add_word ("--></style>\n");
- }
- if (css_ref)
- add_word_args ("<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\n",
- css_ref);
-
- add_word ("</head>\n<body>\n");
- if (title && !html_title_written && titlepage_cmd_present)
- {
- add_word_args ("<h1 class=\"settitle\">%s</h1>\n", html_title);
- html_title_written = 1;
- }
- free (encoding);
- }
- /* Escape HTML special characters in the string if necessary,
- returning a pointer to a possibly newly-allocated one. */
- char *
- escape_string (char *string)
- {
- char *newstring;
- int i = 0, newlen = 0;
- do
- {
- /* Find how much to allocate. */
- switch (string[i])
- {
- case '"':
- newlen += 6; /* `"' */
- break;
- case '&':
- newlen += 5; /* `&' */
- break;
- case '<':
- case '>':
- newlen += 4; /* `<', `>' */
- break;
- default:
- newlen++;
- }
- }
- while (string[i++]);
- if (newlen == i) return string; /* Already OK. */
- newstring = xmalloc (newlen);
- i = 0;
- do
- {
- switch (string[i])
- {
- case '"':
- strcpy (newstring, """);
- newstring += 6;
- break;
- case '&':
- strcpy (newstring, "&");
- newstring += 5;
- break;
- case '<':
- strcpy (newstring, "<");
- newstring += 4;
- break;
- case '>':
- strcpy (newstring, ">");
- newstring += 4;
- break;
- default:
- newstring[0] = string[i];
- newstring++;
- }
- }
- while (string[i++]);
- return newstring - newlen;
- }
- /* Save current tag. */
- static void
- push_tag (char *tag, char *attribs)
- {
- HSTACK *newstack = xmalloc (sizeof (HSTACK));
- newstack->tag = tag;
- newstack->attribs = xstrdup (attribs);
- newstack->next = htmlstack;
- htmlstack = newstack;
- }
- /* Get last tag. */
- static void
- pop_tag (void)
- {
- HSTACK *tos = htmlstack;
- if (!tos)
- {
- line_error (_("[unexpected] no html tag to pop"));
- return;
- }
- free (htmlstack->attribs);
- htmlstack = htmlstack->next;
- free (tos);
- }
- /* Check if tag is an empty or a whitespace only element.
- If so, remove it, keeping whitespace intact. */
- int
- rollback_empty_tag (char *tag)
- {
- int check_position = output_paragraph_offset;
- int taglen = strlen (tag);
- int rollback_happened = 0;
- char *contents = ""; /* FIXME (ptr to constant, later
- assigned to malloc'd address).
- */
- char *contents_canon_white = "";
- /* If output_paragraph is empty, we cannot rollback :-\ */
- if (output_paragraph_offset <= 0)
- return 0;
- /* Find the end of the previous tag. */
- while (check_position > 0 && output_paragraph[check_position-1] != '>')
- check_position--;
- /* Save stuff between tag's end to output_paragraph's end. */
- if (check_position != output_paragraph_offset)
- {
- contents = xmalloc (output_paragraph_offset - check_position + 1);
- memcpy (contents, output_paragraph + check_position,
- output_paragraph_offset - check_position);
- contents[output_paragraph_offset - check_position] = '\0';
- contents_canon_white = xstrdup (contents);
- canon_white (contents_canon_white);
- }
- /* Find the start of the previous tag. */
- while (check_position > 0 && output_paragraph[check_position-1] != '<')
- check_position--;
- /* Check to see if this is the tag. */
- if (strncmp ((char *) output_paragraph + check_position, tag, taglen) == 0
- && (whitespace (output_paragraph[check_position + taglen])
- || output_paragraph[check_position + taglen] == '>'))
- {
- if (!contents_canon_white || !*contents_canon_white)
- {
- /* Empty content after whitespace removal, so roll it back. */
- output_paragraph_offset = check_position - 1;
- rollback_happened = 1;
- /* Original contents may not be empty (whitespace.) */
- if (contents && *contents)
- {
- insert_string (contents);
- free (contents);
- }
- }
- }
- return rollback_happened;
- }
- /* Open or close TAG according to START_OR_END. */
- void
- insert_html_tag_with_attribute (int start_or_end, char *tag, char *format, ...)
- {
- char *old_tag = NULL;
- char *old_attribs = NULL;
- char formatted_attribs[2000]; /* xx no fixed limits */
- int do_return = 0;
- extern int in_html_elt;
- if (start_or_end != START)
- pop_tag ();
- if (htmlstack)
- {
- old_tag = htmlstack->tag;
- old_attribs = htmlstack->attribs;
- }
-
- if (format)
- {
- va_list ap;
- va_start (ap, format);
- vsnprintf (formatted_attribs, sizeof (formatted_attribs), format, ap);
- va_end (ap);
- }
- else
- formatted_attribs[0] = '\0';
- /* Exception: can nest multiple spans. */
- if (htmlstack
- && STREQ (htmlstack->tag, tag)
- && !(STREQ (tag, "span") && STREQ (old_attribs, formatted_attribs)))
- do_return = 1;
- if (start_or_end == START)
- push_tag (tag, formatted_attribs);
- if (do_return)
- return;
- in_html_elt++;
- /* texinfo.tex doesn't support more than one font attribute
- at the same time. */
- if ((start_or_end == START) && old_tag && *old_tag
- && !STREQ (old_tag, "samp")
- && !rollback_empty_tag (old_tag))
- add_word_args ("</%s>", old_tag);
- if (*tag)
- {
- if (start_or_end == START)
- add_word_args (format ? "<%s %s>" : "<%s>", tag, formatted_attribs);
- else if (STREQ (tag, "samp") || !rollback_empty_tag (tag))
- /* Insert close tag only if we didn't rollback,
- in which case the opening tag is removed. */
- add_word_args ("</%s>", tag);
- }
- if ((start_or_end != START) && old_tag && *old_tag && !STREQ (old_tag, "samp"))
- add_word_args (strlen (old_attribs) > 0 ? "<%s %s>" : "<%s>",
- old_tag, old_attribs);
- in_html_elt--;
- }
- void
- insert_html_tag (int start_or_end, char *tag)
- {
- insert_html_tag_with_attribute (start_or_end, tag, NULL);
- }
- /* Output an HTML <link> to the filename for NODE, including the
- other string as extra attributes. */
- void
- add_link (char *nodename, char *attributes)
- {
- if (nodename)
- {
- char *escaped_nodename;
- add_html_elt ("<link ");
- add_word_args ("%s", attributes);
- add_word_args (" href=\"");
- add_anchor_name (nodename, 1);
- escaped_nodename = escape_string (nodename);
- add_word_args ("\" title=\"%s\">\n", escaped_nodename);
- if (escaped_nodename != nodename)
- free (escaped_nodename);
- }
- }
- /* Copy a name with characters escaped as appropriate for an anchor
- name, i.e., escape URL special characters with our _00hh convention.
- (See the manual for details on the new scheme.) */
-
- char *
- escaped_anchor_name (const char *name)
- {
- /* The factor 5 in the next allocation allows all chars to be expanded. */
- char *res = xmalloc (5 * strlen (name) + 1);
- char *d = res;
-
- for (; *name; name++)
- {
- if (cr_or_whitespace (*name))
- *d++ = '-';
- else if (! URL_SAFE_CHAR (*name))
- {
- sprintf (d, "_00%x", (unsigned char) *name);
- /* do this manually since sprintf returns char * on
- SunOS 4 and other old systems. */
- while (*d)
- d++;
- }
- else
- *d++ = *name;
- }
- *d = 0;
- return res;
- }
- /* Output NAME with characters escaped as appropriate for an anchor
- name, i.e., escape URL special characters with our _00hh convention
- if OLD is zero. (See the manual for details on the new scheme.)
-
- If OLD is nonzero, generate the node name with the 4.6-and-earlier
- convention of %hh (and more special characters output as-is, notably
- - and *). This is only so that external references to old names can
- still work with HTML generated by the new makeinfo; the gcc folks
- needed this. Our own HTML does not refer to these names. */
- void
- add_escaped_anchor_name (char *name, int old)
- {
- canon_white (name);
- if (!old && !strchr ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
- *name))
- { /* XHTML does not allow anything but an ASCII letter to start an
- identifier. Therefore kludge in this constant string if we
- have a nonletter. */
- add_word ("g_t");
- }
- if (!old)
- {
- char *expanded = escaped_anchor_name (name);
- add_word (expanded);
- free (expanded);
- }
- else for (; *name; name++)
- {
- if (cr_or_whitespace (*name))
- add_char ('-');
- else if (!URL_SAFE_CHAR (*name) && !OLD_URL_SAFE_CHAR (*name))
- /* Cast so characters with the high bit set are treated as >128,
- for example o-umlaut should be 246, not -10. */
- add_word_args ("%%%x", (unsigned char) *name);
- else
- add_char (*name);
- }
- }
- /* Insert the text for the name of a reference in an HTML anchor
- appropriate for NODENAME.
-
- If HREF is zero, generate text for name= in the new node name
- conversion convention.
- If HREF is negative, generate text for name= in the old convention.
- If HREF is positive, generate the name for an href= attribute, i.e.,
- including the `#' if it's an internal reference. */
- void
- add_anchor_name (char *nodename, int href)
- {
- if (href > 0)
- {
- if (splitting)
- add_url_name (nodename, href);
- add_char ('#');
- }
- /* Always add NODENAME, so that the reference would pinpoint the
- exact node on its file. This is so several nodes could share the
- same file, in case of file-name clashes, but also for more
- accurate browser positioning. */
- if (mbscasecmp (nodename, "(dir)") == 0)
- /* Strip the parens, but keep the original letter-case. */
- add_word_args ("%.3s", nodename + 1);
- else if (mbscasecmp (nodename, "top") == 0)
- add_word ("Top");
- else
- add_escaped_anchor_name (nodename, href < 0);
- }
- /* Insert the text for the name of a reference in an HTML url, aprropriate
- for NODENAME */
- void
- add_url_name (char *nodename, int href)
- {
- add_nodename_to_filename (nodename, href);
- }
- /* Convert non [A-Za-z0-9] characters depending on the command line options given.
- If --transliterate-file-names is specified, these are replaced with their ASCII
- phonetic transliteration. Otherwise, _00xx notation is used, where xx means the
- hexadecimal representation of the ASCII character. Also convert spaces and
- newlines to dashes. */
- static void
- fix_filename (char *filename)
- {
- int i;
- int len = strlen (filename);
- char *oldname = xstrdup (filename);
- *filename = '\0';
- for (i = 0; i < len; i++)
- {
- const char *p = lang_transliterate_char (oldname[i]);
- if (p)
- strcat (filename, p);
- else if (cr_or_whitespace (oldname[i]))
- strcat (filename, "-");
- else if (URL_SAFE_CHAR (oldname[i]))
- strncat (filename, (char *) oldname + i, 1);
- else
- {
- char *hexchar = xmalloc (6 * sizeof (char));
- sprintf (hexchar, "_00%x", (unsigned char) oldname[i]);
- strcat (filename, hexchar);
- free (hexchar);
- }
- /* Check if we are nearing boundaries. */
- if (strlen (filename) >= PATH_MAX - 20)
- break;
- }
- free (oldname);
- }
- /* As we can't look-up a (forward-referenced) nodes' html filename
- from the tentry, we take the easy way out. We assume that
- nodenames are unique, and generate the html filename from the
- nodename, that's always known. */
- static char *
- nodename_to_filename_1 (char *nodename, int href)
- {
- char *p;
- char *filename;
- char dirname[PATH_MAX];
- if (mbscasecmp (nodename, "Top") == 0)
- {
- /* We want to convert references to the Top node into
- "index.html#Top". */
- if (href)
- filename = xstrdup ("index.html"); /* "#Top" is added by our callers */
- else
- filename = xstrdup ("Top");
- }
- else if (mbscasecmp (nodename, "(dir)") == 0)
- /* We want to convert references to the (dir) node into
- "../index.html". */
- filename = xstrdup ("../index.html");
- else
- {
- filename = xmalloc (PATH_MAX);
- dirname[0] = '\0';
- *filename = '\0';
- /* Check for external reference: ``(info-document)node-name''
- Assume this node lives at: ``../info-document/node-name.html''
- We need to handle the special case (sigh): ``(info-document)'',
- ie, an external top-node, which should translate to:
- ``../info-document/info-document.html'' */
- p = nodename;
- if (*nodename == '(')
- {
- int length;
- p = strchr (nodename, ')');
- if (p == NULL)
- {
- line_error (_("[unexpected] invalid node name: `%s'"), nodename);
- xexit (1);
- }
- length = p - nodename - 1;
- if (length > 5 &&
- FILENAME_CMPN (p - 5, ".info", 5) == 0)
- length -= 5;
- /* This is for DOS, and also for Windows and GNU/Linux
- systems that might have Info files copied from a DOS 8+3
- filesystem. */
- if (length > 4 &&
- FILENAME_CMPN (p - 4, ".inf", 4) == 0)
- length -= 4;
- strcpy (filename, "../");
- strncpy (dirname, nodename + 1, length);
- *(dirname + length) = '\0';
- fix_filename (dirname);
- strcat (filename, dirname);
- strcat (filename, "/");
- p++;
- }
- /* In the case of just (info-document), there will be nothing
- remaining, and we will refer to ../info-document/, which will
- work fine. */
- strcat (filename, p);
- if (*p)
- {
- /* Hmm */
- fix_filename (filename + strlen (filename) - strlen (p));
- strcat (filename, ".html");
- }
- }
- /* Produce a file name suitable for the underlying filesystem. */
- normalize_filename (filename);
- #if 0
- /* We add ``#Nodified-filename'' anchor to external references to be
- prepared for non-split HTML support. Maybe drop this. */
- if (href && *dirname)
- {
- strcat (filename, "#");
- strcat (filename, p);
- /* Hmm, again */
- fix_filename (filename + strlen (filename) - strlen (p));
- }
- #endif
- return filename;
- }
- /* If necessary, ie, if current filename != filename of node, output
- the node name. */
- void
- add_nodename_to_filename (char *nodename, int href)
- {
- /* for now, don't check: always output filename */
- char *filename = nodename_to_filename_1 (nodename, href);
- add_word (filename);
- free (filename);
- }
- char *
- nodename_to_filename (char *nodename)
- {
- /* The callers of nodename_to_filename use the result to produce
- <a href=, so call nodename_to_filename_1 with last arg non-zero. */
- return nodename_to_filename_1 (nodename, 1);
- }
|