static void man_text(FILE *, word *, int newline, int quote_props);
static void man_codepara(FILE *, word *);
+static int man_convert(wchar_t *s, int maxlen,
+ char **result, int quote_props);
+
+typedef struct {
+ wchar_t *th;
+ int headnumbers;
+ int mindepth;
+} manconfig;
+
+static manconfig man_configure(paragraph *source) {
+ manconfig ret;
+
+ /*
+ * Defaults.
+ */
+ ret.th = NULL;
+ ret.headnumbers = FALSE;
+ ret.mindepth = 0;
+
+ for (; source; source = source->next) {
+ if (source->type == para_Config) {
+ if (!ustricmp(source->keyword, L"man-identity")) {
+ wchar_t *wp, *ep;
+
+ wp = uadv(source->keyword);
+ ep = wp;
+ while (*ep)
+ ep = uadv(ep);
+ ret.th = mknewa(wchar_t, ep - wp + 1);
+ memcpy(ret.th, wp, (ep - wp + 1) * sizeof(wchar_t));
+ } else if (!ustricmp(source->keyword, L"man-headnumbers")) {
+ ret.headnumbers = utob(uadv(source->keyword));
+ } else if (!ustricmp(source->keyword, L"man-mindepth")) {
+ ret.mindepth = utoi(uadv(source->keyword));
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void man_conf_cleanup(manconfig cf)
+{
+ sfree(cf.th);
+}
#define QUOTE_INITCTRL 1 /* quote initial . and ' on a line */
#define QUOTE_QUOTES 2 /* quote double quotes by doubling them */
paragraph *p;
FILE *fp;
char const *sep;
+ manconfig conf;
IGNORE(keywords); /* we don't happen to need this */
IGNORE(idx); /* or this */
+ conf = man_configure(sourceform);
+
/*
* Determine the output file name, and open the output file
*
man_text(fp, p->words, TRUE, 0);
}
- /* FIXME: .TH name-of-program manual-section */
- fprintf(fp, ".TH FIXME 1\n");
+ /* .TH name-of-program manual-section */
+ {
+ char *c;
+ if (conf.th && *conf.th) {
+ wchar_t *wp;
+ fprintf(fp, ".TH");
+
+ for (wp = conf.th; *wp; wp = uadv(wp)) {
+ fputs(" \"", fp);
+ man_convert(wp, 0, &c, QUOTE_QUOTES);
+ fputs(c, fp);
+ sfree(c);
+ fputc('"', fp);
+ }
+ fputc('\n', fp);
+ }
+ }
fprintf(fp, ".UC\n");
sep = "\n";
}
- /*
- * FIXME:
- *
- * - figure out precisely what needs to be escaped.
- * * A dot or apostrophe at the start of a line wants to be
- * preceded by `\&', which is a zero-width space.
- * * Literal backslashes always want doubling.
- * * Within double quotes, a double quote needs doubling
- * too.
- *
- * - work out what to do about hyphens / minuses...
- */
for (p = sourceform; p; p = p->next) switch (p->type) {
/*
* Things we ignore because we've already processed them or
case para_UnnumberedChapter:
case para_Heading:
case para_Subsect:
- fprintf(fp, ".SH \"");
- /* FIXME: disable this, at _least_ by default */
- if (p->kwtext)
- man_text(fp, p->kwtext, FALSE, QUOTE_QUOTES);
- fprintf(fp, " ");
- man_text(fp, p->words, FALSE, QUOTE_QUOTES);
- fprintf(fp, "\"\n");
- break;
+ {
+ int depth;
+ if (p->type == para_Subsect)
+ depth = p->aux + 2;
+ else if (p->type == para_Heading)
+ depth = 1;
+ else
+ depth = 0;
+ if (depth >= conf.mindepth) {
+ fprintf(fp, ".SH \"");
+ if (conf.headnumbers && p->kwtext) {
+ man_text(fp, p->kwtext, FALSE, QUOTE_QUOTES);
+ fprintf(fp, " ");
+ }
+ man_text(fp, p->words, FALSE, QUOTE_QUOTES);
+ fprintf(fp, "\"\n");
+ }
+ break;
+ }
/*
* Code paragraphs.
case para_Rule:
/*
- * FIXME.
+ * This isn't terribly good. Anyone who wants to do better
+ * should feel free!
*/
+ fprintf(fp, ".PP\n----------------------------------------\n");
break;
case para_LcontPush:
* Tidy up.
*/
fclose(fp);
+ man_conf_cleanup(conf);
}
/*
* of things. I know I at least need to escape backslash, and full
* stops at the starts of words are probably trouble as well.
*/
-static int man_convert(wchar_t *s, char **result, int quote_props) {
+static int man_convert(wchar_t *s, int maxlen,
+ char **result, int quote_props) {
/*
* FIXME. Currently this is ISO8859-1 only.
*/
char *p = NULL;
int plen = 0, psize = 0;
- for (; *s; s++) {
+ if (maxlen <= 0)
+ maxlen = -1;
+
+ for (; *s && maxlen != 0; s++, maxlen--) {
wchar_t c = *s;
char outc;
(attraux(text->aux) == attr_First ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "\\fI");
- else if (towordstyle(text->type) == word_Code &&
+ else if ((towordstyle(text->type) == word_Code ||
+ towordstyle(text->type) == word_WeakCode) &&
(attraux(text->aux) == attr_First ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "\\fB");
if (removeattr(text->type) == word_Normal) {
if (rs->pos > 0)
quote_props &= ~QUOTE_INITCTRL; /* not at start any more */
- if (man_convert(text->text, &c, quote_props))
+ if (man_convert(text->text, 0, &c, quote_props))
rdaddsc(rs, c);
else
man_rdaddwc(rs, text->alt, NULL, quote_props);
} else if (removeattr(text->type) == word_WhiteSpace) {
rdaddc(rs, ' ');
} else if (removeattr(text->type) == word_Quote) {
- rdaddc(rs, quoteaux(text->aux) == quote_Open ? '`' : '\'');
- /* FIXME: configurability */
+ rdaddc(rs, '"');
+ if (quote_props & QUOTE_QUOTES)
+ rdaddc(rs, '"');
}
if (towordstyle(text->type) == word_Emph &&
(attraux(text->aux) == attr_Last ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "\\fP");
- else if (towordstyle(text->type) == word_Code &&
+ else if ((towordstyle(text->type) == word_Code ||
+ towordstyle(text->type) == word_WeakCode) &&
(attraux(text->aux) == attr_Last ||
attraux(text->aux) == attr_Only))
rdaddsc(rs, "\\fP");
fprintf(fp, ".nf\n");
for (; text; text = text->next) if (text->type == word_WeakCode) {
char *c;
- man_convert(text->text, &c, QUOTE_INITCTRL);
+ wchar_t *t, *e;
+ int quote_props = QUOTE_INITCTRL;
+
+ t = text->text;
+ if (text->next && text->next->type == word_Emph) {
+ e = text->next->text;
+ text = text->next;
+ } else
+ e = NULL;
+
+ while (e && *e && *t) {
+ int n;
+ int ec = *e;
+
+ for (n = 0; t[n] && e[n] && e[n] == ec; n++);
+ if (ec == 'i')
+ fprintf(fp, "\\fI");
+ else if (ec == 'b')
+ fprintf(fp, "\\fB");
+ man_convert(t, n, &c, quote_props);
+ quote_props &= ~QUOTE_INITCTRL;
+ fprintf(fp, "%s", c);
+ sfree(c);
+ if (ec == 'i' || ec == 'b')
+ fprintf(fp, "\\fP");
+ t += n;
+ e += n;
+ }
+ man_convert(t, 0, &c, quote_props);
fprintf(fp, "%s\n", c);
sfree(c);
}
FONT_NORMAL,
FONT_EMPH,
FONT_CODE,
+ FONT_ITAL_CODE,
+ FONT_BOLD_CODE,
FONT_TITLE,
FONT_TITLE_EMPH,
FONT_TITLE_CODE,
};
static void whlp_rdaddwc(rdstringc *rs, word *text);
-static int whlp_convert(wchar_t *s, char **result, int hard_spaces);
+static int whlp_convert(wchar_t *s, int maxlen,
+ char **result, int hard_spaces);
static void whlp_mkparagraph(struct bk_whlp_state *state,
int font, word *text, int subsidiary);
static void whlp_navmenu(struct bk_whlp_state *state, paragraph *p);
WHLP_FONT_ITALIC, 0, 0, 0);
whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
0, 0, 0, 0);
+ whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
+ WHLP_FONT_ITALIC, 0, 0, 0);
+ whlp_create_font(h, "Courier New", WHLP_FONTFAM_FIXED, 24,
+ WHLP_FONT_BOLD, 0, 0, 0);
whlp_create_font(h, "Arial", WHLP_FONTFAM_SERIF, 30,
WHLP_FONT_BOLD, 0, 0, 0);
whlp_create_font(h, "Arial", WHLP_FONTFAM_SERIF, 30,
if (p->type == para_Config && p->parent) {
if (!ustricmp(p->keyword, L"winhelp-topic")) {
char *topicname;
- whlp_convert(uadv(p->keyword), &topicname, 0);
+ whlp_convert(uadv(p->keyword), 0, &topicname, 0);
/* Store the topic name in the private_data field of the
* containing section. */
p->parent->private_data = topicname;
*/
{
word *w;
+ wchar_t *t, *e;
char *c;
- for (w = p->words; w; w = w->next) {
+
+ for (w = p->words; w; w = w->next) if (w->type == word_WeakCode) {
+ t = w->text;
+ if (w->next && w->next->type == word_Emph) {
+ w = w->next;
+ e = w->text;
+ } else
+ e = NULL;
+
if (!w->next)
whlp_para_attr(h, WHLP_PARA_SPACEBELOW, 12);
+
whlp_para_attr(h, WHLP_PARA_LEFTINDENT, 72*nesting);
whlp_begin_para(h, WHLP_PARA_SCROLL);
+ while (e && *e && *t) {
+ int n;
+ int ec = *e;
+
+ for (n = 0; t[n] && e[n] && e[n] == ec; n++);
+ if (ec == 'i')
+ whlp_set_font(h, FONT_ITAL_CODE);
+ else if (ec == 'b')
+ whlp_set_font(h, FONT_BOLD_CODE);
+ else
+ whlp_set_font(h, FONT_CODE);
+ whlp_convert(t, n, &c, FALSE);
+ whlp_text(h, c);
+ sfree(c);
+ t += n;
+ e += n;
+ }
whlp_set_font(h, FONT_CODE);
- whlp_convert(w->text, &c, FALSE);
+ whlp_convert(t, 0, &c, FALSE);
whlp_text(h, c);
sfree(c);
whlp_end_para(h);
whlp_set_font(state->h, newfont);
}
if (removeattr(text->type) == word_Normal) {
- if (whlp_convert(text->text, &c, TRUE))
+ if (whlp_convert(text->text, 0, &c, TRUE))
whlp_text(state->h, c);
else
whlp_mkparagraph(state, deffont, text->alt, FALSE);
assert(text->type != word_CodeQuote &&
text->type != word_WkCodeQuote);
if (removeattr(text->type) == word_Normal) {
- if (whlp_convert(text->text, &c, FALSE))
+ if (whlp_convert(text->text, 0, &c, FALSE))
rdaddsc(rs, c);
else
whlp_rdaddwc(rs, text->alt);
* characters are OK but `result' is non-NULL, a result _will_
* still be generated!
*/
-static int whlp_convert(wchar_t *s, char **result, int hard_spaces) {
+static int whlp_convert(wchar_t *s, int maxlen,
+ char **result, int hard_spaces) {
/*
* FIXME. Currently this is ISO8859-1 only.
*/
char *p = NULL;
int plen = 0, psize = 0;
- for (; *s; s++) {
+ if (maxlen <= 0)
+ maxlen = -1;
+
+ for (; *s && maxlen != 0; s++, maxlen--) {
wchar_t c = *s;
char outc;
static int xhtml_para_level(paragraph *);
static int xhtml_reservedchar(int);
-static int xhtml_convert(wchar_t *, char **, int);
+static int xhtml_convert(wchar_t *, int, char **, int);
static void xhtml_rdaddwc(rdstringc *, word *, word *);
static void xhtml_para(FILE *, word *);
static void xhtml_codepara(FILE *, word *);
* characters are OK but `result' is non-NULL, a result _will_
* still be generated!
*/
-static int xhtml_convert(wchar_t *s, char **result, int hard_spaces) {
+static int xhtml_convert(wchar_t *s, int maxlen, char **result,
+ int hard_spaces) {
int doing = (result != 0);
int ok = TRUE;
char *p = NULL;
int plen = 0, psize = 0;
- for (; *s; s++) {
+ if (maxlen <= 0)
+ maxlen = -1;
+
+ for (; *s && maxlen != 0; s++, maxlen--) {
wchar_t c = *s;
#define ensure_size(i) if (i>=psize) { psize = i+256; p = resize(p, psize); }
rdaddsc(rs, "<code>");
if (removeattr(text->type) == word_Normal) {
- if (xhtml_convert(text->text, &c, TRUE)) /* spaces in the word are hard */
+ if (xhtml_convert(text->text, 0, &c, TRUE)) /* spaces in the word are hard */
rdaddsc(rs, c);
else
xhtml_rdaddwc(rs, text->alt, NULL);
xhtml_rdaddwc(&t, nprefix, NULL);
if (fmt) {
char *c;
- if (xhtml_convert(fmt->number_suffix, &c, FALSE)) {
+ if (xhtml_convert(fmt->number_suffix, 0, &c, FALSE)) {
rdaddsc(&t, c);
sfree(c);
}
xhtml_rdaddwc(&t, tprefix, NULL);
if (fmt) {
char *c;
- if (xhtml_convert(fmt->number_suffix, &c, FALSE)) {
+ if (xhtml_convert(fmt->number_suffix, 0, &c, FALSE)) {
rdaddsc(&t, c);
sfree(c);
}
{
fprintf(fp, "<pre>");
for (; text; text = text->next) if (text->type == word_WeakCode) {
+ word *here, *next;
char *c;
- xhtml_convert(text->text, &c, FALSE);
- fprintf(fp, "%s\n", c);
- sfree(c);
+
+ /*
+ * See if this WeakCode is followed by an Emph to indicate
+ * emphasis.
+ */
+ here = text;
+ if (text->next && text->next->type == word_Emph) {
+ next = text = text->next;
+ } else
+ next = NULL;
+
+ if (next) {
+ wchar_t *t, *e;
+ int n;
+
+ t = here->text;
+ e = next->text;
+
+ while (*e) {
+ int ec = *e;
+
+ for (n = 0; t[n] && e[n] && e[n] == ec; n++);
+ xhtml_convert(t, n, &c, FALSE);
+ fprintf(fp, "%s%s%s",
+ (ec == 'i' ? "<em>" : ec == 'b' ? "<b>" : ""),
+ c,
+ (ec == 'i' ? "</em>" : ec == 'b' ? "</b>" : ""));
+ sfree(c);
+
+ t += n;
+ e += n;
+ }
+
+ xhtml_convert(t, 0, &c, FALSE);
+ fprintf(fp, "%s\n", c);
+ sfree(c);
+ } else {
+ xhtml_convert(here->text, 0, &c, FALSE);
+ fprintf(fp, "%s\n", c);
+ sfree(c);
+ }
}
fprintf(fp, "</pre>\n");
}
* Parse code paragraphs separately.
*/
if (t.type == tok_cmd && t.cmd == c_c && !isbrace(in)) {
+ int wtype = word_WeakCode;
+
par.type = para_Code;
par.fpos = t.pos;
while (1) {
dtor(t), t = get_codepar_token(in);
- wd.type = word_WeakCode;
+ wd.type = wtype;
wd.breaks = FALSE; /* shouldn't need this... */
wd.text = ustrdup(t.text);
wd.alt = NULL;
}
if (t.type == tok_eop || t.type == tok_eof)
break;
- else if (t.type != tok_cmd || t.cmd != c_c) {
+ else if (t.type == tok_cmd && t.cmd == c_c)
+ wtype = word_WeakCode;
+ else if (t.type == tok_cmd && t.cmd == c_e &&
+ wtype == word_WeakCode)
+ wtype = word_Emph;
+ else {
error(err_brokencodepara, &t.pos);
prev_para_type = par.type;
addpara(par, ret);
Lines, Not Just Two. How's That For Ludicrous?
\cfg{xhtml-leaf-smallest-contents}{2}
-
\cfg{xhtml-leaf-contains-contents}{true}
+\cfg{man-headnumbers}{true}
\preamble This manual is a small joke effort, designed to use every
feature \#{ comment } that Halibut's input format supports. Creation
\define{coopt} co\u00F6{-o}pt
-\versionid $Id: test.but,v 1.20 2004/03/23 20:10:23 simon Exp $
+\versionid $Id: test.but,v 1.21 2004/03/24 19:23:21 simon Exp $
\C{ch\\ap} First chapter title; for similar wrapping reasons this
chapter title will be ludicrously long. I wonder how much more
\c Two blank lines precede this one.
\c Two leading spaces
\c We can use \ { and } with impunity here.
+\c We can use discretionary bold and italic in code paragraphs!
+\e bbbb iiiiii
+\c Isn't that ludicrous?
This is a list: