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