xref: /original-bsd/old/vfilters/rvsort/rvsort.c (revision e2b66ddc)
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.5 (Berkeley) 03/02/91";
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 
main(argc,argv)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 
ofile()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 
getch()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 
error(s)263 error(s)
264 	char *s;
265 {
266 
267 	fflush(out);
268 	fprintf(stderr, "vsort: %s\n", s);
269 }
270 
crail(nrail)271 crail(nrail)
272 	int nrail;
273 {
274 
275 	railmag = nrail;
276 	loadfont(nrail, cpsize);
277 }
278 
loadfont(fnum,size)279 loadfont(fnum, size)
280 	int fnum;
281 	int size;
282 {
283 
284 	cpsize = size;
285 	return(0);
286 }
287 
stuffc(code)288 stuffc(code)
289 	register int code;
290 {
291 	register struct achar *ap, **bp;
292 
293 	if (col < 0 || col >= 500*8)
294 		return;
295 	if (afreel) {
296 		ap = afreel;
297 		afreel = ap->next;
298 	} else
299 		ap = (struct achar *)malloc(sizeof (*ap));
300 	ap->row = row;
301 	ap->col = col;
302 	ap->psize = cpsize;
303 	ap->verd = verd;
304 	ap->back = back;
305 	ap->mcase = mcase;
306 	ap->code = code;
307 	ap->railmag = railmag;
308 	bp = &piles[col / 8];
309 	ap->next = *bp;
310 	*bp = ap;
311 }
312 
allflush()313 allflush()
314 {
315 
316 	linesflush();
317 	if (row > orow)
318 		ptlead(row - orow);
319 	row -= pagelength;
320 	orow = row;
321 }
322 
323 
linesflush()324 linesflush()
325 {
326 	register struct achar **ap, *bp, *cp;
327 	static notfirst;
328 
329 	if (notfirst)
330 		putc(0115, out);
331 	orow = 0;
332 	ocol = 0;
333 	notfirst = 1;
334 	for (ap = &piles[0]; ap < &piles[500]; ap++) {
335 		for (bp = *ap; bp; bp = cp) {
336 			sendchar(bp);
337 			cp = bp->next;
338 			bp->next = afreel;
339 			afreel = bp;
340 		}
341 		*ap = 0;
342 	}
343 }
344 
sendchar(cp)345 sendchar(cp)
346 	register struct achar *cp;
347 {
348 	register int i;
349 
350 #ifdef DUMPCHAR
351 	dumpchar(cp);
352 #endif
353 	if(cp->railmag != orailmag)
354 		ptrail(cp->railmag);
355 	if(cp->psize != opsize)
356 		ptsize(cp->psize);
357 	if(cp->mcase != omcase)
358 		ptmcase();
359 	if(cp->row != orow)
360 		ptlead(cp->row - orow);
361 	if(cp->col != ocol)
362 		ptesc(cp->col - ocol);
363 	if(cp->back != oback)
364 		ptback();
365 	putc(cp->code, out);
366 	orow = cp->row;
367 	orailmag = cp->railmag;
368 	opsize = cp->psize;
369 	omcase = cp->mcase;
370 	ocol = cp->col;
371 	oback = cp->back;
372 }
373 
ptrail(rlmg)374 ptrail(rlmg)
375 	register int rlmg;
376 {
377 
378 	if((rlmg & 01) != (orailmag & 01))
379 		putc((rlmg & 01) ? 0102:0101, out);	/*  rail  */
380 	if((rlmg & 02) != (orailmag & 02))
381 		putc((rlmg & 02) ? 0103:0104, out);	/*  mag  */
382 }
383 
ptback()384 ptback()
385 {
386 
387 	putc(oback ? 0107:0110, out);
388 	oback = !oback;
389 }
390 
ptsize(size)391 ptsize(size)
392 	register int size;
393 {
394 
395 	putc(0120 | (size & 017), out);
396 	ptesc(-stupidadj(size, opsize));
397 }
398 
stupidadj(code,lcode)399 stupidadj(code, lcode)
400 	register int code;
401 	int lcode;
402 {
403 	register struct point_sizes *psp;
404 	register struct point_sizes *lpsp;
405 
406 	psp = point_sizes;
407 	while(psp->real_code != 0) {
408 		if((psp->stupid_code & 017) == code)
409 			break;
410 		psp++;
411 	}
412 	lpsp = point_sizes;
413 	while(lpsp->real_code != 0) {
414 		if((lpsp->stupid_code & 017) == lcode)
415 			break;
416 		lpsp++;
417 	}
418 	code = 0;
419 	if(!(lpsp->stupid_code & 0200) && (psp->stupid_code & 0200))
420 		code = -55;
421 	else
422 		if((lpsp->stupid_code & 0200) && !(psp->stupid_code & 0200))
423 			code = 55;
424 	return(code);
425 }
426 
ptmcase()427 ptmcase()
428 {
429 
430 	putc(omcase ? 0105:0106, out);
431 }
432 
ptesc(escc)433 ptesc(escc)
434 	register int escc;
435 {
436 
437 	if((escc < 0 && !oback ) || (escc >= 0 && oback))
438 		ptback();
439 	escc = abs(escc);
440 	while(escc > 0177) {
441 		putc(0200, out);
442 		escc -= 0177;
443 	}
444 	if(escc)
445 		putc(0200 | ((~escc) & 0177), out);
446 }
447 
ptlead(leadd)448 ptlead(leadd)
449 	register int leadd;
450 {
451 
452 	if (leadd == 0)
453 		return;
454 	if (leadd < 0) {
455 		if (overd == 0)
456 			putc(0114, out), overd = 1;
457 		leadd = -leadd;
458 	} else {
459 		if (overd)
460 			putc(0112, out), overd = 0;
461 	}
462 	if (leadd > 64) {
463 		putc(0116, out);
464 		putc(leadd / 64, out);
465 		leadd %= 64;
466 	}
467 	while (leadd > 037) {
468 		putc(0140, out);
469 		leadd -= 037;
470 	}
471 	if (leadd)
472 		putc(0140 | ((~leadd) & 037), out);
473 }
474 
475 #ifdef DUMPLINE
dumpchar(cp)476 dumpchar(cp)
477 register struct achar *cp;
478 {
479 
480 	fprintf(stderr,
481 "code %o psize %d col %d row %d railmag %d verd %d back %d mcase %d\n",
482 	    cp->code, cp->psize, cp->col, cp->row, cp->railmag, cp->verd,
483 	    cp->back, cp->mcase);
484 }
485 #endif
486