Skip to content
Newer
Older
100644 352 lines (311 sloc) 8.16 KB
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
1 /* lp.c */
2 /* Copyright 1995 by Steve Kirkendall */
3
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
4 char id_lp[] = "$Id: lp.c,v 2.28 1997/11/02 18:54:45 steve Exp $";
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
5
6 /* This file contains generic printing code. */
7
8 #include "elvis.h"
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
9 #ifdef FEATURE_LPR
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
10
11 #if USE_PROTOTYPES
12 static LPTYPE *findtype(char *name);
13 #if defined (GUI_WIN32)
14 static void dummyprt(_CHAR_ ch);
15 #endif
16 static void prtchar(_CHAR_ ch);
17 static void draw(CHAR *p, long qty, _char_ font, long offset);
18 #endif
19
20
21 /* This is a list of all known printer types. The first one is the default. */
22 static LPTYPE *alltypes[] = {&lpepson, &lppana, &lpibm, &lphp, &lpdumb, &lpcr, &lpbs, &lpps, &lpps2,
23 #if defined (GUI_WIN32)
24 &lpwindows,
25 #endif
26 };
27 static LPTYPE *type; /* type of printer being used at the moment */
28
29 /* Page formatting variables */
30 static int pagenum; /* page number withing this printing */
31 static int linesleft; /* number of usable lines left on this page */
32 static int column; /* column number, used to implement wrapping */
33 static WINDOW prwin; /* window doing the printing */
34 static BOOLEAN anytext; /* False if blank page, True if any text */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
35 static long lnum; /* line number of current line */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
36
37 /* Output buffering variables */
38 static CHAR *iobuf; /* pointer to the I/O buffer */
39 static int iomax; /* number of CHARS that the iobuf can hold */
40 static int ionext; /* number of CHARS currently in iobuf */
41
42 /* This function converts a type name to an LPTYPE pointer. Returns NULL if
43 * unsuccessful. If the name is NULL, it returns the default LPTYPE.
44 */
45 static LPTYPE *findtype(name)
46 char *name; /* name of printer type */
47 {
48 int i;
49
50 /* if name is NULL, return the default type */
51 if (name == NULL)
52 {
53 return alltypes[0];
54 }
55
56 /* search for the name in the list */
57 for (i = 0; i < QTY(alltypes); i++)
58 {
59 if (!strcmp(name, alltypes[i]->name))
60 {
61 return alltypes[i];
62 }
63 }
64
65 /* failed */
66 return NULL;
67 }
68
69 #if defined (GUI_WIN32)
70 static void dummyprt(ch)
71 _CHAR_ ch; /* character to be sent to printer */
72 {
73 }
74 #endif
75 /* This function copies a single character to the printer (or file).
76 * Internally, is uses a large I/O buffer for the sake of efficiency.
77 */
78 static void prtchar(ch)
79 _CHAR_ ch; /* character to be sent to printer */
80 {
81 assert(ionext >= 0 && ionext < iomax);
82 iobuf[ionext++] = ch;
83 if (ionext == iomax)
84 {
85 iowrite(iobuf, ionext);
86 ionext = 0;
87 }
88 }
89
90 /* This function takes a single character from the mode's image() function
91 * and passes it to the LP driver. This function also performs newline
92 * conversion, line wrapping/clipping, and page breaks.
93 */
94 static void draw(p, qty, font, offset)
95 CHAR *p; /* character to be output */
96 long qty; /* number of characters to be output */
97 _char_ font; /* font of character */
98 long offset; /* buffer offset of ch, or -1 if not from buffer */
99 {
100 WINDOW win;
101 long delta;
102 CHAR ch;
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
103 char lnumstr[20];
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
104
105 /* A negative qty indicates that the character *p is to be repeated.
106 */
107 if (qty < 0)
108 {
109 delta = 0;
110 qty = -qty;
111 }
112 else
113 {
114 delta = 1;
115 }
116
117 for ( ; qty > 0; qty--, p += delta)
118 {
119 ch = *p;
120
121 /* VTAB is treated either as a '\f', or as two '\n's */
122 if (ch == '\013' || (o_lplines == 0 && ch == '\f'))
123 {
124 if (o_lplines == 0 || linesleft >= 5)
125 {
126 ch = '\n';
127 draw(&ch, 1L, font, offset);
128 }
129 else
130 {
131 ch = '\f';
132 }
133 }
134
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
135 /* maybe output a line number */
136 if (column == 0 /* at start of line */
137 && o_lpnumber /* "lpnumber" option is set */
138 && offset >= -1 /* not doing header or line number */
139 && ch != '\f') /* character isn't formfeed */
140 {
141 /* output a line number */
142 sprintf(lnumstr, "%6ld ", lnum);
143 draw(toCHAR(lnumstr), 8, 'n', -2L);
144 }
145
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
146 /* if line is too long, then wrap it or clip it */
147 if (o_lpcolumns > 0 && column >= o_lpcolumns && ch != '\f' && ch != '\n')
148 {
149 /* if we're supposed to clip, then just ignore this char */
150 if (!o_lpwrap)
151 {
152 continue;
153 }
154
155 /* else insert a newline */
156 if (o_lpcrlf)
157 {
158 (*type->fontch)(font, '\r');
159 }
160 (*type->fontch)(font, '\n');
161
162 /* that newline has the side-effects of incrementing the line
163 * number and resetting the column number.
164 */
165 linesleft--;
166 column = 0;
167 }
168
169 /* FF is treated specially, below */
170 if (ch != '\f')
171 {
172 /* maybe convert newline to CR-LF */
173 if (ch == '\n' && o_lpcrlf)
174 {
175 (*type->fontch)(font, '\r');
176 }
177
178 /* pass the character to the LP driver */
179 (*type->fontch)(font, ch);
180
181 /* if the character was newline, then decrement the number of
182 * lines left on this page, and reset the column to 0.
183 */
184 if (ch == '\n')
185 {
186 linesleft--;
187 column = 0;
188 }
189 else /* must have been a normal printable character */
190 {
191 column++;
192 anytext = True;
193 }
194 }
195
196 if ((ch == '\f' && anytext) || (o_lplines > 0 && linesleft <= 1))
197 {
198 /* End the line, if it has any characters in it */
199 if (column > 0)
200 {
201 (*type->fontch)('n', '\n');
202 column = 0;
203 linesleft--;
204 }
205
206 /* End this page */
207 (*type->page)(linesleft);
208 linesleft = o_lplines;
209
210 /* Start the next page by calling the mode's header() function.
211 * This can cause this draw() function to be called recursively.
212 * If the header is larger than the page size, we could
213 * potentially get stuck in a loop. To avoid this, we will
214 * temporarily set prwin to NULL.
215 */
216 pagenum++;
217 if (prwin && prwin->md->header)
218 {
219 win = prwin;
220 prwin = NULL;
221 (*win->md->header)(win, pagenum, win->mi, draw);
222 prwin = win;
223 }
224 anytext = False;
225 }
226 }
227 }
228
229 /* This function performs printing. */
230 RESULT lp(win, top, bottom, force)
231 WINDOW win; /* window where print request was generated */
232 MARK top; /* start of text to be printed */
233 MARK bottom; /* end of text to be printed */
234 BOOLEAN force; /* allow an existing file to be clobbered? */
235 {
236 long oldcurs;
237 MARK next;
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
238 CHAR *origdisplay = NULL;
239 char *out;
240 char rwa;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
241
242 /* convert the value of o_lptype to an LPTYPE pointer */
243 type = findtype(tochar8(o_lptype));
244 if (!type)
245 {
246 msg(MSG_ERROR, "bad lptype");
247 return RESULT_ERROR;
248 }
249
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
250 /* Switch to the bufdisplay display mode, if not that way already */
251 if (CHARcmp(o_display(win), o_bufdisplay(markbuffer(top))))
252 {
253 origdisplay = CHARdup(o_display(win));
254 if (!dispset(win, tochar8(o_bufdisplay(markbuffer(top)))))
255 {
256 safefree(origdisplay);
257 return RESULT_ERROR;
258 }
259 }
260
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
261 /* Call the mode's setup function. Pretend the cursor is at the
262 * top of the print region, so setup() doesn't try to scroll.
263 */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
264 next = (*win->md->setup)(win, top, markoffset(top), bottom, win->mi);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
265
266 /* open file or filter program */
267 if (type->spooled)
268 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
269 rwa = 'w';
270 out = tochar8(o_lpout);
271 if (!out || !*out)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
272 {
273 msg(MSG_ERROR, "must set lpout");
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
274 goto Error;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
275 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
276 if (out[0] == '>' && out[1] == '>')
277 out += 2, rwa = 'a';
278 if (!ioopen(out, rwa, True, force, 'b'))
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
279 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
280 goto Error;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
281 }
282 }
283
284 /* allocate the I/O buffer */
285 iomax = 1024;
286 iobuf = (CHAR *)safealloc(iomax, sizeof(CHAR));
287 ionext = 0;
288
289 /* initialize the LP driver */
290 #if defined (GUI_WIN32)
291 if (strcmp (o_lptype, "windows") == 0)
292 (*type->before)(type->minorno, dummyprt);
293 else
294 #endif
295 (*type->before)(type->minorno, prtchar);
296
297 /* start the first page */
298 pagenum = 1;
299 linesleft = o_lplines;
300 column = 0;
301 prwin = win;
302 if (win->md->header)
303 {
304 (*win->md->header)(win, pagenum, win->mi, draw);
305 }
306 anytext = False;
307
308 /* generate image lines, and send them to the printer. Temporarily
309 * move the cursor to the end of the buffer so it doesn't affect
310 * the appearance of the text.
311 */
312 oldcurs = markoffset(win->cursor);
313 marksetoffset(win->cursor, o_bufchars(markbuffer(win->cursor)));
314 while (markoffset(next) < markoffset(bottom))
315 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
316 lnum = markline(next);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
317 next = (*win->md->image)(win, next, win->mi, draw);
318 }
319 marksetoffset(win->cursor, oldcurs);
320
321 /* end the printout */
322 (*type->after)(linesleft);
323
324 /* end the I/O */
325 if (ionext > 0)
326 {
327 iowrite(iobuf, ionext);
328 }
329 safefree(iobuf);
330 msg(MSG_INFO, "[d]$1 pages", (long)pagenum);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
331 if (type->spooled && ioclose())
332 goto Error;
333
334 /* clean up and return success */
335 if (origdisplay)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
336 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
337 (void)dispset(win, tochar8(origdisplay));
338 safefree(origdisplay);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
339 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
340 return RESULT_COMPLETE;
341
342 Error:
343 /* clean up and return failure */
344 if (origdisplay)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
345 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
346 (void)dispset(win, tochar8(origdisplay));
347 safefree(origdisplay);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
348 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
349 return RESULT_ERROR;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
350 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
351 #endif /* FEATURE_LPR */
Something went wrong with that request. Please try again.