General configurability upgrade for the info back end.
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 23 Apr 2004 18:23:05 +0000 (18:23 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 23 Apr 2004 18:23:05 +0000 (18:23 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/halibut@4131 cda61777-01e9-0310-a592-d414129be87e

bk_info.c
doc/index.but
doc/output.but

index d513587..5c05817 100644 (file)
--- a/bk_info.c
+++ b/bk_info.c
@@ -3,8 +3,6 @@
  * 
  * Possible future work:
  * 
- *  - configurable indentation, bullets, emphasis, quotes etc?
- * 
  *  - configurable choice of how to allocate node names?
  *     + possibly a template-like approach, choosing node names to
  *      be the full section title or perhaps the internal keyword?
@@ -34,6 +32,13 @@ typedef struct {
     char *filename;
     int maxfilesize;
     int charset;
+    int listindentbefore, listindentafter;
+    int indent_code, width, index_width;
+    wchar_t *bullet, *listsuffix;
+    wchar_t *startemph, *endemph;
+    wchar_t *lquote, *rquote;
+    wchar_t *sectsuffix, *underline;
+    wchar_t *rule;
 } infoconfig;
 
 typedef struct {
@@ -66,23 +71,24 @@ static int info_rdadds(info_data *, wchar_t const *);
 static int info_rdaddc(info_data *, char);
 static int info_rdaddsc(info_data *, char const *);
 
-static void info_heading(info_data *, word *, word *, int);
-static void info_rule(info_data *, int, int);
+static void info_heading(info_data *, word *, word *, int, infoconfig *);
+static void info_rule(info_data *, int, int, infoconfig *);
 static void info_para(info_data *, word *, wchar_t *, word *, keywordlist *,
-                     int, int, int);
+                     int, int, int, infoconfig *);
 static void info_codepara(info_data *, word *, int, int);
-static void info_versionid(info_data *, word *);
-static void info_menu_item(info_data *, node *, paragraph *);
+static void info_versionid(info_data *, word *, infoconfig *);
+static void info_menu_item(info_data *, node *, paragraph *, infoconfig *);
 static word *info_transform_wordlist(word *, keywordlist *);
 static int info_check_index(word *, node *, indexdata *);
 
-static int info_rdaddwc(info_data *, word *, word *, int);
+static int info_rdaddwc(info_data *, word *, word *, int, infoconfig *);
 
 static node *info_node_new(char *name, int charset);
-static char *info_node_name(paragraph *p, int charset);
+static char *info_node_name(paragraph *p, infoconfig *);
 
 static infoconfig info_configure(paragraph *source) {
     infoconfig ret;
+    paragraph *p;
 
     /*
      * Defaults.
@@ -90,22 +96,113 @@ static infoconfig info_configure(paragraph *source) {
     ret.filename = dupstr("output.info");
     ret.maxfilesize = 64 << 10;
     ret.charset = CS_ASCII;
+    ret.width = 70;
+    ret.listindentbefore = 1;
+    ret.listindentafter = 3;
+    ret.indent_code = 2;
+    ret.index_width = 40;
+    ret.listsuffix = L".";
+    ret.bullet = L"\x2022\0-\0\0";
+    ret.rule = L"\x2500\0-\0\0";
+    ret.startemph = L"_\0_\0\0";
+    ret.endemph = uadv(ret.startemph);
+    ret.lquote = L"\x2018\0\x2019\0`\0'\0\0";
+    ret.rquote = uadv(ret.lquote);
+    ret.sectsuffix = L": ";
+    ret.underline = L"\x203E\0-\0\0";
+
+    /*
+     * Two-pass configuration so that we can pick up global config
+     * (e.g. `quotes') before having it overridden by specific
+     * config (`info-quotes'), irrespective of the order in which
+     * they occur.
+     */
+    for (p = source; p; p = p->next) {
+       if (p->type == para_Config) {
+           if (!ustricmp(p->keyword, L"quotes")) {
+               if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) {
+                   ret.lquote = uadv(p->keyword);
+                   ret.rquote = uadv(ret.lquote);
+               }
+           }
+       }
+    }
 
-    for (; source; source = source->next) {
-       if (source->type == para_Config) {
-           if (!ustricmp(source->keyword, L"info-filename")) {
+    for (p = source; p; p = p->next) {
+       if (p->type == para_Config) {
+           if (!ustricmp(p->keyword, L"info-filename")) {
                sfree(ret.filename);
-               ret.filename = dupstr(adv(source->origkeyword));
-           } else if (!ustricmp(source->keyword, L"info-charset")) {
-               char *csname = utoa_dup(uadv(source->keyword), CS_ASCII);
+               ret.filename = dupstr(adv(p->origkeyword));
+           } else if (!ustricmp(p->keyword, L"info-charset")) {
+               char *csname = utoa_dup(uadv(p->keyword), CS_ASCII);
                ret.charset = charset_from_localenc(csname);
                sfree(csname);
-           } else if (!ustricmp(source->keyword, L"info-max-file-size")) {
-               ret.maxfilesize = utoi(uadv(source->keyword));
+           } else if (!ustricmp(p->keyword, L"info-max-file-size")) {
+               ret.maxfilesize = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-width")) {
+               ret.width = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-indent-code")) {
+               ret.indent_code = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-index-width")) {
+               ret.index_width = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-list-indent")) {
+               ret.listindentbefore = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-listitem-indent")) {
+               ret.listindentafter = utoi(uadv(p->keyword));
+           } else if (!ustricmp(p->keyword, L"info-section-suffix")) {
+               ret.sectsuffix = uadv(p->keyword);
+           } else if (!ustricmp(p->keyword, L"info-underline")) {
+               ret.underline = uadv(p->keyword);
+           } else if (!ustricmp(p->keyword, L"info-bullet")) {
+               ret.bullet = uadv(p->keyword);
+           } else if (!ustricmp(p->keyword, L"info-rule")) {
+               ret.rule = uadv(p->keyword);
+           } else if (!ustricmp(p->keyword, L"info-list-suffix")) {
+               ret.listsuffix = uadv(p->keyword);
+           } else if (!ustricmp(p->keyword, L"info-emphasis")) {
+               if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) {
+                   ret.startemph = uadv(p->keyword);
+                   ret.endemph = uadv(ret.startemph);
+               }
+           } else if (!ustricmp(p->keyword, L"info-quotes")) {
+               if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) {
+                   ret.lquote = uadv(p->keyword);
+                   ret.rquote = uadv(ret.lquote);
+               }
            }
        }
     }
 
+    /*
+     * Now process fallbacks on quote characters, underlines, the
+     * rule character, the emphasis characters, and bullets.
+     */
+    while (*uadv(ret.rquote) && *uadv(uadv(ret.rquote)) &&
+          (!cvt_ok(ret.charset, ret.lquote) ||
+           !cvt_ok(ret.charset, ret.rquote))) {
+       ret.lquote = uadv(ret.rquote);
+       ret.rquote = uadv(ret.lquote);
+    }
+
+    while (*uadv(ret.endemph) && *uadv(uadv(ret.endemph)) &&
+          (!cvt_ok(ret.charset, ret.startemph) ||
+           !cvt_ok(ret.charset, ret.endemph))) {
+       ret.startemph = uadv(ret.endemph);
+       ret.endemph = uadv(ret.startemph);
+    }
+
+    while (*ret.underline && *uadv(ret.underline) &&
+          !cvt_ok(ret.charset, ret.underline))
+       ret.underline = uadv(ret.underline);
+
+    while (*ret.bullet && *uadv(ret.bullet) &&
+          !cvt_ok(ret.charset, ret.bullet))
+       ret.bullet = uadv(ret.bullet);
+
+    while (*ret.rule && *uadv(ret.rule) &&
+          !cvt_ok(ret.charset, ret.rule))
+       ret.rule = uadv(ret.rule);
+
     return ret;
 }
 
@@ -130,12 +227,6 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
     word bullet;
     FILE *fp;
 
-    /*
-     * FIXME: possibly configurability?
-     */
-    int width = 70, listindentbefore = 1, listindentafter = 3;
-    int indent_code = 2, index_width = 40;
-
     IGNORE(unused);
 
     conf = info_configure(sourceform);
@@ -158,7 +249,7 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
            node *newnode, *upnode;
            char *nodename;
 
-           nodename = info_node_name(p, conf.charset);
+           nodename = info_node_name(p, &conf);
            newnode = info_node_new(nodename, conf.charset);
            sfree(nodename);
 
@@ -196,7 +287,7 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
            ii->nnodes = ii->nodesize = 0;
            ii->nodes = NULL;
 
-           ii->length = info_rdaddwc(&id, entry->text, NULL, FALSE);
+           ii->length = info_rdaddwc(&id, entry->text, NULL, FALSE, &conf);
 
            ii->text = id.output.text;
 
@@ -259,11 +350,11 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
     for (p = sourceform; p; p = p->next)
        if (p->type == para_Copyright)
            info_para(&intro_text, NULL, NULL, p->words, keywords,
-                     0, 0, width);
+                     0, 0, conf.width, &conf);
 
     for (p = sourceform; p; p = p->next)
        if (p->type == para_VersionID)
-           info_versionid(&intro_text, p->words);
+           info_versionid(&intro_text, p->words, &conf);
 
     if (intro_text.output.text[intro_text.output.pos-1] != '\n')
        info_rdaddc(&intro_text, '\n');
@@ -271,9 +362,9 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
     /* Do the title */
     for (p = sourceform; p; p = p->next)
        if (p->type == para_Title)
-           info_heading(&topnode->text, NULL, p->words, width);
+           info_heading(&topnode->text, NULL, p->words, conf.width, &conf);
 
-    nestindent = listindentbefore + listindentafter;
+    nestindent = conf.listindentbefore + conf.listindentafter;
     nesting = 0;
 
     currnode = topnode;
@@ -325,15 +416,15 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
            info_rdaddsc(&currnode->up->text, "* Menu:\n\n");
            currnode->up->started_menu = TRUE;
        }
-       info_menu_item(&currnode->up->text, currnode, p);
+       info_menu_item(&currnode->up->text, currnode, p, &conf);
 
        has_index |= info_check_index(p->words, currnode, idx);
-       info_heading(&currnode->text, p->kwtext, p->words, width);
+       info_heading(&currnode->text, p->kwtext, p->words, conf.width, &conf);
        nesting = 0;
        break;
 
       case para_Rule:
-       info_rule(&currnode->text, nesting, width - nesting);
+       info_rule(&currnode->text, nesting, conf.width - nesting, &conf);
        break;
 
       case para_Normal:
@@ -348,21 +439,21 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
            bullet.next = NULL;
            bullet.alt = NULL;
            bullet.type = word_Normal;
-           bullet.text = L"-";        /* FIXME: configurability */
+           bullet.text = conf.bullet;
            prefix = &bullet;
            prefixextra = NULL;
-           indentb = listindentbefore;
-           indenta = listindentafter;
+           indentb = conf.listindentbefore;
+           indenta = conf.listindentafter;
        } else if (p->type == para_NumberedList) {
            prefix = p->kwtext;
-           prefixextra = L".";        /* FIXME: configurability */
-           indentb = listindentbefore;
-           indenta = listindentafter;
+           prefixextra = conf.listsuffix;
+           indentb = conf.listindentbefore;
+           indenta = conf.listindentafter;
        } else if (p->type == para_Description) {
            prefix = NULL;
            prefixextra = NULL;
-           indentb = listindentbefore;
-           indenta = listindentafter;
+           indentb = conf.listindentbefore;
+           indenta = conf.listindentafter;
        } else {
            prefix = NULL;
            prefixextra = NULL;
@@ -382,7 +473,7 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
        }
        info_para(&currnode->text, prefix, prefixextra, body, keywords,
                  nesting + indentb, indenta,
-                 width - nesting - indentb - indenta);
+                 conf.width - nesting - indentb - indenta, &conf);
        if (wp) {
            wp->next = NULL;
            free_word_list(body);
@@ -391,8 +482,8 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
 
       case para_Code:
        info_codepara(&currnode->text, p->words,
-                     nesting + indent_code,
-                     width - nesting - 2 * indent_code);
+                     nesting + conf.indent_code,
+                     conf.width - nesting - 2 * conf.indent_code);
        break;
     }
 
@@ -413,7 +504,7 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
 
        info_rdaddsc(&newnode->text, "Index\n-----\n\n");
 
-       info_menu_item(&topnode->text, newnode, NULL);
+       info_menu_item(&topnode->text, newnode, NULL, &conf);
 
        for (i = 0; (entry = index234(idx->entries, i)) != NULL; i++) {
            info_idx *ii = (info_idx *)entry->backend_data;
@@ -427,9 +518,9 @@ void info_backend(paragraph *sourceform, keywordlist *keywords,
                 */
                if (j == 0)
                    info_rdaddsc(&newnode->text, ii->text);
-               for (k = (j ? 0 : ii->length); k < index_width; k++)
+               for (k = (j ? 0 : ii->length); k < conf.index_width-2; k++)
                    info_rdaddc(&newnode->text, ' ');
-               info_rdaddsc(&newnode->text, "   *Note ");
+               info_rdaddsc(&newnode->text, "  *Note ");
                info_rdaddsc(&newnode->text, ii->nodes[j]->name);
                info_rdaddsc(&newnode->text, "::\n");
            }
@@ -657,7 +748,8 @@ static word *info_transform_wordlist(word *words, keywordlist *keywords)
     return ret;
 }
 
-static int info_rdaddwc(info_data *id, word *words, word *end, int xrefs) {
+static int info_rdaddwc(info_data *id, word *words, word *end, int xrefs,
+                       infoconfig *cfg) {
     int ret = 0;
 
     for (; words && words != end; words = words->next) switch (words->type) {
@@ -684,30 +776,30 @@ static int info_rdaddwc(info_data *id, word *words, word *end, int xrefs) {
        if (towordstyle(words->type) == word_Emph &&
            (attraux(words->aux) == attr_First ||
             attraux(words->aux) == attr_Only))
-           ret += info_rdadd(id, L'_');      /* FIXME: configurability */
+           ret += info_rdadds(id, cfg->startemph);
        else if (towordstyle(words->type) == word_Code &&
                 (attraux(words->aux) == attr_First ||
                  attraux(words->aux) == attr_Only))
-           ret += info_rdadd(id, L'`');      /* FIXME: configurability */
+           ret += info_rdadds(id, cfg->lquote);
        if (removeattr(words->type) == word_Normal) {
            if (cvt_ok(id->charset, words->text) || !words->alt)
                ret += info_rdadds(id, words->text);
            else
-               ret += info_rdaddwc(id, words->alt, NULL, FALSE);
+               ret += info_rdaddwc(id, words->alt, NULL, FALSE, cfg);
        } else if (removeattr(words->type) == word_WhiteSpace) {
            ret += info_rdadd(id, L' ');
        } else if (removeattr(words->type) == word_Quote) {
-           ret += info_rdadd(id, quoteaux(words->aux) == quote_Open ? L'`' : L'\'');
-                                      /* FIXME: configurability */
+           ret += info_rdadds(id, quoteaux(words->aux) == quote_Open ?
+                              cfg->lquote : cfg->rquote);
        }
        if (towordstyle(words->type) == word_Emph &&
            (attraux(words->aux) == attr_Last ||
             attraux(words->aux) == attr_Only))
-           ret += info_rdadd(id, L'_');     /* FIXME: configurability */
+           ret += info_rdadds(id, cfg->endemph);
        else if (towordstyle(words->type) == word_Code &&
                 (attraux(words->aux) == attr_Last ||
                  attraux(words->aux) == attr_Only))
-           ret += info_rdadd(id, L'\'');     /* FIXME: configurability */
+           ret += info_rdadds(id, cfg->rquote);
        break;
 
       case word_UpperXref:
@@ -727,18 +819,21 @@ static int info_rdaddwc(info_data *id, word *words, word *end, int xrefs) {
     return ret;
 }
 
-static int info_width_internal(word *words, int xrefs, int charset);
+static int info_width_internal(word *words, int xrefs, infoconfig *cfg);
 
-static int info_width_internal_list(word *words, int xrefs, int charset) {
+static int info_width_internal_list(word *words, int xrefs, infoconfig *cfg) {
     int w = 0;
     while (words) {
-       w += info_width_internal(words, xrefs, charset);
+       w += info_width_internal(words, xrefs, cfg);
        words = words->next;
     }
     return w;
 }
 
-static int info_width_internal(word *words, int xrefs, int charset) {
+static int info_width_internal(word *words, int xrefs, infoconfig *cfg) {
+    int wid;
+    int attr;
+
     switch (words->type) {
       case word_HyperLink:
       case word_HyperEnd:
@@ -746,18 +841,44 @@ static int info_width_internal(word *words, int xrefs, int charset) {
       case word_IndexRef:
        return 0;
 
+      case word_UpperXref:
+      case word_LowerXref:
+       if (xrefs && words->private_data) {
+           /* "*Note " plus "::" comes to 8 characters */
+           return 8 + strwid(((node *)words->private_data)->name,
+                             cfg->charset);
+       } else
+           return 0;
+    }
+
+    assert(words->type < word_internal_endattrs);
+
+    wid = 0;
+    attr = towordstyle(words->type);
+
+    if (attr == word_Emph || attr == word_Code) {
+       if (attraux(words->aux) == attr_Only ||
+           attraux(words->aux) == attr_First)
+           wid += ustrwid(attr == word_Emph ? cfg->startemph : cfg->lquote,
+                          cfg->charset);
+    }
+    if (attr == word_Emph || attr == word_Code) {
+       if (attraux(words->aux) == attr_Only ||
+           attraux(words->aux) == attr_Last)
+           wid += ustrwid(attr == word_Emph ? cfg->startemph : cfg->lquote,
+                          cfg->charset);
+    }
+
+    switch (words->type) {
       case word_Normal:
       case word_Emph:
       case word_Code:
       case word_WeakCode:
-       return (((words->type == word_Emph ||
-                 words->type == word_Code)
-                ? (attraux(words->aux) == attr_Only ? 2 :
-                   attraux(words->aux) == attr_Always ? 0 : 1)
-                : 0) +
-               (cvt_ok(charset, words->text) || !words->alt ?
-                ustrwid(words->text, charset) :
-                info_width_internal_list(words->alt, xrefs, charset)));
+       if (cvt_ok(cfg->charset, words->text) || !words->alt)
+           wid += ustrwid(words->text, cfg->charset);
+       else
+           wid += info_width_internal_list(words->alt, xrefs, cfg);
+       return wid;
 
       case word_WhiteSpace:
       case word_EmphSpace:
@@ -769,54 +890,50 @@ static int info_width_internal(word *words, int xrefs, int charset) {
       case word_WkCodeQuote:
        assert(words->type != word_CodeQuote &&
               words->type != word_WkCodeQuote);
-       return (((towordstyle(words->type) == word_Emph ||
-                 towordstyle(words->type) == word_Code)
-                ? (attraux(words->aux) == attr_Only ? 2 :
-                   attraux(words->aux) == attr_Always ? 0 : 1)
-                : 0) + 1);
-
-      case word_UpperXref:
-      case word_LowerXref:
-       if (xrefs && words->private_data) {
-           /* "*Note " plus "::" comes to 8 characters */
-           return 8 + strwid(((node *)words->private_data)->name, charset);
-       }
-       break;
+       if (removeattr(words->type) == word_Quote) {
+           if (quoteaux(words->aux) == quote_Open)
+               wid += ustrwid(cfg->lquote, cfg->charset);
+           else
+               wid += ustrwid(cfg->rquote, cfg->charset);
+       } else
+           wid++;                     /* space */
     }
-    return 0;                         /* should never happen */
+    return wid;
 }
 
 static int info_width_noxrefs(void *ctx, word *words)
 {
-    return info_width_internal(words, FALSE, *(int *)ctx);
+    return info_width_internal(words, FALSE, (infoconfig *)ctx);
 }
 static int info_width_xrefs(void *ctx, word *words)
 {
-    return info_width_internal(words, TRUE, *(int *)ctx);
+    return info_width_internal(words, TRUE, (infoconfig *)ctx);
 }
 
 static void info_heading(info_data *text, word *tprefix,
-                        word *words, int width) {
+                        word *words, int width, infoconfig *cfg) {
     int length;
     int firstlinewidth, wrapwidth;
     wrappedline *wrapping, *p;
 
     length = 0;
     if (tprefix) {
-       length += info_rdaddwc(text, tprefix, NULL, FALSE);
-       length += info_rdadds(text, L": ");/* FIXME: configurability */
+       length += info_rdaddwc(text, tprefix, NULL, FALSE, cfg);
+       length += info_rdadds(text, cfg->sectsuffix);
     }
 
     wrapwidth = width;
     firstlinewidth = width - length;
 
     wrapping = wrap_para(words, firstlinewidth, wrapwidth,
-                        info_width_noxrefs, &text->charset, 0);
+                        info_width_noxrefs, cfg, 0);
     for (p = wrapping; p; p = p->next) {
-       length += info_rdaddwc(text, p->begin, p->end, FALSE);
+       length += info_rdaddwc(text, p->begin, p->end, FALSE, cfg);
        info_rdadd(text, L'\n');
-       while (length--)
-           info_rdadd(text, L'-');  /* FIXME: configurability */
+       while (length > 0) {
+           info_rdadds(text, cfg->underline);
+           length -= ustrwid(cfg->underline, cfg->charset);
+       }
        info_rdadd(text, L'\n');
        length = 0;
     }
@@ -824,16 +941,20 @@ static void info_heading(info_data *text, word *tprefix,
     info_rdadd(text, L'\n');
 }
 
-static void info_rule(info_data *text, int indent, int width) {
+static void info_rule(info_data *text, int indent, int width, infoconfig *cfg)
+{
     while (indent--) info_rdadd(text, L' ');
-    while (width--) info_rdadd(text, L'-');
+    while (width > 0) {
+       info_rdadds(text, cfg->rule);
+       width -= ustrwid(cfg->rule, cfg->charset);
+    }
     info_rdadd(text, L'\n');
     info_rdadd(text, L'\n');
 }
 
 static void info_para(info_data *text, word *prefix, wchar_t *prefixextra,
-                     word *input, keywordlist *keywords,
-                     int indent, int extraindent, int width) {
+                     word *input, keywordlist *keywords, int indent,
+                     int extraindent, int width, infoconfig *cfg) {
     wrappedline *wrapping, *p;
     word *words;
     int e;
@@ -845,7 +966,7 @@ static void info_para(info_data *text, word *prefix, wchar_t *prefixextra,
     if (prefix) {
        for (i = 0; i < indent; i++)
            info_rdadd(text, L' ');
-       e = info_rdaddwc(text, prefix, NULL, FALSE);
+       e = info_rdaddwc(text, prefix, NULL, FALSE, cfg);
        if (prefixextra)
            e += info_rdadds(text, prefixextra);
        /* If the prefix is too long, shorten the first line to fit. */
@@ -863,11 +984,11 @@ static void info_para(info_data *text, word *prefix, wchar_t *prefixextra,
        e = indent + extraindent;
 
     wrapping = wrap_para(words, firstlinewidth, width, info_width_xrefs,
-                        &text->charset, 0);
+                        cfg, 0);
     for (p = wrapping; p; p = p->next) {
        for (i = 0; i < e; i++)
            info_rdadd(text, L' ');
-       info_rdaddwc(text, p->begin, p->end, TRUE);
+       info_rdaddwc(text, p->begin, p->end, TRUE, cfg);
        info_rdadd(text, L'\n');
        e = indent + extraindent;
     }
@@ -893,9 +1014,9 @@ static void info_codepara(info_data *text, word *words,
     info_rdadd(text, L'\n');
 }
 
-static void info_versionid(info_data *text, word *words) {
-    info_rdadd(text, L'[');                   /* FIXME: configurability */
-    info_rdaddwc(text, words, NULL, FALSE);
+static void info_versionid(info_data *text, word *words, infoconfig *cfg) {
+    info_rdadd(text, L'[');
+    info_rdaddwc(text, words, NULL, FALSE, cfg);
     info_rdadds(text, L"]\n");
 }
 
@@ -913,13 +1034,14 @@ static node *info_node_new(char *name, int charset)
     return n;
 }
 
-static char *info_node_name(paragraph *par, int charset)
+static char *info_node_name(paragraph *par, infoconfig *cfg)
 {
     info_data id = EMPTY_INFO_DATA;
     char *p, *q;
 
-    id.charset = charset;
-    info_rdaddwc(&id, par->kwtext ? par->kwtext : par->words, NULL, FALSE);
+    id.charset = cfg->charset;
+    info_rdaddwc(&id, par->kwtext ? par->kwtext : par->words,
+                NULL, FALSE, cfg);
     info_rdaddsc(&id, NULL);
 
     /*
@@ -940,7 +1062,8 @@ static char *info_node_name(paragraph *par, int charset)
     return id.output.text;
 }
 
-static void info_menu_item(info_data *text, node *n, paragraph *p)
+static void info_menu_item(info_data *text, node *n, paragraph *p,
+                          infoconfig *cfg)
 {
     /*
      * FIXME: Depending on how we're doing node names in this info
@@ -960,7 +1083,7 @@ static void info_menu_item(info_data *text, node *n, paragraph *p)
     info_rdaddsc(text, "::");
     if (p) {
        info_rdaddc(text, ' ');
-       info_rdaddwc(text, p->words, NULL, FALSE);
+       info_rdaddwc(text, p->words, NULL, FALSE, cfg);
     }
     info_rdaddc(text, '\n');
 }
@@ -1026,7 +1149,7 @@ static int info_rdaddsc(info_data *d, char const *cs)
 
     if (cs) {
        rdaddsc(&d->output, cs);
-       return strlen(cs);
+       return strwid(cs, d->charset);
     } else
        return 0;
 }
index c51a85a..f57f51b 100644 (file)
 \IM{\\cfg\{info-max-file-size\}} \c{info-max-file-size} configuration directive
 \IM{\\cfg\{info-max-file-size\}} \cw{\\cfg\{info-max-file-size\}}
 
+\IM{\\cfg\{info-width\}} \c{info-width} configuration directive
+\IM{\\cfg\{info-width\}} \cw{\\cfg\{info-width\}}
+
+\IM{\\cfg\{info-indent-code\}} \c{info-indent-code} configuration
+directive
+\IM{\\cfg\{info-indent-code\}} \cw{\\cfg\{info-indent-code\}}
+
+\IM{\\cfg\{info-index-width\}} \c{info-index-width} configuration
+directive
+\IM{\\cfg\{info-index-width\}} \cw{\\cfg\{info-index-width\}}
+
+\IM{\\cfg\{info-list-indent\}} \c{info-list-indent} configuration
+directive
+\IM{\\cfg\{info-list-indent\}} \cw{\\cfg\{info-list-indent\}}
+
+\IM{\\cfg\{info-listitem-indent\}} \c{info-listitem-indent}
+configuration directive
+\IM{\\cfg\{info-listitem-indent\}} \cw{\\cfg\{info-listitem-indent\}}
+
+\IM{\\cfg\{info-section-suffix\}} \c{info-section-suffix}
+configuration directive
+\IM{\\cfg\{info-section-suffix\}} \cw{\\cfg\{info-section-suffix\}}
+
+\IM{\\cfg\{info-underline\}} \c{info-underline} configuration
+directive
+\IM{\\cfg\{info-underline\}} \cw{\\cfg\{info-underline\}}
+
+\IM{\\cfg\{info-bullet\}} \c{info-bullet} configuration directive
+\IM{\\cfg\{info-bullet\}} \cw{\\cfg\{info-bullet\}}
+
+\IM{\\cfg\{info-rule\}} \c{info-rule} configuration directive
+\IM{\\cfg\{info-rule\}} \cw{\\cfg\{info-rule\}}
+
+\IM{\\cfg\{info-list-suffix\}} \c{info-list-suffix} configuration
+directive
+\IM{\\cfg\{info-list-suffix\}} \cw{\\cfg\{info-list-suffix\}}
+
+\IM{\\cfg\{info-emphasis\}} \c{info-emphasis} configuration directive
+\IM{\\cfg\{info-emphasis\}} \cw{\\cfg\{info-emphasis\}}
+
+\IM{\\cfg\{info-quotes\}} \c{info-quotes} configuration directive
+\IM{\\cfg\{info-quotes\}} \cw{\\cfg\{info-quotes\}}
+
 \IM{\\cfg\{winhelp-filename\}} \c{winhelp-filename} configuration directive
 \IM{\\cfg\{winhelp-filename\}} \cw{\\cfg\{winhelp-filename\}}
 
index dbc9b70..3eeecda 100644 (file)
@@ -246,7 +246,7 @@ silly; I mention it only as an example.)
 
 \dt \I{\cw{\\cfg\{text-emphasis\}}}\cw{\\cfg\{text-emphasis\}\{}\e{start-emph}\cw{\}\{}\e{end-emph}\cw{\}}[\cw{\{}\e{start-emph}\cw{\}\{}\e{end-emph}...\cw{\}}]
 
-\dd This specifies the text which should be used to surround
+\dd This specifies the characters which should be used to surround
 emphasised text (written using the \c{\\e} command; see
 \k{input-emph}).
 
@@ -873,6 +873,86 @@ creation and remain useful.
 
 }
 
+\dt \I{\cw{\\cfg\{info-width\}}}\cw{\\cfg\{info-width\}\{}\e{width}\cw{\}}
+
+\dd Sets the \I{text width}width of the main part of the document,
+in characters. Works exactly like the \cw{\\cfg\{text-width\}}
+directive (see \k{output-text-dimensions}).
+
+\dt \I{\cw{\\cfg\{info-indent-code\}}}\cw{\\cfg\{info-indent-code\}\{}\e{indent}\cw{\}}
+
+\dd Specifies the extra indentation for \I{code paragraphs,
+indentation} code paragraphs. Works exactly like the
+\cw{\\cfg\{text-indent-code\}} directive (see
+\k{output-text-dimensions}).
+
+\dt \I{\cw{\\cfg\{info-index-width\}}}\cw{\\cfg\{info-index-width\}\{}\e{width}\cw{\}}
+
+\dd Specifies how much horizontal space to leave in the index node
+for the text of \i{index terms}, before displaying the sections the
+terms occur in.
+
+\dt \I{\cw{\\cfg\{info-list-indent\}}}\cw{\\cfg\{info-list-indent\}\{}\e{indent}\cw{\}}
+
+\dd Specifies the extra indentation before the bullet or number in a
+\I{bulletted list, indentation}\I{numbered list, indentation}list
+item. Works exactly like the \cw{\\cfg\{text-list-indent\}}
+directive (see \k{output-text-dimensions}).
+
+\dt \I{\cw{\\cfg\{info-listitem-indent\}}}\cw{\\cfg\{info-listitem-indent\}\{}\e{indent}\cw{\}}
+
+\dd Specifies the additional indentation before the body of a list
+item. Works exactly like the \cw{\\cfg\{text-listitem-indent\}}
+directive (see \k{output-text-dimensions}).
+
+\dt \I{\cw{\\cfg\{info-section-suffix\}}}\cw{\\cfg\{info-section-suffix\}\{}\e{text}\cw{\}}
+
+\dd Specifies the suffix text to be appended to each section number
+before displaying the section title. For example, if you set this to
+\q{\cw{:\_}}, then a typical section title might look something like
+\q{Section 3.1: Something Like This}.
+
+\dt \I{\cw{\\cfg\{info-underline\}}}\cw{\\cfg\{info-underline\}\{}\e{text}\cw{\}}[\cw{\{}\e{text}\cw{\}}...]
+
+\dd Specifies the text to be used to underline section titles. Works
+very much like the \cw{\\cfg\{text-chapter-underline\}} directive
+(see \k{output-text-headings}). You can specify more than one
+option, and Halibut will choose the first one supported by the
+character set.
+
+\dt \I{\cw{\\cfg\{info-bullet\}}}\cw{\\cfg\{info-bullet\}\{}\e{text}\cw{\}}[\cw{\{}\e{text}\cw{\}}...]
+
+\dd Specifies the text to use as the \i{bullet} in bulletted lists.
+You can specify multiple fallback options. Works exactly like the
+\cw{\\cfg\{text-bullet\}} directive (see
+\k{output-text-characters}).
+
+\dt \I{\cw{\\cfg\{info-rule\}}}\cw{\\cfg\{info-rule\}\{}\e{text}\cw{\}}[\cw{\{}\e{text}\cw{\}}...]
+
+\dd Specifies the text used to draw \i{horizontal rules}. You can
+specify multiple fallback options. Works exactly like the
+\cw{\\cfg\{text-rule\}} directive (see \k{output-text-characters}).
+
+\dt \I{\cw{\\cfg\{info-quotes\}}}\cw{\\cfg\{info-quotes\}\{}\e{open-quote}\cw{\}\{}\e{close-quote}\cw{\}}[\cw{\{}\e{open-quote}\cw{\}\{}\e{close-quote}...\cw{\}}]
+
+\dd Specifies the quotation marks to use. You can specify multiple
+fallback options. Works exactly like the \cw{\\cfg\{text-quotes\}}
+directive (see \k{output-text-characters}).
+
+\dt \I{\cw{\\cfg\{info-emphasis\}}}\cw{\\cfg\{info-emphasis\}\{}\e{start-emph}\cw{\}\{}\e{end-emph}\cw{\}}[\cw{\{}\e{start-emph}\cw{\}\{}\e{end-emph}...\cw{\}}]
+
+\dd Specifies how to display emphasised text. You can specify
+multiple fallback options. Works exactly like the
+\cw{\\cfg\{text-emphasis\}} directive (see
+\k{output-text-characters}).
+
+\dt \I{\cw{\\cfg\{info-list-suffix\}}}\cw{\\cfg\{info-list-suffix\}\{}\e{text}\cw{\}}
+
+\dd Specifies the text to append to the item numbers in a
+\i{numbered list}. Works exactly like the
+\cw{\\cfg\{text-list-suffix\}} directive (see
+\k{output-text-misc}).
+
 \dt \I{\cw{\\cfg\{info-max-file-size\}}}\cw{\\cfg\{info-max-file-size\}\{}\e{bytes}\cw{\}}
 
 \dd Sets the preferred \i{maximum file size} for each subsidiary
@@ -942,6 +1022,29 @@ if the output file were called \c{mygames.info} and the keyword
 
 }
 
+The \i{default settings} for the \c{info} output format are:
+
+\c \cfg{info-filename}{output.info}
+\c
+\c \cfg{info-width}{70}
+\c \cfg{info-indent-code}{2}
+\c \cfg{info-index-width}{40}
+\c \cfg{info-list-indent}{1}
+\c \cfg{info-listitem-indent}{3}
+\c
+\c \cfg{info-section-suffix}{: }
+\c
+\c \cfg{info-underline}{\u203e}{-}
+\c \cfg{info-bullet}{\u2022}{-}
+\c \cfg{info-rule}{\u2500}{-}
+\c \cfg{info-quotes}{\u2018}{\u2019}{`}{'}
+\c \cfg{info-emphasis}{_}{_}
+\c
+\c \cfg{info-list-suffix}{.}
+\c \cfg{info-max-file-size}{65536}
+
+and no \cw{\\cfg\{info-dir-entry\}} directives.
+
 \H{output-ps} \i{PostScript}
 
 This output format generates a printable manual in PostScript format.