1 /* $Id: mdoc_term.c,v 1.364 2017/06/14 17:51:15 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
5 * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include "config.h"
20
21 #include <sys/types.h>
22
23 #include <assert.h>
24 #include <ctype.h>
266
267 n = mdoc->first->child;
268 if (p->synopsisonly) {
269 while (n != NULL) {
270 if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
271 if (n->child->next->child != NULL)
272 print_mdoc_nodelist(p, NULL,
273 &mdoc->meta,
274 n->child->next->child);
275 term_newln(p);
276 break;
277 }
278 n = n->next;
279 }
280 } else {
281 save_defindent = p->defindent;
282 if (p->defindent == 0)
283 p->defindent = 5;
284 term_begin(p, print_mdoc_head, print_mdoc_foot,
285 &mdoc->meta);
286 while (n != NULL && n->flags & NODE_NOPRT)
287 n = n->next;
288 if (n != NULL) {
289 if (n->tok != MDOC_Sh)
290 term_vspace(p);
291 print_mdoc_nodelist(p, NULL, &mdoc->meta, n);
292 }
293 term_end(p);
294 p->defindent = save_defindent;
295 }
296 }
297
298 static void
299 print_mdoc_nodelist(DECL_ARGS)
300 {
301
302 while (n != NULL) {
303 print_mdoc_node(p, pair, meta, n);
304 n = n->next;
305 }
306 }
307
308 static void
309 print_mdoc_node(DECL_ARGS)
310 {
311 int chld;
312 struct termpair npair;
313 size_t offset, rmargin;
314
315 if (n->flags & NODE_NOPRT)
316 return;
317
318 chld = 1;
319 offset = p->tcol->offset;
320 rmargin = p->tcol->rmargin;
321 n->flags &= ~NODE_ENDED;
322 n->prev_font = p->fonti;
323
324 memset(&npair, 0, sizeof(struct termpair));
325 npair.ppair = pair;
326
327 /*
328 * Keeps only work until the end of a line. If a keep was
329 * invoked in a prior line, revert it to PREKEEP.
330 */
331
332 if (p->flags & TERMP_KEEP && n->flags & NODE_LINE) {
333 p->flags &= ~TERMP_KEEP;
334 p->flags |= TERMP_PREKEEP;
335 }
550 */
551 static void
552 print_bvspace(struct termp *p,
553 const struct roff_node *bl,
554 const struct roff_node *n)
555 {
556 const struct roff_node *nn;
557
558 assert(n);
559
560 term_newln(p);
561
562 if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
563 return;
564 if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
565 return;
566
567 /* Do not vspace directly after Ss/Sh. */
568
569 nn = n;
570 while (nn->prev != NULL && nn->prev->flags & NODE_NOPRT)
571 nn = nn->prev;
572 while (nn->prev == NULL) {
573 do {
574 nn = nn->parent;
575 if (nn->type == ROFFT_ROOT)
576 return;
577 } while (nn->type != ROFFT_BLOCK);
578 if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
579 return;
580 if (nn->tok == MDOC_It &&
581 nn->parent->parent->norm->Bl.type != LIST_item)
582 break;
583 }
584
585 /* A `-column' does not assert vspace within the list. */
586
587 if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
588 if (n->prev && MDOC_It == n->prev->tok)
589 return;
590
1533 p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1534 }
1535
1536 static void
1537 termp_pf_post(DECL_ARGS)
1538 {
1539
1540 if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
1541 p->flags |= TERMP_NOSPACE;
1542 }
1543
1544 static int
1545 termp_ss_pre(DECL_ARGS)
1546 {
1547 struct roff_node *nn;
1548
1549 switch (n->type) {
1550 case ROFFT_BLOCK:
1551 term_newln(p);
1552 for (nn = n->prev; nn != NULL; nn = nn->prev)
1553 if ((nn->flags & NODE_NOPRT) == 0)
1554 break;
1555 if (nn != NULL)
1556 term_vspace(p);
1557 break;
1558 case ROFFT_HEAD:
1559 term_fontpush(p, TERMFONT_BOLD);
1560 p->tcol->offset = term_len(p, (p->defindent+1)/2);
1561 break;
1562 case ROFFT_BODY:
1563 p->tcol->offset = term_len(p, p->defindent);
1564 term_tab_set(p, NULL);
1565 term_tab_set(p, "T");
1566 term_tab_set(p, ".5i");
1567 break;
1568 default:
1569 break;
1570 }
1571
1572 return 1;
1573 }
1647 switch (n->tok) {
1648 case MDOC_Ao:
1649 case MDOC_Aq:
1650 term_word(p, n->child != NULL && n->child->next == NULL &&
1651 n->child->tok == MDOC_Mt ? "<" : "\\(la");
1652 break;
1653 case MDOC_Bro:
1654 case MDOC_Brq:
1655 term_word(p, "{");
1656 break;
1657 case MDOC_Oo:
1658 case MDOC_Op:
1659 case MDOC_Bo:
1660 case MDOC_Bq:
1661 term_word(p, "[");
1662 break;
1663 case MDOC__T:
1664 /* FALLTHROUGH */
1665 case MDOC_Do:
1666 case MDOC_Dq:
1667 term_word(p, "\\(Lq");
1668 break;
1669 case MDOC_En:
1670 if (NULL == n->norm->Es ||
1671 NULL == n->norm->Es->child)
1672 return 1;
1673 term_word(p, n->norm->Es->child->string);
1674 break;
1675 case MDOC_Po:
1676 case MDOC_Pq:
1677 term_word(p, "(");
1678 break;
1679 case MDOC_Qo:
1680 case MDOC_Qq:
1681 term_word(p, "\"");
1682 break;
1683 case MDOC_Ql:
1684 case MDOC_So:
1685 case MDOC_Sq:
1686 term_word(p, "\\(oq");
1687 break;
1705 switch (n->tok) {
1706 case MDOC_Ao:
1707 case MDOC_Aq:
1708 term_word(p, n->child != NULL && n->child->next == NULL &&
1709 n->child->tok == MDOC_Mt ? ">" : "\\(ra");
1710 break;
1711 case MDOC_Bro:
1712 case MDOC_Brq:
1713 term_word(p, "}");
1714 break;
1715 case MDOC_Oo:
1716 case MDOC_Op:
1717 case MDOC_Bo:
1718 case MDOC_Bq:
1719 term_word(p, "]");
1720 break;
1721 case MDOC__T:
1722 /* FALLTHROUGH */
1723 case MDOC_Do:
1724 case MDOC_Dq:
1725 term_word(p, "\\(Rq");
1726 break;
1727 case MDOC_En:
1728 if (n->norm->Es == NULL ||
1729 n->norm->Es->child == NULL ||
1730 n->norm->Es->child->next == NULL)
1731 p->flags &= ~TERMP_NOSPACE;
1732 else
1733 term_word(p, n->norm->Es->child->next->string);
1734 break;
1735 case MDOC_Po:
1736 case MDOC_Pq:
1737 term_word(p, ")");
1738 break;
1739 case MDOC_Qo:
1740 case MDOC_Qq:
1741 term_word(p, "\"");
1742 break;
1743 case MDOC_Ql:
1744 case MDOC_So:
1745 case MDOC_Sq:
1923 if (NULL == n->next) {
1924 term_word(p, ".");
1925 p->flags |= TERMP_SENTENCE;
1926 } else
1927 term_word(p, ",");
1928 }
1929
1930 static int
1931 termp_li_pre(DECL_ARGS)
1932 {
1933
1934 termp_tag_pre(p, pair, meta, n);
1935 term_fontpush(p, TERMFONT_NONE);
1936 return 1;
1937 }
1938
1939 static int
1940 termp_lk_pre(DECL_ARGS)
1941 {
1942 const struct roff_node *link, *descr, *punct;
1943 int display;
1944
1945 if ((link = n->child) == NULL)
1946 return 0;
1947
1948 /* Find beginning of trailing punctuation. */
1949 punct = n->last;
1950 while (punct != link && punct->flags & NODE_DELIMC)
1951 punct = punct->prev;
1952 punct = punct->next;
1953
1954 /* Link text. */
1955 if ((descr = link->next) != NULL && descr != punct) {
1956 term_fontpush(p, TERMFONT_UNDER);
1957 while (descr != punct) {
1958 if (descr->flags & (NODE_DELIMC | NODE_DELIMO))
1959 p->flags |= TERMP_NOSPACE;
1960 term_word(p, descr->string);
1961 descr = descr->next;
1962 }
1963 term_fontpop(p);
1964 p->flags |= TERMP_NOSPACE;
1965 term_word(p, ":");
1966 }
1967
1968 /* Link target. */
1969 display = term_strlen(p, link->string) >= 26;
1970 if (display) {
1971 term_newln(p);
1972 p->tcol->offset += term_len(p, p->defindent + 1);
1973 }
1974 term_fontpush(p, TERMFONT_BOLD);
1975 term_word(p, link->string);
1976 term_fontpop(p);
1977
1978 /* Trailing punctuation. */
1979 while (punct != NULL) {
1980 p->flags |= TERMP_NOSPACE;
1981 term_word(p, punct->string);
1982 punct = punct->next;
1983 }
1984 if (display)
1985 term_newln(p);
1986 return 0;
1987 }
1988
1989 static int
1990 termp_bk_pre(DECL_ARGS)
1991 {
1992
1993 switch (n->type) {
1994 case ROFFT_BLOCK:
1995 break;
1996 case ROFFT_HEAD:
1997 return 0;
1998 case ROFFT_BODY:
1999 if (n->parent->args != NULL || n->prev->child == NULL)
2000 p->flags |= TERMP_PREKEEP;
2001 break;
2002 default:
2003 abort();
2004 }
2005
|
1 /* $Id: mdoc_term.c,v 1.367 2018/04/11 17:11:13 schwarze Exp $ */
2 /*
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
5 * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19 #include "config.h"
20
21 #include <sys/types.h>
22
23 #include <assert.h>
24 #include <ctype.h>
266
267 n = mdoc->first->child;
268 if (p->synopsisonly) {
269 while (n != NULL) {
270 if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) {
271 if (n->child->next->child != NULL)
272 print_mdoc_nodelist(p, NULL,
273 &mdoc->meta,
274 n->child->next->child);
275 term_newln(p);
276 break;
277 }
278 n = n->next;
279 }
280 } else {
281 save_defindent = p->defindent;
282 if (p->defindent == 0)
283 p->defindent = 5;
284 term_begin(p, print_mdoc_head, print_mdoc_foot,
285 &mdoc->meta);
286 while (n != NULL &&
287 (n->type == ROFFT_COMMENT ||
288 n->flags & NODE_NOPRT))
289 n = n->next;
290 if (n != NULL) {
291 if (n->tok != MDOC_Sh)
292 term_vspace(p);
293 print_mdoc_nodelist(p, NULL, &mdoc->meta, n);
294 }
295 term_end(p);
296 p->defindent = save_defindent;
297 }
298 }
299
300 static void
301 print_mdoc_nodelist(DECL_ARGS)
302 {
303
304 while (n != NULL) {
305 print_mdoc_node(p, pair, meta, n);
306 n = n->next;
307 }
308 }
309
310 static void
311 print_mdoc_node(DECL_ARGS)
312 {
313 int chld;
314 struct termpair npair;
315 size_t offset, rmargin;
316
317 if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
318 return;
319
320 chld = 1;
321 offset = p->tcol->offset;
322 rmargin = p->tcol->rmargin;
323 n->flags &= ~NODE_ENDED;
324 n->prev_font = p->fonti;
325
326 memset(&npair, 0, sizeof(struct termpair));
327 npair.ppair = pair;
328
329 /*
330 * Keeps only work until the end of a line. If a keep was
331 * invoked in a prior line, revert it to PREKEEP.
332 */
333
334 if (p->flags & TERMP_KEEP && n->flags & NODE_LINE) {
335 p->flags &= ~TERMP_KEEP;
336 p->flags |= TERMP_PREKEEP;
337 }
552 */
553 static void
554 print_bvspace(struct termp *p,
555 const struct roff_node *bl,
556 const struct roff_node *n)
557 {
558 const struct roff_node *nn;
559
560 assert(n);
561
562 term_newln(p);
563
564 if (MDOC_Bd == bl->tok && bl->norm->Bd.comp)
565 return;
566 if (MDOC_Bl == bl->tok && bl->norm->Bl.comp)
567 return;
568
569 /* Do not vspace directly after Ss/Sh. */
570
571 nn = n;
572 while (nn->prev != NULL &&
573 (nn->prev->type == ROFFT_COMMENT ||
574 nn->prev->flags & NODE_NOPRT))
575 nn = nn->prev;
576 while (nn->prev == NULL) {
577 do {
578 nn = nn->parent;
579 if (nn->type == ROFFT_ROOT)
580 return;
581 } while (nn->type != ROFFT_BLOCK);
582 if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss)
583 return;
584 if (nn->tok == MDOC_It &&
585 nn->parent->parent->norm->Bl.type != LIST_item)
586 break;
587 }
588
589 /* A `-column' does not assert vspace within the list. */
590
591 if (MDOC_Bl == bl->tok && LIST_column == bl->norm->Bl.type)
592 if (n->prev && MDOC_It == n->prev->tok)
593 return;
594
1537 p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
1538 }
1539
1540 static void
1541 termp_pf_post(DECL_ARGS)
1542 {
1543
1544 if ( ! (n->next == NULL || n->next->flags & NODE_LINE))
1545 p->flags |= TERMP_NOSPACE;
1546 }
1547
1548 static int
1549 termp_ss_pre(DECL_ARGS)
1550 {
1551 struct roff_node *nn;
1552
1553 switch (n->type) {
1554 case ROFFT_BLOCK:
1555 term_newln(p);
1556 for (nn = n->prev; nn != NULL; nn = nn->prev)
1557 if (nn->type != ROFFT_COMMENT &&
1558 (nn->flags & NODE_NOPRT) == 0)
1559 break;
1560 if (nn != NULL)
1561 term_vspace(p);
1562 break;
1563 case ROFFT_HEAD:
1564 term_fontpush(p, TERMFONT_BOLD);
1565 p->tcol->offset = term_len(p, (p->defindent+1)/2);
1566 break;
1567 case ROFFT_BODY:
1568 p->tcol->offset = term_len(p, p->defindent);
1569 term_tab_set(p, NULL);
1570 term_tab_set(p, "T");
1571 term_tab_set(p, ".5i");
1572 break;
1573 default:
1574 break;
1575 }
1576
1577 return 1;
1578 }
1652 switch (n->tok) {
1653 case MDOC_Ao:
1654 case MDOC_Aq:
1655 term_word(p, n->child != NULL && n->child->next == NULL &&
1656 n->child->tok == MDOC_Mt ? "<" : "\\(la");
1657 break;
1658 case MDOC_Bro:
1659 case MDOC_Brq:
1660 term_word(p, "{");
1661 break;
1662 case MDOC_Oo:
1663 case MDOC_Op:
1664 case MDOC_Bo:
1665 case MDOC_Bq:
1666 term_word(p, "[");
1667 break;
1668 case MDOC__T:
1669 /* FALLTHROUGH */
1670 case MDOC_Do:
1671 case MDOC_Dq:
1672 term_word(p, "\\(lq");
1673 break;
1674 case MDOC_En:
1675 if (NULL == n->norm->Es ||
1676 NULL == n->norm->Es->child)
1677 return 1;
1678 term_word(p, n->norm->Es->child->string);
1679 break;
1680 case MDOC_Po:
1681 case MDOC_Pq:
1682 term_word(p, "(");
1683 break;
1684 case MDOC_Qo:
1685 case MDOC_Qq:
1686 term_word(p, "\"");
1687 break;
1688 case MDOC_Ql:
1689 case MDOC_So:
1690 case MDOC_Sq:
1691 term_word(p, "\\(oq");
1692 break;
1710 switch (n->tok) {
1711 case MDOC_Ao:
1712 case MDOC_Aq:
1713 term_word(p, n->child != NULL && n->child->next == NULL &&
1714 n->child->tok == MDOC_Mt ? ">" : "\\(ra");
1715 break;
1716 case MDOC_Bro:
1717 case MDOC_Brq:
1718 term_word(p, "}");
1719 break;
1720 case MDOC_Oo:
1721 case MDOC_Op:
1722 case MDOC_Bo:
1723 case MDOC_Bq:
1724 term_word(p, "]");
1725 break;
1726 case MDOC__T:
1727 /* FALLTHROUGH */
1728 case MDOC_Do:
1729 case MDOC_Dq:
1730 term_word(p, "\\(rq");
1731 break;
1732 case MDOC_En:
1733 if (n->norm->Es == NULL ||
1734 n->norm->Es->child == NULL ||
1735 n->norm->Es->child->next == NULL)
1736 p->flags &= ~TERMP_NOSPACE;
1737 else
1738 term_word(p, n->norm->Es->child->next->string);
1739 break;
1740 case MDOC_Po:
1741 case MDOC_Pq:
1742 term_word(p, ")");
1743 break;
1744 case MDOC_Qo:
1745 case MDOC_Qq:
1746 term_word(p, "\"");
1747 break;
1748 case MDOC_Ql:
1749 case MDOC_So:
1750 case MDOC_Sq:
1928 if (NULL == n->next) {
1929 term_word(p, ".");
1930 p->flags |= TERMP_SENTENCE;
1931 } else
1932 term_word(p, ",");
1933 }
1934
1935 static int
1936 termp_li_pre(DECL_ARGS)
1937 {
1938
1939 termp_tag_pre(p, pair, meta, n);
1940 term_fontpush(p, TERMFONT_NONE);
1941 return 1;
1942 }
1943
1944 static int
1945 termp_lk_pre(DECL_ARGS)
1946 {
1947 const struct roff_node *link, *descr, *punct;
1948
1949 if ((link = n->child) == NULL)
1950 return 0;
1951
1952 /* Find beginning of trailing punctuation. */
1953 punct = n->last;
1954 while (punct != link && punct->flags & NODE_DELIMC)
1955 punct = punct->prev;
1956 punct = punct->next;
1957
1958 /* Link text. */
1959 if ((descr = link->next) != NULL && descr != punct) {
1960 term_fontpush(p, TERMFONT_UNDER);
1961 while (descr != punct) {
1962 if (descr->flags & (NODE_DELIMC | NODE_DELIMO))
1963 p->flags |= TERMP_NOSPACE;
1964 term_word(p, descr->string);
1965 descr = descr->next;
1966 }
1967 term_fontpop(p);
1968 p->flags |= TERMP_NOSPACE;
1969 term_word(p, ":");
1970 }
1971
1972 /* Link target. */
1973 term_fontpush(p, TERMFONT_BOLD);
1974 term_word(p, link->string);
1975 term_fontpop(p);
1976
1977 /* Trailing punctuation. */
1978 while (punct != NULL) {
1979 p->flags |= TERMP_NOSPACE;
1980 term_word(p, punct->string);
1981 punct = punct->next;
1982 }
1983 return 0;
1984 }
1985
1986 static int
1987 termp_bk_pre(DECL_ARGS)
1988 {
1989
1990 switch (n->type) {
1991 case ROFFT_BLOCK:
1992 break;
1993 case ROFFT_HEAD:
1994 return 0;
1995 case ROFFT_BODY:
1996 if (n->parent->args != NULL || n->prev->child == NULL)
1997 p->flags |= TERMP_PREKEEP;
1998 break;
1999 default:
2000 abort();
2001 }
2002
|