xref: /csrg-svn/old/vfilters/vpsf/vpsf.c (revision 14667)
1 #ifndef lint
2 static char sccsid[] = "@(#)vpsf.c	4.6 (Berkeley) 08/16/83";
3 #endif
4 
5 /*
6  * Versatec printer filter
7  * 	make wide listings by placing pages side by side
8  */
9 
10 #include <stdio.h>
11 #include <sys/vcmd.h>
12 
13 #define	LINELN 440
14 #define	PAGELN  86
15 #define	LMARG   10
16 
17 int	pltmode[] = {VPLOT};
18 int	prtmode[] = {VPRINT};
19 
20 char	screen[PAGELN][LINELN];
21 char	ul[PAGELN][LINELN];
22 char	anyul[PAGELN];
23 int	origin;		/* first column of a page */
24 int	origin_ind;	/* origin plus indent */
25 int	outline;	/* current line number */
26 int	outcol;		/* current column number */
27 int	npages;
28 int	width = 106;	/* default page width */
29 int	length = 86;	/* default page length */
30 int	indent = 0;	/* default indent */
31 
32 int	literal;
33 char	*name;		/* user's login name */
34 char	*host;		/* user's machine name */
35 char	*acctfile;	/* accounting information file */
36 
37 main(argc, argv)
38 	int argc;
39 	char *argv[];
40 {
41 	register int i;
42 
43 	while (--argc) {
44 		if (*(*++argv) == '-') {
45 			switch (argv[0][1]) {
46 			case 'n':
47 				argc--;
48 				name = *++argv;
49 				break;
50 
51 			case 'h':
52 				argc--;
53 				host = *++argv;
54 				break;
55 
56 			case 'w':
57 				if ((i = atoi(&argv[0][2])) > 0 && i <= LINELN)
58 					width = i;
59 				break;
60 
61 			case 'l':
62 				if ((i = atoi(&argv[0][2])) > 0 && i <= PAGELN)
63 					length = i;
64 				break;
65 
66 			case 'i':
67 				if ((i = atoi(&argv[0][2])) >= 0 &&
68 				    i < LINELN - 1)
69 					indent = i;
70 				break;
71 
72 			case 'c':	/* Print input without throwing away
73 					   control chars and without putting
74 					   in page breaks. */
75 				literal++;
76 				break;
77 			}
78 		} else
79 			acctfile = *argv;
80 	}
81 	indent += literal ? 1 : LMARG;
82 	if (indent >= width)
83 		indent = width - 1;
84 
85 	/*
86 	 * input file is open on file descriptor 0.
87 	 * vp should be open on file descriptor 1.
88 	 * The error log file is open on file descriptor 2.
89 	 */
90 	ioctl(1, VSETSTATE, prtmode);
91 	process();
92 
93 	/*
94 	 * Put out an extra null to ensure versatec will get an even
95 	 * number of good characters.
96 	 */
97 	putchar('\0');
98 
99 	if (ferror(stdout))
100 		exit(1);
101 	if (name && acctfile && access(acctfile, 02) >= 0 &&
102 	    freopen(acctfile, "a", stdout) != NULL) {
103 		if (host)
104 			printf("%7.2f\t%s:%s\n", (float)npages, host, name);
105 		else
106 			printf("%7.2f\t%s\n", (float)npages, name);
107 	}
108 	exit(0);
109 }
110 
111 set_up()
112 {
113 	clear(screen, sizeof(screen));
114 	origin = 0;
115 	origin_ind = outcol = origin + indent;
116 	outline = 0;
117 	cutmark(origin);
118 }
119 
120 process()
121 {
122 	register int c;
123 
124 	set_up();
125 
126 	while ((c = getchar()) != EOF)
127 		switch (c) {
128 		case ' ':
129 			outcol++;
130 			break;
131 
132 		case '\t':
133 			outcol = ((outcol - origin_ind) | 07) + origin_ind + 1;
134 			break;
135 
136 		case '\b':
137 			if (outcol > origin_ind)
138 				outcol--;
139 			break;
140 
141 		case '\r':
142 			outcol = origin_ind;
143 			break;
144 
145 		case '\f':
146 			outline = length;
147 			/* fall into ... */
148 
149 		case '\n':
150 			if (++outline >= length) {
151 				origin += width + 1;
152  				origin_ind += width + 1;
153 				cutmark(origin);
154 				if (origin + width + 1 >= LINELN) {
155 					oflush();
156 					break;
157 				}
158 				outline = 0;
159 			}
160 			outcol = origin_ind;
161 			break;
162 
163 		default:
164 			outchar(c);
165 			break;
166 		}
167 
168 	if (outline || origin) {
169 		cutmark(origin + width + 1);
170 		oflush();
171 	}
172 	printf("\n\n\n\n\n");
173 }
174 
175 outchar(c)
176 	register int c;
177 {
178 	register char *cp;
179 	register int d;
180 
181 	if (!literal && (c < 040 || c >= 0177))
182 		return;
183 	if (outcol >= origin + width + 1) {
184 		outcol++;
185 		return;
186 	}
187 	cp = &screen[outline][outcol];
188 	d = *cp;
189 	if (d != ' ') {
190 		if (d == '_' || c == '_') {
191 			if (c == d) {
192 				outcol++;
193 				return;
194 			}
195 			if (anyul[outline] == 0)
196 				clear(ul[outline], LINELN);
197 			anyul[outline] = 1;
198 			ul[outline][outcol] = 0377;
199 			if (c == '_')
200 				c = d;
201 		}
202 	}
203 	*cp = c;
204 	outcol++;
205 }
206 
207 oflush()
208 {
209 	register char *cp, *dp;
210 	register int i, j, oc, dc, c;
211 
212 	npages++;
213 	putchar('\n');
214 	for (i = 0; i < length; i++)
215 		putline(i);
216 	for (i = 0; i < LINELN; i++)
217 		putchar('_');
218 	putchar('\n');
219 
220 	set_up();
221 }
222 
223 clear(cp, i)
224 	register char *cp;
225 	register int i;
226 {
227 	if (i > 0)
228 		do
229 			*cp++ = ' ';
230 		while (--i);
231 }
232 
233 cutmark(o)
234 	register int o;
235 {
236 	register int i;
237 
238 	screen[0][o] = '|';
239 	screen[1][o] = '|';
240 	screen[length - 1][o] = '|';
241 	screen[length - 2][o] = '|';
242 }
243 
244 putline(n)
245 	register int n;
246 {
247 	register char *cp;
248 	register int j;
249 
250 	fwrite(screen[n], sizeof(char), sizeof(screen[0]), stdout);
251 	if (anyul[n]) {
252 		putchar('\n');
253 		putchar('\0');
254 		fflush(stdout);
255 		ioctl(1, VSETSTATE, pltmode);
256 		cp = ul[n];
257 		j = LINELN;
258 		do {
259 			putchar(*cp & 0377);
260 			putchar(*cp++ & 0377);
261 		} while (--j);
262 		fflush(stdout);
263 		ioctl(1, VSETSTATE, prtmode);
264 	} else
265 		putchar('\n');
266 	if (ferror(stdout))
267 		exit(1);
268 }
269