The R Project SVN R

Rev

Rev 1160 | Rev 1917 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1160 Rev 1839
Line 28... Line 28...
28
#endif
28
#endif
29
#ifdef Unix
29
#ifdef Unix
30
 
30
 
31
static DevDesc *mathDevice;
31
static DevDesc *mathDevice;
32
 
32
 
33
		/* return maximum of two doubles */
33
/* Return maximum of two doubles. */
34
 
34
 
35
static double max(double x, double y)
35
static double max(double x, double y)
36
{
36
{
37
	if (x > y) return x;
37
    if (x > y) return x;
38
	else return y;
38
    else return y;
39
}
39
}
40
 
40
 
41
		/* determine match between symbol name and string */
41
/* Determine match between symbol name and string. */
42
 
42
 
43
static int symbolMatch(SEXP expr, char *aString)
43
static int symbolMatch(SEXP expr, char *aString)
44
{
44
{
45
	return !strcmp(CHAR(PRINTNAME(expr)), aString);
45
    return !strcmp(CHAR(PRINTNAME(expr)), aString);
46
}
46
}
47
 
47
 
48
		/* code to determine the ascii code corresponding */
48
/* Code to determine the ascii code corresponding */
49
		/* to an element of a mathematical expression */
49
/* to an element of a mathematical expression. */
50
 
50
 
51
static int hatAscii()
51
static int hatAscii()
52
{
52
{
53
	return 94;
53
    return 94;
54
}
54
}
55
 
55
 
56
static int tildeAscii()
56
static int tildeAscii()
57
{
57
{
58
	return 126;
58
    return 126;
59
}
59
}
60
 
60
 
61
static int accentAscii(SEXP expr)
61
static int accentAscii(SEXP expr)
62
{
62
{
63
	int result = 0;
63
    int result = 0;
64
 
64
 
65
	if (symbolMatch(expr, "hat"))
65
    if (symbolMatch(expr, "hat"))
66
		result = hatAscii();
66
	result = hatAscii();
67
	else if (symbolMatch(expr, "tilde"))
67
    else if (symbolMatch(expr, "tilde"))
68
		result = tildeAscii();
68
	result = tildeAscii();
69
 
-
 
70
	return result;
69
    return result;
71
}
70
}
72
 
71
 
73
static int operatorAscii(SEXP expr)
72
static int operatorAscii(SEXP expr)
74
{
73
{
75
	int result = 0;
74
    int result = 0;
76
 
-
 
77
	if (symbolMatch(expr, "sum"))
75
    if (symbolMatch(expr, "sum"))
78
		result = 229;
76
	result = 229;
79
	else if (symbolMatch(expr, "integral"))
77
    else if (symbolMatch(expr, "integral"))
80
		result = 242;
78
	result = 242;
81
	else if (symbolMatch(expr, "product"))
79
    else if (symbolMatch(expr, "product"))
82
		result = 213;
80
	result = 213;
83
 
-
 
84
	return result;
81
    return result;
85
}
82
}
86
 
83
 
87
static int integralAscii(int section)
84
static int integralAscii(int section)
88
{
85
{
89
  if (section == 1)
86
    if (section == 1)
90
    return 243;
87
	return 243;
91
  else if (section == 2)
88
    else if (section == 2)
92
    return 244;
89
	return 244;
93
  else
90
    else
94
    return 245;
91
	return 245;
95
}
92
}
96
 
93
 
97
static int groupOpenAscii()
94
static int groupOpenAscii()
98
{
95
{
99
	return 40;
96
    return 40;
100
}
97
}
101
 
98
 
102
static int groupCloseAscii()
99
static int groupCloseAscii()
103
{
100
{
104
	return 41;
101
    return 41;
105
}
102
}
106
 
103
 
107
static int commaAscii()
104
static int commaAscii()
108
{
105
{
109
	return 44;
106
    return 44;
110
}
107
}
111
 
108
 
112
static int spaceAscii()
109
static int spaceAscii()
113
{
110
{
114
	return 32;
111
    return 32;
115
}
112
}
116
 
113
 
117
static int radicalAscii()
114
static int radicalAscii()
118
{
115
{
119
	return 214;
116
    return 214;
120
}
117
}
121
 
118
 
122
static int radicalExAscii()
119
static int radicalExAscii()
123
{
120
{
124
	return 96;
121
    return 96;
125
}
122
}
126
 
123
 
127
static struct {
124
static struct {
128
	char *name;
125
    char *name;
129
	int code;
126
    int code;
-
 
127
}
130
} GreekTable[] = {
128
GreekTable[] = {
131
 
129
 
132
	"Alpha", 65,
130
    "Alpha",    65,
133
	"Beta", 66,
131
    "Beta",     66,
134
	"Chi", 67,
132
    "Chi",      67,
135
	"Delta", 68,
133
    "Delta",    68,
136
	"Epsilon", 69,
134
    "Epsilon",  69,
137
	"Phi", 70,
135
    "Phi",      70,
138
	"Gamma", 71,
136
    "Gamma",    71,
139
	"Eta", 72,
137
    "Eta",      72,
140
	"Iota", 73,
138
    "Iota",     73,
141
	"Phi1", 74,
139
    "Phi1",     74,
142
	"Kappa", 75,
140
    "Kappa",    75,
143
	"Lambda", 76,
141
    "Lambda",   76,
144
	"Mu", 77,
142
    "Mu",       77,
145
	"Nu", 78,
143
    "Nu",       78,
146
	"Omicron", 79,
144
    "Omicron",  79,
147
	"Pi", 80,
145
    "Pi",       80,
148
	"Theta", 81,
146
    "Theta",    81,
149
	"Rho", 82,
147
    "Rho",      82,
150
	"Sigma", 83,
148
    "Sigma",    83,
151
	"Tau", 84,
149
    "Tau",      84,
152
	"Upsilon", 85,
150
    "Upsilon",  85,
153
	"sigma1", 86,
151
    "sigma1",   86,
154
	"Omega", 87,
152
    "Omega",    87,
155
	"Xi", 88,
153
    "Xi",       88,
156
	"Psi", 89,
154
    "Psi",      89,
157
	"Zeta", 90,
155
    "Zeta",     90,
158
 
156
 
159
	"alpha", 97,
157
    "alpha",    97,
160
	"beta", 98,
158
    "beta",     98,
161
	"chi", 99,
159
    "chi",      99,
162
	"delta", 100,
160
    "delta",   100,
163
	"epsilon", 101,
161
    "epsilon", 101,
164
	"phi", 102,
162
    "phi",     102,
165
	"gamma", 103,
163
    "gamma",   103,
166
	"eta", 104,
164
    "eta",     104,
167
	"iota", 105,
165
    "iota",    105,
168
	"phi1", 106,
166
    "phi1",    106,
169
	"kappa", 107,
167
    "kappa",   107,
170
	"lambda", 108,
168
    "lambda",  108,
171
	"mu", 109,
169
    "mu",      109,
172
	"nu", 110,
170
    "nu",      110,
173
	"omicron", 111,
171
    "omicron", 111,
174
	"pi", 112,
172
    "pi",      112,
175
	"theta", 113,
173
    "theta",   113,
176
	"rho", 114,
174
    "rho",     114,
177
	"sigma", 115,
175
    "sigma",   115,
178
	"tau", 116,
176
    "tau",     116,
179
	"upsilon", 117,
177
    "upsilon", 117,
180
	"omega1", 118,
178
    "omega1",  118,
181
	"omega", 119,
179
    "omega",   119,
182
	"xi", 120,
180
    "xi",      120,
183
	"psi", 121,
181
    "psi",     121,
184
	"zeta", 122,
182
    "zeta",    122,
185
 
183
 
186
	NULL, 0,
184
    NULL,      0,
187
};
185
};
188
 
186
 
189
static int greekAscii(SEXP expr)
187
static int greekAscii(SEXP expr)
190
{
188
{
191
	int i;
189
    int i;
192
 
-
 
193
	for (i = 0; GreekTable[i].code; i++)
190
    for (i = 0; GreekTable[i].code; i++)
194
		if (symbolMatch(expr, GreekTable[i].name))
191
	if (symbolMatch(expr, GreekTable[i].name))
195
			return GreekTable[i].code;
192
	    return GreekTable[i].code;
196
	return 0;
193
    return 0;
197
}
194
}
198
 
195
 
199
static int relAscii() { return 61; }
196
static int relAscii()
-
 
197
{
-
 
198
    return 61;
-
 
199
}
200
 
200
 
201
	/* initialisation code for mathematical notation */
201
/* Initialisation code for mathematical notation. */
202
 
202
 
203
static double ratioScale = 0.8;
203
static double ratioScale = 0.8;
204
static double scriptScale = 0.65;
204
static double scriptScale = 0.65;
205
static int ratioDepth = 0;
205
static int ratioDepth = 0;
206
static int metricUnit = INCHES;
206
static int metricUnit = INCHES;
Line 214... Line 214...
214
static SEXP subSymbol;
214
static SEXP subSymbol;
215
static SEXP groupSymbol;
215
static SEXP groupSymbol;
216
 
216
 
217
static void initFormulaSymbols()
217
static void initFormulaSymbols()
218
{
218
{
219
	plusSymbol = install("+");
219
    plusSymbol = install("+");
220
	minusSymbol = install("-");
220
    minusSymbol = install("-");
221
	timesSymbol = install("*");
221
    timesSymbol = install("*");
222
	divideSymbol = install("/");
222
    divideSymbol = install("/");
223
	equalSymbol = install("==");
223
    equalSymbol = install("==");
224
	superSymbol = install("^");
224
    superSymbol = install("^");
225
	subSymbol = install("[");
225
    subSymbol = install("[");
226
	groupSymbol = install("(");
226
    groupSymbol = install("(");
227
}
227
}
228
 
228
 
229
	/* code to determine the nature of an expression */
229
/* Code to determine the nature of an expression. */
230
 
230
 
231
static int formulaExpression(SEXP expr)
231
static int formulaExpression(SEXP expr)
232
{
232
{
233
	return (TYPEOF(expr) == LANGSXP);
233
    return (TYPEOF(expr) == LANGSXP);
234
}
234
}
235
 
235
 
236
static int symbolAtom(SEXP expr)
236
static int symbolAtom(SEXP expr)
237
{
237
{
238
	return (TYPEOF(expr) == SYMSXP);
238
    return (TYPEOF(expr) == SYMSXP);
239
}
239
}
240
 
240
 
241
static int numberAtom(SEXP expr)
241
static int numberAtom(SEXP expr)
242
{
242
{
243
	return (TYPEOF(expr) == REALSXP) ||
243
    return ((TYPEOF(expr) == REALSXP) ||
244
	    (TYPEOF(expr) == INTSXP) ||
244
	    (TYPEOF(expr) == INTSXP)  ||
245
	    (TYPEOF(expr) == CPLXSXP);
245
	    (TYPEOF(expr) == CPLXSXP));
246
}
246
}
247
 
247
 
248
static int stringAtom(SEXP expr)
248
static int stringAtom(SEXP expr)
249
{
249
{
250
	return (TYPEOF(expr) == STRSXP);
250
    return (TYPEOF(expr) == STRSXP);
251
}
251
}
252
 
252
 
253
static int binAtom(SEXP expr)
253
static int binAtom(SEXP expr)
254
{
254
{
255
	int result = symbolAtom(expr) &&
255
    int result = symbolAtom(expr) &&
256
	((expr == plusSymbol) ||
256
	((expr == plusSymbol)  ||
257
	 (expr == minusSymbol) ||
257
	 (expr == minusSymbol) ||
258
	 (expr == timesSymbol) ||
258
	 (expr == timesSymbol) ||
259
	 (expr == divideSymbol));
259
	 (expr == divideSymbol));
260
	return result;
260
    return result;
261
}
261
}
262
 
262
 
263
static int relAtom(SEXP expr)
263
static int relAtom(SEXP expr)
264
{
264
{
265
	return symbolAtom(expr) &&
265
    return symbolAtom(expr) &&
266
	    (expr == equalSymbol);
266
	(expr == equalSymbol);
267
}
267
}
268
 
268
 
269
static int multiplicationOperator(SEXP expr)
269
static int multiplicationOperator(SEXP expr)
270
{
270
{
271
	return binAtom(expr) &&
271
    return binAtom(expr) &&
272
	    (expr == timesSymbol);
272
	(expr == timesSymbol);
273
}
273
}
274
 
274
 
275
static int superAtom(SEXP expr)
275
static int superAtom(SEXP expr)
276
{
276
{
277
	return symbolAtom(expr) &&
277
    return symbolAtom(expr) &&
278
	    (expr == superSymbol);
278
	(expr == superSymbol);
279
}
279
}
280
 
280
 
281
static int subAtom(SEXP expr)
281
static int subAtom(SEXP expr)
282
{
282
{
283
	return symbolAtom(expr) &&
283
    return symbolAtom(expr) &&
284
	    (expr == subSymbol);
284
	(expr == subSymbol);
285
}
285
}
286
 
286
 
287
static int hatAtom(SEXP expr)
287
static int hatAtom(SEXP expr)
288
{
288
{
289
	return symbolMatch(expr, "hat");
289
    return symbolMatch(expr, "hat");
290
}
290
}
291
 
291
 
292
static int barAtom(SEXP expr)
292
static int barAtom(SEXP expr)
293
{
293
{
294
	return symbolMatch(expr, "bar");
294
    return symbolMatch(expr, "bar");
295
}
295
}
296
 
296
 
297
static int accentAtom(SEXP expr)
297
static int accentAtom(SEXP expr)
298
{
298
{
299
	return symbolAtom(expr) &&
299
    return symbolAtom(expr) &&
300
	    (hatAtom(expr) || barAtom(expr) ||
-
 
301
	     symbolMatch(expr, "tilde"));
300
	(hatAtom(expr) || barAtom(expr) || symbolMatch(expr, "tilde"));
302
}
301
}
303
 
302
 
304
static int fractionAtom(SEXP expr)
303
static int fractionAtom(SEXP expr)
305
{
304
{
306
	return symbolAtom(expr) &&
305
    return symbolAtom(expr) &&
307
	    (symbolMatch(expr, "over") || symbolMatch(expr, "frac"));
306
	(symbolMatch(expr, "over") || symbolMatch(expr, "frac"));
308
}
307
}
309
 
308
 
310
static int groupAtom(SEXP expr)
309
static int groupAtom(SEXP expr)
311
{
310
{
312
	return symbolAtom(expr) && (expr == groupSymbol);
311
    return symbolAtom(expr) && (expr == groupSymbol);
313
}
312
}
314
 
313
 
315
static int operatorAtom(SEXP expr)
314
static int operatorAtom(SEXP expr)
316
{
315
{
317
	return symbolAtom(expr) &&
316
    return symbolAtom(expr) &&
318
	    (symbolMatch(expr, "sum") ||
317
	(symbolMatch(expr, "sum") ||
319
	     symbolMatch(expr, "integral") ||
318
	 symbolMatch(expr, "integral") ||
320
	     symbolMatch(expr, "product"));
319
	 symbolMatch(expr, "product"));
321
}
320
}
322
 
321
 
323
static int integralOperator(SEXP expr)
322
static int integralOperator(SEXP expr)
324
{
323
{
325
  return symbolAtom(expr) && symbolMatch(expr, "integral");
324
    return symbolAtom(expr) && symbolMatch(expr, "integral");
326
}
325
}
327
 
326
 
328
static int radicalAtom(SEXP expr)
327
static int radicalAtom(SEXP expr)
329
{
328
{
330
	return symbolAtom(expr) &&
329
    return symbolAtom(expr) &&
331
	    (symbolMatch(expr, "root") ||
-
 
332
	     symbolMatch(expr, "sqrt"));
330
	(symbolMatch(expr, "root") || symbolMatch(expr, "sqrt"));
333
}
331
}
334
 
332
 
335
static int absAtom(SEXP expr)
333
static int absAtom(SEXP expr)
336
{
334
{
337
	return symbolAtom(expr) && symbolMatch(expr, "abs");
335
    return symbolAtom(expr) && symbolMatch(expr, "abs");
338
}
336
}
339
 
337
 
340
static int curlyAtom(SEXP expr)
338
static int curlyAtom(SEXP expr)
341
{
339
{
342
	return symbolAtom(expr) && symbolMatch(expr, "{");
340
    return symbolAtom(expr) && symbolMatch(expr, "{");
343
}
341
}
344
 
342
 
345
static int boldAtom(SEXP expr)
343
static int boldAtom(SEXP expr)
346
{
344
{
347
	return symbolAtom(expr) && symbolMatch(expr, "bold");
345
    return symbolAtom(expr) && symbolMatch(expr, "bold");
348
}
346
}
349
 
347
 
350
static int italicAtom(SEXP expr)
348
static int italicAtom(SEXP expr)
351
{
349
{
352
	return symbolAtom(expr) && symbolMatch(expr, "italic");
350
    return symbolAtom(expr) && symbolMatch(expr, "italic");
353
}
351
}
354
 
352
 
355
static int plainAtom(SEXP expr)
353
static int plainAtom(SEXP expr)
356
{
354
{
357
	return symbolAtom(expr) && symbolMatch(expr, "plain");
355
    return symbolAtom(expr) && symbolMatch(expr, "plain");
358
}
356
}
359
 
357
 
360
static int boldItalicAtom(SEXP expr)
358
static int boldItalicAtom(SEXP expr)
361
{
359
{
362
	return symbolAtom(expr) && symbolMatch(expr, "bolditalic");
360
    return symbolAtom(expr) && symbolMatch(expr, "bolditalic");
363
}
361
}
364
 
362
 
365
static int italicExpression(SEXP expr)
363
static int italicExpression(SEXP expr)
366
{
364
{
367
	return formulaExpression(expr) &&
365
    return formulaExpression(expr) &&
368
	       (italicAtom(CAR(expr)) || boldItalicAtom(CAR(expr)));
366
	(italicAtom(CAR(expr)) || boldItalicAtom(CAR(expr)));
369
}
367
}
370
 
368
 
371
static int nonItalicExpression(SEXP expr)
369
static int nonItalicExpression(SEXP expr)
372
{
370
{
373
	return formulaExpression(expr) &&
371
    return formulaExpression(expr) &&
374
	       (boldAtom(CAR(expr)) || plainAtom(CAR(expr)));
372
	(boldAtom(CAR(expr)) || plainAtom(CAR(expr)));
375
}
373
}
376
 
374
 
377
static int concatenateAtom(SEXP expr)
375
static int concatenateAtom(SEXP expr)
378
{
376
{
379
	return symbolAtom(expr) && symbolMatch(expr, "paste");
377
    return symbolAtom(expr) && symbolMatch(expr, "paste");
380
}
378
}
381
 
379
 
382
static int greekSymbol(SEXP expr)
380
static int greekSymbol(SEXP expr)
383
{
381
{
384
	int i;
382
    int i;
385
	if (symbolAtom(expr)) {
383
    if (symbolAtom(expr)) {
386
		for (i = 0; GreekTable[i].code; i++)
384
	for (i = 0; GreekTable[i].code; i++)
387
			if (symbolMatch(expr, GreekTable[i].name))
385
	    if (symbolMatch(expr, GreekTable[i].name))
388
				return 1;
386
		return 1;
389
	}
387
    }
390
	return 0;
388
    return 0;
391
}
389
}
392
 
390
 
393
		/* code to determine a font from the */
391
/* Code to determine a font from the */
394
		/* nature of the expression */
392
/* nature of the expression */
395
 
393
 
396
static int currentFont = 3;
394
static int currentFont = 3;
397
 
395
 
398
static int getFont() { return currentFont; }
396
static int getFont() { return currentFont; }
399
 
397
 
Line 406... Line 404...
406
 
404
 
407
static int isItalic() { return (getFont() == 3 || getFont() == 4); }
405
static int isItalic() { return (getFont() == 3 || getFont() == 4); }
408
 
406
 
409
static int atomFontFace(SEXP expr)
407
static int atomFontFace(SEXP expr)
410
{
408
{
411
	int fontFace = 1;
409
    int fontFace = 1;
412
	if (symbolAtom(expr)) {
410
    if (symbolAtom(expr)) {
413
		if (greekSymbol(expr) ||
411
	if (greekSymbol(expr) ||
414
		    binAtom(expr) ||
412
	    binAtom(expr) ||
415
		    relAtom(expr) ||
413
	    relAtom(expr) ||
416
		    groupAtom(expr) ||
414
	    groupAtom(expr) ||
417
		    operatorAtom(expr) ||
415
	    operatorAtom(expr) ||
418
		    radicalAtom(expr))
416
	    radicalAtom(expr))
419
			fontFace = 5;
417
	    fontFace = 5;
420
		else
418
	else
421
#ifdef OLD
419
#ifdef OLD
422
			fontFace = 3;
420
	    fontFace = 3;
423
#else
421
#else
424
			fontFace = getFont();
422
	fontFace = getFont();
425
#endif
423
#endif
426
	}
424
    }
427
	return fontFace;
425
    return fontFace;
428
}
426
}
429
 
427
 
430
	/* a forward declaration */
428
/* a forward declaration */
431
static double fontHeight();
429
static double fontHeight();
432
 
430
 
433
	/* some forward declarations */
431
/* some forward declarations */
434
 
-
 
435
typedef struct {
432
typedef struct {
436
	double height;
433
    double height;
437
	double depth;
434
    double depth;
438
	double width;
435
    double width;
439
} BBOX;
436
} BBOX;
440
 
437
 
441
static double bboxHeight(BBOX bbox)
438
static double bboxHeight(BBOX bbox)
442
{
439
{
443
	return bbox.height;
440
    return bbox.height;
444
}
441
}
445
static double bboxDepth(BBOX bbox)
442
static double bboxDepth(BBOX bbox)
446
{
443
{
447
	return bbox.depth;
444
    return bbox.depth;
448
}
445
}
449
static double bboxWidth(BBOX bbox)
446
static double bboxWidth(BBOX bbox)
450
{
447
{
451
	return bbox.width;
448
    return bbox.width;
452
}
449
}
453
static BBOX asciiBBox(int ascii);
450
static BBOX asciiBBox(int ascii);
454
static BBOX elementBBox(SEXP expr);
451
static BBOX elementBBox(SEXP expr);
455
static void drawElement(SEXP expr);
452
static void drawElement(SEXP expr);
456
 
453
 
457
 
454
 
458
	/* code to determine superscript offsets, etc ... */
455
/* code to determine superscript offsets, etc ... */
459
 
456
 
460
	/* these "twiddle factors" are given as  */
457
/* these "twiddle factors" are given as  */
461
	/* proportions of the current font height */
458
/* proportions of the current font height */
462
	/* NOTE that metric information is obtained */
459
/* NOTE that metric information is obtained */
463
	/* in INCHES so that the information will */
460
/* in INCHES so that the information will */
464
	/* be useful for rotated math.text */
461
/* be useful for rotated math.text */
465
 
462
 
466
 
463
 
467
static float SuperDrop = 0.3;
464
static float SuperDrop = 0.3;
468
static float Superscript = 0.3;
465
static float Superscript = 0.3;
469
static float SubDrop = 0.1;
466
static float SubDrop = 0.1;
Line 478... Line 475...
478
static float AbsSpace = 0.2;
475
static float AbsSpace = 0.2;
479
static float OperatorSpace[] = { 0.1, 0.15, 0.2, 0.6, 0.1 };
476
static float OperatorSpace[] = { 0.1, 0.15, 0.2, 0.6, 0.1 };
480
 
477
 
481
static double fontHeight()
478
static double fontHeight()
482
{
479
{
483
	double height, depth, width;
480
    double height, depth, width;
484
	GMetricInfo(0, &height, &depth, &width, metricUnit, mathDevice);
481
    GMetricInfo(0, &height, &depth, &width, metricUnit, mathDevice);
485
	return height + depth;
482
    return height + depth;
486
}
483
}
487
 
484
 
488
static double xHeight()
485
static double xHeight()
489
{
486
{
490
	int x = 'x';
487
    int x = 'x';
491
	double xheight, depth, width;
488
    double xheight, depth, width;
492
	GMetricInfo(x, &xheight, &depth, &width, metricUnit, mathDevice);
489
    GMetricInfo(x, &xheight, &depth, &width, metricUnit, mathDevice);
493
	return xheight;
490
    return xheight;
494
}
491
}
495
 
492
 
496
static double axisHeight()
493
static double axisHeight()
497
{
494
{
498
	int plus = '+';
495
    int plus = '+';
499
	double plusHeight, depth, width;
496
    double plusHeight, depth, width;
500
	GMetricInfo(plus, &plusHeight, &depth, &width, metricUnit, mathDevice);
497
    GMetricInfo(plus, &plusHeight, &depth, &width, metricUnit, mathDevice);
501
	return 0.5 * plusHeight;
498
    return 0.5 * plusHeight;
502
}
499
}
503
 
500
 
504
static double superscriptDrop()
501
static double superscriptDrop()
505
{
502
{
506
	return SuperDrop * fontHeight();
503
    return SuperDrop * fontHeight();
507
}
504
}
508
static double subscriptDrop()
505
static double subscriptDrop()
509
{
506
{
510
	return SubDrop * fontHeight();
507
    return SubDrop * fontHeight();
511
}
508
}
512
static double superscript()
509
static double superscript()
513
{
510
{
514
	return Superscript * fontHeight();
511
    return Superscript * fontHeight();
515
}
512
}
516
static double subscript()
513
static double subscript()
517
{
514
{
518
	return Subscript * fontHeight();
515
    return Subscript * fontHeight();
519
}
516
}
520
static double lineWidth()
517
static double lineWidth()
521
{
518
{
522
	return LineWidth * fontHeight();
519
    return LineWidth * fontHeight();
523
}
520
}
524
static double numeratorShift()
521
static double numeratorShift()
525
{
522
{
526
	return axisHeight() + 3 * lineWidth();
523
    return axisHeight() + 3 * lineWidth();
527
}
524
}
528
static double denominatorShift()
525
static double denominatorShift()
529
{
526
{
530
	return axisHeight() - 3 * lineWidth() - xHeight();
527
    return axisHeight() - 3 * lineWidth() - xHeight();
531
}
528
}
532
static double radicalDrop()
529
static double radicalDrop()
533
{
530
{
534
	return 1.25 * lineWidth();
531
    return 1.25 * lineWidth();
535
}
532
}
536
static double customAccentGap()
533
static double customAccentGap()
537
{
534
{
538
	return CustomAccentGap * fontHeight();
535
    return CustomAccentGap * fontHeight();
539
}
536
}
540
static double customHatHeight()
537
static double customHatHeight()
541
{
538
{
542
	return CustomHatHeight * fontHeight();
539
    return CustomHatHeight * fontHeight();
543
}
540
}
544
static double customRadicalWidth()
541
static double customRadicalWidth()
545
{
542
{
546
	return CustomRadicalWidth * fontHeight();
543
    return CustomRadicalWidth * fontHeight();
547
}
544
}
548
static double customRadicalSpace()
545
static double customRadicalSpace()
549
{
546
{
550
	return CustomRadicalSpace * fontHeight();
547
    return CustomRadicalSpace * fontHeight();
551
}
548
}
552
static double customRadicalGap()
549
static double customRadicalGap()
553
{
550
{
554
	return CustomRadicalGap * fontHeight();
551
    return CustomRadicalGap * fontHeight();
555
}
552
}
556
static double absSpace()
553
static double absSpace()
557
{
554
{
558
	return AbsSpace * fontHeight();
555
    return AbsSpace * fontHeight();
559
}
556
}
560
static double operatorSpace(int i)
557
static double operatorSpace(int i)
561
{
558
{
562
  return OperatorSpace[i] * fontHeight();
559
    return OperatorSpace[i] * fontHeight();
563
}
560
}
564
 
561
 
565
 
562
 
566
	/* should only be called when font=5 (symbol) */
563
/* Should only be called when font=5 (symbol) */
567
 
564
 
568
static double radicalExWidth()
565
static double radicalExWidth()
569
{
566
{
570
	int radicalEx = 96;
567
    int radicalEx = 96;
571
	double height, depth, REWidth;
568
    double height, depth, REWidth;
572
	GMetricInfo(radicalEx, &height, &depth, &REWidth, metricUnit, mathDevice);
569
    GMetricInfo(radicalEx, &height, &depth, &REWidth, metricUnit, mathDevice);
573
	return REWidth;
570
    return REWidth;
574
}
571
}
575
 
572
 
576
static double superscriptShift(SEXP body, SEXP sup)
573
static double superscriptShift(SEXP body, SEXP sup)
577
{
574
{
578
	BBOX bodyBBox = elementBBox(body);
575
    BBOX bodyBBox = elementBBox(body);
579
	BBOX superscriptBBox;
576
    BBOX superscriptBBox;
580
	float cexSaved = mathDevice->gp.cex;
577
    float cexSaved = mathDevice->gp.cex;
581
	double temp1 = bboxHeight(bodyBBox) - superscriptDrop();
578
    double temp1 = bboxHeight(bodyBBox) - superscriptDrop();
582
	double temp2 = superscript();
579
    double temp2 = superscript();
583
	double temp3;
580
    double temp3;
584
 
581
 
585
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
582
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
586
	superscriptBBox = elementBBox(sup);
583
    superscriptBBox = elementBBox(sup);
587
	mathDevice->gp.cex = cexSaved;
584
    mathDevice->gp.cex = cexSaved;
588
	temp3 = bboxDepth(superscriptBBox) + 0.25 * xHeight();
585
    temp3 = bboxDepth(superscriptBBox) + 0.25 * xHeight();
589
 
586
 
590
	return max(temp1, max(temp2, temp3));
587
    return max(temp1, max(temp2, temp3));
591
}
588
}
592
 
589
 
593
static double subscriptShift(SEXP body, SEXP sub, int subOnly)
590
static double subscriptShift(SEXP body, SEXP sub, int subOnly)
594
{
591
{
595
	BBOX bodyBBox = elementBBox(body);
592
    BBOX bodyBBox = elementBBox(body);
596
	BBOX subscriptBBox;
593
    BBOX subscriptBBox;
597
	float cexSaved = mathDevice->gp.cex;
594
    float cexSaved = mathDevice->gp.cex;
598
	double temp1 = bboxDepth(bodyBBox) + subscriptDrop();
595
    double temp1 = bboxDepth(bodyBBox) + subscriptDrop();
599
	double temp2 = subscript();
596
    double temp2 = subscript();
600
	double temp3;
597
    double temp3;
601
 
598
 
602
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
599
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
603
	subscriptBBox = elementBBox(sub);
600
    subscriptBBox = elementBBox(sub);
604
	mathDevice->gp.cex = cexSaved;
601
    mathDevice->gp.cex = cexSaved;
605
	temp3 = bboxHeight(subscriptBBox) - (4 * xHeight() / 5);
602
    temp3 = bboxHeight(subscriptBBox) - (4 * xHeight() / 5);
606
 
603
 
607
	if (subOnly)
604
    if (subOnly)
608
		return max(temp1, max(temp2, temp3));
605
	return max(temp1, max(temp2, temp3));
609
	else
606
    else
610
		return max(temp1, temp2);
607
	return max(temp1, temp2);
611
}
608
}
612
 
609
 
613
static void supsubShift(SEXP body, SEXP sup, SEXP sub,
610
static void supsubShift(SEXP body, SEXP sup, SEXP sub,
614
			double *supShift, double *subShift)
611
			double *supShift, double *subShift)
615
{
612
{
616
	BBOX superscriptBBox, subscriptBBox;
613
    BBOX superscriptBBox, subscriptBBox;
617
	float cexSaved = mathDevice->gp.cex;
614
    float cexSaved = mathDevice->gp.cex;
618
	double temp1, temp2;
615
    double temp1, temp2;
619
 
616
 
620
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
617
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
621
	superscriptBBox = elementBBox(sup);
618
    superscriptBBox = elementBBox(sup);
622
	subscriptBBox = elementBBox(sub);
619
    subscriptBBox = elementBBox(sub);
623
	mathDevice->gp.cex = cexSaved;
620
    mathDevice->gp.cex = cexSaved;
624
	*supShift = superscriptShift(body, sup);
621
    *supShift = superscriptShift(body, sup);
625
	*subShift = subscriptShift(body, sub, 0);
622
    *subShift = subscriptShift(body, sub, 0);
626
 
623
 
627
	temp1 = (*supShift - bboxDepth(superscriptBBox)) -
624
    temp1 = (*supShift - bboxDepth(superscriptBBox)) -
628
	    (bboxHeight(subscriptBBox) - *subShift);
625
	(bboxHeight(subscriptBBox) - *subShift);
629
	if (temp1 < (4 * lineWidth()))
626
    if (temp1 < (4 * lineWidth()))
630
		*subShift = bboxHeight(subscriptBBox) -
627
	*subShift = bboxHeight(subscriptBBox) -
631
		    *supShift +
628
	    *supShift +
632
		    bboxDepth(superscriptBBox) +
629
	    bboxDepth(superscriptBBox) +
633
		    (4 * lineWidth());
630
	    (4 * lineWidth());
634
 
631
 
635
	temp2 = (4 * xHeight() / 5) -
632
    temp2 = (4 * xHeight() / 5) -
636
	    (*supShift - bboxDepth(superscriptBBox));
633
	(*supShift - bboxDepth(superscriptBBox));
637
	if (temp2 > 0) {
634
    if (temp2 > 0) {
638
		*supShift = *supShift + temp2;
635
	*supShift = *supShift + temp2;
639
		*subShift = *subShift - temp2;
636
	*subShift = *subShift - temp2;
640
	}
637
    }
641
}
638
}
642
 
639
 
643
static double accentVShift(SEXP body)
640
static double accentVShift(SEXP body)
644
{
641
{
645
	double temp = xHeight();
642
    double temp = xHeight();
646
	double bodyHeight = bboxHeight(elementBBox(body));
643
    double bodyHeight = bboxHeight(elementBBox(body));
647
 
644
 
648
	if (bodyHeight > temp)
645
    if (bodyHeight > temp)
649
		return bodyHeight - temp;
646
	return bodyHeight - temp;
650
	else
647
    else
651
		return 0;
648
	return 0;
652
}
649
}
653
 
650
 
654
static double accentHShift(SEXP body, SEXP accent)
651
static double accentHShift(SEXP body, SEXP accent)
655
{
652
{
656
	return (bboxWidth(elementBBox(body)) -
653
    return (bboxWidth(elementBBox(body)) -
657
		bboxWidth(elementBBox(accent))) / 2;
654
	    bboxWidth(elementBBox(accent))) / 2;
658
}
655
}
659
 
656
 
660
static double numeratorVShift(SEXP num)
657
static double numeratorVShift(SEXP num)
661
{
658
{
662
	BBOX numBBox;
659
    BBOX numBBox;
663
	float cexSaved = mathDevice->gp.cex;
660
    float cexSaved = mathDevice->gp.cex;
664
	double theShift, theClearance, minClearance;
661
    double theShift, theClearance, minClearance;
665
 
662
 
666
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
663
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
667
	numBBox = elementBBox(num);
664
    numBBox = elementBBox(num);
668
	mathDevice->gp.cex = cexSaved;
665
    mathDevice->gp.cex = cexSaved;
669
 
666
 
670
	theShift = numeratorShift();
667
    theShift = numeratorShift();
671
	theClearance = numeratorShift() - bboxDepth(numBBox) -
668
    theClearance = numeratorShift() - bboxDepth(numBBox) -
672
	    (axisHeight() + 0.5 * lineWidth());
669
	(axisHeight() + 0.5 * lineWidth());
673
	minClearance = 3 * lineWidth();
670
    minClearance = 3 * lineWidth();
674
 
671
 
675
	if (theClearance < minClearance)
672
    if (theClearance < minClearance)
676
		theShift += minClearance - theClearance;
673
	theShift += minClearance - theClearance;
677
 
674
 
678
	return theShift;
675
    return theShift;
679
}
676
}
680
 
677
 
681
/* RATIO */
678
/* RATIO */
682
static double denominatorVShift(SEXP denom)
679
static double denominatorVShift(SEXP denom)
683
{
680
{
684
	BBOX denomBBox;
681
    BBOX denomBBox;
685
	float cexSaved = mathDevice->gp.cex;
682
    float cexSaved = mathDevice->gp.cex;
686
	double theShift, theClearance, minClearance;
683
    double theShift, theClearance, minClearance;
687
 
684
 
688
#ifdef OLD
685
#ifdef OLD
689
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
686
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
690
#else
687
#else
691
	mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
688
    mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
692
#endif
689
#endif
693
	denomBBox = elementBBox(denom);
690
    denomBBox = elementBBox(denom);
694
#ifdef OLD
691
#ifdef OLD
695
	mathDevice->gp.cex = cexSaved;
692
    mathDevice->gp.cex = cexSaved;
696
#else
693
#else
697
	mathDevice->gp.cex = cexSaved;
694
    mathDevice->gp.cex = cexSaved;
698
#endif
695
#endif
699
 
696
 
700
	theShift = denominatorShift();
697
    theShift = denominatorShift();
701
	theClearance = axisHeight() - 0.5 * lineWidth() -
698
    theClearance = axisHeight() - 0.5 * lineWidth() -
702
	    (bboxHeight(denomBBox) - denominatorShift());
699
	(bboxHeight(denomBBox) - denominatorShift());
703
	minClearance = 3 * lineWidth();
700
    minClearance = 3 * lineWidth();
704
 
701
 
705
	if (theClearance < minClearance)
702
    if (theClearance < minClearance)
706
		theShift += minClearance - theClearance;
703
	theShift += minClearance - theClearance;
707
 
704
 
708
	return theShift;
705
    return theShift;
709
}
706
}
710
 
707
 
711
/* RATIO */
708
/* RATIO */
712
static double fractionWidth(SEXP num, SEXP denom)
709
static double fractionWidth(SEXP num, SEXP denom)
713
{
710
{
714
	BBOX numBBox;
711
    BBOX numBBox;
715
	BBOX denomBBox;
712
    BBOX denomBBox;
716
	float cexSaved = mathDevice->gp.cex;
713
    float cexSaved = mathDevice->gp.cex;
717
	double temp1, temp2;
714
    double temp1, temp2;
718
 
715
 
719
#ifdef OLD
716
#ifdef OLD
720
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
717
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
721
#else
718
#else
722
	mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
719
    mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
723
#endif
720
#endif
724
	numBBox = elementBBox(num);
721
    numBBox = elementBBox(num);
725
	denomBBox = elementBBox(denom);
722
    denomBBox = elementBBox(denom);
726
#ifdef OLD
723
#ifdef OLD
727
	mathDevice->gp.cex = cexSaved;
724
    mathDevice->gp.cex = cexSaved;
728
#else
725
#else
729
	mathDevice->gp.cex = cexSaved;
726
    mathDevice->gp.cex = cexSaved;
730
#endif
727
#endif
731
	temp1 = bboxWidth(numBBox);
728
    temp1 = bboxWidth(numBBox);
732
	temp2 = bboxWidth(denomBBox);
729
    temp2 = bboxWidth(denomBBox);
733
 
730
 
734
	return max(temp1, temp2);
731
    return max(temp1, temp2);
735
}
732
}
736
 
733
 
737
/* RATIO */
734
/* RATIO */
738
static void numdenomHShift(SEXP num, SEXP denom,
735
static void numdenomHShift(SEXP num, SEXP denom,
739
			   double *numShift, double *denomShift)
736
			   double *numShift, double *denomShift)
740
{
737
{
741
	BBOX numBBox;
738
    BBOX numBBox;
742
	BBOX denomBBox;
739
    BBOX denomBBox;
743
	float cexSaved = mathDevice->gp.cex;
740
    float cexSaved = mathDevice->gp.cex;
744
	double temp1, temp2;
741
    double temp1, temp2;
745
 
742
 
746
#ifdef OLD
743
#ifdef OLD
747
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
744
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
748
#else
745
#else
749
	mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
746
    mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
750
#endif
747
#endif
751
	numBBox = elementBBox(num);
748
    numBBox = elementBBox(num);
752
	denomBBox = elementBBox(denom);
749
    denomBBox = elementBBox(denom);
753
#ifdef OLD
750
#ifdef OLD
754
	mathDevice->gp.cex = cexSaved;
751
    mathDevice->gp.cex = cexSaved;
755
#else
752
#else
756
	mathDevice->gp.cex = cexSaved;
753
    mathDevice->gp.cex = cexSaved;
757
#endif
754
#endif
758
	temp1 = bboxWidth(numBBox);
755
    temp1 = bboxWidth(numBBox);
759
	temp2 = bboxWidth(denomBBox);
756
    temp2 = bboxWidth(denomBBox);
760
 
757
 
761
	if (temp1 > temp2) {
758
    if (temp1 > temp2) {
762
		*numShift = 0;
759
	*numShift = 0;
763
		*denomShift = (temp1 - temp2) / 2;
760
	*denomShift = (temp1 - temp2) / 2;
764
	}
761
    }
765
	else {
762
    else {
766
		*numShift = (temp2 - temp1) / 2;
763
	*numShift = (temp2 - temp1) / 2;
767
		*denomShift = 0;
764
	*denomShift = 0;
768
	}
765
    }
769
}
766
}
770
 
767
 
771
static int normalRadical(SEXP body)
768
static int normalRadical(SEXP body)
772
{
769
{
773
	BBOX bodyBBox = elementBBox(body);
770
    BBOX bodyBBox = elementBBox(body);
774
	BBOX radicalBBox = asciiBBox(radicalAscii());
771
    BBOX radicalBBox = asciiBBox(radicalAscii());
775
 
772
 
776
	return ((bboxHeight(bodyBBox) + radicalDrop())
773
    return ((bboxHeight(bodyBBox) + radicalDrop())
777
		<= bboxHeight(radicalBBox)) &&
774
	    <= bboxHeight(radicalBBox)) &&
778
	    (bboxDepth(bodyBBox) <= bboxDepth(radicalBBox));
775
	(bboxDepth(bodyBBox) <= bboxDepth(radicalBBox));
779
}
776
}
780
 
777
 
781
static double radicalVShift(SEXP body)
778
static double radicalVShift(SEXP body)
782
{
779
{
783
	BBOX bodyBBox = elementBBox(body);
780
    BBOX bodyBBox = elementBBox(body);
784
	return bboxHeight(bodyBBox) + radicalDrop();
781
    return bboxHeight(bodyBBox) + radicalDrop();
785
}
782
}
786
 
783
 
787
 
784
 
788
static BBOX theOperatorBBox(SEXP operator);
785
static BBOX theOperatorBBox(SEXP operator);
789
 
786
 
790
static BBOX operatorLimitBBox(SEXP operator);
787
static BBOX operatorLimitBBox(SEXP operator);
791
 
788
 
792
static double operatorLowerShift(SEXP operator, SEXP lower)
789
static double operatorLowerShift(SEXP operator, SEXP lower)
793
{
790
{
794
  BBOX opBBox = theOperatorBBox(operator);
791
    BBOX opBBox = theOperatorBBox(operator);
795
  BBOX lowerBBox;
792
    BBOX lowerBBox;
796
  double lowerHeight;
793
    double lowerHeight;
797
  double spacing2 = operatorSpace(1);
794
    double spacing2 = operatorSpace(1);
798
  double spacing4 = operatorSpace(3);
795
    double spacing4 = operatorSpace(3);
799
 
796
 
800
  lowerBBox = operatorLimitBBox(lower);
797
    lowerBBox = operatorLimitBBox(lower);
801
  lowerHeight = bboxHeight(lowerBBox);
798
    lowerHeight = bboxHeight(lowerBBox);
802
  if (spacing2 > (spacing4 - lowerHeight))
799
    if (spacing2 > (spacing4 - lowerHeight))
803
    return bboxDepth(opBBox) + spacing2 + lowerHeight;
800
	return bboxDepth(opBBox) + spacing2 + lowerHeight;
804
  else
801
    else
805
    return bboxDepth(opBBox) + spacing4;
802
	return bboxDepth(opBBox) + spacing4;
806
}
803
}
807
 
804
 
808
static double operatorUpperShift(SEXP operator, SEXP upper)
805
static double operatorUpperShift(SEXP operator, SEXP upper)
809
{
806
{
810
  BBOX opBBox = theOperatorBBox(operator);
807
    BBOX opBBox = theOperatorBBox(operator);
811
  BBOX upperBBox;
808
    BBOX upperBBox;
812
  double upperDepth;
809
    double upperDepth;
813
  double spacing1 = operatorSpace(0);
810
    double spacing1 = operatorSpace(0);
814
  double spacing3 = operatorSpace(2);
811
    double spacing3 = operatorSpace(2);
815
 
812
 
816
  upperBBox = operatorLimitBBox(upper);
813
    upperBBox = operatorLimitBBox(upper);
817
  upperDepth = bboxDepth(upperBBox);
814
    upperDepth = bboxDepth(upperBBox);
818
  if (spacing1 > (spacing3 - upperDepth))
815
    if (spacing1 > (spacing3 - upperDepth))
819
    return bboxHeight(opBBox) + spacing1 + upperDepth;
816
	return bboxHeight(opBBox) + spacing1 + upperDepth;
820
  else
817
    else
821
    return bboxHeight(opBBox) + spacing3;
818
	return bboxHeight(opBBox) + spacing3;
822
}
819
}
823
 
820
 
824
static double operatorLowerHShift(SEXP operator, SEXP lower)
821
static double operatorLowerHShift(SEXP operator, SEXP lower)
825
{
822
{
826
  BBOX opBBox = theOperatorBBox(operator);
823
    BBOX opBBox = theOperatorBBox(operator);
827
  BBOX lowerBBox;
824
    BBOX lowerBBox;
828
  double maxWidth = bboxWidth(opBBox);
825
    double maxWidth = bboxWidth(opBBox);
829
 
826
 
830
  lowerBBox = operatorLimitBBox(lower);
827
    lowerBBox = operatorLimitBBox(lower);
831
  if (bboxWidth(lowerBBox) < maxWidth)
828
    if (bboxWidth(lowerBBox) < maxWidth)
832
    return (maxWidth - bboxWidth(lowerBBox))/2;
829
	return (maxWidth - bboxWidth(lowerBBox))/2;
833
  else
830
    else
834
    return 0;
831
	return 0;
835
}
832
}
836
 
833
 
837
static double operatorHShift(SEXP operator, SEXP lower)
834
static double operatorHShift(SEXP operator, SEXP lower)
838
{
835
{
839
  BBOX opBBox = theOperatorBBox(operator);
836
    BBOX opBBox = theOperatorBBox(operator);
840
  BBOX lowerBBox;
837
    BBOX lowerBBox;
841
  double maxWidth = bboxWidth(opBBox);
838
    double maxWidth = bboxWidth(opBBox);
842
 
839
 
843
  lowerBBox = operatorLimitBBox(lower);
840
    lowerBBox = operatorLimitBBox(lower);
844
  if (bboxWidth(lowerBBox) > maxWidth)
841
    if (bboxWidth(lowerBBox) > maxWidth)
845
    return (bboxWidth(lowerBBox) - maxWidth)/2;
842
	return (bboxWidth(lowerBBox) - maxWidth)/2;
846
  else
843
    else
847
    return 0;
844
	return 0;
848
}
845
}
849
 
846
 
850
static double operatorLowerHShiftAll(SEXP operator, SEXP lower, SEXP upper)
847
static double operatorLowerHShiftAll(SEXP operator, SEXP lower, SEXP upper)
851
{
848
{
852
  BBOX opBBox = theOperatorBBox(operator);
849
    BBOX opBBox = theOperatorBBox(operator);
853
  BBOX lowerBBox, upperBBox;
850
    BBOX lowerBBox, upperBBox;
854
  double maxWidth = bboxWidth(opBBox);
851
    double maxWidth = bboxWidth(opBBox);
855
 
852
 
856
  lowerBBox = operatorLimitBBox(lower);
853
    lowerBBox = operatorLimitBBox(lower);
857
  upperBBox = operatorLimitBBox(upper);
854
    upperBBox = operatorLimitBBox(upper);
858
  maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
855
    maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
859
 
856
 
860
  if (bboxWidth(lowerBBox) < maxWidth)
857
    if (bboxWidth(lowerBBox) < maxWidth)
861
    return (maxWidth - bboxWidth(lowerBBox))/2;
858
	return (maxWidth - bboxWidth(lowerBBox))/2;
862
  else
859
    else
863
    return 0;
860
	return 0;
864
}
861
}
865
 
862
 
866
static double operatorUpperHShiftAll(SEXP operator, SEXP lower, SEXP upper)
863
static double operatorUpperHShiftAll(SEXP operator, SEXP lower, SEXP upper)
867
{
864
{
868
  BBOX opBBox = theOperatorBBox(operator);
865
    BBOX opBBox = theOperatorBBox(operator);
869
  BBOX lowerBBox, upperBBox;
866
    BBOX lowerBBox, upperBBox;
870
  double maxWidth = bboxWidth(opBBox);
867
    double maxWidth = bboxWidth(opBBox);
871
 
868
 
872
  lowerBBox = operatorLimitBBox(lower);
869
    lowerBBox = operatorLimitBBox(lower);
873
  upperBBox = operatorLimitBBox(upper);
870
    upperBBox = operatorLimitBBox(upper);
874
  maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
871
    maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
875
 
872
 
876
  if (bboxWidth(upperBBox) < maxWidth)
873
    if (bboxWidth(upperBBox) < maxWidth)
877
    return (maxWidth - bboxWidth(upperBBox))/2;
874
	return (maxWidth - bboxWidth(upperBBox))/2;
878
  else
875
    else
879
    return 0;
876
	return 0;
880
}
877
}
881
 
878
 
882
static double operatorHShiftAll(SEXP operator, SEXP lower, SEXP upper)
879
static double operatorHShiftAll(SEXP operator, SEXP lower, SEXP upper)
883
{
880
{
884
  BBOX opBBox = theOperatorBBox(operator);
881
    BBOX opBBox = theOperatorBBox(operator);
885
  BBOX lowerBBox, upperBBox;
882
    BBOX lowerBBox, upperBBox;
886
  double maxWidth = bboxWidth(opBBox);
883
    double maxWidth = bboxWidth(opBBox);
887
 
884
 
888
  lowerBBox = operatorLimitBBox(lower);
885
    lowerBBox = operatorLimitBBox(lower);
889
  upperBBox = operatorLimitBBox(upper);
886
    upperBBox = operatorLimitBBox(upper);
890
  maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
887
    maxWidth = max(maxWidth, max(bboxWidth(lowerBBox), bboxWidth(upperBBox)));
891
 
888
 
892
  if (bboxWidth(opBBox) < maxWidth)
889
    if (bboxWidth(opBBox) < maxWidth)
893
    return (maxWidth - bboxWidth(opBBox))/2;
890
	return (maxWidth - bboxWidth(opBBox))/2;
894
  else
891
    else
895
    return 0;
892
	return 0;
896
}
893
}
897
 
894
 
898
	/* code to generate bounding boxes and draw formulae */
895
/* Code to generate bounding boxes and draw formulae. */
899
 
896
 
900
/* Bounding box basics */
897
/* Bounding box basics. */
901
 
898
 
902
static BBOX makeBBox(double height, double depth, double width)
899
static BBOX makeBBox(double height, double depth, double width)
903
{
900
{
904
	BBOX bbox;
901
    BBOX bbox;
905
	bbox.height = height;
902
    bbox.height = height;
906
	bbox.depth = depth;
903
    bbox.depth = depth;
907
	bbox.width = width;
904
    bbox.width = width;
908
	return bbox;
905
    return bbox;
909
}
906
}
910
 
907
 
911
static BBOX nullBBox()
908
static BBOX nullBBox()
912
{
909
{
913
	return makeBBox(0.0, 0.0, 0.0);
910
    return makeBBox(0.0, 0.0, 0.0);
914
}
911
}
915
 
912
 
916
static BBOX makeBBoxFromChar(int chr)
913
static BBOX makeBBoxFromChar(int chr)
917
{
914
{
918
	double height, depth, width;
915
    double height, depth, width;
919
	GMetricInfo(chr, &height, &depth, &width, metricUnit, mathDevice);
916
    GMetricInfo(chr, &height, &depth, &width, metricUnit, mathDevice);
920
	return makeBBox(height, depth, width);
917
    return makeBBox(height, depth, width);
921
}
918
}
922
 
919
 
923
static BBOX shiftBBox(BBOX bbox, double shiftV)
920
static BBOX shiftBBox(BBOX bbox, double shiftV)
924
{
921
{
925
	return makeBBox(bboxHeight(bbox) + shiftV,
922
    return makeBBox(bboxHeight(bbox) + shiftV,
926
			bboxDepth(bbox) - shiftV,
923
		    bboxDepth(bbox) - shiftV,
927
			bboxWidth(bbox));
924
		    bboxWidth(bbox));
928
}
925
}
929
 
926
 
930
static BBOX combineBBoxes(BBOX bbox1, BBOX bbox2)
927
static BBOX combineBBoxes(BBOX bbox1, BBOX bbox2)
931
{
928
{
932
	return makeBBox(max(bboxHeight(bbox1), bboxHeight(bbox2)),
929
    return makeBBox(max(bboxHeight(bbox1), bboxHeight(bbox2)),
933
			max(bboxDepth(bbox1), bboxDepth(bbox2)),
930
		    max(bboxDepth(bbox1), bboxDepth(bbox2)),
934
			bboxWidth(bbox1) + bboxWidth(bbox2));
931
		    bboxWidth(bbox1) + bboxWidth(bbox2));
935
}
932
}
936
 
933
 
937
static BBOX combineAlignedBBoxes(BBOX bbox1, BBOX bbox2)
934
static BBOX combineAlignedBBoxes(BBOX bbox1, BBOX bbox2)
938
{
935
{
939
	return makeBBox(max(bboxHeight(bbox1), bboxHeight(bbox2)),
936
    return makeBBox(max(bboxHeight(bbox1), bboxHeight(bbox2)),
940
			max(bboxDepth(bbox1), bboxDepth(bbox2)),
937
		    max(bboxDepth(bbox1), bboxDepth(bbox2)),
941
			max(bboxWidth(bbox1), bboxWidth(bbox2)));
938
		    max(bboxWidth(bbox1), bboxWidth(bbox2)));
942
}
939
}
943
 
940
 
944
/* Drawing basics */
941
/* Drawing basics */
945
 
942
 
946
static double referenceX;
943
static double referenceX;
Line 949... Line 946...
949
static double currentY;
946
static double currentY;
950
static double currentAngle;
947
static double currentAngle;
951
static double cosAngle;
948
static double cosAngle;
952
static double sinAngle;
949
static double sinAngle;
953
 
950
 
954
		/*
-
 
955
		   // convert currentX and currentY from 0 angle
951
/* Convert currentX and currentY from 0 angle */
956
		   // to and currentAngle
952
/* to and currentAngle */
957
		 */
953
 
958
static double convertedX()
954
static double convertedX()
959
{
955
{
960
	double rotatedX = referenceX +
956
    double rotatedX = referenceX +
961
	(currentX - referenceX) * cosAngle -
957
	(currentX - referenceX) * cosAngle -
962
	(currentY - referenceY) * sinAngle;
958
	(currentY - referenceY) * sinAngle;
963
	return rotatedX;
959
    return rotatedX;
964
}
960
}
965
 
961
 
966
static double convertedY()
962
static double convertedY()
967
{
963
{
968
	double rotatedY = referenceY +
964
    double rotatedY = referenceY +
969
	(currentY - referenceY) * cosAngle +
965
	(currentY - referenceY) * cosAngle +
970
	(currentX - referenceX) * sinAngle;
966
	(currentX - referenceX) * sinAngle;
971
	return rotatedY;
967
    return rotatedY;
972
}
968
}
973
 
969
 
974
static void moveAcross(double xamount)
970
static void moveAcross(double xamount)
975
{
971
{
976
	currentX += xamount;
972
    currentX += xamount;
977
}
973
}
978
 
974
 
979
static void moveUp(double yamount)
975
static void moveUp(double yamount)
980
{
976
{
981
	currentY += yamount;
977
    currentY += yamount;
982
}
978
}
983
 
979
 
984
static void moveTo(double x, double y)
980
static void moveTo(double x, double y)
985
{
981
{
986
	currentX = x;
982
    currentX = x;
987
	currentY = y;
983
    currentY = y;
988
}
984
}
989
 
985
 
990
/* code for ascii atoms */
986
/* Code for ascii atoms. */
991
 
987
 
992
	/* NOTE that i assume that all symbols which have */
988
/* NOTE that I assume that all symbols which have */
993
	/* been converted to ascii are in the symbol font */
989
/* been converted to ascii are in the symbol font. */
994
 
990
 
995
static BBOX asciiBBox(int ascii)
991
static BBOX asciiBBox(int ascii)
996
{
992
{
997
	if ((ascii == hatAscii()) || (ascii == tildeAscii()))
993
    if ((ascii == hatAscii()) || (ascii == tildeAscii()))
998
		mathDevice->gp.font = 1;
994
	mathDevice->gp.font = 1;
999
	else
995
    else
1000
		mathDevice->gp.font = 5;
996
	mathDevice->gp.font = 5;
1001
	return makeBBoxFromChar(ascii);
997
    return makeBBoxFromChar(ascii);
1002
}
998
}
1003
 
999
 
1004
static void drawAscii(int ascii)
1000
static void drawAscii(int ascii)
1005
{
1001
{
1006
	char asciiStr[2];
1002
    char asciiStr[2];
1007
 
1003
 
1008
	if ((ascii == hatAscii()) || (ascii == tildeAscii()))
1004
    if ((ascii == hatAscii()) || (ascii == tildeAscii()))
1009
		mathDevice->gp.font = 1;
1005
	mathDevice->gp.font = 1;
1010
	else
1006
    else
1011
		mathDevice->gp.font = 5;
1007
	mathDevice->gp.font = 5;
1012
	asciiStr[0] = ascii;
1008
    asciiStr[0] = ascii;
1013
	asciiStr[1] = '\0';
1009
    asciiStr[1] = '\0';
1014
	GText(convertedX(), convertedY(), INCHES, asciiStr,
1010
    GText(convertedX(), convertedY(), INCHES, asciiStr,
1015
	      0.0, 0.0, currentAngle, mathDevice);
1011
	  0.0, 0.0, currentAngle, mathDevice);
1016
	moveAcross(GStrWidth(asciiStr, metricUnit, mathDevice));
1012
    moveAcross(GStrWidth(asciiStr, metricUnit, mathDevice));
1017
}
1013
}
1018
 
1014
 
1019
/* code for character atoms */
1015
/* Code for character atoms. */
1020
 
1016
 
1021
static BBOX charBBox(char *str, SEXP expr)
1017
static BBOX charBBox(char *str, SEXP expr)
1022
{
1018
{
1023
	BBOX resultBBox = nullBBox();
1019
    BBOX resultBBox = nullBBox();
1024
	int i;
1020
    int i;
1025
 
1021
 
1026
	mathDevice->gp.font = atomFontFace(expr);
1022
    mathDevice->gp.font = atomFontFace(expr);
1027
	for (i = 0; i < strlen(str); i++)
1023
    for (i = 0; i < strlen(str); i++)
1028
		resultBBox = combineBBoxes(resultBBox, makeBBoxFromChar(str[i]));
1024
	resultBBox = combineBBoxes(resultBBox, makeBBoxFromChar(str[i]));
1029
 
1025
 
1030
	return resultBBox;
1026
    return resultBBox;
1031
}
1027
}
1032
 
1028
 
1033
static void drawChar(char *str, SEXP expr)
1029
static void drawChar(char *str, SEXP expr)
1034
{
1030
{
1035
	mathDevice->gp.font = atomFontFace(expr);
1031
    mathDevice->gp.font = atomFontFace(expr);
1036
	GText(convertedX(), convertedY(), INCHES, str,
1032
    GText(convertedX(), convertedY(), INCHES, str,
1037
	      0.0, 0.0, currentAngle, mathDevice);
1033
	  0.0, 0.0, currentAngle, mathDevice);
1038
	moveAcross(GStrWidth(str, metricUnit, mathDevice));
1034
    moveAcross(GStrWidth(str, metricUnit, mathDevice));
1039
}
1035
}
1040
 
1036
 
1041
/* code for symbol atoms */
1037
/* code for symbol atoms */
1042
 
1038
 
1043
static BBOX symbolBBox(SEXP expr)
1039
static BBOX symbolBBox(SEXP expr)
1044
{
1040
{
1045
	if (greekSymbol(expr))
1041
    if (greekSymbol(expr))
1046
		return asciiBBox(greekAscii(expr));
1042
	return asciiBBox(greekAscii(expr));
1047
	else
1043
    else
1048
		return charBBox(CHAR(PRINTNAME(expr)), expr);
1044
	return charBBox(CHAR(PRINTNAME(expr)), expr);
1049
}
1045
}
1050
 
1046
 
1051
static void drawSymbol(SEXP expr)
1047
static void drawSymbol(SEXP expr)
1052
{
1048
{
1053
	if (greekSymbol(expr))
1049
    if (greekSymbol(expr))
1054
		drawAscii(greekAscii(expr));
1050
	drawAscii(greekAscii(expr));
1055
	else
1051
    else
1056
		drawChar(CHAR(PRINTNAME(expr)), expr);
1052
	drawChar(CHAR(PRINTNAME(expr)), expr);
1057
}
1053
}
1058
 
1054
 
1059
/* code for numeric atoms */
1055
/* code for numeric atoms */
1060
 
1056
 
1061
static BBOX numberBBox(SEXP expr)
1057
static BBOX numberBBox(SEXP expr)
1062
{
1058
{
1063
	return charBBox(CHAR(asChar(expr)), expr);
1059
    return charBBox(CHAR(asChar(expr)), expr);
1064
}
1060
}
1065
 
1061
 
1066
static void drawNumber(SEXP expr)
1062
static void drawNumber(SEXP expr)
1067
{
1063
{
1068
	drawChar(CHAR(asChar(expr)), expr);
1064
    drawChar(CHAR(asChar(expr)), expr);
1069
}
1065
}
1070
 
1066
 
1071
/* code for string atoms */
1067
/* code for string atoms */
1072
 
1068
 
1073
static BBOX stringBBox(SEXP expr)
1069
static BBOX stringBBox(SEXP expr)
1074
{
1070
{
1075
	return charBBox(CHAR(STRING(expr)[0]), expr);
1071
    return charBBox(CHAR(STRING(expr)[0]), expr);
1076
}
1072
}
1077
 
1073
 
1078
static void drawString(SEXP expr)
1074
static void drawString(SEXP expr)
1079
{
1075
{
1080
	drawChar(CHAR(STRING(expr)[0]), expr);
1076
    drawChar(CHAR(STRING(expr)[0]), expr);
1081
}
1077
}
1082
 
1078
 
1083
/* code for atoms */
1079
/* code for atoms */
1084
 
1080
 
1085
static BBOX atomBBox(SEXP expr)
1081
static BBOX atomBBox(SEXP expr)
1086
{
1082
{
1087
	if (symbolAtom(expr))
1083
    if (symbolAtom(expr))
1088
		return symbolBBox(expr);
1084
	return symbolBBox(expr);
1089
	else if (numberAtom(expr))
1085
    else if (numberAtom(expr))
1090
		return numberBBox(expr);
1086
	return numberBBox(expr);
1091
	else if (stringAtom(expr))
1087
    else if (stringAtom(expr))
1092
		return stringBBox(expr);
1088
	return stringBBox(expr);
1093
}
1089
}
1094
 
1090
 
1095
static void drawAtom(SEXP expr)
1091
static void drawAtom(SEXP expr)
1096
{
1092
{
1097
	if (symbolAtom(expr))
1093
    if (symbolAtom(expr))
1098
		drawSymbol(expr);
1094
	drawSymbol(expr);
1099
	else if (numberAtom(expr))
1095
    else if (numberAtom(expr))
1100
		drawNumber(expr);
1096
	drawNumber(expr);
1101
	else if (stringAtom(expr))
1097
    else if (stringAtom(expr))
1102
		drawString(expr);
1098
	drawString(expr);
1103
}
1099
}
1104
 
1100
 
1105
/* code for italic corrections */
1101
/* code for italic corrections */
1106
 
1102
 
1107
static double half_pi = 1.57079632679489661922;
1103
static double half_pi = 1.57079632679489661922;
1108
 
1104
 
1109
static double italicCorrection(SEXP expr)
1105
static double italicCorrection(SEXP expr)
1110
{
1106
{
1111
  BBOX exprBBox = elementBBox(expr);
1107
    BBOX exprBBox = elementBBox(expr);
1112
  return bboxHeight(exprBBox) * tan(half_pi / 6);
1108
    return bboxHeight(exprBBox) * tan(half_pi / 6);
1113
}
1109
}
1114
 
1110
 
1115
	/* correction within expression checks for current font italic */
1111
	/* correction within expression checks for current font italic */
1116
 
1112
 
1117
static BBOX correctionWithinBBox(SEXP expr)
1113
static BBOX correctionWithinBBox(SEXP expr)
1118
{
1114
{
1119
  if (isItalic() && !nonItalicExpression(expr))
1115
    if (isItalic() && !nonItalicExpression(expr))
1120
    return makeBBox(0, 0, italicCorrection(expr));
1116
	return makeBBox(0, 0, italicCorrection(expr));
1121
  else
1117
    else
1122
    return nullBBox();
1118
	return nullBBox();
1123
}
1119
}
1124
 
1120
 
1125
static void drawCorrectionWithin(SEXP expr)
1121
static void drawCorrectionWithin(SEXP expr)
1126
{
1122
{
1127
  if (isItalic() && !nonItalicExpression(expr))
1123
    if (isItalic() && !nonItalicExpression(expr))
1128
    moveAcross(italicCorrection(expr));
1124
	moveAcross(italicCorrection(expr));
1129
}
1125
}
1130
 
1126
 
1131
	/* correction between expressions checks current font and font */
1127
	/* correction between expressions checks current font and font */
1132
	/* of each expression */
1128
	/* of each expression */
1133
 
1129
 
1134
static BBOX correctionBetweenBBox(SEXP expr1, SEXP expr2)
1130
static BBOX correctionBetweenBBox(SEXP expr1, SEXP expr2)
1135
{
1131
{
1136
  if (((isItalic() && !nonItalicExpression(expr1)) ||
1132
    if (((isItalic() && !nonItalicExpression(expr1)) ||
1137
       italicExpression(expr1)) &&
1133
	 italicExpression(expr1)) &&
1138
      ((!isItalic() && !italicExpression(expr2)) ||
1134
	((!isItalic() && !italicExpression(expr2)) ||
1139
       nonItalicExpression(expr2)))
1135
	 nonItalicExpression(expr2)))
1140
    return makeBBox(0, 0, italicCorrection(expr1));
1136
	return makeBBox(0, 0, italicCorrection(expr1));
1141
  else
1137
    else
1142
    return nullBBox();
1138
	return nullBBox();
1143
}
1139
}
1144
 
1140
 
1145
static void drawCorrectionBetween(SEXP expr1, SEXP expr2)
1141
static void drawCorrectionBetween(SEXP expr1, SEXP expr2)
1146
{
1142
{
1147
  if (((isItalic() && !nonItalicExpression(expr1)) ||
1143
    if (((isItalic() && !nonItalicExpression(expr1)) ||
1148
       italicExpression(expr1)) &&
1144
	 italicExpression(expr1)) &&
1149
      ((!isItalic() && !italicExpression(expr2)) ||
1145
	((!isItalic() && !italicExpression(expr2)) ||
1150
       nonItalicExpression(expr2)))
1146
	 nonItalicExpression(expr2)))
1151
    moveAcross(italicCorrection(expr1));
1147
	moveAcross(italicCorrection(expr1));
1152
}
1148
}
1153
 
1149
 
1154
/* code for gaps */
1150
/* code for gaps */
1155
 
1151
 
1156
static int cexGap = 1;
1152
static int cexGap = 1;
Line 1160... Line 1156...
1160
  cexGap = mathDevice->gp.cex;
1156
  cexGap = mathDevice->gp.cex;
1161
}
1157
}
1162
 
1158
 
1163
static BBOX gapBBox(double gap)
1159
static BBOX gapBBox(double gap)
1164
{
1160
{
1165
  double cexSaved = mathDevice->gp.cex;
1161
    double cexSaved = mathDevice->gp.cex;
1166
  BBOX theBBox;
1162
    BBOX theBBox;
1167
 
1163
 
1168
  mathDevice->gp.cex = cexGap;
1164
    mathDevice->gp.cex = cexGap;
1169
  theBBox = makeBBox(0, 0, gap * fontHeight());
1165
    theBBox = makeBBox(0, 0, gap * fontHeight());
1170
  mathDevice->gp.cex = cexSaved;
1166
    mathDevice->gp.cex = cexSaved;
1171
 
1167
 
1172
  return theBBox;
1168
    return theBBox;
1173
}
1169
}
1174
 
1170
 
1175
static BBOX smallgapBBox(double gap)
1171
static BBOX smallgapBBox(double gap)
1176
{
1172
{
1177
  double cexSaved = mathDevice->gp.cex;
1173
    double cexSaved = mathDevice->gp.cex;
1178
  BBOX theBBox;
1174
    BBOX theBBox;
1179
 
1175
 
1180
  mathDevice->gp.cex = cexGap;
1176
    mathDevice->gp.cex = cexGap;
1181
  theBBox = makeBBox(0, 0, 0.5 * gap * fontHeight());
1177
    theBBox = makeBBox(0, 0, 0.5 * gap * fontHeight());
1182
  mathDevice->gp.cex = cexSaved;
1178
    mathDevice->gp.cex = cexSaved;
1183
 
1179
 
1184
  return theBBox;
1180
    return theBBox;
1185
}
1181
}
1186
 
1182
 
1187
static void drawGap(double gap)
1183
static void drawGap(double gap)
1188
{
1184
{
1189
  double cexSaved = mathDevice->gp.cex;
1185
    double cexSaved = mathDevice->gp.cex;
1190
 
1186
 
1191
  mathDevice->gp.cex = cexGap;
1187
    mathDevice->gp.cex = cexGap;
1192
  moveAcross(gap * fontHeight());
1188
    moveAcross(gap * fontHeight());
1193
  mathDevice->gp.cex = cexSaved;
1189
    mathDevice->gp.cex = cexSaved;
1194
}
1190
}
1195
 
1191
 
1196
static void drawSmallGap(double gap)
1192
static void drawSmallGap(double gap)
1197
{
1193
{
1198
  double cexSaved = mathDevice->gp.cex;
1194
    double cexSaved = mathDevice->gp.cex;
1199
 
1195
 
1200
  mathDevice->gp.cex = cexGap;
1196
    mathDevice->gp.cex = cexGap;
1201
  moveAcross(0.5 * gap * fontHeight());
1197
    moveAcross(0.5 * gap * fontHeight());
1202
  mathDevice->gp.cex = cexSaved;
1198
    mathDevice->gp.cex = cexSaved;
1203
}
1199
}
1204
 
1200
 
1205
/* code for binary operator (+, -, *, /) expressions */
1201
/* Code for binary operator (+, -, *, /) expressions */
1206
 
1202
 
1207
/* NOTE that gaps are specified as proportions of the current font height */
1203
/* NOTE that gaps are specified as proportions */
-
 
1204
/* of the current font height */
1208
 
1205
 
1209
static double binGapBefore(SEXP beforeOperand)
1206
static double binGapBefore(SEXP beforeOperand)
1210
{
1207
{
1211
  return 0.2;
1208
    return 0.2;
1212
}
1209
}
1213
 
1210
 
1214
static double binGapBetween(SEXP operand1, SEXP operand2)
1211
static double binGapBetween(SEXP operand1, SEXP operand2)
1215
{
1212
{
1216
    return 0;
1213
    return 0;
Line 1221... Line 1218...
1221
    return 0.2;
1218
    return 0.2;
1222
}
1219
}
1223
 
1220
 
1224
static BBOX binBBox(SEXP expr)
1221
static BBOX binBBox(SEXP expr)
1225
{
1222
{
1226
	SEXP operator, operand1, operand2;
1223
    SEXP operator, operand1, operand2;
1227
	BBOX middleBBox;
1224
    BBOX middleBBox;
1228
 
1225
 
1229
	operator = CAR(expr);
1226
    operator = CAR(expr);
1230
	operand1 = CADR(expr);
1227
    operand1 = CADR(expr);
1231
        setGapCEX();
1228
    setGapCEX();
1232
	if(length(expr) == 3) {
1229
    if(length(expr) == 3) {
1233
		operand2 = CADDR(expr);
1230
	operand2 = CADDR(expr);
1234
		if (multiplicationOperator(operator))
1231
	if (multiplicationOperator(operator))
1235
			middleBBox =
1232
	    middleBBox =
1236
			  correctionBetweenBBox(operand1, operand2);
1233
		correctionBetweenBBox(operand1, operand2);
1237
		else
1234
	else
1238
			middleBBox =
1235
	    middleBBox =
1239
                          combineBBoxes(
1236
		combineBBoxes(
1240
                            gapBBox(binGapBefore(operand1)),
1237
			      gapBBox(binGapBefore(operand1)),
1241
			    combineBBoxes(atomBBox(operator),
1238
			      combineBBoxes(atomBBox(operator),
1242
					  gapBBox(binGapAfter(operand2))));
1239
					    gapBBox(binGapAfter(operand2))));
1243
 
1240
 
1244
		return combineBBoxes(elementBBox(operand1),
1241
	return combineBBoxes(elementBBox(operand1),
1245
				     combineBBoxes(middleBBox,
1242
			     combineBBoxes(middleBBox,
1246
						   elementBBox(operand2)));
1243
					   elementBBox(operand2)));
1247
	}
1244
    }
1248
	else if(length(expr) == 2) {
1245
    else if(length(expr) == 2) {
1249
		middleBBox = combineBBoxes(atomBBox(operator),
1246
	middleBBox = combineBBoxes(atomBBox(operator),
1250
				   smallgapBBox(binGapAfter(operand1)));
1247
				   smallgapBBox(binGapAfter(operand1)));
1251
		return combineBBoxes(middleBBox, elementBBox(operand1));
1248
	return combineBBoxes(middleBBox, elementBBox(operand1));
1252
	}
1249
    }
1253
	else error("invalid formula\n");
1250
    else error("invalid formula\n");
1254
}
1251
}
1255
 
1252
 
1256
static void drawBin(SEXP expr)
1253
static void drawBin(SEXP expr)
1257
{
1254
{
1258
	SEXP operator, operand1, operand2;
1255
    SEXP operator, operand1, operand2;
1259
 
1256
 
1260
	operator = CAR(expr);
1257
    operator = CAR(expr);
1261
	operand1 = CADR(expr);
1258
    operand1 = CADR(expr);
1262
	setGapCEX();
1259
    setGapCEX();
1263
	if(length(expr) == 3) {
1260
    if(length(expr) == 3) {
1264
		operand2 = CADDR(expr);
1261
	operand2 = CADDR(expr);
1265
		drawElement(operand1);
1262
	drawElement(operand1);
1266
		if (multiplicationOperator(operator))
1263
	if (multiplicationOperator(operator))
1267
		  drawGap(binGapBetween(operand1, operand2));
1264
	    drawGap(binGapBetween(operand1, operand2));
1268
		else {
-
 
1269
			drawGap(binGapBefore(operand1));
-
 
1270
			drawAtom(operator);
-
 
1271
			drawGap(binGapAfter(operand2));
-
 
1272
		}
-
 
1273
		drawElement(operand2);
-
 
1274
	}
-
 
1275
	else {
1265
	else {
-
 
1266
	    drawGap(binGapBefore(operand1));
1276
		drawAtom(operator);
1267
	    drawAtom(operator);
1277
		drawSmallGap(binGapAfter(operand1));
1268
	    drawGap(binGapAfter(operand2));
1278
		drawElement(operand1);
-
 
1279
	}
1269
	}
-
 
1270
	drawElement(operand2);
-
 
1271
    }
-
 
1272
    else {
-
 
1273
	drawAtom(operator);
-
 
1274
	drawSmallGap(binGapAfter(operand1));
-
 
1275
	drawElement(operand1);
-
 
1276
    }
1280
}
1277
}
1281
 
1278
 
1282
/* code for superscript and subscript expressions */
1279
/* Code for superscript and subscript expressions */
1283
 
1280
 
1284
static BBOX supsubBBox(SEXP body, SEXP superscript, SEXP subscript);
1281
static BBOX supsubBBox(SEXP body, SEXP superscript, SEXP subscript);
1285
 
1282
 
1286
static BBOX superscriptBBox(SEXP superscript)
1283
static BBOX superscriptBBox(SEXP superscript)
1287
{
1284
{
1288
	BBOX result;
1285
    BBOX result;
1289
	float cexSaved = mathDevice->gp.cex;
1286
    float cexSaved = mathDevice->gp.cex;
1290
 
1287
 
1291
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1288
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1292
	result = elementBBox(superscript);
1289
    result = elementBBox(superscript);
1293
	mathDevice->gp.cex = cexSaved;
1290
    mathDevice->gp.cex = cexSaved;
1294
 
1291
 
1295
	return result;
1292
    return result;
1296
}
1293
}
1297
 
1294
 
1298
static BBOX supBBox(SEXP expr)
1295
static BBOX supBBox(SEXP expr)
1299
{
1296
{
1300
	SEXP body = CADR(expr);
1297
    SEXP body = CADR(expr);
1301
	SEXP superscript = CADDR(expr);
1298
    SEXP superscript = CADDR(expr);
1302
	int supsub = 0;
1299
    int supsub = 0;
1303
 
1300
 
1304
	if (formulaExpression(body))
1301
    if (formulaExpression(body))
1305
		if (subAtom(CAR(body)))
1302
	if (subAtom(CAR(body)))
1306
			supsub = 1;
1303
	    supsub = 1;
1307
 
1304
 
1308
	if (supsub)
1305
    if (supsub)
1309
		return supsubBBox(CADR(body), superscript, (CADDR(body)));
1306
	return supsubBBox(CADR(body), superscript, (CADDR(body)));
1310
	else
1307
    else
1311
		return combineBBoxes(
1308
	return combineBBoxes(elementBBox(body),
1312
			 elementBBox(body),
-
 
1313
			 combineBBoxes(
-
 
1314
			   correctionWithinBBox(body),
1309
			     combineBBoxes(correctionWithinBBox(body),
1315
			   shiftBBox(superscriptBBox(superscript),
1310
					   shiftBBox(superscriptBBox(superscript),
1316
				     superscriptShift(body, superscript))));
1311
						     superscriptShift(body, superscript))));
1317
}
1312
}
1318
 
1313
 
1319
static BBOX subscriptBBox(SEXP subscript)
1314
static BBOX subscriptBBox(SEXP subscript)
1320
{
1315
{
1321
	BBOX result;
1316
    BBOX result;
1322
	float cexSaved = mathDevice->gp.cex;
1317
    float cexSaved = mathDevice->gp.cex;
1323
 
1318
 
1324
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1319
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1325
	result = elementBBox(subscript);
1320
    result = elementBBox(subscript);
1326
	mathDevice->gp.cex = cexSaved;
1321
    mathDevice->gp.cex = cexSaved;
1327
 
1322
 
1328
	return result;
1323
    return result;
1329
}
1324
}
1330
 
1325
 
1331
static BBOX subBBox(SEXP expr)
1326
static BBOX subBBox(SEXP expr)
1332
{
1327
{
1333
	SEXP body = CADR(expr);
1328
    SEXP body = CADR(expr);
1334
	SEXP subscript = CADDR(expr);
1329
    SEXP subscript = CADDR(expr);
1335
 
1330
 
1336
	return combineBBoxes(elementBBox(body),
1331
    return combineBBoxes(elementBBox(body),
1337
		             shiftBBox(subscriptBBox(subscript),
1332
			 shiftBBox(subscriptBBox(subscript),
1338
			               subscriptShift(body, subscript, 1)));
1333
				   subscriptShift(body, subscript, 1)));
1339
}
1334
}
1340
 
1335
 
1341
static BBOX supsubBBox(SEXP body, SEXP superscript, SEXP subscript)
1336
static BBOX supsubBBox(SEXP body, SEXP superscript, SEXP subscript)
1342
{
1337
{
1343
	double supShift, subShift;
1338
    double supShift, subShift;
1344
	supsubShift(body, superscript, subscript, &supShift, &subShift);
1339
    supsubShift(body, superscript, subscript, &supShift, &subShift);
1345
 
1340
 
1346
	return combineBBoxes(
1341
    return combineBBoxes(elementBBox(body),
1347
		 elementBBox(body),
-
 
1348
		 combineAlignedBBoxes(
1342
	       combineAlignedBBoxes(
1349
		   combineBBoxes(
-
 
1350
		     correctionWithinBBox(body),
1343
	           combineBBoxes(correctionWithinBBox(body),
1351
		     shiftBBox(superscriptBBox(superscript), supShift)),
1344
			    shiftBBox(superscriptBBox(superscript), supShift)),
1352
		   shiftBBox(subscriptBBox(subscript), subShift)));
1345
		   shiftBBox(subscriptBBox(subscript), subShift)));
1353
}
1346
}
1354
 
1347
 
1355
static void drawScriptElement(SEXP expr)
1348
static void drawScriptElement(SEXP expr)
1356
{
1349
{
1357
	float cexSaved = mathDevice->gp.cex;
1350
    float cexSaved = mathDevice->gp.cex;
1358
 
1351
 
1359
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1352
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1360
	drawElement(expr);
1353
    drawElement(expr);
1361
	mathDevice->gp.cex = cexSaved;
1354
    mathDevice->gp.cex = cexSaved;
1362
}
1355
}
1363
 
1356
 
1364
static void drawSupSub(SEXP body, SEXP superscript, SEXP subscript);
1357
static void drawSupSub(SEXP body, SEXP superscript, SEXP subscript);
1365
 
1358
 
1366
static void drawSuper(SEXP expr)
1359
static void drawSuper(SEXP expr)
1367
{
1360
{
1368
	SEXP body = CADR(expr);
1361
    SEXP body = CADR(expr);
1369
	SEXP superscript = CADDR(expr);
1362
    SEXP superscript = CADDR(expr);
1370
	double supShift = superscriptShift(body, superscript);
1363
    double supShift = superscriptShift(body, superscript);
1371
	int supsub = 0;
1364
    int supsub = 0;
1372
 
1365
 
1373
	if (formulaExpression(body))
1366
    if (formulaExpression(body))
1374
		if (subAtom(CAR(body)))
1367
	if (subAtom(CAR(body)))
1375
			supsub = 1;
1368
	    supsub = 1;
1376
 
1369
 
1377
	if (supsub)
1370
    if (supsub)
1378
		drawSupSub(CADR(body), superscript, CADDR(body));
1371
	drawSupSub(CADR(body), superscript, CADDR(body));
1379
	else {
1372
    else {
1380
		drawElement(body);
1373
	drawElement(body);
1381
		drawCorrectionWithin(body);
1374
	drawCorrectionWithin(body);
1382
		moveUp(supShift);
1375
	moveUp(supShift);
1383
		drawScriptElement(superscript);
1376
	drawScriptElement(superscript);
1384
		moveUp(-supShift);
1377
	moveUp(-supShift);
1385
	}
1378
    }
1386
}
1379
}
1387
 
1380
 
1388
static void drawSub(SEXP expr)
1381
static void drawSub(SEXP expr)
1389
{
1382
{
1390
	SEXP body = CADR(expr);
1383
    SEXP body = CADR(expr);
1391
	SEXP subscript = CADDR(expr);
1384
    SEXP subscript = CADDR(expr);
1392
	double subShift = subscriptShift(body, subscript, 1);
1385
    double subShift = subscriptShift(body, subscript, 1);
1393
 
1386
 
1394
	drawElement(body);
1387
    drawElement(body);
1395
	moveUp(-subShift);
1388
    moveUp(-subShift);
1396
	drawScriptElement(subscript);
1389
    drawScriptElement(subscript);
1397
	moveUp(subShift);
1390
    moveUp(subShift);
1398
}
1391
}
1399
 
1392
 
1400
static void drawSupSub(SEXP body, SEXP superscript, SEXP subscript)
1393
static void drawSupSub(SEXP body, SEXP superscript, SEXP subscript)
1401
{
1394
{
1402
	double supShift, subShift;
1395
    double supShift, subShift;
1403
	double savedX, savedY;
1396
    double savedX, savedY;
1404
	BBOX supBBox = elementBBox(superscript);
1397
    BBOX supBBox = elementBBox(superscript);
1405
	BBOX subBBox = elementBBox(subscript);
1398
    BBOX subBBox = elementBBox(subscript);
1406
 
1399
 
1407
	supsubShift(body, superscript, subscript, &supShift, &subShift);
1400
    supsubShift(body, superscript, subscript, &supShift, &subShift);
1408
	drawElement(body);
1401
    drawElement(body);
1409
	savedX = currentX;
1402
    savedX = currentX;
1410
	savedY = currentY;
1403
    savedY = currentY;
1411
	drawCorrectionWithin(body);
1404
    drawCorrectionWithin(body);
1412
	moveUp(supShift);
1405
    moveUp(supShift);
1413
	drawScriptElement(superscript);
1406
    drawScriptElement(superscript);
1414
	moveTo(savedX, savedY);
1407
    moveTo(savedX, savedY);
1415
	moveUp(-subShift);
1408
    moveUp(-subShift);
1416
	drawScriptElement(subscript);
1409
    drawScriptElement(subscript);
1417
	moveTo(savedX, savedY);
1410
    moveTo(savedX, savedY);
1418
	moveAcross(max(bboxWidth(supBBox), bboxWidth(subBBox)));
1411
    moveAcross(max(bboxWidth(supBBox), bboxWidth(subBBox)));
1419
}
1412
}
1420
 
1413
 
1421
/* code for accented expressions (hat, bar, ...) */
1414
/* code for accented expressions (hat, bar, ...) */
1422
 
1415
 
1423
static BBOX hatBBox(SEXP body)
1416
static BBOX hatBBox(SEXP body)
1424
{
1417
{
1425
	BBOX bodyBBox = elementBBox(body);
1418
    BBOX bodyBBox = elementBBox(body);
1426
	return combineAlignedBBoxes(bodyBBox,
1419
    return combineAlignedBBoxes(bodyBBox,
1427
				    makeBBox(bboxHeight(bodyBBox) +
1420
				makeBBox(bboxHeight(bodyBBox) +
1428
					     customAccentGap() +
1421
					 customAccentGap() +
1429
					     customHatHeight(), 0, 0));
1422
					 customHatHeight(), 0, 0));
1430
}
1423
}
1431
 
1424
 
1432
static BBOX barBBox(SEXP body)
1425
static BBOX barBBox(SEXP body)
1433
{
1426
{
1434
	BBOX bodyBBox = elementBBox(body);
1427
    BBOX bodyBBox = elementBBox(body);
1435
	return combineAlignedBBoxes(bodyBBox,
1428
    return combineAlignedBBoxes(bodyBBox,
1436
				    makeBBox(bboxHeight(bodyBBox) +
1429
				makeBBox(bboxHeight(bodyBBox) +
1437
					     customAccentGap(), 0, 0));
1430
					 customAccentGap(), 0, 0));
1438
}
1431
}
1439
 
1432
 
1440
static BBOX accentBBox(SEXP expr)
1433
static BBOX accentBBox(SEXP expr)
1441
{
1434
{
1442
	SEXP accent = CAR(expr);
1435
    SEXP accent = CAR(expr);
1443
	SEXP body = CADR(expr);
1436
    SEXP body = CADR(expr);
1444
 
1437
 
1445
	if (hatAtom(accent))
1438
    if (hatAtom(accent))
1446
		return hatBBox(body);
1439
	return hatBBox(body);
1447
	else if (barAtom(accent))
1440
    else if (barAtom(accent))
1448
		return barBBox(body);
1441
	return barBBox(body);
1449
	else
1442
    else
1450
		return combineAlignedBBoxes(
1443
	return combineAlignedBBoxes(elementBBox(body),
1451
						   elementBBox(body),
-
 
1452
		combineBBoxes(makeBBox(accentHShift(body, accent), 0, 0),
1444
		    combineBBoxes(makeBBox(accentHShift(body, accent), 0, 0),
1453
			      shiftBBox(asciiBBox(accentAscii(accent)),
1445
				  shiftBBox(asciiBBox(accentAscii(accent)),
1454
					accentVShift(body))));
1446
					    accentVShift(body))));
1455
}
1447
}
1456
 
1448
 
1457
static void drawHat(SEXP body)
1449
static void drawHat(SEXP body)
1458
{
1450
{
1459
	BBOX bodyBBox = elementBBox(body);
1451
    BBOX bodyBBox = elementBBox(body);
1460
	double width = bboxWidth(bodyBBox);
1452
    double width = bboxWidth(bodyBBox);
1461
	double savedX = currentX;
1453
    double savedX = currentX;
1462
	double savedY = currentY;
1454
    double savedY = currentY;
1463
	double x[3], y[3];
1455
    double x[3], y[3];
1464
 
1456
 
1465
	moveUp(bboxHeight(bodyBBox) + customAccentGap());
1457
    moveUp(bboxHeight(bodyBBox) + customAccentGap());
1466
	x[0] = convertedX(); y[0] = convertedY();
1458
    x[0] = convertedX(); y[0] = convertedY();
1467
	moveUp(customHatHeight());
1459
    moveUp(customHatHeight());
1468
	moveAcross(width / 2);
1460
    moveAcross(width / 2);
1469
	x[1] = convertedX(); y[1] = convertedY();
1461
    x[1] = convertedX(); y[1] = convertedY();
1470
	moveUp(-customHatHeight());
1462
    moveUp(-customHatHeight());
1471
	moveAcross(width / 2);
1463
    moveAcross(width / 2);
1472
	x[2] = convertedX(); y[2] = convertedY();
1464
    x[2] = convertedX(); y[2] = convertedY();
1473
	GPolyline(3, x, y, INCHES, mathDevice);
1465
    GPolyline(3, x, y, INCHES, mathDevice);
1474
	moveTo(savedX, savedY);
1466
    moveTo(savedX, savedY);
1475
	drawElement(body);
1467
    drawElement(body);
1476
}
1468
}
1477
 
1469
 
1478
static void drawBar(SEXP body)
1470
static void drawBar(SEXP body)
1479
{
1471
{
1480
	BBOX bodyBBox = elementBBox(body);
1472
    BBOX bodyBBox = elementBBox(body);
1481
	double savedX = currentX;
1473
    double savedX = currentX;
1482
	double savedY = currentY;
1474
    double savedY = currentY;
1483
	double x[2], y[2];
1475
    double x[2], y[2];
1484
 
1476
 
1485
	moveUp(bboxHeight(bodyBBox) + customAccentGap());
1477
    moveUp(bboxHeight(bodyBBox) + customAccentGap());
1486
	x[0] = convertedX(); y[0] = convertedY();
1478
    x[0] = convertedX(); y[0] = convertedY();
1487
	moveAcross(bboxWidth(bodyBBox));
1479
    moveAcross(bboxWidth(bodyBBox));
1488
	x[1] = convertedX(); y[1] = convertedY();
1480
    x[1] = convertedX(); y[1] = convertedY();
1489
	GPolyline(2, x, y, INCHES, mathDevice);
1481
    GPolyline(2, x, y, INCHES, mathDevice);
1490
	moveTo(savedX, savedY);
1482
    moveTo(savedX, savedY);
1491
	drawElement(body);
1483
    drawElement(body);
1492
}
1484
}
1493
 
1485
 
1494
static void drawAccent(SEXP expr)
1486
static void drawAccent(SEXP expr)
1495
{
1487
{
1496
	SEXP accent = CAR(expr);
1488
    SEXP accent = CAR(expr);
1497
	SEXP body = CADR(expr);
1489
    SEXP body = CADR(expr);
1498
	double savedX = currentX;
1490
    double savedX = currentX;
1499
	double savedY = currentY;
1491
    double savedY = currentY;
1500
 
1492
 
1501
	if (hatAtom(accent))
1493
    if (hatAtom(accent))
1502
		drawHat(body);
1494
	drawHat(body);
1503
	else if (barAtom(accent))
1495
    else if (barAtom(accent))
1504
		drawBar(body);
1496
	drawBar(body);
1505
	else {
1497
    else {
1506
		moveAcross(accentHShift(body, accent));
1498
	moveAcross(accentHShift(body, accent));
1507
		moveUp(accentVShift(body));
1499
	moveUp(accentVShift(body));
1508
		drawAscii(accentAscii(accent));
1500
	drawAscii(accentAscii(accent));
1509
		moveTo(savedX, savedY);
1501
	moveTo(savedX, savedY);
1510
		drawElement(body);
1502
	drawElement(body);
1511
	}
1503
    }
1512
}
1504
}
1513
 
1505
 
1514
/* code for fraction expressions (over) */
1506
/* Code for fraction expressions (over) */
1515
 
1507
 
1516
static BBOX fractionBBox(SEXP expr)
1508
static BBOX fractionBBox(SEXP expr)
1517
{
1509
{
1518
	SEXP numerator = CADR(expr);
1510
    SEXP numerator = CADR(expr);
1519
	SEXP denominator = CADDR(expr);
1511
    SEXP denominator = CADDR(expr);
1520
	BBOX numBBox, denomBBox;
1512
    BBOX numBBox, denomBBox;
1521
	double numHShift, denomHShift;
1513
    double numHShift, denomHShift;
1522
	float cexSaved = mathDevice->gp.cex;
1514
    float cexSaved = mathDevice->gp.cex;
1523
 
1515
 
1524
#ifdef OLD
1516
#ifdef OLD
1525
	mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1517
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1526
#else
1518
#else
1527
	mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
1519
    mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
1528
#endif
1520
#endif
1529
	numBBox = elementBBox(numerator);
1521
    numBBox = elementBBox(numerator);
1530
	denomBBox = elementBBox(denominator);
1522
    denomBBox = elementBBox(denominator);
1531
#ifdef OLD
1523
#ifdef OLD
1532
	mathDevice->gp.cex = cexSaved;
1524
    mathDevice->gp.cex = cexSaved;
1533
#else
1525
#else
1534
	mathDevice->gp.cex = cexSaved;
1526
    mathDevice->gp.cex = cexSaved;
1535
#endif
1527
#endif
1536
	numdenomHShift(numerator, denominator, &numHShift, &denomHShift);
1528
    numdenomHShift(numerator, denominator, &numHShift, &denomHShift);
1537
 
1529
 
1538
	return combineAlignedBBoxes(
1530
    return combineAlignedBBoxes(
1539
	     shiftBBox(combineBBoxes(makeBBox(numHShift, 0, 0), numBBox),
1531
	      shiftBBox(combineBBoxes(makeBBox(numHShift, 0, 0), numBBox),
1540
		       numeratorVShift(numerator)),
1532
			numeratorVShift(numerator)),
1541
	 shiftBBox(combineBBoxes(makeBBox(denomHShift, 0, 0), denomBBox),
1533
	      shiftBBox(combineBBoxes(makeBBox(denomHShift, 0, 0), denomBBox),
1542
		   -denominatorVShift(denominator)));
1534
			-denominatorVShift(denominator)));
1543
}
1535
}
1544
 
1536
 
1545
static void drawRatioElement(SEXP expr)
1537
static void drawRatioElement(SEXP expr)
1546
{
1538
{
1547
	float cexSaved = mathDevice->gp.cex;
1539
    float cexSaved = mathDevice->gp.cex;
1548
	mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
1540
    mathDevice->gp.cex = mathDevice->gp.cex * ratioScale;
1549
	drawElement(expr);
1541
    drawElement(expr);
1550
	mathDevice->gp.cex = cexSaved;
1542
    mathDevice->gp.cex = cexSaved;
1551
}
1543
}
1552
 
1544
 
1553
static void drawFraction(SEXP expr)
1545
static void drawFraction(SEXP expr)
1554
{
1546
{
1555
	SEXP numerator = CADR(expr);
1547
    SEXP numerator = CADR(expr);
1556
	SEXP denominator = CADDR(expr);
1548
    SEXP denominator = CADDR(expr);
1557
	double savedX = currentX;
1549
    double savedX = currentX;
1558
	double savedY = currentY;
1550
    double savedY = currentY;
1559
	double fWidth = fractionWidth(numerator, denominator);
1551
    double fWidth = fractionWidth(numerator, denominator);
1560
	double numHShift, denomHShift;
1552
    double numHShift, denomHShift;
1561
	double x[2], y[2];
1553
    double x[2], y[2];
1562
 
1554
 
1563
	numdenomHShift(numerator, denominator, &numHShift, &denomHShift);
1555
    numdenomHShift(numerator, denominator, &numHShift, &denomHShift);
1564
	moveAcross(numHShift);
1556
    moveAcross(numHShift);
1565
	moveUp(numeratorVShift(numerator));
1557
    moveUp(numeratorVShift(numerator));
1566
#ifdef OLD
1558
#ifdef OLD
1567
	drawScriptElement(numerator);
1559
    drawScriptElement(numerator);
1568
#else
1560
#else
1569
	drawRatioElement(numerator);
1561
    drawRatioElement(numerator);
1570
#endif
1562
#endif
1571
	moveTo(savedX, savedY);
1563
    moveTo(savedX, savedY);
1572
	moveUp(axisHeight());
1564
    moveUp(axisHeight());
1573
	x[0] = convertedX(); y[0] = convertedY();
1565
    x[0] = convertedX(); y[0] = convertedY();
1574
	moveAcross(fWidth);
1566
    moveAcross(fWidth);
1575
	x[1] = convertedX(); y[1] = convertedY();
1567
    x[1] = convertedX(); y[1] = convertedY();
1576
	GPolyline(2, x, y, INCHES, mathDevice);
1568
    GPolyline(2, x, y, INCHES, mathDevice);
1577
	moveTo(savedX, savedY);
1569
    moveTo(savedX, savedY);
1578
	moveAcross(denomHShift);
1570
    moveAcross(denomHShift);
1579
	moveUp(-denominatorVShift(denominator));
1571
    moveUp(-denominatorVShift(denominator));
1580
#ifdef OLD
1572
#ifdef OLD
1581
	drawScriptElement(denominator);
1573
    drawScriptElement(denominator);
1582
#else
1574
#else
1583
	drawRatioElement(denominator);
1575
    drawRatioElement(denominator);
1584
#endif
1576
#endif
1585
	moveTo(savedX + fWidth, savedY);
1577
    moveTo(savedX + fWidth, savedY);
1586
}
1578
}
1587
 
1579
 
1588
/* code for group expressions (expressions within parentheses) */
1580
/* code for group expressions (expressions within parentheses) */
1589
 
1581
 
1590
static BBOX groupBBox(SEXP expr)
1582
static BBOX groupBBox(SEXP expr)
1591
{
1583
{
1592
	return combineBBoxes(
1584
    return combineBBoxes(
1593
		 asciiBBox(groupOpenAscii()),
1585
	      asciiBBox(groupOpenAscii()),
1594
		 combineBBoxes(
-
 
1595
		   elementBBox(CADR(expr)),
1586
	      combineBBoxes(elementBBox(CADR(expr)),
1596
		   combineBBoxes(correctionWithinBBox(CADR(expr)),
1587
			    combineBBoxes(correctionWithinBBox(CADR(expr)),
1597
				 asciiBBox(groupCloseAscii()))));
1588
					  asciiBBox(groupCloseAscii()))));
1598
}
1589
}
1599
 
1590
 
1600
static void drawGroup(SEXP expr)
1591
static void drawGroup(SEXP expr)
1601
{
1592
{
1602
	drawAscii(groupOpenAscii());
1593
    drawAscii(groupOpenAscii());
1603
	drawElement(CADR(expr));
1594
    drawElement(CADR(expr));
1604
	drawCorrectionWithin(CADR(expr));
1595
    drawCorrectionWithin(CADR(expr));
1605
	drawAscii(groupCloseAscii());
1596
    drawAscii(groupCloseAscii());
1606
}
1597
}
1607
 
1598
 
1608
/* code for operator expressions (sum, product, integral) */
1599
/* code for operator expressions (sum, product, integral) */
1609
 
1600
 
1610
/* NOTE that gaps are specified as proportions of the current font height */
1601
/* NOTE that gaps are specified as proportions of the current font height */
Line 1618... Line 1609...
1618
 
1609
 
1619
static double integralBottomShift() { return -0.5 * fontHeight(); }
1610
static double integralBottomShift() { return -0.5 * fontHeight(); }
1620
 
1611
 
1621
static BBOX theOperatorBBox(SEXP operator)
1612
static BBOX theOperatorBBox(SEXP operator)
1622
{
1613
{
1623
  if (integralOperator(operator))
1614
    if (integralOperator(operator))
1624
    return combineAlignedBBoxes(
1615
	return combineAlignedBBoxes(
1625
	     shiftBBox(asciiBBox(integralAscii(1)), integralTopShift()),
1616
		  shiftBBox(asciiBBox(integralAscii(1)), integralTopShift()),
1626
	     combineAlignedBBoxes(asciiBBox(integralAscii(2)),
1617
		  combineAlignedBBoxes(asciiBBox(integralAscii(2)),
1627
				  shiftBBox(asciiBBox(integralAscii(3)),
1618
				       shiftBBox(asciiBBox(integralAscii(3)),
1628
					    integralBottomShift())));
1619
						 integralBottomShift())));
1629
  else
1620
    else
1630
    return asciiBBox(operatorAscii(operator));
1621
	return asciiBBox(operatorAscii(operator));
1631
}
1622
}
1632
 
1623
 
1633
static int useRelGap = 1;
1624
static int useRelGap = 1;
1634
 
1625
 
1635
static BBOX operatorLimitBBox(SEXP limit)
1626
static BBOX operatorLimitBBox(SEXP limit)
1636
{
1627
{
1637
  float cexSaved = mathDevice->gp.cex;
1628
    float cexSaved = mathDevice->gp.cex;
1638
  BBOX limitBBox;
1629
    BBOX limitBBox;
1639
 
1630
 
1640
  mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1631
    mathDevice->gp.cex = mathDevice->gp.cex * scriptScale;
1641
  useRelGap = 0;
1632
    useRelGap = 0;
1642
  limitBBox = elementBBox(limit);
1633
    limitBBox = elementBBox(limit);
1643
  useRelGap = 1;
1634
    useRelGap = 1;
1644
  mathDevice->gp.cex = cexSaved;
1635
    mathDevice->gp.cex = cexSaved;
1645
 
1636
 
1646
  return limitBBox;
1637
    return limitBBox;
1647
}
1638
}
1648
 
1639
 
1649
static BBOX operatorBBox(SEXP expr)
1640
static BBOX operatorBBox(SEXP expr)
1650
{
1641
{
1651
  SEXP operator = CAR(expr);
1642
    SEXP operator = CAR(expr);
1652
  SEXP body, lower, upper;
1643
    SEXP body, lower, upper;
1653
  BBOX opBBox = theOperatorBBox(operator);
1644
    BBOX opBBox = theOperatorBBox(operator);
1654
  BBOX bodyBBox, lowerBBox, upperBBox;
1645
    BBOX bodyBBox, lowerBBox, upperBBox;
1655
  setGapCEX();
1646
    setGapCEX();
1656
 
1647
 
1657
  if (length(expr) > 1) {
1648
    if (length(expr) > 1) {
1658
    body = CADR(expr);
1649
	body = CADR(expr);
1659
    bodyBBox = combineBBoxes(opBBox,
1650
	bodyBBox = combineBBoxes(
-
 
1651
		      opBBox,
1660
                             combineBBoxes(gapBBox(operatorGap(body)),
1652
		      combineBBoxes(gapBBox(operatorGap(body)),
1661
					   elementBBox(body)));
1653
				    elementBBox(body)));
1662
 
1654
 
1663
    if (length(expr) > 2) {
1655
	if (length(expr) > 2) {
1664
      lower = CADDR(expr);
1656
	    lower = CADDR(expr);
1665
      lowerBBox = operatorLimitBBox(lower);
1657
	    lowerBBox = operatorLimitBBox(lower);
-
 
1658
 
-
 
1659
	    if (length(expr) > 3) {
-
 
1660
		upper = CADDDR(expr);
-
 
1661
		upperBBox = operatorLimitBBox(upper);
1666
 
1662
 
1667
      if (length(expr) > 3) {
-
 
1668
	upper = CADDDR(expr);
-
 
1669
	upperBBox = operatorLimitBBox(upper);
-
 
1670
 
-
 
1671
	return combineAlignedBBoxes(
1663
		return combineAlignedBBoxes(
1672
		 combineBBoxes(
1664
			 combineBBoxes(
-
 
1665
			   makeBBox(
1673
                   makeBBox(operatorHShiftAll(operator, lower, upper), 0, 0),
1666
			     operatorHShiftAll(operator,lower, upper),
-
 
1667
			     0, 0),
1674
		   bodyBBox),
1668
			   bodyBBox),
1675
		 combineAlignedBBoxes(
1669
			 combineAlignedBBoxes(
1676
                   shiftBBox(
1670
			   shiftBBox(
1677
                     combineBBoxes(
1671
                             combineBBoxes(
-
 
1672
			       makeBBox(
1678
                       makeBBox(operatorUpperHShiftAll(operator, lower, upper),
1673
                                 operatorUpperHShiftAll(
-
 
1674
				   operator,lower, upper),
1679
				0, 0),
1675
				 0, 0),
1680
		       upperBBox),
1676
			       upperBBox),
1681
		     operatorUpperShift(operator, upper)),
1677
			     operatorUpperShift(operator, upper)),
1682
		   shiftBBox(
1678
			   shiftBBox(
-
 
1679
                             combineBBoxes(
1683
		     combineBBoxes(
1680
			       makeBBox(
-
 
1681
				 operatorLowerHShiftAll(
1684
		       makeBBox(operatorLowerHShiftAll(operator, lower, upper),
1682
				   operator, lower, upper),
1685
				0, 0),
1683
				 0, 0),
1686
		       lowerBBox),
1684
			       lowerBBox),
1687
		     operatorLowerShift(operator, lower))));
1685
			     operatorLowerShift(operator, lower))));
1688
      }
1686
	    }
1689
      else
1687
	    else
1690
	return combineAlignedBBoxes(
1688
		return combineAlignedBBoxes(
1691
                 combineBBoxes(
1689
			 combineBBoxes(
-
 
1690
			   makeBBox(
1692
		   makeBBox(operatorHShift(operator, lower), 0, 0),
1691
			     operatorHShift(operator, lower), 0, 0),
1693
		   bodyBBox),
1692
			   bodyBBox),
1694
		 shiftBBox(
1693
			 shiftBBox(
1695
		   combineBBoxes(
1694
			   combineBBoxes(
1696
		     makeBBox(operatorLowerHShift(operator, lower), 0, 0),
1695
			     makeBBox(operatorLowerHShift(operator, lower),
-
 
1696
				      0, 0),
1697
		     lowerBBox),
1697
			     lowerBBox),
1698
		   operatorLowerShift(operator, lower)));
1698
			   operatorLowerShift(operator, lower)));
-
 
1699
	}
-
 
1700
	else
-
 
1701
	    return bodyBBox;
1699
    }
1702
    }
1700
    else
1703
    else
1701
      return bodyBBox;
-
 
1702
  }
-
 
1703
  else
-
 
1704
    error("Invalid Formula\n");
1704
	error("Invalid Formula\n");
1705
}
1705
}
1706
 
1706
 
1707
static void drawTheOperator(SEXP operator)
1707
static void drawTheOperator(SEXP operator)
1708
{
1708
{
1709
  if (integralOperator(operator)) {
1709
    if (integralOperator(operator)) {
1710
    double savedX = currentX;
1710
	double savedX = currentX;
1711
    double savedY = currentY;
1711
	double savedY = currentY;
1712
    moveUp(integralTopShift());
1712
	moveUp(integralTopShift());
1713
    drawAscii(integralAscii(1));
1713
	drawAscii(integralAscii(1));
1714
    moveTo(savedX, savedY);
1714
	moveTo(savedX, savedY);
1715
    moveUp(integralBottomShift());
1715
	moveUp(integralBottomShift());
1716
    drawAscii(integralAscii(3));
1716
	drawAscii(integralAscii(3));
1717
    moveTo(savedX, savedY);
1717
	moveTo(savedX, savedY);
1718
    drawAscii(integralAscii(2));
1718
	drawAscii(integralAscii(2));
1719
  }
1719
    }
1720
  else
1720
    else
1721
    drawAscii(operatorAscii(operator));
1721
	drawAscii(operatorAscii(operator));
1722
}
1722
}
1723
 
1723
 
1724
static void drawOperatorLimit(SEXP limit)
1724
static void drawOperatorLimit(SEXP limit)
1725
{
1725
{
1726
  useRelGap = 0;
1726
    useRelGap = 0;
1727
  drawScriptElement(limit);
1727
    drawScriptElement(limit);
1728
  useRelGap = 1;
1728
    useRelGap = 1;
1729
}
1729
}
1730
 
1730
 
1731
static void drawOperator(SEXP expr)
1731
static void drawOperator(SEXP expr)
1732
{
1732
{
1733
  SEXP operator = CAR(expr);
1733
    SEXP operator = CAR(expr);
1734
  SEXP body = CADR(expr);
1734
    SEXP body = CADR(expr);
1735
  SEXP lower, upper;
1735
    SEXP lower, upper;
1736
  double savedX = currentX;
1736
    double savedX = currentX;
1737
  double savedY = currentY;
1737
    double savedY = currentY;
1738
 
1738
 
1739
  setGapCEX();
1739
    setGapCEX();
1740
 
1740
 
1741
  if (length(expr) > 2) {
1741
    if (length(expr) > 2) {
1742
    lower = CADDR(expr);
1742
	lower = CADDR(expr);
1743
 
1743
 
1744
    if (length(expr) > 3) {
1744
	if (length(expr) > 3) {
1745
      upper = CADDDR(expr);
1745
	    upper = CADDDR(expr);
1746
      moveUp(operatorUpperShift(operator, upper));
1746
	    moveUp(operatorUpperShift(operator, upper));
1747
      moveAcross(operatorUpperHShiftAll(operator, lower, upper));
1747
	    moveAcross(operatorUpperHShiftAll(operator, lower, upper));
1748
      drawOperatorLimit(upper);
1748
	    drawOperatorLimit(upper);
1749
      moveTo(savedX, savedY);
1749
	    moveTo(savedX, savedY);
1750
      moveUp(-operatorLowerShift(operator, lower));
1750
	    moveUp(-operatorLowerShift(operator, lower));
1751
      moveAcross(operatorLowerHShiftAll(operator, lower, upper));
1751
	    moveAcross(operatorLowerHShiftAll(operator, lower, upper));
1752
      drawOperatorLimit(lower);
1752
	    drawOperatorLimit(lower);
1753
      moveTo(savedX, savedY);
1753
	    moveTo(savedX, savedY);
1754
      moveAcross(operatorHShiftAll(operator, lower, upper));
1754
	    moveAcross(operatorHShiftAll(operator, lower, upper));
1755
    }
1755
	}
1756
 
1756
 
1757
    else{
1757
	else{
1758
      moveUp(-operatorLowerShift(operator, lower));
1758
	    moveUp(-operatorLowerShift(operator, lower));
1759
      moveAcross(operatorLowerHShift(operator, lower));
1759
	    moveAcross(operatorLowerHShift(operator, lower));
1760
      drawOperatorLimit(lower);
1760
	    drawOperatorLimit(lower);
1761
      moveTo(savedX, savedY);
1761
	    moveTo(savedX, savedY);
1762
      moveAcross(operatorHShift(operator, lower));
1762
	    moveAcross(operatorHShift(operator, lower));
-
 
1763
	}
1763
    }
1764
    }
1764
  }
-
 
1765
 
1765
 
1766
  drawTheOperator(operator);
1766
    drawTheOperator(operator);
1767
  drawGap(operatorGap(body));
1767
    drawGap(operatorGap(body));
1768
  drawElement(body);
1768
    drawElement(body);
1769
}
1769
}
1770
 
1770
 
1771
/* code for radical expressions (root) */
1771
/* Code for radical expressions (root) */
1772
 
1772
 
1773
static BBOX customRadicalBBox(SEXP body)
1773
static BBOX customRadicalBBox(SEXP body)
1774
{
1774
{
1775
	BBOX bodyBBox = elementBBox(body);
1775
    BBOX bodyBBox = elementBBox(body);
1776
	return combineBBoxes(makeBBox(bboxHeight(bodyBBox) + customRadicalGap(),
1776
    return combineBBoxes(makeBBox(bboxHeight(bodyBBox) + customRadicalGap(),
1777
				      0, customRadicalWidth()),
1777
				  0, customRadicalWidth()),
1778
		      combineBBoxes(makeBBox(0, 0, customRadicalSpace()),
1778
			 combineBBoxes(makeBBox(0, 0, customRadicalSpace()),
1779
				    bodyBBox));
1779
				       bodyBBox));
1780
}
1780
}
1781
 
1781
 
1782
static BBOX radicalBBox(SEXP expr)
1782
static BBOX radicalBBox(SEXP expr)
1783
{
1783
{
1784
	SEXP body = CADR(expr);
1784
    SEXP body = CADR(expr);
1785
	return customRadicalBBox(body);
1785
    return customRadicalBBox(body);
1786
}
1786
}
1787
 
1787
 
1788
static void drawCustomRadical(SEXP body)
1788
static void drawCustomRadical(SEXP body)
1789
{
1789
{
1790
	BBOX bodyBBox = elementBBox(body);
1790
    BBOX bodyBBox = elementBBox(body);
1791
	double height = bboxHeight(bodyBBox);
1791
    double height = bboxHeight(bodyBBox);
1792
	double depth = bboxDepth(bodyBBox);
1792
    double depth = bboxDepth(bodyBBox);
1793
	double width = bboxWidth(bodyBBox);
1793
    double width = bboxWidth(bodyBBox);
1794
	double twiddleHeight = (height - depth) / 2;
1794
    double twiddleHeight = (height - depth) / 2;
1795
	double savedX = currentX;
1795
    double savedX = currentX;
1796
	double savedY = currentY;
1796
    double savedY = currentY;
1797
	double x[5], y[5];
1797
    double x[5], y[5];
1798
 
1798
 
1799
	moveUp(0.8 * twiddleHeight);
1799
    moveUp(0.8 * twiddleHeight);
1800
	x[0] = convertedX(); y[0] = convertedY();
1800
    x[0] = convertedX(); y[0] = convertedY();
1801
	moveUp(0.2 * twiddleHeight);
1801
    moveUp(0.2 * twiddleHeight);
1802
	moveAcross(0.3 * customRadicalWidth());
1802
    moveAcross(0.3 * customRadicalWidth());
1803
	x[1] = convertedX(); y[1] = convertedY();
1803
    x[1] = convertedX(); y[1] = convertedY();
1804
	moveUp(-(twiddleHeight + depth));
1804
    moveUp(-(twiddleHeight + depth));
1805
	moveAcross(0.3 * customRadicalWidth());
1805
    moveAcross(0.3 * customRadicalWidth());
1806
	x[2] = convertedX(); y[2] = convertedY();
1806
    x[2] = convertedX(); y[2] = convertedY();
1807
	moveUp(depth + height + customRadicalGap());
1807
    moveUp(depth + height + customRadicalGap());
1808
	moveAcross(0.4 * customRadicalWidth());
1808
    moveAcross(0.4 * customRadicalWidth());
1809
	x[3] = convertedX(); y[3] = convertedY();
1809
    x[3] = convertedX(); y[3] = convertedY();
1810
	moveAcross(customRadicalSpace() + width);
1810
    moveAcross(customRadicalSpace() + width);
1811
	x[4] = convertedX(); y[4] = convertedY();
1811
    x[4] = convertedX(); y[4] = convertedY();
1812
	GPolyline(5, x, y, INCHES, mathDevice);
1812
    GPolyline(5, x, y, INCHES, mathDevice);
1813
	moveTo(savedX, savedY);
1813
    moveTo(savedX, savedY);
1814
	moveAcross(customRadicalWidth() + customRadicalSpace());
1814
    moveAcross(customRadicalWidth() + customRadicalSpace());
1815
	drawElement(body);
1815
    drawElement(body);
1816
}
1816
}
1817
 
1817
 
1818
static void drawRadical(SEXP expr)
1818
static void drawRadical(SEXP expr)
1819
{
1819
{
1820
	SEXP body = CADR(expr);
1820
    SEXP body = CADR(expr);
1821
	drawCustomRadical(body);
1821
    drawCustomRadical(body);
1822
}
1822
}
1823
 
1823
 
1824
/* code for absolute expressions (abs) */
1824
/* Code for absolute expressions (abs). */
1825
 
1825
 
1826
static BBOX absBBox(SEXP expr)
1826
static BBOX absBBox(SEXP expr)
1827
{
1827
{
1828
	SEXP body = CADR(expr);
1828
    SEXP body = CADR(expr);
1829
	return combineBBoxes(makeBBox(0, 0, absSpace()),
1829
    return combineBBoxes(makeBBox(0, 0, absSpace()),
1830
			     combineBBoxes(elementBBox(body),
1830
			 combineBBoxes(elementBBox(body),
1831
					   makeBBox(0, 0, absSpace())));
1831
				       makeBBox(0, 0, absSpace())));
1832
}
1832
}
1833
 
1833
 
1834
static void drawAbs(SEXP expr)
1834
static void drawAbs(SEXP expr)
1835
{
1835
{
1836
	SEXP body = CADR(expr);
1836
    SEXP body = CADR(expr);
1837
	BBOX bodyBBox = elementBBox(expr);
1837
    BBOX bodyBBox = elementBBox(expr);
1838
	double height = bboxHeight(bodyBBox);
1838
    double height = bboxHeight(bodyBBox);
1839
	double depth = bboxDepth(bodyBBox);
1839
    double depth = bboxDepth(bodyBBox);
1840
	double x[2], y[2];
1840
    double x[2], y[2];
1841
 
1841
 
1842
	moveUp(-depth);
1842
    moveUp(-depth);
1843
	x[0] = convertedX(); y[0] = convertedY();
1843
    x[0] = convertedX(); y[0] = convertedY();
1844
	moveUp(depth + height);
1844
    moveUp(depth + height);
1845
	x[1] = convertedX(); y[1] = convertedY();
1845
    x[1] = convertedX(); y[1] = convertedY();
1846
	GPolyline(2, x, y, INCHES, mathDevice);
1846
    GPolyline(2, x, y, INCHES, mathDevice);
1847
	moveUp(-height);
1847
    moveUp(-height);
1848
	moveAcross(absSpace());
1848
    moveAcross(absSpace());
1849
	drawElement(body);
1849
    drawElement(body);
1850
	moveAcross(absSpace());
1850
    moveAcross(absSpace());
1851
	moveUp(-depth);
1851
    moveUp(-depth);
1852
	x[0] = convertedX(); y[0] = convertedY();
1852
    x[0] = convertedX(); y[0] = convertedY();
1853
	moveUp(depth + height);
1853
    moveUp(depth + height);
1854
	x[1] = convertedX(); y[1] = convertedY();
1854
    x[1] = convertedX(); y[1] = convertedY();
1855
	GPolyline(2, x, y, INCHES, mathDevice);
1855
    GPolyline(2, x, y, INCHES, mathDevice);
1856
	moveUp(-height);
1856
    moveUp(-height);
1857
}
1857
}
1858
 
1858
 
1859
/* code for general expressions with no special meaning in */
1859
/* Code for general expressions with no special meaning */
1860
/* mathematical notation syntax (e.g., f(x)) */
1860
/* in mathematical notation syntax (e.g., f(x)) */
1861
 
1861
 
1862
static BBOX expressionBBox(SEXP expr)
1862
static BBOX expressionBBox(SEXP expr)
1863
{
1863
{
1864
	int i;
1864
    int i;
1865
	int numParams = length(expr) - 1;
1865
    int numParams = length(expr) - 1;
1866
	BBOX resultBBox = elementBBox(CAR(expr));
1866
    BBOX resultBBox = elementBBox(CAR(expr));
1867
        SEXP lastTerm;
1867
    SEXP lastTerm;
1868
 
1868
 
-
 
1869
    lastTerm = CAR(expr);
-
 
1870
    expr = CDR(expr);
-
 
1871
    resultBBox = combineBBoxes(resultBBox, asciiBBox(groupOpenAscii()));
-
 
1872
    for (i = 0; i < numParams; i++) {
-
 
1873
	resultBBox = combineBBoxes(resultBBox, elementBBox(CAR(expr)));
1869
	lastTerm = CAR(expr);
1874
	lastTerm = CAR(expr);
1870
	expr = CDR(expr);
1875
	expr = CDR(expr);
1871
	resultBBox = combineBBoxes(resultBBox, asciiBBox(groupOpenAscii()));
-
 
1872
	for (i = 0; i < numParams; i++) {
-
 
1873
		resultBBox = combineBBoxes(resultBBox, elementBBox(CAR(expr)));
-
 
1874
	        lastTerm = CAR(expr);
-
 
1875
		expr = CDR(expr);
-
 
1876
		if (i < numParams - 1)
1876
	if (i < numParams - 1)
1877
			resultBBox = combineBBoxes(resultBBox,
1877
	    resultBBox = combineBBoxes(resultBBox,
1878
				   combineBBoxes(asciiBBox(commaAscii()),
1878
				       combineBBoxes(asciiBBox(commaAscii()),
1879
					       asciiBBox(spaceAscii())));
1879
						     asciiBBox(spaceAscii())));
1880
	}
1880
    }
1881
	return combineBBoxes(resultBBox,
1881
    return combineBBoxes(resultBBox,
1882
			     combineBBoxes(correctionWithinBBox(lastTerm),
1882
			 combineBBoxes(correctionWithinBBox(lastTerm),
1883
					   asciiBBox(groupCloseAscii())));
1883
				       asciiBBox(groupCloseAscii())));
1884
}
1884
}
1885
 
1885
 
1886
static void drawExpression(SEXP expr)
1886
static void drawExpression(SEXP expr)
1887
{
1887
{
1888
	int i;
1888
    int i;
1889
	int numParams = length(expr) - 1;
1889
    int numParams = length(expr) - 1;
1890
	SEXP lastTerm;
1890
    SEXP lastTerm;
1891
 
1891
 
-
 
1892
    drawElement(CAR(expr));
-
 
1893
    lastTerm = CAR(expr);
-
 
1894
    expr = CDR(expr);
-
 
1895
    drawAscii(groupOpenAscii());
-
 
1896
    for (i = 0; i < numParams; i++) {
1892
	drawElement(CAR(expr));
1897
	drawElement(CAR(expr));
1893
	lastTerm = CAR(expr);
1898
	lastTerm = CAR(expr);
1894
	expr = CDR(expr);
1899
	expr = CDR(expr);
1895
	drawAscii(groupOpenAscii());
-
 
1896
	for (i = 0; i < numParams; i++) {
-
 
1897
		drawElement(CAR(expr));
-
 
1898
	        lastTerm = CAR(expr);
-
 
1899
		expr = CDR(expr);
-
 
1900
		if (i < numParams - 1) {
1900
	if (i < numParams - 1) {
1901
			drawAscii(commaAscii());
1901
	    drawAscii(commaAscii());
1902
			drawAscii(spaceAscii());
1902
	    drawAscii(spaceAscii());
1903
		}
-
 
1904
	}
1903
	}
-
 
1904
    }
1905
	drawCorrectionWithin(lastTerm);
1905
    drawCorrectionWithin(lastTerm);
1906
	drawAscii(groupCloseAscii());
1906
    drawAscii(groupCloseAscii());
1907
}
1907
}
1908
 
1908
 
1909
/* code for curly expressions (i.e., { ... } ) */
1909
/* Code for curly expressions (i.e., { ... } ) */
1910
 
1910
 
1911
static BBOX curlyBBox(SEXP expr)
1911
static BBOX curlyBBox(SEXP expr)
1912
{
1912
{
1913
	return expressionBBox(CADR(expr));
1913
    return expressionBBox(CADR(expr));
1914
}
1914
}
1915
 
1915
 
1916
static void drawFormula(SEXP);
1916
static void drawFormula(SEXP);
1917
 
1917
 
1918
static void drawCurly(SEXP expr)
1918
static void drawCurly(SEXP expr)
1919
{
1919
{
1920
	drawFormula(CADR(expr));
1920
    drawFormula(CADR(expr));
1921
}
1921
}
1922
 
1922
 
1923
/* code for relation expressions (i.e. ... == ...) */
1923
/* code for relation expressions (i.e. ... == ...) */
1924
 
1924
 
1925
static double relGap()
1925
static double relGap()
1926
{
1926
{
1927
  if (useRelGap)
1927
    if (useRelGap)
1928
    return 0.3;
1928
	return 0.3;
1929
  else
1929
    else
1930
    return 0.1;
1930
	return 0.1;
1931
}
1931
}
1932
 
1932
 
1933
static BBOX relBBox(SEXP expr)
1933
static BBOX relBBox(SEXP expr)
1934
{
1934
{
1935
  SEXP arg1 = CADR(expr);
1935
    SEXP arg1 = CADR(expr);
1936
  SEXP arg2 = CADDR(expr);
1936
    SEXP arg2 = CADDR(expr);
1937
 
1937
 
1938
  return combineBBoxes(
1938
    return combineBBoxes(
1939
	   elementBBox(arg1),
1939
	      elementBBox(arg1),
1940
	   combineBBoxes(
1940
	      combineBBoxes(
1941
			 gapBBox(relGap()),
1941
	         gapBBox(relGap()),
1942
			 combineBBoxes(
1942
	         combineBBoxes(
1943
				       asciiBBox(relAscii()),
1943
		    asciiBBox(relAscii()),
1944
				       combineBBoxes(
1944
		    combineBBoxes(
1945
						     gapBBox(relGap()),
1945
		       gapBBox(relGap()),
1946
						     elementBBox(arg2)))));
1946
		       elementBBox(arg2)))));
1947
}
1947
}
1948
 
1948
 
1949
static void drawRel(SEXP expr)
1949
static void drawRel(SEXP expr)
1950
{
1950
{
1951
  SEXP arg1 = CADR(expr);
1951
    SEXP arg1 = CADR(expr);
1952
  SEXP arg2 = CADDR(expr);
1952
    SEXP arg2 = CADDR(expr);
1953
 
1953
 
1954
  drawElement(arg1);
1954
    drawElement(arg1);
1955
  drawGap(relGap());
1955
    drawGap(relGap());
1956
  drawAscii(relAscii());
1956
    drawAscii(relAscii());
1957
  drawGap(relGap());
1957
    drawGap(relGap());
1958
  drawElement(arg2);
1958
    drawElement(arg2);
1959
}
1959
}
1960
 
1960
 
1961
/* code for bold expressions */
1961
/* code for bold expressions */
1962
 
1962
 
1963
static BBOX boldBBox(SEXP expr)
1963
static BBOX boldBBox(SEXP expr)
1964
{
1964
{
1965
  BBOX result;
1965
    BBOX result;
1966
  int savedFont = getFont();
1966
    int savedFont = getFont();
1967
 
1967
 
1968
  boldFont();
1968
    boldFont();
1969
  result = elementBBox(CADR(expr));
1969
    result = elementBBox(CADR(expr));
1970
  setFont(savedFont);
1970
    setFont(savedFont);
1971
 
1971
 
1972
  return result;
1972
    return result;
1973
}
1973
}
1974
 
1974
 
1975
static void drawBold(SEXP expr)
1975
static void drawBold(SEXP expr)
1976
{
1976
{
1977
  int savedFont = getFont();
1977
    int savedFont = getFont();
1978
 
1978
 
1979
  boldFont();
1979
    boldFont();
1980
  drawElement(CADR(expr));
1980
    drawElement(CADR(expr));
1981
  setFont(savedFont);
1981
    setFont(savedFont);
1982
}
1982
}
1983
 
1983
 
1984
/* code for italic expressions */
1984
/* code for italic expressions */
1985
 
1985
 
1986
static BBOX italicBBox(SEXP expr)
1986
static BBOX italicBBox(SEXP expr)
1987
{
1987
{
1988
  BBOX result;
1988
    BBOX result;
1989
  SEXP body = CADR(expr);
1989
    SEXP body = CADR(expr);
1990
  int savedFont = getFont();
1990
    int savedFont = getFont();
1991
 
1991
 
1992
  italicFont();
1992
    italicFont();
1993
  result = elementBBox(body);
1993
    result = elementBBox(body);
1994
  setFont(savedFont);
1994
    setFont(savedFont);
1995
 
1995
 
1996
  return result;
1996
    return result;
1997
}
1997
}
1998
 
1998
 
1999
static void drawItalic(SEXP expr)
1999
static void drawItalic(SEXP expr)
2000
{
2000
{
2001
  SEXP body = CADR(expr);
2001
    SEXP body = CADR(expr);
2002
  int savedFont = getFont();
2002
    int savedFont = getFont();
2003
 
2003
 
2004
  italicFont();
2004
    italicFont();
2005
  drawElement(body);
2005
    drawElement(body);
2006
  setFont(savedFont);
2006
    setFont(savedFont);
2007
}
2007
}
2008
 
2008
 
2009
/* code for plain expressions */
2009
/* code for plain expressions */
2010
 
2010
 
2011
static BBOX plainBBox(SEXP expr)
2011
static BBOX plainBBox(SEXP expr)
2012
{
2012
{
2013
  BBOX result = nullBBox();
2013
    BBOX result = nullBBox();
2014
  int savedFont = getFont();
2014
    int savedFont = getFont();
2015
 
2015
 
2016
  plainFont();
2016
    plainFont();
2017
  result = elementBBox(CADR(expr));
2017
    result = elementBBox(CADR(expr));
2018
  setFont(savedFont);
2018
    setFont(savedFont);
2019
 
2019
 
2020
  return result;
2020
    return result;
2021
}
2021
}
2022
 
2022
 
2023
static void drawPlain(SEXP expr)
2023
static void drawPlain(SEXP expr)
2024
{
2024
{
2025
  int savedFont = getFont();
2025
    int savedFont = getFont();
2026
 
2026
 
2027
  plainFont();
2027
    plainFont();
2028
  drawElement(CADR(expr));
2028
    drawElement(CADR(expr));
2029
  setFont(savedFont);
2029
    setFont(savedFont);
2030
}
2030
}
2031
 
2031
 
2032
/* code for bolditalic expressions */
2032
/* code for bolditalic expressions */
2033
 
2033
 
2034
static BBOX boldItalicBBox(SEXP expr)
2034
static BBOX boldItalicBBox(SEXP expr)
2035
{
2035
{
2036
  BBOX result;
2036
    BBOX result;
2037
  int savedFont = getFont();
2037
    int savedFont = getFont();
2038
 
2038
 
2039
  boldItalicFont();
2039
    boldItalicFont();
2040
  result = elementBBox(CADR(expr));
2040
    result = elementBBox(CADR(expr));
2041
  setFont(savedFont);
2041
    setFont(savedFont);
2042
 
2042
 
2043
  return result;
2043
    return result;
2044
}
2044
}
2045
 
2045
 
2046
static void drawBoldItalic(SEXP expr)
2046
static void drawBoldItalic(SEXP expr)
2047
{
2047
{
2048
  int savedFont = getFont();
2048
    int savedFont = getFont();
2049
 
2049
 
2050
  boldItalicFont();
2050
    boldItalicFont();
2051
  drawElement(CADR(expr));
2051
    drawElement(CADR(expr));
2052
  setFont(savedFont);
2052
    setFont(savedFont);
2053
}
2053
}
2054
 
2054
 
2055
/* code for concatenating expressions c(...) */
2055
/* code for concatenating expressions c(...) */
2056
 
2056
 
2057
static BBOX concatenateBBox(SEXP expr)
2057
static BBOX concatenateBBox(SEXP expr)
2058
{
2058
{
2059
  SEXP args = CDR(expr);
2059
    SEXP args = CDR(expr);
2060
  SEXP lastArg;
2060
    SEXP lastArg;
2061
  int i;
2061
    int i;
2062
  int numArgs = length(args);
2062
    int numArgs = length(args);
2063
  BBOX result = nullBBox();
2063
    BBOX result = nullBBox();
2064
 
2064
 
2065
  if (numArgs > 0)
2065
    if (numArgs > 0)
2066
  result = elementBBox(CAR(args));
2066
	result = elementBBox(CAR(args));
2067
  lastArg = CAR(args);
-
 
2068
  args = CDR(args);
-
 
2069
 
-
 
2070
  for (i=1; i<numArgs; i++) {
-
 
2071
    result = combineBBoxes(
-
 
2072
	       result,
-
 
2073
	       combineBBoxes(correctionBetweenBBox(lastArg, CAR(args)),
-
 
2074
			     elementBBox(CAR(args))));
-
 
2075
    lastArg = CAR(args);
2067
    lastArg = CAR(args);
2076
    args = CDR(args);
2068
    args = CDR(args);
2077
  }
-
 
2078
 
2069
 
-
 
2070
    for (i=1; i<numArgs; i++) {
-
 
2071
	result = combineBBoxes(result,
-
 
2072
		    combineBBoxes(
-
 
2073
		       correctionBetweenBBox(lastArg, CAR(args)),
-
 
2074
		       elementBBox(CAR(args))));
-
 
2075
	lastArg = CAR(args);
-
 
2076
	args = CDR(args);
-
 
2077
    }
-
 
2078
 
2079
  return result;
2079
    return result;
2080
}
2080
}
2081
 
2081
 
2082
static void drawConcatenate(SEXP expr)
2082
static void drawConcatenate(SEXP expr)
2083
{
2083
{
2084
  SEXP args = CDR(expr);
2084
    SEXP args = CDR(expr);
2085
  SEXP lastArg;
2085
    SEXP lastArg;
2086
  int i;
2086
    int i;
2087
  int numArgs = length(args);
2087
    int numArgs = length(args);
2088
 
2088
 
2089
  for (i=0; i<numArgs; i++) {
2089
    for (i=0; i<numArgs; i++) {
2090
    if (i > 0)
2090
	if (i > 0)
2091
      drawCorrectionBetween(lastArg, CAR(args));
2091
	    drawCorrectionBetween(lastArg, CAR(args));
2092
    drawElement(CAR(args));
2092
	drawElement(CAR(args));
2093
    lastArg = CAR(args);
2093
	lastArg = CAR(args);
2094
    args = CDR(args);
2094
	args = CDR(args);
2095
  }
2095
    }
2096
}
2096
}
2097
 
2097
 
2098
/* dispatching procedure which determines nature of expression */
2098
/* Dispatching procedure which determines nature of expression. */
2099
 
2099
 
2100
static BBOX formulaBBox(SEXP expr)
2100
static BBOX formulaBBox(SEXP expr)
2101
{
2101
{
2102
	SEXP head = CAR(expr);
2102
    SEXP head = CAR(expr);
2103
 
2103
 
2104
	if (binAtom(head))
2104
    if (binAtom(head))
2105
		return binBBox(expr);
2105
	return binBBox(expr);
2106
	else if (superAtom(head))
2106
    else if (superAtom(head))
2107
		return supBBox(expr);
2107
	return supBBox(expr);
2108
	else if (subAtom(head))
2108
    else if (subAtom(head))
2109
		return subBBox(expr);
2109
	return subBBox(expr);
2110
	else if (accentAtom(head))
2110
    else if (accentAtom(head))
2111
		return accentBBox(expr);
2111
	return accentBBox(expr);
2112
	else if (fractionAtom(head))
2112
    else if (fractionAtom(head))
2113
		return fractionBBox(expr);
2113
	return fractionBBox(expr);
2114
	else if (groupAtom(head))
2114
    else if (groupAtom(head))
2115
		return groupBBox(expr);
2115
	return groupBBox(expr);
2116
	else if (operatorAtom(head))
2116
    else if (operatorAtom(head))
2117
		return operatorBBox(expr);
2117
	return operatorBBox(expr);
2118
	else if (radicalAtom(head))
2118
    else if (radicalAtom(head))
2119
		return radicalBBox(expr);
2119
	return radicalBBox(expr);
2120
	else if (absAtom(head))
2120
    else if (absAtom(head))
2121
		return absBBox(expr);
2121
	return absBBox(expr);
2122
	else if (curlyAtom(head))
2122
    else if (curlyAtom(head))
2123
		return curlyBBox(expr);
2123
	return curlyBBox(expr);
2124
	else if (relAtom(head))
2124
    else if (relAtom(head))
2125
	  return relBBox(expr);
2125
	return relBBox(expr);
2126
	else if (boldAtom(head))
2126
    else if (boldAtom(head))
2127
	  return boldBBox(expr);
2127
	return boldBBox(expr);
2128
	else if (italicAtom(head))
2128
    else if (italicAtom(head))
2129
	  return italicBBox(expr);
2129
	return italicBBox(expr);
2130
	else if (plainAtom(head))
2130
    else if (plainAtom(head))
2131
	  return plainBBox(expr);
2131
	return plainBBox(expr);
2132
	else if (boldItalicAtom(head))
2132
    else if (boldItalicAtom(head))
2133
	  return boldItalicBBox(expr);
2133
	return boldItalicBBox(expr);
2134
	else if (concatenateAtom(head))
2134
    else if (concatenateAtom(head))
2135
		return concatenateBBox(expr);
2135
	return concatenateBBox(expr);
2136
	else
2136
    else
2137
		return expressionBBox(expr);
2137
	return expressionBBox(expr);
2138
}
2138
}
2139
 
2139
 
2140
static void drawFormula(SEXP expr)
2140
static void drawFormula(SEXP expr)
2141
{
2141
{
2142
	SEXP head = CAR(expr);
2142
    SEXP head = CAR(expr);
2143
 
2143
 
2144
	if (binAtom(head))
2144
    if (binAtom(head))
2145
		drawBin(expr);
2145
	drawBin(expr);
2146
	else if (superAtom(head))
2146
    else if (superAtom(head))
2147
		drawSuper(expr);
2147
	drawSuper(expr);
2148
	else if (subAtom(head))
2148
    else if (subAtom(head))
2149
		drawSub(expr);
2149
	drawSub(expr);
2150
	else if (accentAtom(head))
2150
    else if (accentAtom(head))
2151
		drawAccent(expr);
2151
	drawAccent(expr);
2152
	else if (fractionAtom(head))
2152
    else if (fractionAtom(head))
2153
		drawFraction(expr);
2153
	drawFraction(expr);
2154
	else if (groupAtom(head))
2154
    else if (groupAtom(head))
2155
		drawGroup(expr);
2155
	drawGroup(expr);
2156
	else if (operatorAtom(head))
2156
    else if (operatorAtom(head))
2157
		drawOperator(expr);
2157
	drawOperator(expr);
2158
	else if (radicalAtom(head))
2158
    else if (radicalAtom(head))
2159
		drawRadical(expr);
2159
	drawRadical(expr);
2160
	else if (absAtom(head))
2160
    else if (absAtom(head))
2161
		drawAbs(expr);
2161
	drawAbs(expr);
2162
	else if (curlyAtom(head))
2162
    else if (curlyAtom(head))
2163
		drawCurly(expr);
2163
	drawCurly(expr);
2164
	else if (relAtom(head))
2164
    else if (relAtom(head))
2165
	  drawRel(expr);
2165
	drawRel(expr);
2166
	else if (boldAtom(head))
2166
    else if (boldAtom(head))
2167
	  drawBold(expr);
2167
	drawBold(expr);
2168
	else if (italicAtom(head))
2168
    else if (italicAtom(head))
2169
	  drawItalic(expr);
2169
	drawItalic(expr);
2170
	else if (plainAtom(head))
2170
    else if (plainAtom(head))
2171
	  drawPlain(expr);
2171
	drawPlain(expr);
2172
	else if (boldItalicAtom(head))
2172
    else if (boldItalicAtom(head))
2173
	  drawBoldItalic(expr);
2173
	drawBoldItalic(expr);
2174
	else if (concatenateAtom(head))
2174
    else if (concatenateAtom(head))
2175
		drawConcatenate(expr);
2175
	drawConcatenate(expr);
2176
 
2176
 
2177
	/* if expression is not a special mathematical notation */
2177
    /* if expression is not a special mathematical notation */
2178
	/* function then just reconstruct expression */
2178
    /* function then just reconstruct expression */
2179
 
2179
 
2180
	else
2180
    else
2181
		drawExpression(expr);
2181
	drawExpression(expr);
2182
}
2182
}
2183
 
2183
 
2184
/* top-level:  dispatch on whether atom (symbol, string, number, ...) */
2184
/* top-level:  dispatch on whether atom (symbol, string, number, ...) */
2185
/* or formula (some sort of expression) */
2185
/* or formula (some sort of expression) */
2186
 
2186
 
2187
static BBOX elementBBox(SEXP expr)
2187
static BBOX elementBBox(SEXP expr)
2188
{
2188
{
2189
	if (formulaExpression(expr))
2189
    if (formulaExpression(expr))
2190
		return formulaBBox(expr);
2190
	return formulaBBox(expr);
2191
	else
2191
    else
2192
		return atomBBox(expr);
2192
	return atomBBox(expr);
2193
}
2193
}
2194
 
2194
 
2195
static void drawElement(SEXP expr)
2195
static void drawElement(SEXP expr)
2196
{
2196
{
2197
	if (formulaExpression(expr))
2197
    if (formulaExpression(expr))
2198
		drawFormula(expr);
2198
	drawFormula(expr);
2199
	else
2199
    else
2200
		drawAtom(expr);
2200
	drawAtom(expr);
2201
}
2201
}
2202
 
2202
 
2203
        /* calculate width of expression */
2203
        /* calculate width of expression */
2204
        /* BBOXes are in INCHES (see metricUnit) */
2204
        /* BBOXes are in INCHES (see metricUnit) */
2205
double GExpressionWidth(SEXP expr, int units, DevDesc *dd)
2205
double GExpressionWidth(SEXP expr, int units, DevDesc *dd)
2206
{
2206
{
2207
        BBOX exprBBox = elementBBox(expr);
2207
    BBOX exprBBox = elementBBox(expr);
2208
        double w  = exprBBox.width;
2208
    double w  = exprBBox.width;
2209
	if (units == INCHES)
2209
    if (units == INCHES)
2210
		return w;
2210
	return w;
2211
	else
2211
    else
2212
		return GConvertXUnits(w, INCHES, units, dd);
2212
	return GConvertXUnits(w, INCHES, units, dd);
2213
}
2213
}
2214
 
2214
 
2215
#define ABS(a)  ((a)>=0 ? (a) : -(a))
2215
#define ABS(a)  ((a)>=0 ? (a) : -(a))
2216
 
2216
 
2217
double GExpressionHeight(SEXP expr, int units, DevDesc *dd)
2217
double GExpressionHeight(SEXP expr, int units, DevDesc *dd)
2218
{
2218
{
2219
        BBOX exprBBox = elementBBox(expr);
2219
    BBOX exprBBox = elementBBox(expr);
2220
        double h = exprBBox.height + exprBBox.depth;
2220
    double h = exprBBox.height + exprBBox.depth;
2221
	if (units == INCHES)
2221
    if (units == INCHES)
2222
		return h;
2222
	return h;
2223
	else
2223
    else
2224
		return GConvertYUnits(h, INCHES, units, dd);
2224
	return GConvertYUnits(h, INCHES, units, dd);
2225
}
2225
}
2226
 
2226
 
2227
		/* functions forming the API */
2227
/* Functions forming the API */
2228
 
2228
 
2229
void GMathText(double x, double y, int coords, SEXP expr,
2229
void GMathText(double x, double y, int coords, SEXP expr,
2230
	       double xc, double yc, double rot, DevDesc *dd)
2230
	       double xc, double yc, double rot, DevDesc *dd)
2231
{
2231
{
2232
	BBOX expressionBBox;
2232
    BBOX expressionBBox;
2233
 
2233
 
2234
	mathDevice = dd;
2234
    mathDevice = dd;
2235
 
2235
 
2236
	initFormulaSymbols();
2236
    initFormulaSymbols();
2237
	expressionBBox = elementBBox(expr);
2237
    expressionBBox = elementBBox(expr);
2238
 
2238
 
2239
	referenceX = x;
2239
    referenceX = x;
2240
	referenceY = y;
2240
    referenceY = y;
2241
	GConvert(&referenceX, &referenceY, coords, INCHES, dd);
2241
    GConvert(&referenceX, &referenceY, coords, INCHES, dd);
2242
 
2242
 
2243
	currentX = referenceX - xc * bboxWidth(expressionBBox);
2243
    currentX = referenceX - xc * bboxWidth(expressionBBox);
2244
	currentY = referenceY - yc * bboxHeight(expressionBBox);
2244
    currentY = referenceY - yc * bboxHeight(expressionBBox);
2245
	currentAngle = rot;
2245
    currentAngle = rot;
2246
	cosAngle = cos(rot / 90 * half_pi);
2246
    cosAngle = cos(rot / 90 * half_pi);
2247
	sinAngle = sin(rot / 90 * half_pi);
2247
    sinAngle = sin(rot / 90 * half_pi);
2248
	drawElement(expr);
2248
    drawElement(expr);
2249
}
2249
}
2250
 
2250
 
2251
 
2251
 
2252
void GMMathText(SEXP str, int side, double line, int outer, double at, int las,
2252
void GMMathText(SEXP str, int side, double line, int outer, double at, int las,
2253
		DevDesc *dd)
2253
		DevDesc *dd)
2254
{
2254
{
2255
	int coords;
2255
    int coords;
2256
	double a, xadj, yadj;
2256
    double a, xadj, yadj;
2257
 
2257
 
2258
	mathDevice = dd;
2258
    mathDevice = dd;
2259
 
2259
 
2260
	if (outer) {
2260
    if (outer) {
2261
		switch (side) {
2261
	switch (side) {
2262
		case 1:
2262
	case 1:
2263
			line = line + 1;
2263
	    line = line + 1;
2264
			coords = MAR1;
2264
	    coords = MAR1;
2265
			a = 0.0;
2265
	    a = 0.0;
2266
			xadj = mathDevice->gp.adj;
2266
	    xadj = mathDevice->gp.adj;
2267
			yadj = 0.0;
2267
	    yadj = 0.0;
2268
			break;
2268
	    break;
2269
		case 2:
2269
	case 2:
2270
			coords = MAR2;
2270
	    coords = MAR2;
2271
			a = 90.0;
2271
	    a = 90.0;
2272
			xadj = mathDevice->gp.adj;
2272
	    xadj = mathDevice->gp.adj;
2273
			yadj = 0.0;
2273
	    yadj = 0.0;
2274
			break;
2274
	    break;
2275
		case 3:
2275
	case 3:
2276
			coords = MAR3;
2276
	    coords = MAR3;
2277
			a = 0.0;
2277
	    a = 0.0;
2278
			xadj = mathDevice->gp.adj;
2278
	    xadj = mathDevice->gp.adj;
2279
			yadj = 0.0;
2279
	    yadj = 0.0;
2280
			break;
2280
	    break;
2281
		case 4:
2281
	case 4:
2282
			line = line + 1;
2282
	    line = line + 1;
2283
			coords = MAR4;
2283
	    coords = MAR4;
2284
			a = 90.0;
2284
	    a = 90.0;
2285
			xadj = mathDevice->gp.adj;
2285
	    xadj = mathDevice->gp.adj;
2286
			yadj = 0.0;
2286
	    yadj = 0.0;
2287
			break;
2287
	    break;
2288
		}
-
 
2289
		GMathText(at, line, coords, str, xadj, yadj, a, dd);
-
 
2290
	}
2288
	}
-
 
2289
	GMathText(at, line, coords, str, xadj, yadj, a, dd);
-
 
2290
    }
2291
	else {
2291
    else {
2292
		switch (side) {
2292
	switch (side) {
2293
		case 1:
2293
	case 1:
2294
			if (las == 2) {
2294
	    if (las == 2) {
2295
				at = at - GConvertXUnits(dd->gp.yLineBias,
2295
		at = at - GConvertXUnits(dd->gp.yLineBias,
2296
							 LINES, USER, dd);
2296
					 LINES, USER, dd);
2297
				line = line + dd->gp.yLineBias;
2297
		line = line + dd->gp.yLineBias;
2298
				a = 90.0;
2298
		a = 90.0;
2299
				xadj = 1.0;
2299
		xadj = 1.0;
2300
				yadj = 0.5;
2300
		yadj = 0.5;
2301
			}
2301
	    }
2302
			else {
2302
	    else {
2303
				line = line + 1 - dd->gp.yLineBias;
2303
		line = line + 1 - dd->gp.yLineBias;
2304
				a = 0.0;
2304
		a = 0.0;
2305
				xadj = mathDevice->gp.adj;
2305
		xadj = mathDevice->gp.adj;
2306
				yadj = 0.0;
2306
		yadj = 0.0;
2307
			}
2307
	    }
2308
			coords = MAR1;
2308
	    coords = MAR1;
2309
			break;
2309
	    break;
2310
		case 2:
2310
	case 2:
2311
			if (las == 1 || las == 2) {
2311
	    if (las == 1 || las == 2) {
2312
				at = at + GConvertYUnits(dd->gp.yLineBias,
2312
		at = at + GConvertYUnits(dd->gp.yLineBias,
2313
							 LINES, USER, dd);
2313
					 LINES, USER, dd);
2314
				line = line + dd->gp.yLineBias;
2314
		line = line + dd->gp.yLineBias;
2315
				a = 0.0;
2315
		a = 0.0;
2316
				xadj = 1.0;
2316
		xadj = 1.0;
2317
				yadj = 0.5;
2317
		yadj = 0.5;
2318
			}
2318
	    }
2319
			else {
2319
	    else {
2320
				line = line + dd->gp.yLineBias;
2320
		line = line + dd->gp.yLineBias;
2321
				a = 90.0;
2321
		a = 90.0;
2322
				xadj = mathDevice->gp.adj;
2322
		xadj = mathDevice->gp.adj;
2323
				yadj = 0.0;
2323
		yadj = 0.0;
2324
			}
2324
	    }
2325
			coords = MAR2;
2325
	    coords = MAR2;
2326
			break;
2326
	    break;
2327
		case 3:
2327
	case 3:
2328
			if (las == 2) {
2328
	    if (las == 2) {
2329
				at = at - GConvertXUnits(dd->gp.yLineBias,
2329
		at = at - GConvertXUnits(dd->gp.yLineBias,
2330
							 LINES, USER, dd);
2330
					 LINES, USER, dd);
2331
				line = line + dd->gp.yLineBias;
2331
		line = line + dd->gp.yLineBias;
2332
				a = 90.0;
2332
		a = 90.0;
2333
				xadj = 0.0;
2333
		xadj = 0.0;
2334
				yadj = 0.5;
2334
		yadj = 0.5;
2335
			}
2335
	    }
2336
			else {
2336
	    else {
2337
				line = line + dd->gp.yLineBias;
2337
		line = line + dd->gp.yLineBias;
2338
				a = 0.0;
2338
		a = 0.0;
2339
				xadj = mathDevice->gp.adj;
2339
		xadj = mathDevice->gp.adj;
2340
				yadj = 0.0;
2340
		yadj = 0.0;
2341
			}
2341
	    }
2342
			coords = MAR3;
2342
	    coords = MAR3;
2343
			break;
2343
	    break;
2344
		case 4:
2344
	case 4:
2345
			if (las == 1 || las == 2) {
2345
	    if (las == 1 || las == 2) {
2346
				at = at + GConvertYUnits(dd->gp.yLineBias,
2346
		at = at + GConvertYUnits(dd->gp.yLineBias,
2347
							 LINES, USER, dd);
2347
					 LINES, USER, dd);
2348
				line = line + dd->gp.yLineBias;
2348
		line = line + dd->gp.yLineBias;
2349
				a = 0.0;
2349
		a = 0.0;
2350
				xadj = 0.0;
2350
		xadj = 0.0;
2351
				yadj = 0.5;
2351
		yadj = 0.5;
2352
			}
2352
	    }
2353
			else {
2353
	    else {
2354
				line = line + 1 - dd->gp.yLineBias;
2354
		line = line + 1 - dd->gp.yLineBias;
2355
				a = 90.0;
2355
		a = 90.0;
2356
				xadj = mathDevice->gp.adj;
2356
		xadj = mathDevice->gp.adj;
2357
				yadj = 0.0;
2357
		yadj = 0.0;
2358
			}
2358
	    }
2359
			coords = MAR4;
2359
	    coords = MAR4;
2360
			break;
2360
	    break;
2361
		}
-
 
2362
		GMathText(at, line, coords, str, xadj, yadj, a, dd);
-
 
2363
	}
2361
	}
-
 
2362
	GMathText(at, line, coords, str, xadj, yadj, a, dd);
-
 
2363
    }
2364
}
2364
}
2365
 
2365
 
2366
#else
2366
#else
2367
 
2367
 
2368
void GMMathText(SEXP str, int side, double line, int outer, double at, int las)
2368
void GMMathText(SEXP str, int side, double line, int outer, double at, int las)
2369
{
2369
{
2370
	error("Can't print math under Windows ... yet\n");
2370
    error("Can't print math under Windows ... yet\n");
2371
}
2371
}
2372
 
2372
 
2373
void GMathText(double x, double y, SEXP expr, double xc, double yc, double rot)
2373
void GMathText(double x, double y, SEXP expr, double xc, double yc, double rot)
2374
{
2374
{
2375
	error("Can't print math under Windows ... yet\n");
2375
    error("Can't print math under Windows ... yet\n");
2376
}
2376
}
2377
#endif
2377
#endif