X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/f15300499bce37cd28ea2ace0f2bd1c364fc835e..ee90d1f0229c97e51b96cb92714de6f6d5b2b450:/bk_man.c diff --git a/bk_man.c b/bk_man.c index b2db5bb..553b2dd 100644 --- a/bk_man.c +++ b/bk_man.c @@ -42,7 +42,7 @@ static manconfig man_configure(paragraph *source) { /* * Two-pass configuration so that we can pick up global config * (e.g. `quotes') before having it overridden by specific - * config (`text-quotes'), irrespective of the order in which + * config (`man-quotes'), irrespective of the order in which * they occur. */ for (p = source; p; p = p->next) { @@ -69,9 +69,7 @@ static manconfig man_configure(paragraph *source) { ret.th = snewn(ep - wp + 1, wchar_t); memcpy(ret.th, wp, (ep - wp + 1) * sizeof(wchar_t)); } else if (!ustricmp(p->keyword, L"man-charset")) { - char *csname = utoa_dup(uadv(p->keyword), CS_ASCII); - ret.charset = charset_from_localenc(csname); - sfree(csname); + ret.charset = charset_from_ustr(&p->fpos, uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"man-headnumbers")) { ret.headnumbers = utob(uadv(p->keyword)); } else if (!ustricmp(p->keyword, L"man-mindepth")) { @@ -81,7 +79,7 @@ static manconfig man_configure(paragraph *source) { ret.filename = dupstr(adv(p->origkeyword)); } else if (!ustricmp(p->keyword, L"man-bullet")) { ret.bullet = uadv(p->keyword); - } else if (!ustricmp(p->keyword, L"text-quotes")) { + } else if (!ustricmp(p->keyword, L"man-quotes")) { if (*uadv(p->keyword) && *uadv(uadv(p->keyword))) { ret.lquote = uadv(p->keyword); ret.rquote = uadv(ret.lquote); @@ -126,6 +124,7 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, paragraph *p; FILE *fp; manconfig conf; + int had_described_thing; IGNORE(unused); IGNORE(keywords); @@ -165,7 +164,12 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, } fputc('\n', fp); - fprintf(fp, ".UC\n"); + had_described_thing = FALSE; +#define cleanup_described_thing do { \ + if (had_described_thing) \ + fprintf(fp, "\n"); \ + had_described_thing = FALSE; \ +} while (0) for (p = sourceform; p; p = p->next) switch (p->type) { /* @@ -189,16 +193,20 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, case para_Heading: case para_Subsect: + cleanup_described_thing; { int depth; if (p->type == para_Subsect) - depth = p->aux + 2; + depth = p->aux + 1; else if (p->type == para_Heading) depth = 1; else depth = 0; if (depth >= conf.mindepth) { - fprintf(fp, ".SH \""); + if (depth > conf.mindepth) + fprintf(fp, ".SS \""); + else + fprintf(fp, ".SH \""); if (conf.headnumbers && p->kwtext) { man_text(fp, p->kwtext, FALSE, QUOTE_QUOTES, &conf); fprintf(fp, " "); @@ -213,6 +221,7 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, * Code paragraphs. */ case para_Code: + cleanup_described_thing; fprintf(fp, ".PP\n"); man_codepara(fp, p->words, conf.charset); break; @@ -222,6 +231,7 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, */ case para_Normal: case para_Copyright: + cleanup_described_thing; fprintf(fp, ".PP\n"); man_text(fp, p->words, TRUE, 0, &conf); break; @@ -233,6 +243,9 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, case para_BiblioCited: case para_Bullet: case para_NumberedList: + if (p->type != para_Description) + cleanup_described_thing; + if (p->type == para_Bullet) { char *bullettext; man_convert(conf.bullet, -1, &bullettext, QUOTE_QUOTES, @@ -244,22 +257,34 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, man_text(fp, p->kwtext, FALSE, QUOTE_QUOTES, &conf); fprintf(fp, "\"\n"); } else if (p->type == para_Description) { - /* - * Do nothing; the .xP for this paragraph is the .IP - * which has come before it in the DescribedThing. - */ + if (had_described_thing) { + /* + * Do nothing; the .xP for this paragraph is the + * .IP which has come before it in the + * DescribedThing. + */ + } else { + /* + * A \dd without a preceding \dt is given a blank + * one. + */ + fprintf(fp, ".IP \"\"\n"); + } } else if (p->type == para_BiblioCited) { fprintf(fp, ".IP \""); man_text(fp, p->kwtext, FALSE, QUOTE_QUOTES, &conf); fprintf(fp, "\"\n"); } man_text(fp, p->words, TRUE, 0, &conf); + had_described_thing = FALSE; break; case para_DescribedThing: + cleanup_described_thing; fprintf(fp, ".IP \""); man_text(fp, p->words, FALSE, QUOTE_QUOTES, &conf); fprintf(fp, "\"\n"); + had_described_thing = TRUE; break; case para_Rule: @@ -267,18 +292,22 @@ void man_backend(paragraph *sourceform, keywordlist *keywords, * This isn't terribly good. Anyone who wants to do better * should feel free! */ + cleanup_described_thing; fprintf(fp, ".PP\n----------------------------------------\n"); break; case para_LcontPush: case para_QuotePush: + cleanup_described_thing; fprintf(fp, ".RS\n"); break; case para_LcontPop: case para_QuotePop: + cleanup_described_thing; fprintf(fp, ".RE\n"); break; } + cleanup_described_thing; /* * Tidy up. @@ -378,9 +407,9 @@ static int man_convert(wchar_t const *s, int maxlen, return !err; } -static void man_rdaddwc(rdstringc *rs, word *text, word *end, - int quote_props, manconfig *conf, - charset_state *state) { +static int man_rdaddwc(rdstringc *rs, word *text, word *end, + int quote_props, manconfig *conf, + charset_state *state) { char *c; for (; text && text != end; text = text->next) switch (text->type) { @@ -410,10 +439,10 @@ static void man_rdaddwc(rdstringc *rs, word *text, word *end, if (towordstyle(text->type) == word_Emph && (attraux(text->aux) == attr_First || attraux(text->aux) == attr_Only)) { - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ man_convert(NULL, 0, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); *state = charset_init_state; rdaddsc(rs, "\\fI"); @@ -421,10 +450,10 @@ static void man_rdaddwc(rdstringc *rs, word *text, word *end, towordstyle(text->type) == word_WeakCode) && (attraux(text->aux) == attr_First || attraux(text->aux) == attr_Only)) { - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ man_convert(NULL, 0, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); *state = charset_init_state; rdaddsc(rs, "\\fB"); @@ -433,38 +462,39 @@ static void man_rdaddwc(rdstringc *rs, word *text, word *end, if (removeattr(text->type) == word_Normal) { charset_state s2 = *state; - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ if (man_convert(text->text, 0, &c, quote_props, conf->charset, &s2) || !text->alt) { rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ *state = s2; } else { - man_rdaddwc(rs, text->alt, NULL, quote_props, conf, state); + quote_props = man_rdaddwc(rs, text->alt, NULL, + quote_props, conf, state); } sfree(c); } else if (removeattr(text->type) == word_WhiteSpace) { - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ man_convert(L" ", 1, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); } else if (removeattr(text->type) == word_Quote) { - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ man_convert(quoteaux(text->aux) == quote_Open ? conf->lquote : conf->rquote, 0, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); } if (towordstyle(text->type) != word_Normal && (attraux(text->aux) == attr_Last || attraux(text->aux) == attr_Only)) { - if (rs->pos > 0) - quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ man_convert(NULL, 0, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); *state = charset_init_state; rdaddsc(rs, "\\fP"); @@ -473,7 +503,11 @@ static void man_rdaddwc(rdstringc *rs, word *text, word *end, } man_convert(NULL, 0, &c, quote_props, conf->charset, state); rdaddsc(rs, c); + if (*c) + quote_props &= ~QUOTE_INITCTRL; /* not at start any more */ sfree(c); + + return quote_props; } static void man_text(FILE *fp, word *text, int newline,