Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/proof/htroff.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	<u.h>
2
#include	<libc.h>
3
#include	<draw.h>
4
#include	<cursor.h>
5
#include	<event.h>
6
#include	<bio.h>
7
#include	"proof.h"
8
 
9
int	res;
10
int	hpos;
11
int	vpos;
12
int	DIV = 11;
13
 
14
Point offset;
15
Point xyoffset = { 0,0 };
16
 
17
Rectangle	view[MAXVIEW];
18
Rectangle	bound[MAXVIEW];		/* extreme points */
19
int	nview = 1;
20
 
21
int	lastp;	/* last page number we were on */
22
 
23
#define	NPAGENUMS	200
24
struct pagenum {
25
	int	num;
26
	long	adr;
27
} pagenums[NPAGENUMS];
28
int	npagenums;
29
 
30
int	curfont, cursize;
31
 
32
char	*getcmdstr(void);
33
 
34
static void	initpage(void);
35
static void	view_setup(int);
36
static Point	scale(Point);
37
static void	clearview(Rectangle);
38
static int	addpage(int);
39
static void	spline(Image *, int, Point *);
40
static int	skipto(int, int);
41
static void	wiggly(int);
42
static void	devcntrl(void);
43
static void	eatline(void);
44
static int	getn(void);
45
static int	botpage(int);
46
static void	getstr(char *);
47
static void	getutf(char *);
48
 
49
#define Do screen->r.min
50
#define Dc screen->r.max
51
 
52
/* declarations and definitions of font stuff are in font.c and main.c */
53
 
54
static void
55
initpage(void)
56
{
57
	int i;
58
 
59
	view_setup(nview);
60
	for (i = 0; i < nview-1; i++)
61
		draw(screen, view[i], screen, nil, view[i+1].min);
62
	clearview(view[nview-1]);
63
	offset = view[nview-1].min;
64
	vpos = 0;
65
}
66
 
67
static void
68
view_setup(int n)
69
{
70
	int i, j, v, dx, dy, r, c;
71
 
72
	switch (n) {
73
	case 1: r = 1; c = 1; break;
74
	case 2: r = 1; c = 2; break;
75
	case 3: r = 1; c = 3; break;
76
	case 4: r = 2; c = 2; break;
77
	case 5: case 6: r = 2; c = 3; break;
78
	case 7: case 8: case 9: r = 3; c = 3; break;
79
	default: r = (n+2)/3; c = 3; break; /* finking out */
80
	}
81
	dx = (Dc.x - Do.x) / c;
82
	dy = (Dc.y - Do.y) / r;
83
	v = 0;
84
	for (i = 0; i < r && v < n; i++)
85
		for (j = 0; j < c && v < n; j++) {
86
			view[v] = screen->r;
87
			view[v].min.x = Do.x + j * dx;
88
			view[v].max.x = Do.x + (j+1) * dx;
89
			view[v].min.y = Do.y + i * dy;
90
			view[v].max.y = Do.y + (i+1) * dy;
91
			v++;
92
		}
93
}
94
 
95
static void
96
clearview(Rectangle r)
97
{
98
	draw(screen, r, display->white, nil, r.min);
99
}
100
 
101
int resized;
102
void eresized(int new)
103
{
104
	/* this is called if we are resized */
105
	if(new && getwindow(display, Refnone) < 0)
106
		drawerror(display, "can't reattach to window");
107
	initpage();
108
	resized = 1;
109
}
110
 
111
static Point
112
scale(Point p)
113
{
114
	p.x /= DIV;
115
	p.y /= DIV;
116
	return addpt(xyoffset, addpt(offset,p));
117
}
118
 
119
static int
120
addpage(int n)
121
{
122
	int i;
123
 
124
	for (i = 0; i < npagenums; i++)
125
		if (n == pagenums[i].num)
126
			return i;
127
	if (npagenums < NPAGENUMS-1) {
128
		pagenums[npagenums].num = n;
129
		pagenums[npagenums].adr = offsetc();
130
		npagenums++;
131
	}
132
	return npagenums;
133
}
134
 
135
void
136
readpage(void)
137
{
138
	int c, i, a, alpha, phi;
139
	static int first = 0;
140
	int m, n, gonow = 1;
141
	Rune r[32], t;
142
	Point p,q,qq;
143
 
144
	offset = screen->clipr.min;
145
	esetcursor(&deadmouse);
146
	while (gonow)
147
	{
148
		c = getc();
149
		switch (c)
150
		{
151
		case -1:
152
			esetcursor(0);
153
			if (botpage(lastp+1)) {
154
				initpage();
155
				break;
156
			}
157
			exits(0);
158
		case 'p':	/* new page */
159
			lastp = getn();
160
			addpage(lastp);
161
			if (first++ > 0) {
162
				esetcursor(0);
163
				botpage(lastp);
164
				esetcursor(&deadmouse);
165
			}
166
			initpage();
167
			break;
168
		case '\n':	/* when input is text */
169
		case ' ':
170
		case 0:		/* occasional noise creeps in */
171
			break;
172
		case '0': case '1': case '2': case '3': case '4':
173
		case '5': case '6': case '7': case '8': case '9':
174
			/* two motion digits plus a character */
175
			hpos += (c-'0')*10 + getc()-'0';
176
 
177
		/* FALLS THROUGH */
178
		case 'c':	/* single ascii character */
179
			r[0] = getrune();
180
			r[1] = 0;
181
			dochar(r);
182
			break;
183
 
184
		case 'C':
185
			for(i=0; ; i++){
186
				t = getrune();
187
				if(isspace(t))
188
					break;
189
				r[i] = t;
190
			}
191
			r[i] = 0;
192
			dochar(r);
193
			break;
194
 
195
		case 'N':
196
			r[0] = getn();
197
			r[1] = 0;
198
			dochar(r);
199
			break;
200
 
201
		case 'D':	/* draw function */
202
			switch (getc())
203
			{
204
			case 'l':	/* draw a line */
205
				n = getn();
206
				m = getn();
207
				p = Pt(hpos,vpos);
208
				q = addpt(p, Pt(n,m));
209
				hpos += n;
210
				vpos += m;
211
				line(screen, scale(p), scale(q), 0, 0, 0, display->black, ZP);
212
				break;
213
			case 'c':	/* circle */
214
				/*nop*/
215
				m = getn()/2;
216
				p = Pt(hpos+m,vpos);
217
				hpos += 2*m;
218
				ellipse(screen, scale(p), m/DIV, m/DIV, 0, display->black, ZP);
219
				/* p=currentpt; p.x+=dmap(m/2);circle bp,p,a,ONES,Mode*/
220
				break;
221
			case 'e':	/* ellipse */
222
				/*nop*/
223
				m = getn()/2;
224
				n = getn()/2;
225
				p = Pt(hpos+m,vpos);
226
				hpos += 2*m;
227
				ellipse(screen, scale(p), m/DIV, n/DIV, 0, display->black, ZP);
228
				break;
229
			case 'a':	/* arc */
230
				p = scale(Pt(hpos,vpos));
231
				n = getn();
232
				m = getn();
233
				hpos += n;
234
				vpos += m;
235
				q = scale(Pt(hpos,vpos));
236
				n = getn();
237
				m = getn();
238
				hpos += n;
239
				vpos += m;
240
				qq = scale(Pt(hpos,vpos));
241
				/*
242
				  * tricky: convert from 3-point clockwise to
243
				  * center, angle1, delta-angle counterclockwise.
244
				 */
245
				a = hypot(qq.x-q.x, qq.y-q.y);
246
				phi = atan2(q.y-p.y, p.x-q.x)*180./PI;
247
				alpha = atan2(q.y-qq.y, qq.x-q.x)*180./PI - phi;
248
				if(alpha < 0)
249
					alpha += 360;
250
				arc(screen, q, a, a, 0, display->black, ZP, phi, alpha);
251
				break;
252
			case '~':	/* wiggly line */
253
				wiggly(0);
254
				break;
255
			default:
256
				break;
257
			}
258
			eatline();
259
			break;
260
		case 's':
261
			n = getn();	/* ignore fractional sizes */
262
			if (cursize == n)
263
				break;
264
			cursize = n;
265
			if (cursize >= NFONT)
266
				cursize = NFONT-1;
267
			break;
268
		case 'f':
269
			curfont = getn();
270
			break;
271
		case 'H':	/* absolute horizontal motion */
272
			hpos = getn();
273
			break;
274
		case 'h':	/* relative horizontal motion */
275
			hpos += getn();
276
			break;
277
		case 'w':	/* word space */
278
			break;
279
		case 'V':
280
			vpos = getn();
281
			break;
282
		case 'v':
283
			vpos += getn();
284
			break;
285
		case '#':	/* comment */
286
		case 'n':	/* end of line */
287
			eatline();
288
			break;
289
		case 'x':	/* device control */
290
			devcntrl();
291
			break;
292
		default:
293
			fprint(2, "unknown input character %o %c at offset %lud\n", c, c, offsetc());
294
			exits("bad char");
295
		}
296
	}
297
	esetcursor(0);
298
}
299
 
300
static void
301
spline(Image *b, int n, Point *pp)
302
{
303
	long w, t1, t2, t3, fac=1000; 
304
	int i, j, steps=10; 
305
	Point p, q;
306
 
307
	for (i = n; i > 0; i--)
308
		pp[i] = pp[i-1];
309
	pp[n+1] = pp[n];
310
	n += 2;
311
	p = pp[0];
312
	for(i = 0; i < n-2; i++)
313
	{
314
		for(j = 0; j < steps; j++)
315
		{
316
			w = fac * j / steps;
317
			t1 = w * w / (2 * fac);
318
			w = w - fac/2;
319
			t2 = 3*fac/4 - w * w / fac;
320
			w = w - fac/2;
321
			t3 = w * w / (2*fac);
322
			q.x = (t1*pp[i+2].x + t2*pp[i+1].x + 
323
				t3*pp[i].x + fac/2) / fac;
324
			q.y = (t1*pp[i+2].y + t2*pp[i+1].y + 
325
				t3*pp[i].y + fac/2) / fac;
326
			line(b, p, q, 0, 0, 0, display->black, ZP);
327
			p = q;
328
		}
329
	}
330
}
331
 
332
/* Have to parse skipped pages, to find out what fonts are loaded. */
333
static int
334
skipto(int gotop, int curp)
335
{
336
	char *p;
337
	int i;
338
 
339
	if (gotop == curp)
340
		return 1;
341
	for (i = 0; i < npagenums; i++)
342
		if (pagenums[i].num == gotop) {
343
			if (seekc(pagenums[i].adr) == Beof) {
344
				fprint(2, "can't rewind input\n");
345
				return 0;
346
			}
347
			return 1;
348
		}
349
	if (gotop <= curp) {
350
	    restart:
351
		if (seekc(0) == Beof) {
352
			fprint(2, "can't rewind input\n");
353
			return 0;
354
		}
355
	}
356
	for(;;){
357
		p = rdlinec();
358
		if (p == 0) {
359
			if(gotop>curp){
360
				gotop = curp;
361
				goto restart;
362
			}
363
			return 0;
364
		} else if (*p == 'p') {
365
			lastp = curp = atoi(p+1);
366
			addpage(lastp);	/* maybe 1 too high */
367
			if (curp>=gotop)
368
				return 1;
369
		}
370
	}
371
}
372
 
373
static void
374
wiggly(int skip)
375
{
376
	Point p[300];
377
	int c,i,n;
378
	for (n = 1; (c = getc()) != '\n' && c>=0; n++) {
379
		ungetc();
380
		p[n].x = getn();
381
		p[n].y = getn();
382
	}
383
	p[0] = Pt(hpos, vpos);
384
	for (i = 1; i < n; i++)
385
		p[i] = addpt(p[i],p[i-1]);
386
	hpos = p[n-1].x;
387
	vpos = p[n-1].y;
388
	for (i = 0; i < n; i++)
389
		p[i] = scale(p[i]);
390
	if (!skip)
391
		spline(screen,n,p);
392
}
393
 
394
static void
395
devcntrl(void)	/* interpret device control functions */
396
{
397
        char str[80];
398
	int n;
399
 
400
	getstr(str);
401
	switch (str[0]) {	/* crude for now */
402
	case 'i':	/* initialize */
403
		break;
404
	case 'T':	/* device name */
405
		getstr(devname);
406
		break;
407
	case 't':	/* trailer */
408
		break;
409
	case 'p':	/* pause -- can restart */
410
		break;
411
	case 's':	/* stop */
412
		break;
413
	case 'r':	/* resolution assumed when prepared */
414
		res=getn();
415
		DIV = floor(.5 + res/(100.0*mag));
416
		if (DIV < 1)
417
			DIV = 1;
418
		mag = res/(100.0*DIV); /* adjust mag according to DIV coarseness */
419
		break;
420
	case 'f':	/* font used */
421
		n = getn();
422
		getstr(str);
423
		loadfontname(n, str);
424
		break;
425
	/* these don't belong here... */
426
	case 'H':	/* char height */
427
		break;
428
	case 'S':	/* slant */
429
		break;
430
	case 'X':
431
		break;
432
	}
433
	eatline();
434
}
435
 
436
int
437
isspace(int c)
438
{
439
	return c==' ' || c=='\t' || c=='\n';
440
}
441
 
442
static void
443
getstr(char *is)
444
{
445
	uchar *s = (uchar *) is;
446
 
447
	for (*s = getc(); isspace(*s); *s = getc())
448
		;
449
	for (; !isspace(*s); *++s = getc())
450
		;
451
	ungetc();
452
	*s = 0;
453
}
454
 
455
static void
456
getutf(char *s)		/* get next utf char, as bytes */
457
{
458
	int c, i;
459
 
460
	for (i=0;;) {
461
		c = getc();
462
		if (c < 0)
463
			return;
464
		s[i++] = c;
465
 
466
		if (fullrune(s, i)) {
467
			s[i] = 0;
468
			return;
469
		}
470
	}
471
}
472
 
473
static void
474
eatline(void)
475
{
476
	int c;
477
 
478
	while ((c=getc()) != '\n' && c >= 0)
479
		;
480
}
481
 
482
static int
483
getn(void)
484
{
485
	int n, c, sign;
486
 
487
	while (c = getc())
488
		if (!isspace(c))
489
			break;
490
	if(c == '-'){
491
		sign = -1;
492
		c = getc();
493
	}else
494
		sign = 1;
495
	for (n = 0; '0'<=c && c<='9'; c = getc())
496
		n = n*10 + c - '0';
497
	while (c == ' ')
498
		c = getc();
499
	ungetc();
500
	return(n*sign);
501
}
502
 
503
static int
504
botpage(int np)	/* called at bottom of page np-1 == top of page np */
505
{
506
	char *p;
507
	int n;
508
 
509
	while (p = getcmdstr()) {
510
		if (*p == '\0')
511
			return 0;
512
		if (*p == 'q')
513
			exits(p);
514
		if (*p == 'c')		/* nop */
515
			continue;
516
		if (*p == 'm') {
517
			mag = atof(p+1);
518
			if (mag <= .1 || mag >= 10)
519
				mag = DEFMAG;
520
			allfree();	/* zap fonts */
521
			DIV = floor(.5 + res/(100.0*mag));
522
			if (DIV < 1)
523
				DIV = 1;
524
			mag = res/(100.0*DIV);
525
			return skipto(np-1, np);	/* reprint the page */
526
		}
527
		if (*p == 'x') {
528
			xyoffset.x += atoi(p+1)*100;
529
			skipto(np-1, np);
530
			return 1;
531
		}
532
		if (*p == 'y') {
533
			xyoffset.y += atoi(p+1)*100;
534
			skipto(np-1, np);
535
			return 1;
536
		}
537
		if (*p == '/') {	/* divide into n pieces */
538
			nview = atoi(p+1);
539
			if (nview < 1)
540
				nview = 1;
541
			else if (nview > MAXVIEW)
542
				nview = MAXVIEW;
543
			return skipto(np-1, np);
544
		}
545
		if (*p == 'p') {
546
			if (p[1] == '\0'){	/* bare 'p' */
547
				if(skipto(np-1, np))
548
					return 1;
549
				continue;
550
			}
551
			p++;
552
		}
553
		if ('0'<=*p && *p<='9') {
554
			n = atoi(p);
555
			if(skipto(n, np))
556
				return 1;
557
			continue;
558
		}
559
		if (*p == '-' || *p == '+') {
560
			n = atoi(p);
561
			if (n == 0)
562
				n = *p == '-' ? -1 : 1;
563
			if(skipto(np - 1 + n, np))
564
				return 1;
565
			continue;
566
		}
567
		if (*p == 'd') {
568
			dbg = 1 - dbg;
569
			continue;
570
		}
571
 
572
		fprint(2, "illegal;  try q, 17, +2, -1, p, m.7, /2, x1, y-.5 or return\n");
573
	}
574
	return 0;
575
}