Annotation of mandoc/term.c, Revision 1.62
1.62 ! kristaps 1: /* $Id: term.c,v 1.61 2009/03/16 23:37:28 kristaps Exp $ */
1.1 kristaps 2: /*
1.61 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
1.50 kristaps 19: #include <sys/types.h>
20:
1.1 kristaps 21: #include <assert.h>
1.25 kristaps 22: #include <ctype.h>
1.23 kristaps 23: #include <err.h>
1.22 kristaps 24: #include <stdio.h>
1.1 kristaps 25: #include <stdlib.h>
26: #include <string.h>
27:
1.10 kristaps 28: #include "term.h"
29:
30: /*
31: * Performs actions on nodes of the abstract syntax tree. Both pre- and
32: * post-fix operations are defined here.
33: */
34:
1.21 kristaps 35: /* FIXME: macro arguments can be escaped. */
1.10 kristaps 36:
37: #define TTYPE_PROG 0
38: #define TTYPE_CMD_FLAG 1
39: #define TTYPE_CMD_ARG 2
40: #define TTYPE_SECTION 3
41: #define TTYPE_FUNC_DECL 4
42: #define TTYPE_VAR_DECL 5
43: #define TTYPE_FUNC_TYPE 6
44: #define TTYPE_FUNC_NAME 7
45: #define TTYPE_FUNC_ARG 8
46: #define TTYPE_LINK 9
47: #define TTYPE_SSECTION 10
48: #define TTYPE_FILE 11
1.11 kristaps 49: #define TTYPE_EMPH 12
1.14 kristaps 50: #define TTYPE_CONFIG 13
51: #define TTYPE_CMD 14
52: #define TTYPE_INCLUDE 15
1.17 kristaps 53: #define TTYPE_SYMB 16
54: #define TTYPE_SYMBOL 17
1.37 kristaps 55: #define TTYPE_DIAG 18
1.51 kristaps 56: #define TTYPE_LINK_ANCHOR 19
57: #define TTYPE_LINK_TEXT 20
1.54 kristaps 58: #define TTYPE_REF_TITLE 21
59: #define TTYPE_NMAX 22
1.10 kristaps 60:
61: /*
62: * These define "styles" for element types, like command arguments or
63: * executable names. This is useful when multiple macros must decorate
64: * the same thing (like .Ex -std cmd and .Nm cmd).
65: */
66:
1.36 kristaps 67: /* TODO: abstract this into mdocterm.c. */
68:
1.10 kristaps 69: const int ttypes[TTYPE_NMAX] = {
1.59 kristaps 70: TERMP_BOLD, /* TTYPE_PROG */
1.10 kristaps 71: TERMP_BOLD, /* TTYPE_CMD_FLAG */
1.59 kristaps 72: TERMP_UNDER, /* TTYPE_CMD_ARG */
1.10 kristaps 73: TERMP_BOLD, /* TTYPE_SECTION */
74: TERMP_BOLD, /* TTYPE_FUNC_DECL */
1.59 kristaps 75: TERMP_UNDER, /* TTYPE_VAR_DECL */
76: TERMP_UNDER, /* TTYPE_FUNC_TYPE */
1.10 kristaps 77: TERMP_BOLD, /* TTYPE_FUNC_NAME */
1.59 kristaps 78: TERMP_UNDER, /* TTYPE_FUNC_ARG */
79: TERMP_UNDER, /* TTYPE_LINK */
1.10 kristaps 80: TERMP_BOLD, /* TTYPE_SSECTION */
1.59 kristaps 81: TERMP_UNDER, /* TTYPE_FILE */
82: TERMP_UNDER, /* TTYPE_EMPH */
1.14 kristaps 83: TERMP_BOLD, /* TTYPE_CONFIG */
84: TERMP_BOLD, /* TTYPE_CMD */
1.17 kristaps 85: TERMP_BOLD, /* TTYPE_INCLUDE */
86: TERMP_BOLD, /* TTYPE_SYMB */
1.37 kristaps 87: TERMP_BOLD, /* TTYPE_SYMBOL */
1.51 kristaps 88: TERMP_BOLD, /* TTYPE_DIAG */
1.59 kristaps 89: TERMP_UNDER, /* TTYPE_LINK_ANCHOR */
1.54 kristaps 90: TERMP_BOLD, /* TTYPE_LINK_TEXT */
1.59 kristaps 91: TERMP_UNDER /* TTYPE_REF_TITLE */
1.10 kristaps 92: };
1.7 kristaps 93:
1.44 kristaps 94: static int arg_hasattr(int, const struct mdoc_node *);
1.54 kristaps 95: static int arg_getattrs(const int *, int *, size_t,
96: const struct mdoc_node *);
1.44 kristaps 97: static int arg_getattr(int, const struct mdoc_node *);
98: static size_t arg_offset(const struct mdoc_argv *);
1.54 kristaps 99: static size_t arg_width(const struct mdoc_argv *, int);
1.39 kristaps 100: static int arg_listtype(const struct mdoc_node *);
1.10 kristaps 101:
102: /*
103: * What follows describes prefix and postfix operations for the abstract
104: * syntax tree descent.
105: */
1.1 kristaps 106:
1.10 kristaps 107: #define DECL_ARGS \
108: struct termp *p, \
1.18 kristaps 109: struct termpair *pair, \
1.10 kristaps 110: const struct mdoc_meta *meta, \
111: const struct mdoc_node *node
112:
113: #define DECL_PRE(name) \
114: static int name##_pre(DECL_ARGS)
115: #define DECL_POST(name) \
116: static void name##_post(DECL_ARGS)
117: #define DECL_PREPOST(name) \
118: DECL_PRE(name); \
119: DECL_POST(name);
120:
121: DECL_PREPOST(termp_aq);
1.12 kristaps 122: DECL_PREPOST(termp_bd);
1.15 kristaps 123: DECL_PREPOST(termp_bq);
1.53 kristaps 124: DECL_PREPOST(termp_brq);
1.10 kristaps 125: DECL_PREPOST(termp_d1);
126: DECL_PREPOST(termp_dq);
127: DECL_PREPOST(termp_fd);
128: DECL_PREPOST(termp_fn);
1.16 kristaps 129: DECL_PREPOST(termp_fo);
1.10 kristaps 130: DECL_PREPOST(termp_ft);
1.30 kristaps 131: DECL_PREPOST(termp_in);
1.10 kristaps 132: DECL_PREPOST(termp_it);
1.47 kristaps 133: DECL_PREPOST(termp_lb);
1.10 kristaps 134: DECL_PREPOST(termp_op);
135: DECL_PREPOST(termp_pf);
1.15 kristaps 136: DECL_PREPOST(termp_pq);
1.10 kristaps 137: DECL_PREPOST(termp_qq);
138: DECL_PREPOST(termp_sh);
139: DECL_PREPOST(termp_ss);
140: DECL_PREPOST(termp_sq);
141: DECL_PREPOST(termp_vt);
142:
1.54 kristaps 143: DECL_PRE(termp__t);
1.48 kristaps 144: DECL_PRE(termp_ap);
1.18 kristaps 145: DECL_PRE(termp_ar);
1.14 kristaps 146: DECL_PRE(termp_at);
1.18 kristaps 147: DECL_PRE(termp_bf);
1.15 kristaps 148: DECL_PRE(termp_bsx);
1.17 kristaps 149: DECL_PRE(termp_bt);
1.18 kristaps 150: DECL_PRE(termp_cd);
151: DECL_PRE(termp_cm);
1.61 kristaps 152: DECL_PRE(termp_dx);
1.18 kristaps 153: DECL_PRE(termp_em);
1.10 kristaps 154: DECL_PRE(termp_ex);
1.18 kristaps 155: DECL_PRE(termp_fa);
156: DECL_PRE(termp_fl);
1.16 kristaps 157: DECL_PRE(termp_fx);
1.18 kristaps 158: DECL_PRE(termp_ic);
1.51 kristaps 159: DECL_PRE(termp_lk);
1.18 kristaps 160: DECL_PRE(termp_ms);
1.51 kristaps 161: DECL_PRE(termp_mt);
1.10 kristaps 162: DECL_PRE(termp_nd);
1.18 kristaps 163: DECL_PRE(termp_nm);
1.10 kristaps 164: DECL_PRE(termp_ns);
165: DECL_PRE(termp_nx);
166: DECL_PRE(termp_ox);
1.18 kristaps 167: DECL_PRE(termp_pa);
1.10 kristaps 168: DECL_PRE(termp_pp);
1.28 kristaps 169: DECL_PRE(termp_rs);
1.14 kristaps 170: DECL_PRE(termp_rv);
1.22 kristaps 171: DECL_PRE(termp_sm);
1.14 kristaps 172: DECL_PRE(termp_st);
1.18 kristaps 173: DECL_PRE(termp_sx);
174: DECL_PRE(termp_sy);
1.10 kristaps 175: DECL_PRE(termp_ud);
1.16 kristaps 176: DECL_PRE(termp_ux);
1.18 kristaps 177: DECL_PRE(termp_va);
1.10 kristaps 178: DECL_PRE(termp_xr);
179:
1.28 kristaps 180: DECL_POST(termp___);
1.10 kristaps 181: DECL_POST(termp_bl);
1.31 kristaps 182: DECL_POST(termp_bx);
1.10 kristaps 183:
184: const struct termact __termacts[MDOC_MAX] = {
185: { NULL, NULL }, /* \" */
186: { NULL, NULL }, /* Dd */
187: { NULL, NULL }, /* Dt */
188: { NULL, NULL }, /* Os */
189: { termp_sh_pre, termp_sh_post }, /* Sh */
190: { termp_ss_pre, termp_ss_post }, /* Ss */
191: { termp_pp_pre, NULL }, /* Pp */
192: { termp_d1_pre, termp_d1_post }, /* D1 */
1.29 kristaps 193: { termp_d1_pre, termp_d1_post }, /* Dl */
1.12 kristaps 194: { termp_bd_pre, termp_bd_post }, /* Bd */
1.10 kristaps 195: { NULL, NULL }, /* Ed */
196: { NULL, termp_bl_post }, /* Bl */
197: { NULL, NULL }, /* El */
198: { termp_it_pre, termp_it_post }, /* It */
199: { NULL, NULL }, /* Ad */
200: { NULL, NULL }, /* An */
1.18 kristaps 201: { termp_ar_pre, NULL }, /* Ar */
202: { termp_cd_pre, NULL }, /* Cd */
203: { termp_cm_pre, NULL }, /* Cm */
1.10 kristaps 204: { NULL, NULL }, /* Dv */
205: { NULL, NULL }, /* Er */
206: { NULL, NULL }, /* Ev */
207: { termp_ex_pre, NULL }, /* Ex */
1.18 kristaps 208: { termp_fa_pre, NULL }, /* Fa */
1.10 kristaps 209: { termp_fd_pre, termp_fd_post }, /* Fd */
1.18 kristaps 210: { termp_fl_pre, NULL }, /* Fl */
1.10 kristaps 211: { termp_fn_pre, termp_fn_post }, /* Fn */
212: { termp_ft_pre, termp_ft_post }, /* Ft */
1.18 kristaps 213: { termp_ic_pre, NULL }, /* Ic */
1.30 kristaps 214: { termp_in_pre, termp_in_post }, /* In */
1.10 kristaps 215: { NULL, NULL }, /* Li */
216: { termp_nd_pre, NULL }, /* Nd */
1.18 kristaps 217: { termp_nm_pre, NULL }, /* Nm */
1.10 kristaps 218: { termp_op_pre, termp_op_post }, /* Op */
219: { NULL, NULL }, /* Ot */
1.18 kristaps 220: { termp_pa_pre, NULL }, /* Pa */
1.14 kristaps 221: { termp_rv_pre, NULL }, /* Rv */
222: { termp_st_pre, NULL }, /* St */
1.18 kristaps 223: { termp_va_pre, NULL }, /* Va */
1.10 kristaps 224: { termp_vt_pre, termp_vt_post }, /* Vt */
225: { termp_xr_pre, NULL }, /* Xr */
1.28 kristaps 226: { NULL, termp____post }, /* %A */
1.29 kristaps 227: { NULL, termp____post }, /* %B */
1.28 kristaps 228: { NULL, termp____post }, /* %D */
1.29 kristaps 229: { NULL, termp____post }, /* %I */
1.28 kristaps 230: { NULL, termp____post }, /* %J */
1.29 kristaps 231: { NULL, termp____post }, /* %N */
232: { NULL, termp____post }, /* %O */
233: { NULL, termp____post }, /* %P */
234: { NULL, termp____post }, /* %R */
1.54 kristaps 235: { termp__t_pre, termp____post }, /* %T */
1.29 kristaps 236: { NULL, termp____post }, /* %V */
1.10 kristaps 237: { NULL, NULL }, /* Ac */
1.14 kristaps 238: { termp_aq_pre, termp_aq_post }, /* Ao */
1.10 kristaps 239: { termp_aq_pre, termp_aq_post }, /* Aq */
1.14 kristaps 240: { termp_at_pre, NULL }, /* At */
1.10 kristaps 241: { NULL, NULL }, /* Bc */
1.18 kristaps 242: { termp_bf_pre, NULL }, /* Bf */
1.15 kristaps 243: { termp_bq_pre, termp_bq_post }, /* Bo */
244: { termp_bq_pre, termp_bq_post }, /* Bq */
245: { termp_bsx_pre, NULL }, /* Bsx */
1.31 kristaps 246: { NULL, termp_bx_post }, /* Bx */
1.10 kristaps 247: { NULL, NULL }, /* Db */
248: { NULL, NULL }, /* Dc */
1.15 kristaps 249: { termp_dq_pre, termp_dq_post }, /* Do */
1.10 kristaps 250: { termp_dq_pre, termp_dq_post }, /* Dq */
251: { NULL, NULL }, /* Ec */
252: { NULL, NULL }, /* Ef */
1.18 kristaps 253: { termp_em_pre, NULL }, /* Em */
1.10 kristaps 254: { NULL, NULL }, /* Eo */
1.16 kristaps 255: { termp_fx_pre, NULL }, /* Fx */
1.18 kristaps 256: { termp_ms_pre, NULL }, /* Ms */
1.10 kristaps 257: { NULL, NULL }, /* No */
258: { termp_ns_pre, NULL }, /* Ns */
259: { termp_nx_pre, NULL }, /* Nx */
260: { termp_ox_pre, NULL }, /* Ox */
261: { NULL, NULL }, /* Pc */
262: { termp_pf_pre, termp_pf_post }, /* Pf */
1.15 kristaps 263: { termp_pq_pre, termp_pq_post }, /* Po */
264: { termp_pq_pre, termp_pq_post }, /* Pq */
1.10 kristaps 265: { NULL, NULL }, /* Qc */
1.16 kristaps 266: { termp_sq_pre, termp_sq_post }, /* Ql */
1.15 kristaps 267: { termp_qq_pre, termp_qq_post }, /* Qo */
1.10 kristaps 268: { termp_qq_pre, termp_qq_post }, /* Qq */
269: { NULL, NULL }, /* Re */
1.28 kristaps 270: { termp_rs_pre, NULL }, /* Rs */
1.10 kristaps 271: { NULL, NULL }, /* Sc */
1.15 kristaps 272: { termp_sq_pre, termp_sq_post }, /* So */
1.10 kristaps 273: { termp_sq_pre, termp_sq_post }, /* Sq */
1.22 kristaps 274: { termp_sm_pre, NULL }, /* Sm */
1.18 kristaps 275: { termp_sx_pre, NULL }, /* Sx */
276: { termp_sy_pre, NULL }, /* Sy */
1.10 kristaps 277: { NULL, NULL }, /* Tn */
1.16 kristaps 278: { termp_ux_pre, NULL }, /* Ux */
1.10 kristaps 279: { NULL, NULL }, /* Xc */
280: { NULL, NULL }, /* Xo */
1.16 kristaps 281: { termp_fo_pre, termp_fo_post }, /* Fo */
1.10 kristaps 282: { NULL, NULL }, /* Fc */
1.16 kristaps 283: { termp_op_pre, termp_op_post }, /* Oo */
1.10 kristaps 284: { NULL, NULL }, /* Oc */
285: { NULL, NULL }, /* Bk */
286: { NULL, NULL }, /* Ek */
1.17 kristaps 287: { termp_bt_pre, NULL }, /* Bt */
1.10 kristaps 288: { NULL, NULL }, /* Hf */
289: { NULL, NULL }, /* Fr */
290: { termp_ud_pre, NULL }, /* Ud */
1.47 kristaps 291: { termp_lb_pre, termp_lb_post }, /* Lb */
1.48 kristaps 292: { termp_ap_pre, NULL }, /* Lb */
1.49 kristaps 293: { termp_pp_pre, NULL }, /* Pp */
1.51 kristaps 294: { termp_lk_pre, NULL }, /* Lk */
295: { termp_mt_pre, NULL }, /* Mt */
1.53 kristaps 296: { termp_brq_pre, termp_brq_post }, /* Brq */
297: { termp_brq_pre, termp_brq_post }, /* Bro */
298: { NULL, NULL }, /* Brc */
1.57 kristaps 299: { NULL, NULL }, /* %C */
1.60 kristaps 300: { NULL, NULL }, /* Es */
301: { NULL, NULL }, /* En */
1.61 kristaps 302: { termp_dx_pre, NULL }, /* Dx */
1.2 kristaps 303: };
304:
1.10 kristaps 305: const struct termact *termacts = __termacts;
306:
307:
308: static size_t
1.54 kristaps 309: arg_width(const struct mdoc_argv *arg, int pos)
1.10 kristaps 310: {
1.27 kristaps 311: size_t v;
312: int i, len;
1.12 kristaps 313:
1.54 kristaps 314: assert(pos < (int)arg->sz && pos >= 0);
315: assert(arg->value[pos]);
316: if (0 == strcmp(arg->value[pos], "indent"))
1.25 kristaps 317: return(INDENT);
1.54 kristaps 318: if (0 == strcmp(arg->value[pos], "indent-two"))
1.25 kristaps 319: return(INDENT * 2);
320:
1.54 kristaps 321: len = (int)strlen(arg->value[pos]);
1.25 kristaps 322: assert(len > 0);
323:
324: for (i = 0; i < len - 1; i++)
1.54 kristaps 325: if ( ! isdigit((u_char)arg->value[pos][i]))
1.25 kristaps 326: break;
327:
328: if (i == len - 1) {
1.54 kristaps 329: if ('n' == arg->value[pos][len - 1]) {
330: v = (size_t)atoi(arg->value[pos]);
1.25 kristaps 331: return(v);
332: }
333:
334: }
1.54 kristaps 335: return(strlen(arg->value[pos]) + 1);
1.12 kristaps 336: }
337:
338:
1.39 kristaps 339: static int
340: arg_listtype(const struct mdoc_node *n)
341: {
342: int i, len;
343:
1.44 kristaps 344: assert(MDOC_BLOCK == n->type);
345:
1.46 kristaps 346: len = (int)(n->args ? n->args->argc : 0);
1.39 kristaps 347:
348: for (i = 0; i < len; i++)
1.44 kristaps 349: switch (n->args->argv[i].arg) {
1.39 kristaps 350: case (MDOC_Bullet):
351: /* FALLTHROUGH */
352: case (MDOC_Dash):
353: /* FALLTHROUGH */
354: case (MDOC_Enum):
355: /* FALLTHROUGH */
356: case (MDOC_Hyphen):
357: /* FALLTHROUGH */
358: case (MDOC_Tag):
359: /* FALLTHROUGH */
360: case (MDOC_Inset):
361: /* FALLTHROUGH */
362: case (MDOC_Diag):
363: /* FALLTHROUGH */
364: case (MDOC_Item):
365: /* FALLTHROUGH */
1.54 kristaps 366: case (MDOC_Column):
367: /* FALLTHROUGH */
1.39 kristaps 368: case (MDOC_Ohang):
1.44 kristaps 369: return(n->args->argv[i].arg);
1.39 kristaps 370: default:
371: break;
372: }
373:
374: errx(1, "list type not supported");
375: /* NOTREACHED */
376: }
377:
378:
1.12 kristaps 379: static size_t
1.44 kristaps 380: arg_offset(const struct mdoc_argv *arg)
1.12 kristaps 381: {
382:
383: /* TODO */
384: assert(*arg->value);
385: if (0 == strcmp(*arg->value, "indent"))
1.10 kristaps 386: return(INDENT);
1.12 kristaps 387: if (0 == strcmp(*arg->value, "indent-two"))
1.10 kristaps 388: return(INDENT * 2);
1.12 kristaps 389: return(strlen(*arg->value));
1.10 kristaps 390: }
391:
1.3 kristaps 392:
1.10 kristaps 393: static int
1.44 kristaps 394: arg_hasattr(int arg, const struct mdoc_node *n)
1.2 kristaps 395: {
396:
1.44 kristaps 397: return(-1 != arg_getattr(arg, n));
1.10 kristaps 398: }
399:
400:
401: static int
1.54 kristaps 402: arg_getattr(int v, const struct mdoc_node *n)
403: {
404: int val;
405:
406: return(arg_getattrs(&v, &val, 1, n) ? val : -1);
407: }
408:
409:
410: static int
411: arg_getattrs(const int *keys, int *vals,
412: size_t sz, const struct mdoc_node *n)
1.10 kristaps 413: {
1.54 kristaps 414: int i, j, k;
1.10 kristaps 415:
1.44 kristaps 416: if (NULL == n->args)
1.54 kristaps 417: return(0);
418:
419: for (k = i = 0; i < (int)n->args->argc; i++)
420: for (j = 0; j < (int)sz; j++)
421: if (n->args->argv[i].arg == keys[j]) {
422: vals[j] = i;
423: k++;
424: }
425: return(k);
1.10 kristaps 426: }
427:
428:
429: /* ARGSUSED */
430: static int
431: termp_dq_pre(DECL_ARGS)
432: {
433:
434: if (MDOC_BODY != node->type)
435: return(1);
436:
1.62 ! kristaps 437: term_word(p, "\\(lq");
1.10 kristaps 438: p->flags |= TERMP_NOSPACE;
439: return(1);
440: }
441:
442:
443: /* ARGSUSED */
444: static void
445: termp_dq_post(DECL_ARGS)
446: {
447:
448: if (MDOC_BODY != node->type)
449: return;
1.3 kristaps 450:
1.10 kristaps 451: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 452: term_word(p, "\\(rq");
1.10 kristaps 453: }
1.2 kristaps 454:
1.3 kristaps 455:
1.10 kristaps 456: /* ARGSUSED */
1.20 kristaps 457: static int
1.39 kristaps 458: termp_it_pre_block(DECL_ARGS)
459: {
460:
1.62 ! kristaps 461: term_newln(p);
1.44 kristaps 462: if ( ! arg_hasattr(MDOC_Compact, node->parent->parent))
1.62 ! kristaps 463: term_vspace(p);
1.39 kristaps 464:
465: return(1);
466: }
467:
468:
469: /* ARGSUSED */
470: static int
1.20 kristaps 471: termp_it_pre(DECL_ARGS)
1.10 kristaps 472: {
1.54 kristaps 473: const struct mdoc_node *bl, *n;
474: char buf[7];
475: int i, type, keys[3], vals[3];
476: size_t width, offset;
1.2 kristaps 477:
1.39 kristaps 478: if (MDOC_BLOCK == node->type)
479: return(termp_it_pre_block(p, pair, meta, node));
1.8 kristaps 480:
1.44 kristaps 481: bl = node->parent->parent->parent;
1.23 kristaps 482:
1.39 kristaps 483: /* Save parent attributes. */
1.23 kristaps 484:
1.20 kristaps 485: pair->offset = p->offset;
486: pair->rmargin = p->rmargin;
1.39 kristaps 487: pair->flag = p->flags;
1.20 kristaps 488:
1.23 kristaps 489: /* Get list width and offset. */
490:
1.54 kristaps 491: keys[0] = MDOC_Width;
492: keys[1] = MDOC_Offset;
493: keys[2] = MDOC_Column;
494:
495: vals[0] = vals[1] = vals[2] = -1;
496:
497: width = offset = 0;
498:
499: (void)arg_getattrs(keys, vals, 3, bl);
500:
501: type = arg_listtype(bl);
502:
503: /* Calculate real width and offset. */
1.20 kristaps 504:
1.54 kristaps 505: switch (type) {
506: case (MDOC_Column):
507: if (MDOC_BODY == node->type)
508: break;
509: for (i = 0, n = node->prev; n; n = n->prev, i++)
510: offset += arg_width
511: (&bl->args->argv[vals[2]], i);
512: assert(i < (int)bl->args->argv[vals[2]].sz);
513: width = arg_width(&bl->args->argv[vals[2]], i);
1.56 kristaps 514: if (vals[1] >= 0)
515: offset += arg_offset(&bl->args->argv[vals[1]]);
1.54 kristaps 516: break;
517: default:
518: if (vals[0] >= 0)
519: width = arg_width(&bl->args->argv[vals[0]], 0);
520: if (vals[1] >= 0)
521: offset = arg_offset(&bl->args->argv[vals[1]]);
522: break;
523: }
1.20 kristaps 524:
1.39 kristaps 525: /*
526: * List-type can override the width in the case of fixed-head
527: * values (bullet, dash/hyphen, enum). Tags need a non-zero
528: * offset.
529: */
1.10 kristaps 530:
1.23 kristaps 531: switch (type) {
532: case (MDOC_Bullet):
533: /* FALLTHROUGH */
534: case (MDOC_Dash):
535: /* FALLTHROUGH */
536: case (MDOC_Enum):
537: /* FALLTHROUGH */
538: case (MDOC_Hyphen):
1.55 kristaps 539: if (width < 4)
1.54 kristaps 540: width = 4;
1.23 kristaps 541: break;
542: case (MDOC_Tag):
1.54 kristaps 543: if (0 == width)
544: width = 10;
545: break;
1.23 kristaps 546: default:
547: break;
548: }
1.10 kristaps 549:
1.39 kristaps 550: /*
551: * Whitespace control. Inset bodies need an initial space.
552: */
1.21 kristaps 553:
1.23 kristaps 554: switch (type) {
1.37 kristaps 555: case (MDOC_Diag):
556: /* FALLTHROUGH */
557: case (MDOC_Inset):
1.39 kristaps 558: if (MDOC_BODY == node->type)
559: p->flags &= ~TERMP_NOSPACE;
560: else
561: p->flags |= TERMP_NOSPACE;
562: break;
563: default:
564: p->flags |= TERMP_NOSPACE;
565: break;
566: }
567:
568: /*
569: * Style flags. Diagnostic heads need TTYPE_DIAG.
570: */
571:
572: switch (type) {
573: case (MDOC_Diag):
1.37 kristaps 574: if (MDOC_HEAD == node->type)
1.39 kristaps 575: p->flags |= ttypes[TTYPE_DIAG];
576: break;
577: default:
1.37 kristaps 578: break;
1.39 kristaps 579: }
580:
581: /*
582: * Pad and break control. This is the tricker part. Lists with
583: * set right-margins for the head get TERMP_NOBREAK because, if
584: * they overrun the margin, they wrap to the new margin.
585: * Correspondingly, the body for these types don't left-pad, as
586: * the head will pad out to to the right.
587: */
588:
589: switch (type) {
1.23 kristaps 590: case (MDOC_Bullet):
591: /* FALLTHROUGH */
592: case (MDOC_Dash):
593: /* FALLTHROUGH */
594: case (MDOC_Enum):
595: /* FALLTHROUGH */
596: case (MDOC_Hyphen):
597: /* FALLTHROUGH */
598: case (MDOC_Tag):
599: if (MDOC_HEAD == node->type)
600: p->flags |= TERMP_NOBREAK;
1.39 kristaps 601: else
1.23 kristaps 602: p->flags |= TERMP_NOLPAD;
1.41 kristaps 603: if (MDOC_HEAD == node->type && MDOC_Tag == type)
604: if (NULL == node->next ||
605: NULL == node->next->child)
606: p->flags |= TERMP_NONOBREAK;
1.23 kristaps 607: break;
1.54 kristaps 608: case (MDOC_Column):
609: if (MDOC_HEAD == node->type) {
610: assert(node->next);
611: if (MDOC_BODY == node->next->type)
612: p->flags &= ~TERMP_NOBREAK;
613: else
614: p->flags |= TERMP_NOBREAK;
615: if (node->prev)
616: p->flags |= TERMP_NOLPAD;
617: }
618: break;
1.39 kristaps 619: case (MDOC_Diag):
620: if (MDOC_HEAD == node->type)
621: p->flags |= TERMP_NOBREAK;
622: break;
1.24 kristaps 623: default:
1.23 kristaps 624: break;
625: }
1.21 kristaps 626:
1.23 kristaps 627: /*
1.39 kristaps 628: * Margin control. Set-head-width lists have their right
629: * margins shortened. The body for these lists has the offset
630: * necessarily lengthened. Everybody gets the offset.
1.23 kristaps 631: */
1.21 kristaps 632:
633: p->offset += offset;
1.23 kristaps 634:
635: switch (type) {
636: case (MDOC_Bullet):
637: /* FALLTHROUGH */
638: case (MDOC_Dash):
639: /* FALLTHROUGH */
640: case (MDOC_Enum):
641: /* FALLTHROUGH */
642: case (MDOC_Hyphen):
643: /* FALLTHROUGH */
644: case (MDOC_Tag):
645: if (MDOC_HEAD == node->type)
646: p->rmargin = p->offset + width;
1.39 kristaps 647: else
1.23 kristaps 648: p->offset += width;
1.54 kristaps 649: break;
650: case (MDOC_Column):
651: p->rmargin = p->offset + width;
652: break;
1.24 kristaps 653: default:
1.23 kristaps 654: break;
655: }
656:
1.39 kristaps 657: /*
658: * The dash, hyphen, bullet and enum lists all have a special
659: * HEAD character. Print it now.
660: */
661:
662: if (MDOC_HEAD == node->type)
663: switch (type) {
664: case (MDOC_Bullet):
1.62 ! kristaps 665: term_word(p, "\\[bu]");
1.39 kristaps 666: break;
667: case (MDOC_Dash):
668: /* FALLTHROUGH */
669: case (MDOC_Hyphen):
1.62 ! kristaps 670: term_word(p, "\\-");
1.39 kristaps 671: break;
672: case (MDOC_Enum):
673: (pair->ppair->ppair->count)++;
674: (void)snprintf(buf, sizeof(buf), "%d.",
675: pair->ppair->ppair->count);
1.62 ! kristaps 676: term_word(p, buf);
1.39 kristaps 677: break;
678: default:
679: break;
680: }
681:
682: /*
1.54 kristaps 683: * If we're not going to process our children, indicate so here.
1.39 kristaps 684: */
685:
1.54 kristaps 686: switch (type) {
687: case (MDOC_Bullet):
688: /* FALLTHROUGH */
689: case (MDOC_Item):
690: /* FALLTHROUGH */
691: case (MDOC_Dash):
692: /* FALLTHROUGH */
693: case (MDOC_Hyphen):
694: /* FALLTHROUGH */
695: case (MDOC_Enum):
696: if (MDOC_HEAD == node->type)
697: return(0);
698: break;
699: case (MDOC_Column):
700: if (MDOC_BODY == node->type)
1.39 kristaps 701: return(0);
1.54 kristaps 702: break;
703: default:
704: break;
1.39 kristaps 705: }
1.23 kristaps 706:
1.39 kristaps 707: return(1);
1.10 kristaps 708: }
709:
710:
711: /* ARGSUSED */
1.20 kristaps 712: static void
713: termp_it_post(DECL_ARGS)
1.10 kristaps 714: {
1.39 kristaps 715: int type;
1.3 kristaps 716:
1.21 kristaps 717: if (MDOC_BODY != node->type && MDOC_HEAD != node->type)
1.20 kristaps 718: return;
1.10 kristaps 719:
1.39 kristaps 720: type = arg_listtype(node->parent->parent->parent);
1.37 kristaps 721:
722: switch (type) {
723: case (MDOC_Diag):
724: /* FALLTHROUGH */
1.39 kristaps 725: case (MDOC_Item):
726: /* FALLTHROUGH */
1.37 kristaps 727: case (MDOC_Inset):
1.54 kristaps 728: if (MDOC_BODY == node->type)
1.62 ! kristaps 729: term_flushln(p);
1.54 kristaps 730: break;
731: case (MDOC_Column):
732: if (MDOC_HEAD == node->type)
1.62 ! kristaps 733: term_flushln(p);
1.37 kristaps 734: break;
735: default:
1.62 ! kristaps 736: term_flushln(p);
1.37 kristaps 737: break;
738: }
1.10 kristaps 739:
1.23 kristaps 740: p->offset = pair->offset;
741: p->rmargin = pair->rmargin;
1.39 kristaps 742: p->flags = pair->flag;
1.2 kristaps 743: }
744:
745:
1.10 kristaps 746: /* ARGSUSED */
1.18 kristaps 747: static int
748: termp_nm_pre(DECL_ARGS)
1.10 kristaps 749: {
750:
1.29 kristaps 751: if (SEC_SYNOPSIS == node->sec)
1.62 ! kristaps 752: term_newln(p);
1.29 kristaps 753:
1.31 kristaps 754: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_PROG]);
1.18 kristaps 755: if (NULL == node->child)
1.62 ! kristaps 756: term_word(p, meta->name);
1.31 kristaps 757:
1.18 kristaps 758: return(1);
1.10 kristaps 759: }
760:
761:
762: /* ARGSUSED */
1.18 kristaps 763: static int
764: termp_fl_pre(DECL_ARGS)
1.10 kristaps 765: {
766:
1.31 kristaps 767: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_FLAG]);
1.62 ! kristaps 768: term_word(p, "\\-");
1.18 kristaps 769: p->flags |= TERMP_NOSPACE;
770: return(1);
1.10 kristaps 771: }
772:
773:
774: /* ARGSUSED */
775: static int
776: termp_ar_pre(DECL_ARGS)
777: {
778:
1.31 kristaps 779: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_ARG]);
1.10 kristaps 780: return(1);
781: }
782:
783:
784: /* ARGSUSED */
785: static int
786: termp_ns_pre(DECL_ARGS)
1.2 kristaps 787: {
788:
789: p->flags |= TERMP_NOSPACE;
1.10 kristaps 790: return(1);
791: }
792:
793:
794: /* ARGSUSED */
795: static int
796: termp_pp_pre(DECL_ARGS)
797: {
798:
1.62 ! kristaps 799: term_vspace(p);
1.10 kristaps 800: return(1);
801: }
802:
803:
804: /* ARGSUSED */
805: static int
1.14 kristaps 806: termp_st_pre(DECL_ARGS)
807: {
1.43 kristaps 808: const char *cp;
1.14 kristaps 809:
1.52 kristaps 810: if (node->child && (cp = mdoc_a2st(node->child->string)))
1.62 ! kristaps 811: term_word(p, cp);
1.43 kristaps 812: return(0);
1.14 kristaps 813: }
814:
815:
816: /* ARGSUSED */
817: static int
1.28 kristaps 818: termp_rs_pre(DECL_ARGS)
819: {
820:
1.30 kristaps 821: if (MDOC_BLOCK == node->type && node->prev)
1.62 ! kristaps 822: term_vspace(p);
1.28 kristaps 823: return(1);
824: }
825:
826:
827: /* ARGSUSED */
828: static int
1.14 kristaps 829: termp_rv_pre(DECL_ARGS)
830: {
831: int i;
832:
1.44 kristaps 833: if (-1 == (i = arg_getattr(MDOC_Std, node)))
834: errx(1, "expected -std argument");
835: if (1 != node->args->argv[i].sz)
836: errx(1, "expected -std argument");
1.14 kristaps 837:
1.62 ! kristaps 838: term_newln(p);
! 839: term_word(p, "The");
1.14 kristaps 840:
841: p->flags |= ttypes[TTYPE_FUNC_NAME];
1.62 ! kristaps 842: term_word(p, *node->args->argv[i].value);
1.14 kristaps 843: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1.57 kristaps 844: p->flags |= TERMP_NOSPACE;
1.14 kristaps 845:
1.62 ! kristaps 846: term_word(p, "() function returns the value 0 if successful;");
! 847: term_word(p, "otherwise the value -1 is returned and the");
! 848: term_word(p, "global variable");
1.14 kristaps 849:
850: p->flags |= ttypes[TTYPE_VAR_DECL];
1.62 ! kristaps 851: term_word(p, "errno");
1.14 kristaps 852: p->flags &= ~ttypes[TTYPE_VAR_DECL];
853:
1.62 ! kristaps 854: term_word(p, "is set to indicate the error.");
1.14 kristaps 855:
856: return(1);
857: }
858:
859:
860: /* ARGSUSED */
861: static int
1.10 kristaps 862: termp_ex_pre(DECL_ARGS)
863: {
864: int i;
865:
1.44 kristaps 866: if (-1 == (i = arg_getattr(MDOC_Std, node)))
867: errx(1, "expected -std argument");
868: if (1 != node->args->argv[i].sz)
869: errx(1, "expected -std argument");
1.10 kristaps 870:
1.62 ! kristaps 871: term_word(p, "The");
1.10 kristaps 872: p->flags |= ttypes[TTYPE_PROG];
1.62 ! kristaps 873: term_word(p, *node->args->argv[i].value);
1.10 kristaps 874: p->flags &= ~ttypes[TTYPE_PROG];
1.62 ! kristaps 875: term_word(p, "utility exits 0 on success, and >0 if an error occurs.");
1.10 kristaps 876:
877: return(1);
878: }
879:
880:
881: /* ARGSUSED */
882: static int
883: termp_nd_pre(DECL_ARGS)
884: {
885:
1.62 ! kristaps 886: term_word(p, "\\-");
1.10 kristaps 887: return(1);
888: }
889:
890:
891: /* ARGSUSED */
892: static void
893: termp_bl_post(DECL_ARGS)
894: {
895:
896: if (MDOC_BLOCK == node->type)
1.62 ! kristaps 897: term_newln(p);
1.10 kristaps 898: }
899:
900:
901: /* ARGSUSED */
902: static void
903: termp_op_post(DECL_ARGS)
904: {
905:
906: if (MDOC_BODY != node->type)
1.2 kristaps 907: return;
1.10 kristaps 908: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 909: term_word(p, "\\(rB");
1.10 kristaps 910: }
911:
912:
913: /* ARGSUSED */
914: static int
915: termp_xr_pre(DECL_ARGS)
916: {
917: const struct mdoc_node *n;
918:
1.44 kristaps 919: if (NULL == (n = node->child))
920: errx(1, "expected text line argument");
1.62 ! kristaps 921: term_word(p, n->string);
1.10 kristaps 922: if (NULL == (n = n->next))
923: return(0);
924: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 925: term_word(p, "(");
1.10 kristaps 926: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 927: term_word(p, n->string);
1.10 kristaps 928: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 929: term_word(p, ")");
1.10 kristaps 930: return(0);
1.2 kristaps 931: }
932:
933:
1.10 kristaps 934: /* ARGSUSED */
935: static int
936: termp_vt_pre(DECL_ARGS)
1.2 kristaps 937: {
938:
1.10 kristaps 939: /* FIXME: this can be "type name". */
1.31 kristaps 940: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
1.10 kristaps 941: return(1);
1.2 kristaps 942: }
943:
944:
1.10 kristaps 945: /* ARGSUSED */
1.2 kristaps 946: static void
1.10 kristaps 947: termp_vt_post(DECL_ARGS)
948: {
949:
950: if (node->sec == SEC_SYNOPSIS)
1.62 ! kristaps 951: term_vspace(p);
1.10 kristaps 952: }
953:
954:
955: /* ARGSUSED */
956: static int
957: termp_fd_pre(DECL_ARGS)
1.2 kristaps 958: {
959:
1.10 kristaps 960: /*
961: * FIXME: this naming is bad. This value is used, in general,
962: * for the #include header or other preprocessor statement.
963: */
1.31 kristaps 964: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_DECL]);
1.10 kristaps 965: return(1);
1.2 kristaps 966: }
967:
968:
1.10 kristaps 969: /* ARGSUSED */
1.2 kristaps 970: static void
1.10 kristaps 971: termp_fd_post(DECL_ARGS)
1.2 kristaps 972: {
973:
1.30 kristaps 974: if (node->sec != SEC_SYNOPSIS)
975: return;
1.62 ! kristaps 976: term_newln(p);
1.30 kristaps 977: if (node->next && MDOC_Fd != node->next->tok)
1.62 ! kristaps 978: term_vspace(p);
1.10 kristaps 979: }
980:
981:
982: /* ARGSUSED */
983: static int
984: termp_sh_pre(DECL_ARGS)
985: {
1.2 kristaps 986:
1.10 kristaps 987: switch (node->type) {
988: case (MDOC_HEAD):
1.62 ! kristaps 989: term_vspace(p);
1.31 kristaps 990: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SECTION]);
1.2 kristaps 991: break;
1.10 kristaps 992: case (MDOC_BODY):
993: p->offset = INDENT;
1.2 kristaps 994: break;
1.10 kristaps 995: default:
996: break;
997: }
998: return(1);
999: }
1000:
1001:
1002: /* ARGSUSED */
1.19 kristaps 1003: static void
1004: termp_sh_post(DECL_ARGS)
1005: {
1006:
1007: switch (node->type) {
1008: case (MDOC_HEAD):
1.62 ! kristaps 1009: term_newln(p);
1.19 kristaps 1010: break;
1011: case (MDOC_BODY):
1.62 ! kristaps 1012: term_newln(p);
1.19 kristaps 1013: p->offset = 0;
1014: break;
1015: default:
1016: break;
1017: }
1018: }
1019:
1020:
1021: /* ARGSUSED */
1.10 kristaps 1022: static int
1023: termp_op_pre(DECL_ARGS)
1024: {
1025:
1026: switch (node->type) {
1027: case (MDOC_BODY):
1.62 ! kristaps 1028: term_word(p, "\\(lB");
1.10 kristaps 1029: p->flags |= TERMP_NOSPACE;
1.2 kristaps 1030: break;
1031: default:
1.10 kristaps 1032: break;
1.2 kristaps 1033: }
1.10 kristaps 1034: return(1);
1035: }
1036:
1037:
1038: /* ARGSUSED */
1039: static int
1.17 kristaps 1040: termp_bt_pre(DECL_ARGS)
1041: {
1042:
1.62 ! kristaps 1043: term_word(p, "is currently in beta test.");
1.17 kristaps 1044: return(1);
1045: }
1046:
1047:
1048: /* ARGSUSED */
1.47 kristaps 1049: static int
1050: termp_lb_pre(DECL_ARGS)
1051: {
1052: const char *lb;
1053:
1054: if (NULL == node->child)
1055: errx(1, "expected text line argument");
1056: if ((lb = mdoc_a2lib(node->child->string))) {
1.62 ! kristaps 1057: term_word(p, lb);
1.47 kristaps 1058: return(0);
1059: }
1.62 ! kristaps 1060: term_word(p, "library");
1.47 kristaps 1061: return(1);
1062: }
1063:
1064:
1065: /* ARGSUSED */
1.43 kristaps 1066: static void
1067: termp_lb_post(DECL_ARGS)
1068: {
1069:
1.62 ! kristaps 1070: term_newln(p);
1.43 kristaps 1071: }
1072:
1073:
1074: /* ARGSUSED */
1.17 kristaps 1075: static int
1.10 kristaps 1076: termp_ud_pre(DECL_ARGS)
1077: {
1078:
1.62 ! kristaps 1079: term_word(p, "currently under development.");
1.10 kristaps 1080: return(1);
1081: }
1082:
1083:
1084: /* ARGSUSED */
1085: static int
1086: termp_d1_pre(DECL_ARGS)
1087: {
1088:
1089: if (MDOC_BODY != node->type)
1090: return(1);
1.62 ! kristaps 1091: term_newln(p);
1.19 kristaps 1092: p->offset += (pair->offset = INDENT);
1.10 kristaps 1093: return(1);
1.2 kristaps 1094: }
1095:
1096:
1.10 kristaps 1097: /* ARGSUSED */
1.2 kristaps 1098: static void
1.10 kristaps 1099: termp_d1_post(DECL_ARGS)
1100: {
1101:
1102: if (MDOC_BODY != node->type)
1103: return;
1.62 ! kristaps 1104: term_newln(p);
1.19 kristaps 1105: p->offset -= pair->offset;
1.10 kristaps 1106: }
1107:
1108:
1109: /* ARGSUSED */
1110: static int
1111: termp_aq_pre(DECL_ARGS)
1.6 kristaps 1112: {
1113:
1.10 kristaps 1114: if (MDOC_BODY != node->type)
1115: return(1);
1.62 ! kristaps 1116: term_word(p, "\\(la");
1.10 kristaps 1117: p->flags |= TERMP_NOSPACE;
1118: return(1);
1119: }
1.6 kristaps 1120:
1121:
1.10 kristaps 1122: /* ARGSUSED */
1123: static void
1124: termp_aq_post(DECL_ARGS)
1125: {
1.6 kristaps 1126:
1.10 kristaps 1127: if (MDOC_BODY != node->type)
1.6 kristaps 1128: return;
1.10 kristaps 1129: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1130: term_word(p, "\\(ra");
1.10 kristaps 1131: }
1.6 kristaps 1132:
1.10 kristaps 1133:
1134: /* ARGSUSED */
1135: static int
1136: termp_ft_pre(DECL_ARGS)
1137: {
1138:
1.34 kristaps 1139: if (SEC_SYNOPSIS == node->sec)
1140: if (node->prev && MDOC_Fo == node->prev->tok)
1.62 ! kristaps 1141: term_vspace(p);
1.31 kristaps 1142: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_TYPE]);
1.10 kristaps 1143: return(1);
1.6 kristaps 1144: }
1145:
1146:
1.10 kristaps 1147: /* ARGSUSED */
1.6 kristaps 1148: static void
1.10 kristaps 1149: termp_ft_post(DECL_ARGS)
1.2 kristaps 1150: {
1151:
1.34 kristaps 1152: if (SEC_SYNOPSIS == node->sec)
1.62 ! kristaps 1153: term_newln(p);
1.10 kristaps 1154: }
1.2 kristaps 1155:
1156:
1.10 kristaps 1157: /* ARGSUSED */
1158: static int
1159: termp_fn_pre(DECL_ARGS)
1160: {
1161: const struct mdoc_node *n;
1162:
1.44 kristaps 1163: if (NULL == node->child)
1164: errx(1, "expected text line arguments");
1.2 kristaps 1165:
1.10 kristaps 1166: /* FIXME: can be "type funcname" "type varname"... */
1.2 kristaps 1167:
1.10 kristaps 1168: p->flags |= ttypes[TTYPE_FUNC_NAME];
1.62 ! kristaps 1169: term_word(p, node->child->string);
1.10 kristaps 1170: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1171:
1.62 ! kristaps 1172: term_word(p, "(");
1.10 kristaps 1173:
1174: p->flags |= TERMP_NOSPACE;
1175: for (n = node->child->next; n; n = n->next) {
1176: p->flags |= ttypes[TTYPE_FUNC_ARG];
1.62 ! kristaps 1177: term_word(p, n->string);
1.10 kristaps 1178: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1.16 kristaps 1179: if (n->next)
1.62 ! kristaps 1180: term_word(p, ",");
1.6 kristaps 1181: }
1.2 kristaps 1182:
1.62 ! kristaps 1183: term_word(p, ")");
1.10 kristaps 1184:
1185: if (SEC_SYNOPSIS == node->sec)
1.62 ! kristaps 1186: term_word(p, ";");
1.10 kristaps 1187:
1188: return(0);
1.2 kristaps 1189: }
1190:
1191:
1.10 kristaps 1192: /* ARGSUSED */
1193: static void
1194: termp_fn_post(DECL_ARGS)
1.2 kristaps 1195: {
1196:
1.30 kristaps 1197: if (node->sec == SEC_SYNOPSIS && node->next)
1.62 ! kristaps 1198: term_vspace(p);
1.10 kristaps 1199:
1200: }
1.2 kristaps 1201:
1202:
1.10 kristaps 1203: /* ARGSUSED */
1204: static int
1205: termp_sx_pre(DECL_ARGS)
1206: {
1.8 kristaps 1207:
1.31 kristaps 1208: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK]);
1.10 kristaps 1209: return(1);
1.2 kristaps 1210: }
1211:
1212:
1.10 kristaps 1213: /* ARGSUSED */
1214: static int
1215: termp_fa_pre(DECL_ARGS)
1216: {
1.16 kristaps 1217: struct mdoc_node *n;
1218:
1219: if (node->parent->tok != MDOC_Fo) {
1.31 kristaps 1220: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FUNC_ARG]);
1.16 kristaps 1221: return(1);
1222: }
1223:
1224: for (n = node->child; n; n = n->next) {
1225: p->flags |= ttypes[TTYPE_FUNC_ARG];
1.62 ! kristaps 1226: term_word(p, n->string);
1.16 kristaps 1227: p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1228: if (n->next)
1.62 ! kristaps 1229: term_word(p, ",");
1.16 kristaps 1230: }
1231:
1232: if (node->next && node->next->tok == MDOC_Fa)
1.62 ! kristaps 1233: term_word(p, ",");
1.2 kristaps 1234:
1.16 kristaps 1235: return(0);
1.10 kristaps 1236: }
1.2 kristaps 1237:
1238:
1.10 kristaps 1239: /* ARGSUSED */
1240: static int
1241: termp_va_pre(DECL_ARGS)
1242: {
1.2 kristaps 1243:
1.31 kristaps 1244: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_VAR_DECL]);
1.10 kristaps 1245: return(1);
1.2 kristaps 1246: }
1247:
1248:
1.10 kristaps 1249: /* ARGSUSED */
1250: static int
1251: termp_bd_pre(DECL_ARGS)
1252: {
1.62 ! kristaps 1253: int i, type, ln;
! 1254:
! 1255: /*
! 1256: * This is fairly tricky due primarily to crappy documentation.
! 1257: * If -ragged or -filled are specified, the block does nothing
! 1258: * but change the indentation.
! 1259: *
! 1260: * If, on the other hand, -unfilled or -literal are specified,
! 1261: * then the game changes. Text is printed exactly as entered in
! 1262: * the display: if a macro line, a newline is appended to the
! 1263: * line. Blank lines are allowed.
! 1264: */
1.1 kristaps 1265:
1.10 kristaps 1266: if (MDOC_BLOCK == node->type) {
1.54 kristaps 1267: /* FIXME: parent prev? */
1.30 kristaps 1268: if (node->prev)
1.62 ! kristaps 1269: term_vspace(p);
1.10 kristaps 1270: return(1);
1271: } else if (MDOC_BODY != node->type)
1272: return(1);
1273:
1.44 kristaps 1274: if (NULL == node->parent->args)
1275: errx(1, "missing display type");
1276:
1.20 kristaps 1277: pair->offset = p->offset;
1.10 kristaps 1278:
1.44 kristaps 1279: for (type = -1, i = 0;
1280: i < (int)node->parent->args->argc; i++) {
1281: switch (node->parent->args->argv[i].arg) {
1.35 kristaps 1282: case (MDOC_Ragged):
1283: /* FALLTHROUGH */
1284: case (MDOC_Filled):
1285: /* FALLTHROUGH */
1286: case (MDOC_Unfilled):
1287: /* FALLTHROUGH */
1288: case (MDOC_Literal):
1.44 kristaps 1289: type = node->parent->args->argv[i].arg;
1290: i = (int)node->parent->args->argc;
1.35 kristaps 1291: break;
1292: default:
1.44 kristaps 1293: break;
1.35 kristaps 1294: }
1295: }
1296:
1.44 kristaps 1297: if (NULL == node->parent->args)
1298: errx(1, "missing display type");
1.12 kristaps 1299:
1.44 kristaps 1300: i = arg_getattr(MDOC_Offset, node->parent);
1.12 kristaps 1301: if (-1 != i) {
1.45 kristaps 1302: if (1 != node->parent->args->argv[i].sz)
1.44 kristaps 1303: errx(1, "expected single value");
1.45 kristaps 1304: p->offset += arg_offset(&node->parent->args->argv[i]);
1.12 kristaps 1305: }
1306:
1.35 kristaps 1307: switch (type) {
1308: case (MDOC_Literal):
1309: /* FALLTHROUGH */
1310: case (MDOC_Unfilled):
1311: break;
1312: default:
1313: return(1);
1314: }
1315:
1.62 ! kristaps 1316: /*
! 1317: * Tricky. Iterate through all children. If we're on a
! 1318: * different parse line, append a newline and then the contents.
! 1319: * Ew.
! 1320: */
! 1321:
1.10 kristaps 1322: p->flags |= TERMP_LITERAL;
1.62 ! kristaps 1323: ln = node->child ? node->child->line : 0;
1.10 kristaps 1324:
1.62 ! kristaps 1325: for (node = node->child; node; node = node->next) {
! 1326: if (ln < node->line) {
! 1327: term_flushln(p);
! 1328: p->flags |= TERMP_NOSPACE;
1.35 kristaps 1329: }
1.62 ! kristaps 1330: ln = node->line;
! 1331: term_node(p, pair, meta, node);
1.10 kristaps 1332: }
1.1 kristaps 1333:
1.10 kristaps 1334: return(0);
1335: }
1.1 kristaps 1336:
1337:
1.10 kristaps 1338: /* ARGSUSED */
1.12 kristaps 1339: static void
1340: termp_bd_post(DECL_ARGS)
1341: {
1342:
1.20 kristaps 1343: if (MDOC_BODY != node->type)
1344: return;
1.35 kristaps 1345:
1346: p->flags &= ~TERMP_LITERAL;
1.20 kristaps 1347: p->offset = pair->offset;
1.62 ! kristaps 1348: p->flags |= TERMP_NOSPACE;
1.12 kristaps 1349: }
1350:
1351:
1352: /* ARGSUSED */
1.10 kristaps 1353: static int
1354: termp_qq_pre(DECL_ARGS)
1355: {
1.1 kristaps 1356:
1.10 kristaps 1357: if (MDOC_BODY != node->type)
1358: return(1);
1.62 ! kristaps 1359: term_word(p, "\"");
1.10 kristaps 1360: p->flags |= TERMP_NOSPACE;
1361: return(1);
1.1 kristaps 1362: }
1363:
1364:
1.10 kristaps 1365: /* ARGSUSED */
1.1 kristaps 1366: static void
1.10 kristaps 1367: termp_qq_post(DECL_ARGS)
1.1 kristaps 1368: {
1369:
1.10 kristaps 1370: if (MDOC_BODY != node->type)
1371: return;
1372: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1373: term_word(p, "\"");
1.10 kristaps 1374: }
1375:
1376:
1377: /* ARGSUSED */
1378: static int
1.15 kristaps 1379: termp_bsx_pre(DECL_ARGS)
1380: {
1381:
1.62 ! kristaps 1382: term_word(p, "BSDI BSD/OS");
1.15 kristaps 1383: return(1);
1384: }
1385:
1386:
1387: /* ARGSUSED */
1.31 kristaps 1388: static void
1389: termp_bx_post(DECL_ARGS)
1.10 kristaps 1390: {
1.1 kristaps 1391:
1.34 kristaps 1392: if (node->child)
1393: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1394: term_word(p, "BSD");
1.10 kristaps 1395: }
1396:
1397:
1398: /* ARGSUSED */
1399: static int
1400: termp_ox_pre(DECL_ARGS)
1401: {
1402:
1.62 ! kristaps 1403: term_word(p, "OpenBSD");
1.10 kristaps 1404: return(1);
1405: }
1406:
1407:
1408: /* ARGSUSED */
1409: static int
1.61 kristaps 1410: termp_dx_pre(DECL_ARGS)
1411: {
1412:
1.62 ! kristaps 1413: term_word(p, "DragonFly");
1.61 kristaps 1414: return(1);
1415: }
1416:
1417:
1418: /* ARGSUSED */
1419: static int
1.16 kristaps 1420: termp_ux_pre(DECL_ARGS)
1421: {
1422:
1.62 ! kristaps 1423: term_word(p, "UNIX");
1.16 kristaps 1424: return(1);
1425: }
1426:
1427:
1428: /* ARGSUSED */
1429: static int
1430: termp_fx_pre(DECL_ARGS)
1431: {
1432:
1.62 ! kristaps 1433: term_word(p, "FreeBSD");
1.16 kristaps 1434: return(1);
1435: }
1436:
1437:
1438: /* ARGSUSED */
1439: static int
1.10 kristaps 1440: termp_nx_pre(DECL_ARGS)
1441: {
1442:
1.62 ! kristaps 1443: term_word(p, "NetBSD");
1.10 kristaps 1444: return(1);
1445: }
1446:
1447:
1448: /* ARGSUSED */
1449: static int
1450: termp_sq_pre(DECL_ARGS)
1451: {
1452:
1453: if (MDOC_BODY != node->type)
1454: return(1);
1.62 ! kristaps 1455: term_word(p, "\\(oq");
1.10 kristaps 1456: p->flags |= TERMP_NOSPACE;
1457: return(1);
1458: }
1.1 kristaps 1459:
1460:
1.10 kristaps 1461: /* ARGSUSED */
1462: static void
1463: termp_sq_post(DECL_ARGS)
1464: {
1465:
1466: if (MDOC_BODY != node->type)
1467: return;
1468: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1469: term_word(p, "\\(aq");
1.10 kristaps 1470: }
1.2 kristaps 1471:
1472:
1.10 kristaps 1473: /* ARGSUSED */
1474: static int
1475: termp_pf_pre(DECL_ARGS)
1476: {
1.1 kristaps 1477:
1.10 kristaps 1478: p->flags |= TERMP_IGNDELIM;
1479: return(1);
1480: }
1.1 kristaps 1481:
1482:
1.10 kristaps 1483: /* ARGSUSED */
1484: static void
1485: termp_pf_post(DECL_ARGS)
1486: {
1.1 kristaps 1487:
1.10 kristaps 1488: p->flags &= ~TERMP_IGNDELIM;
1489: p->flags |= TERMP_NOSPACE;
1490: }
1.1 kristaps 1491:
1492:
1.10 kristaps 1493: /* ARGSUSED */
1494: static int
1495: termp_ss_pre(DECL_ARGS)
1496: {
1.1 kristaps 1497:
1.10 kristaps 1498: switch (node->type) {
1.58 kristaps 1499: case (MDOC_BLOCK):
1.62 ! kristaps 1500: term_newln(p);
1.58 kristaps 1501: if (node->prev)
1.62 ! kristaps 1502: term_vspace(p);
1.58 kristaps 1503: break;
1.10 kristaps 1504: case (MDOC_HEAD):
1.31 kristaps 1505: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SSECTION]);
1.10 kristaps 1506: p->offset = INDENT / 2;
1507: break;
1508: default:
1509: break;
1510: }
1.1 kristaps 1511:
1.10 kristaps 1512: return(1);
1.1 kristaps 1513: }
1514:
1515:
1.10 kristaps 1516: /* ARGSUSED */
1517: static void
1518: termp_ss_post(DECL_ARGS)
1.1 kristaps 1519: {
1520:
1.10 kristaps 1521: switch (node->type) {
1522: case (MDOC_HEAD):
1.62 ! kristaps 1523: term_newln(p);
1.10 kristaps 1524: p->offset = INDENT;
1525: break;
1526: default:
1527: break;
1528: }
1529: }
1.2 kristaps 1530:
1531:
1.10 kristaps 1532: /* ARGSUSED */
1533: static int
1534: termp_pa_pre(DECL_ARGS)
1535: {
1.2 kristaps 1536:
1.31 kristaps 1537: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_FILE]);
1.10 kristaps 1538: return(1);
1.1 kristaps 1539: }
1540:
1541:
1.10 kristaps 1542: /* ARGSUSED */
1.11 kristaps 1543: static int
1544: termp_em_pre(DECL_ARGS)
1545: {
1546:
1.31 kristaps 1547: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.11 kristaps 1548: return(1);
1549: }
1550:
1551:
1552: /* ARGSUSED */
1.14 kristaps 1553: static int
1554: termp_cd_pre(DECL_ARGS)
1555: {
1556:
1.31 kristaps 1557: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CONFIG]);
1.62 ! kristaps 1558: term_newln(p);
1.14 kristaps 1559: return(1);
1560: }
1561:
1562:
1563: /* ARGSUSED */
1564: static int
1565: termp_cm_pre(DECL_ARGS)
1566: {
1567:
1.31 kristaps 1568: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD_FLAG]);
1.14 kristaps 1569: return(1);
1570: }
1571:
1572:
1573: /* ARGSUSED */
1574: static int
1575: termp_ic_pre(DECL_ARGS)
1576: {
1577:
1.31 kristaps 1578: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_CMD]);
1.14 kristaps 1579: return(1);
1580: }
1581:
1582:
1583: /* ARGSUSED */
1584: static int
1585: termp_in_pre(DECL_ARGS)
1586: {
1587:
1.31 kristaps 1588: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_INCLUDE]);
1.62 ! kristaps 1589: term_word(p, "#include");
! 1590: term_word(p, "<");
1.30 kristaps 1591: p->flags |= TERMP_NOSPACE;
1.14 kristaps 1592: return(1);
1593: }
1594:
1595:
1596: /* ARGSUSED */
1.30 kristaps 1597: static void
1598: termp_in_post(DECL_ARGS)
1599: {
1600:
1601: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1602: term_word(p, ">");
1.30 kristaps 1603:
1.62 ! kristaps 1604: term_newln(p);
1.30 kristaps 1605: if (SEC_SYNOPSIS != node->sec)
1606: return;
1607: if (node->next && MDOC_In != node->next->tok)
1.62 ! kristaps 1608: term_vspace(p);
1.30 kristaps 1609: }
1610:
1611:
1612: /* ARGSUSED */
1.14 kristaps 1613: static int
1614: termp_at_pre(DECL_ARGS)
1615: {
1.43 kristaps 1616: const char *att;
1617:
1618: att = NULL;
1.14 kristaps 1619:
1.52 kristaps 1620: if (node->child)
1.44 kristaps 1621: att = mdoc_a2att(node->child->string);
1.43 kristaps 1622: if (NULL == att)
1623: att = "AT&T UNIX";
1624:
1.62 ! kristaps 1625: term_word(p, att);
1.14 kristaps 1626: return(0);
1627: }
1.15 kristaps 1628:
1629:
1630: /* ARGSUSED */
1631: static int
1.53 kristaps 1632: termp_brq_pre(DECL_ARGS)
1633: {
1634:
1635: if (MDOC_BODY != node->type)
1636: return(1);
1.62 ! kristaps 1637: term_word(p, "\\(lC");
1.53 kristaps 1638: p->flags |= TERMP_NOSPACE;
1639: return(1);
1640: }
1641:
1642:
1643: /* ARGSUSED */
1644: static void
1645: termp_brq_post(DECL_ARGS)
1646: {
1647:
1648: if (MDOC_BODY != node->type)
1649: return;
1650: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1651: term_word(p, "\\(rC");
1.53 kristaps 1652: }
1653:
1654:
1655: /* ARGSUSED */
1656: static int
1.15 kristaps 1657: termp_bq_pre(DECL_ARGS)
1658: {
1659:
1660: if (MDOC_BODY != node->type)
1661: return(1);
1.62 ! kristaps 1662: term_word(p, "\\(lB");
1.15 kristaps 1663: p->flags |= TERMP_NOSPACE;
1664: return(1);
1665: }
1666:
1667:
1668: /* ARGSUSED */
1669: static void
1670: termp_bq_post(DECL_ARGS)
1671: {
1672:
1673: if (MDOC_BODY != node->type)
1674: return;
1.53 kristaps 1675: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1676: term_word(p, "\\(rB");
1.15 kristaps 1677: }
1678:
1679:
1680: /* ARGSUSED */
1681: static int
1682: termp_pq_pre(DECL_ARGS)
1683: {
1684:
1685: if (MDOC_BODY != node->type)
1686: return(1);
1.62 ! kristaps 1687: term_word(p, "\\&(");
1.15 kristaps 1688: p->flags |= TERMP_NOSPACE;
1689: return(1);
1690: }
1691:
1692:
1693: /* ARGSUSED */
1694: static void
1695: termp_pq_post(DECL_ARGS)
1696: {
1697:
1698: if (MDOC_BODY != node->type)
1699: return;
1.62 ! kristaps 1700: term_word(p, ")");
1.15 kristaps 1701: }
1702:
1703:
1.16 kristaps 1704: /* ARGSUSED */
1705: static int
1706: termp_fo_pre(DECL_ARGS)
1707: {
1708: const struct mdoc_node *n;
1709:
1710: if (MDOC_BODY == node->type) {
1.62 ! kristaps 1711: term_word(p, "(");
1.16 kristaps 1712: p->flags |= TERMP_NOSPACE;
1713: return(1);
1714: } else if (MDOC_HEAD != node->type)
1715: return(1);
1716:
1.17 kristaps 1717: /* XXX - groff shows only first parameter */
1718:
1.16 kristaps 1719: p->flags |= ttypes[TTYPE_FUNC_NAME];
1720: for (n = node->child; n; n = n->next) {
1.44 kristaps 1721: if (MDOC_TEXT != n->type)
1722: errx(1, "expected text line argument");
1.62 ! kristaps 1723: term_word(p, n->string);
1.16 kristaps 1724: }
1725: p->flags &= ~ttypes[TTYPE_FUNC_NAME];
1726:
1727: return(0);
1728: }
1729:
1730:
1731: /* ARGSUSED */
1732: static void
1733: termp_fo_post(DECL_ARGS)
1734: {
1735:
1736: if (MDOC_BODY != node->type)
1737: return;
1.53 kristaps 1738: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1739: term_word(p, ")");
1.53 kristaps 1740: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1741: term_word(p, ";");
! 1742: term_newln(p);
1.16 kristaps 1743: }
1744:
1745:
1.17 kristaps 1746: /* ARGSUSED */
1747: static int
1748: termp_bf_pre(DECL_ARGS)
1749: {
1750: const struct mdoc_node *n;
1751:
1.44 kristaps 1752: if (MDOC_HEAD == node->type) {
1.17 kristaps 1753: return(0);
1.44 kristaps 1754: } else if (MDOC_BLOCK != node->type)
1.17 kristaps 1755: return(1);
1756:
1.44 kristaps 1757: if (NULL == (n = node->head->child)) {
1758: if (arg_hasattr(MDOC_Emphasis, node))
1.31 kristaps 1759: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.44 kristaps 1760: else if (arg_hasattr(MDOC_Symbolic, node))
1.31 kristaps 1761: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1.17 kristaps 1762:
1763: return(1);
1764: }
1765:
1.44 kristaps 1766: if (MDOC_TEXT != n->type)
1767: errx(1, "expected text line arguments");
1.17 kristaps 1768:
1.44 kristaps 1769: if (0 == strcmp("Em", n->string))
1.31 kristaps 1770: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.44 kristaps 1771: else if (0 == strcmp("Sy", n->string))
1.31 kristaps 1772: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_EMPH]);
1.17 kristaps 1773:
1774: return(1);
1775: }
1776:
1777:
1778: /* ARGSUSED */
1779: static int
1780: termp_sy_pre(DECL_ARGS)
1781: {
1782:
1.31 kristaps 1783: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMB]);
1.17 kristaps 1784: return(1);
1785: }
1786:
1787:
1788: /* ARGSUSED */
1789: static int
1790: termp_ms_pre(DECL_ARGS)
1791: {
1792:
1.31 kristaps 1793: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_SYMBOL]);
1.17 kristaps 1794: return(1);
1795: }
1796:
1.22 kristaps 1797:
1798:
1799: /* ARGSUSED */
1800: static int
1801: termp_sm_pre(DECL_ARGS)
1802: {
1803:
1804: #if notyet
1805: assert(node->child);
1806: if (0 == strcmp("off", node->child->data.text.string)) {
1807: p->flags &= ~TERMP_NONOSPACE;
1808: p->flags &= ~TERMP_NOSPACE;
1809: } else {
1810: p->flags |= TERMP_NONOSPACE;
1811: p->flags |= TERMP_NOSPACE;
1812: }
1813: #endif
1814:
1815: return(0);
1816: }
1.28 kristaps 1817:
1818:
1819: /* ARGSUSED */
1820: static int
1.48 kristaps 1821: termp_ap_pre(DECL_ARGS)
1822: {
1823:
1824: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1825: term_word(p, "\\(aq");
1.48 kristaps 1826: p->flags |= TERMP_NOSPACE;
1827: return(1);
1828: }
1829:
1830:
1831: /* ARGSUSED */
1832: static int
1.28 kristaps 1833: termp__t_pre(DECL_ARGS)
1834: {
1835:
1.54 kristaps 1836: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_REF_TITLE]);
1.28 kristaps 1837: return(1);
1838: }
1839:
1840:
1841: /* ARGSUSED */
1842: static void
1843: termp____post(DECL_ARGS)
1844: {
1845:
1846: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1847: term_word(p, node->next ? "," : ".");
1.28 kristaps 1848: }
1.51 kristaps 1849:
1850:
1851: /* ARGSUSED */
1852: static int
1853: termp_lk_pre(DECL_ARGS)
1854: {
1855: const struct mdoc_node *n;
1856:
1857: if (NULL == (n = node->child))
1.52 kristaps 1858: errx(1, "expected line argument");
1.51 kristaps 1859:
1860: p->flags |= ttypes[TTYPE_LINK_ANCHOR];
1.62 ! kristaps 1861: term_word(p, n->string);
1.51 kristaps 1862: p->flags &= ~ttypes[TTYPE_LINK_ANCHOR];
1863: p->flags |= TERMP_NOSPACE;
1.62 ! kristaps 1864: term_word(p, ":");
1.51 kristaps 1865:
1866: p->flags |= ttypes[TTYPE_LINK_TEXT];
1867: for ( ; n; n = n->next) {
1.62 ! kristaps 1868: term_word(p, n->string);
1.51 kristaps 1869: }
1870: p->flags &= ~ttypes[TTYPE_LINK_TEXT];
1871:
1872: return(0);
1873: }
1874:
1875:
1876: /* ARGSUSED */
1877: static int
1878: termp_mt_pre(DECL_ARGS)
1879: {
1880:
1881: TERMPAIR_SETFLAG(p, pair, ttypes[TTYPE_LINK_ANCHOR]);
1882: return(1);
1883: }
1884:
CVSweb