+typedef struct {
+ wchar_t *th;
+ int headnumbers;
+ int mindepth;
+ char *filename;
+ int charset;
+ wchar_t *bullet, *lquote, *rquote;
+} manconfig;
+
+static void man_text(FILE *, word *,
+ int newline, int quote_props, manconfig *conf);
+static void man_codepara(FILE *, word *, int charset);
+static int man_convert(wchar_t const *s, int maxlen,
+ char **result, int quote_props,
+ int charset, charset_state *state);
+
+static manconfig man_configure(paragraph *source) {
+ paragraph *p;
+ manconfig ret;
+
+ /*
+ * Defaults.
+ */
+ ret.th = NULL;
+ ret.headnumbers = FALSE;
+ ret.mindepth = 0;
+ ret.filename = dupstr("output.1");
+ ret.charset = CS_ASCII;
+ ret.bullet = L"\x2022\0o\0\0";
+ ret.lquote = L"\x2018\0\x2019\0\"\0\"\0\0";
+ ret.rquote = uadv(ret.lquote);
+
+ /*
+ * Two-pass configuration so that we can pick up global config
+ * (e.g. `quotes') before having it overridden by specific
+ * config (`man-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 (p = source; p; p = p->next) {
+ if (p->type == para_Config) {
+ if (!ustricmp(p->keyword, L"man-identity")) {
+ wchar_t *wp, *ep;
+
+ wp = uadv(p->keyword);
+ ep = wp;
+ while (*ep)
+ ep = uadv(ep);
+ sfree(ret.th);
+ 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")) {
+ 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")) {
+ ret.mindepth = utoi(uadv(p->keyword));
+ } else if (!ustricmp(p->keyword, L"man-filename")) {
+ sfree(ret.filename);
+ 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"man-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 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 (*ret.bullet && *uadv(ret.bullet) &&
+ !cvt_ok(ret.charset, ret.bullet))
+ ret.bullet = uadv(ret.bullet);
+
+ return ret;
+}
+
+static void man_conf_cleanup(manconfig cf)
+{
+ sfree(cf.th);
+ sfree(cf.filename);
+}
+
+paragraph *man_config_filename(char *filename)
+{
+ return cmdline_cfg_simple("man-filename", filename, NULL);
+}