]>
git.cameronkatri.com Git - mandoc.git/blob - eqn_term.c
1 /* $Id: eqn_term.c,v 1.17 2017/08/23 21:56:20 schwarze Exp $ */
3 * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/types.h>
32 static const enum termfont fontmap
[EQNFONT__MAX
] = {
33 TERMFONT_NONE
, /* EQNFONT_NONE */
34 TERMFONT_NONE
, /* EQNFONT_ROMAN */
35 TERMFONT_BOLD
, /* EQNFONT_BOLD */
36 TERMFONT_BOLD
, /* EQNFONT_FAT */
37 TERMFONT_UNDER
/* EQNFONT_ITALIC */
40 static void eqn_box(struct termp
*, const struct eqn_box
*);
44 term_eqn(struct termp
*p
, const struct eqn_box
*bp
)
48 p
->flags
&= ~TERMP_NOSPACE
;
52 eqn_box(struct termp
*p
, const struct eqn_box
*bp
)
54 const struct eqn_box
*child
;
58 /* Delimiters around this box? */
60 if ((bp
->type
== EQN_LIST
&& bp
->expectargs
> 1) ||
61 (bp
->type
== EQN_PILE
&& (bp
->prev
|| bp
->next
)) ||
62 (bp
->parent
!= NULL
&& (bp
->parent
->pos
== EQNPOS_SQRT
||
63 /* Diacritic followed by ^ or _. */
64 ((bp
->top
!= NULL
|| bp
->bottom
!= NULL
) &&
65 bp
->parent
->type
== EQN_SUBEXPR
&&
66 bp
->parent
->pos
!= EQNPOS_OVER
&& bp
->next
!= NULL
) ||
67 /* Nested over, sub, sup, from, to. */
68 (bp
->type
== EQN_SUBEXPR
&& bp
->pos
!= EQNPOS_SQRT
&&
69 ((bp
->parent
->type
== EQN_LIST
&& bp
->expectargs
== 1) ||
70 (bp
->parent
->type
== EQN_SUBEXPR
&&
71 bp
->pos
!= EQNPOS_SQRT
)))))) {
72 if ((bp
->parent
->type
== EQN_SUBEXPR
&& bp
->prev
!= NULL
) ||
73 (bp
->type
== EQN_LIST
&&
75 bp
->first
->type
!= EQN_PILE
&&
76 bp
->first
->type
!= EQN_MATRIX
&&
78 (bp
->prev
->type
== EQN_LIST
||
79 (bp
->prev
->type
== EQN_TEXT
&&
80 (*bp
->prev
->text
== '\\' ||
81 isalpha((unsigned char)*bp
->prev
->text
))))))
82 p
->flags
|= TERMP_NOSPACE
;
83 term_word(p
, bp
->left
!= NULL
? bp
->left
: "(");
84 p
->flags
|= TERMP_NOSPACE
;
89 /* Handle Fonts and text. */
91 if (bp
->font
!= EQNFONT_NONE
)
92 term_fontpush(p
, fontmap
[(int)bp
->font
]);
94 if (bp
->text
!= NULL
) {
95 if (strchr("!\"'),.:;?]}", *bp
->text
) != NULL
)
96 p
->flags
|= TERMP_NOSPACE
;
97 term_word(p
, bp
->text
);
98 if ((cp
= strchr(bp
->text
, '\0')) > bp
->text
&&
99 (strchr("\"'([{", cp
[-1]) != NULL
||
100 (bp
->prev
== NULL
&& (cp
[-1] == '-' ||
101 (cp
>= bp
->text
+ 5 &&
102 strcmp(cp
- 5, "\\[mi]") == 0)))))
103 p
->flags
|= TERMP_NOSPACE
;
106 /* Special box types. */
108 if (bp
->pos
== EQNPOS_SQRT
) {
109 term_word(p
, "sqrt");
110 if (bp
->first
!= NULL
) {
111 p
->flags
|= TERMP_NOSPACE
;
112 eqn_box(p
, bp
->first
);
114 } else if (bp
->type
== EQN_SUBEXPR
) {
117 p
->flags
|= TERMP_NOSPACE
;
118 term_word(p
, bp
->pos
== EQNPOS_OVER
? "/" :
119 (bp
->pos
== EQNPOS_SUP
||
120 bp
->pos
== EQNPOS_TO
) ? "^" : "_");
123 p
->flags
|= TERMP_NOSPACE
;
125 if (bp
->pos
== EQNPOS_FROMTO
||
126 bp
->pos
== EQNPOS_SUBSUP
) {
127 p
->flags
|= TERMP_NOSPACE
;
129 p
->flags
|= TERMP_NOSPACE
;
137 if (bp
->type
== EQN_MATRIX
&&
139 child
->type
== EQN_LIST
&&
140 child
->expectargs
> 1)
141 child
= child
->first
;
142 while (child
!= NULL
) {
144 bp
->type
== EQN_PILE
&&
145 child
->type
== EQN_LIST
&&
146 child
->expectargs
> 1 &&
148 child
->first
: child
);
153 /* Handle Fonts and diacritics. */
155 if (bp
->font
!= EQNFONT_NONE
)
157 if (bp
->top
!= NULL
) {
158 p
->flags
|= TERMP_NOSPACE
;
159 term_word(p
, bp
->top
);
161 if (bp
->bottom
!= NULL
) {
162 p
->flags
|= TERMP_NOSPACE
;
166 /* Right delimiter after this box? */
169 p
->flags
|= TERMP_NOSPACE
;
170 term_word(p
, bp
->right
!= NULL
? bp
->right
: ")");
171 if (bp
->parent
->type
== EQN_SUBEXPR
&& bp
->next
!= NULL
)
172 p
->flags
|= TERMP_NOSPACE
;