xref: /original-bsd/old/vfilters/rvsort/rvsort.c (revision 5e36add1)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)rvsort.c	5.4 (Berkeley) 06/01/90";
16 #endif /* not lint */
17 
18 /*
19  * Sort troff output for versatec to reduce amount of reverse leading
20  */
21 
22 # include <stdio.h>
23 
24 #define NULL 0
25 
26 double atof();
27 char *calloc();
28 
29 FILE *in,*out;
30 
31 struct achar *piles[500], *afreel;
32 
33 int skipfirst = 1;	/* skip the first leading so start at top of page */
34 int cpsize = 02;	/*  Funny sizes  */
35 struct point_sizes {
36 	int stupid_code;
37 	int real_code;
38 } point_sizes[] = {
39 	010, 6,
40 	0, 7,
41 	01, 8,
42 	07, 9,
43 	02, 10,
44 	03, 11,
45 	04, 12,
46 	05, 14,
47 	0211, 16,
48 	06, 18,
49 	0212, 20,
50 	0213, 22,
51 	0214, 24,
52 	0215, 28,
53 	0216, 36,
54 	0, 0
55 };
56 
57 int	pagelength = 144 * 11;	/* in Leading units */
58 int	pagemod;		/* horizontal page number (for versatec) */
59 #define	MODOFF 3672		/* 432 * 8.5 */
60 
61 int	esc, lead, back, verd, mcase, railmag;
62 int	col, row;
63 
64 int	oback, omcase, orailmag, ocol, orow, overd;
65 int	opsize = 02;
66 
67 struct	achar
68 {
69 	char	code;
70 	char	psize;
71 	short	col;
72 	short	row;
73 	char	railmag;
74 	char	verd;
75 	char	back;
76 	char	mcase;
77 	struct	achar *next;
78 };
79 
80 main(argc, argv)
81 	int argc;
82 	char *argv[];
83 {
84 	register i;
85 
86 	for(i = 3; i < 15; i++)
87 		close(i);
88 	while (argc > 1 && argv[1][0] == '-') {
89 		switch (argv[1][1]) {
90 			case 'l': {
91 				float f = 144 * atof(argv[1] + 2);
92 				if (f < 144) {
93 					error("bad length");
94 					exit(1);
95 				}
96 				pagelength = f;
97 				break;
98 			}
99 		}
100 		argc--; argv++;
101 	}
102 	out = stdout;
103 	if(argc > 1) {
104 		while(--argc) {
105 			argv++;
106 			if((in=fopen(argv[0], "r")) == NULL)
107 				perror("vsort");
108 			else {
109 				ofile();
110 				fclose(in);
111 			}
112 		}
113 	} else {
114 		in = stdin;
115 		ofile();
116 	}
117 	exit(0);
118 }
119 
120 ofile()
121 {
122 	register int c;
123 	static int initialized;
124 
125 	while((c = getch()) != -1) {
126 		if(!c)
127 			continue;
128 		if(c & 0200) {		/* escape (left/right) */
129 			esc += (~c) & 0177;
130 			continue;
131 		}
132 		if(esc) {
133 			if(back)
134 				esc = -esc;
135 			col += esc;
136 			esc = 0;
137 		}
138 		if((c & 0377) < 0100)	/*  Purely for efficiency  */
139 			goto normal_char;
140 		switch(c) {
141 
142 		case 0100:
143 			if(initialized++) {
144 				linesflush();
145 				return;
146 			}
147 			row = 0;
148 			col = 0;	esc = 0;
149 			lead = 0;
150 			verd = 0;	back = 0;	mcase = 0;
151 			railmag = 0;
152 			ocol = 0;
153 			orow = 0;
154 			oback = 0;	omcase = 0;
155 			orailmag = 0;
156 			if(loadfont(railmag, cpsize) < 0)
157 				error("init");
158 			putc(0100, out);
159 			break;
160 
161 		case 0101:	/* lower rail */
162 			crail(railmag &= ~01);
163 			break;
164 
165 		case 0102:	/* upper rail */
166 			crail(railmag |= 01);
167 			break;
168 
169 		case 0103:	/* upper mag */
170 			crail(railmag |= 02);
171 			break;
172 
173 		case 0104:	/* lower mag */
174 			crail(railmag &= ~02);
175 			break;
176 
177 		case 0105:	/* lower case */
178 			mcase = 0;
179 			break;
180 
181 		case 0106:	/* upper case */
182 			mcase = 1;
183 			break;
184 
185 		case 0107:	/* escape forward */
186 			back = 0;
187 			break;
188 
189 		case 0110:	/* escape backwards */
190 			back = 1;
191 			break;
192 
193 		case 0111:	/* stop */
194 			break;
195 
196 		case 0112:	/* lead forward */
197 			verd = 0;
198 			break;
199 
200 		case 0113:	/* undefined */
201 			break;
202 
203 		case 0114:	/* lead backward */
204 			verd = 1;
205 			break;
206 
207 		case 0115:	/* undefined */
208 		case 0116:
209 		case 0117:
210 			break;
211 
212 		default:
213 			if((c & 0340) == 0140) {/* leading */
214 				lead = (~c) & 037;
215 				if(verd)
216 					lead = -lead;
217 				if (skipfirst > 0) {
218 					skipfirst--;
219 					continue;
220 				}
221 				row += lead;
222 				if (row >= pagelength)
223 					allflush();
224 				continue;
225 			}
226 			if((c & 0360)== 0120) {	/* size change */
227 				col += stupidadj(c & 017, cpsize);
228 				loadfont(railmag, c & 017);
229 				continue;
230 			}
231 			if(c & 0300)
232 				continue;
233 		normal_char:
234 			c = (c & 077);
235 			stuffc(c);
236 		}
237 	}
238 	linesflush();
239 	putc(0111, out);
240 	putc(0111, out);
241 	putc(0111, out);
242 	putc(0111, out);
243 	putc(0111, out);
244 	putc(0111, out);
245 	putc(0111, out);
246 	putc(0111, out);
247 }
248 
249 int	peekc;
250 
251 getch()
252 {
253 	register c;
254 
255 	if(peekc) {
256 		c = peekc;
257 		peekc = 0;
258 		return(c);
259 	}
260 	return(getc(in));
261 }
262 
263 ungetc(c)
264 {
265 	peekc = c;
266 }
267 
268 error(s)
269 	char *s;
270 {
271 
272 	fflush(out);
273 	fprintf(stderr, "vsort: %s\n", s);
274 }
275 
276 crail(nrail)
277 	int nrail;
278 {
279 
280 	railmag = nrail;
281 	loadfont(nrail, cpsize);
282 }
283 
284 loadfont(fnum, size)
285 	int fnum;
286 	int size;
287 {
288 
289 	cpsize = size;
290 	return(0);
291 }
292 
293 stuffc(code)
294 	register int code;
295 {
296 	register struct achar *ap, **bp;
297 
298 	if (col < 0 || col >= 500*8)
299 		return;
300 	if (afreel) {
301 		ap = afreel;
302 		afreel = ap->next;
303 	} else
304 		ap = (struct achar *)malloc(sizeof (*ap));
305 	ap->row = row;
306 	ap->col = col;
307 	ap->psize = cpsize;
308 	ap->verd = verd;
309 	ap->back = back;
310 	ap->mcase = mcase;
311 	ap->code = code;
312 	ap->railmag = railmag;
313 	bp = &piles[col / 8];
314 	ap->next = *bp;
315 	*bp = ap;
316 }
317 
318 allflush()
319 {
320 
321 	linesflush();
322 	if (row > orow)
323 		ptlead(row - orow);
324 	row -= pagelength;
325 	orow = row;
326 }
327 
328 
329 linesflush()
330 {
331 	register struct achar **ap, *bp, *cp;
332 	static notfirst;
333 
334 	if (notfirst)
335 		putc(0115, out);
336 	orow = 0;
337 	ocol = 0;
338 	notfirst = 1;
339 	for (ap = &piles[0]; ap < &piles[500]; ap++) {
340 		for (bp = *ap; bp; bp = cp) {
341 			sendchar(bp);
342 			cp = bp->next;
343 			bp->next = afreel;
344 			afreel = bp;
345 		}
346 		*ap = 0;
347 	}
348 }
349 
350 sendchar(cp)
351 	register struct achar *cp;
352 {
353 	register int i;
354 
355 #ifdef DUMPCHAR
356 	dumpchar(cp);
357 #endif
358 	if(cp->railmag != orailmag)
359 		ptrail(cp->railmag);
360 	if(cp->psize != opsize)
361 		ptsize(cp->psize);
362 	if(cp->mcase != omcase)
363 		ptmcase();
364 	if(cp->row != orow)
365 		ptlead(cp->row - orow);
366 	if(cp->col != ocol)
367 		ptesc(cp->col - ocol);
368 	if(cp->back != oback)
369 		ptback();
370 	putc(cp->code, out);
371 	orow = cp->row;
372 	orailmag = cp->railmag;
373 	opsize = cp->psize;
374 	omcase = cp->mcase;
375 	ocol = cp->col;
376 	oback = cp->back;
377 }
378 
379 ptrail(rlmg)
380 	register int rlmg;
381 {
382 
383 	if((rlmg & 01) != (orailmag & 01))
384 		putc((rlmg & 01) ? 0102:0101, out);	/*  rail  */
385 	if((rlmg & 02) != (orailmag & 02))
386 		putc((rlmg & 02) ? 0103:0104, out);	/*  mag  */
387 }
388 
389 ptback()
390 {
391 
392 	putc(oback ? 0107:0110, out);
393 	oback = !oback;
394 }
395 
396 ptsize(size)
397 	register int size;
398 {
399 
400 	putc(0120 | (size & 017), out);
401 	ptesc(-stupidadj(size, opsize));
402 }
403 
404 stupidadj(code, lcode)
405 	register int code;
406 	int lcode;
407 {
408 	register struct point_sizes *psp;
409 	register struct point_sizes *lpsp;
410 
411 	psp = point_sizes;
412 	while(psp->real_code != 0) {
413 		if((psp->stupid_code & 017) == code)
414 			break;
415 		psp++;
416 	}
417 	lpsp = point_sizes;
418 	while(lpsp->real_code != 0) {
419 		if((lpsp->stupid_code & 017) == lcode)
420 			break;
421 		lpsp++;
422 	}
423 	code = 0;
424 	if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200))
425 		code = -55;
426 	else
427 		if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200))
428 			code = 55;
429 	return(code);
430 }
431 
432 ptmcase()
433 {
434 
435 	putc(omcase ? 0105:0106, out);
436 }
437 
438 ptesc(escc)
439 	register int escc;
440 {
441 
442 	if((escc < 0 && !oback ) || (escc >= 0 && oback))
443 		ptback();
444 	escc = abs(escc);
445 	while(escc > 0177) {
446 		putc(0200, out);
447 		escc -= 0177;
448 	}
449 	if(escc)
450 		putc(0200 | ((~escc) & 0177), out);
451 }
452 
453 ptlead(leadd)
454 	register int leadd;
455 {
456 
457 	if (leadd == 0)
458 		return;
459 	if (leadd < 0) {
460 		if (overd == 0)
461 			putc(0114, out), overd = 1;
462 		leadd = -leadd;
463 	} else {
464 		if (overd)
465 			putc(0112, out), overd = 0;
466 	}
467 	if (leadd > 64) {
468 		putc(0116, out);
469 		putc(leadd / 64, out);
470 		leadd %= 64;
471 	}
472 	while (leadd > 037) {
473 		putc(0140, out);
474 		leadd -= 037;
475 	}
476 	if (leadd)
477 		putc(0140 | ((~leadd) & 037), out);
478 }
479 
480 #ifdef DUMPLINE
481 dumpchar(cp)
482 register struct achar *cp;
483 {
484 
485 	fprintf(stderr,
486 "code %o psize %d col %d row %d railmag %d verd %d back %d mcase %d\n",
487 	    cp->code, cp->psize, cp->col, cp->row, cp->railmag, cp->verd,
488 	    cp->back, cp->mcase);
489 }
490 #endif
491