aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/eqn/paren.c
blob: 4a9fea0bb93383c3d0a01cbb919cb33d39fe6051 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "e.h"

#define abs(x) ((x) > 0 ? (x) : (-(x)))

extern void brack(int, char *, char *, char *);

void paren(int leftc, int p1, int rightc)
{
	int n, m, j;
	double h1, b1;
	double v, bv;	/* v = shift of inside, bv = shift of brackets */
	extern double Parenbase, Parenshift, Parenheight;

	bv = ttype == DEVPOST ? Parenshift : 0;	/* move brackets down this much */
	h1 = eht[p1];
	b1 = ebase[p1];
	yyval = p1;
	lfont[yyval] = rfont[yyval] = 0;
	n = REL(h1,ps) + 0.99;	/* ceiling */
	if (n < 2)
		n = 1;
	m = n - 2;
	if (leftc == '{' || rightc == '}') {
		n = n%2 ? n : n+1;
		if (n < 3)
			n = 3;
		m = n-3;
	}
	eht[yyval] = EM((double) n + Parenheight, ps);
	ebase[yyval] = eht[yyval]/2 - EM(Parenbase, ps);

	/* try to cope with things that are badly centered */
	/* (top heavy or bottom heavy) */
	if (abs(h1/2 - b1) >= EM(0.5, ps))
		v = REL(-ebase[yyval] + (eht[yyval]-h1)/2 + b1, ps);
	else
		v = 0;	/* don't shift it at all */

	printf(".ds %d \\^", (int)yyval);	/* was \| */
	if (bv)
		printf("\\v'%gm'", bv);
	switch (leftc) {
	case 'n':	/* nothing */
	case '\0':
		break;
	case 'f':	/* floor */
		if (n <= 1)
			printf("\\(lf");
		else
			brack(m, "\\(bv", "\\(bv", "\\(lf");
		break;
	case 'c':	/* ceiling */
		if (n <= 1)
			printf("\\(lc");
		else
			brack(m, "\\(lc", "\\(bv", "\\(bv");
		break;
	case '{':
		printf("\\b'\\(lt");
		for(j = 0; j < m; j += 2) printf("\\(bv");
		printf("\\(lk");
		for(j = 0; j < m; j += 2) printf("\\(bv");
		printf("\\(lb'");
		break;
	case '(':
		brack(m, "\\(lt", "\\(bv", "\\(lb");
		break;
	case '[':
		brack(m, "\\(lc", "\\(bv", "\\(lf");
		break;
	case '|':
		brack(m, "|", "|", "|");
		break;
	default:
		brack(m, (char *) &leftc, (char *) &leftc, (char *) &leftc);
		break;
	}
	if (bv)
		printf("\\v'%gm'", -bv);
	if (v)
		printf("\\v'%gm'\\*(%d\\v'%gm'", -v, p1, v);
	else
		printf("\\*(%d", p1);
	if (rightc) {
		if (bv)
			printf("\\v'%gm'", bv);
		switch (rightc) {
		case 'f':	/* floor */
			if (n <= 1)
				printf("\\(rf");
			else
				brack(m, "\\(bv", "\\(bv", "\\(rf");
			break;
		case 'c':	/* ceiling */
			if (n <= 1)
				printf("\\(rc");
			else
				brack(m, "\\(rc", "\\(bv", "\\(bv");
			break;
		case '}':
			printf("\\b'\\(rt");
			for(j = 0; j < m; j += 2) printf("\\(bv");
			printf("\\(rk");
			for(j = 0; j < m; j += 2) printf("\\(bv");
			printf("\\(rb'");
			break;
		case ']':
			brack(m, "\\(rc", "\\(bv", "\\(rf");
			break;
		case ')':
			brack(m, "\\(rt", "\\(bv", "\\(rb");
			break;
		case '|':
			brack(m, "|", "|", "|");
			break;
		default:
			brack(m, (char *) &rightc, (char *) &rightc, (char *) &rightc);
			break;
		}
		if (bv)
			printf("\\v'%gm'", -bv);
	}
	printf("\n");
	dprintf(".\tcurly: h=%g b=%g n=%d v=%g l=%c, r=%c\n", 
		eht[yyval], ebase[yyval], n, v, leftc, rightc);
}

void brack(int m, char *t, char *c, char *b)
{
	int j;
	printf("\\b'%s", t);
	for( j=0; j < m; j++)
		printf("%s", c);
	printf("%s'", b);
}