/src/libspectre/ghostscript/devices/gdevepsn.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* |
18 | | * Epson (and similar) dot-matrix printer driver for Ghostscript. |
19 | | * |
20 | | * Four devices are defined here: 'epson', 'eps9mid', 'eps9high', and 'ibmpro'. |
21 | | * The 'epson' device is the generic device, for 9-pin and 24-pin printers. |
22 | | * 'eps9high' is a special mode for 9-pin printers where scan lines are |
23 | | * interleaved in multiple passes to produce high vertical resolution at |
24 | | * the expense of several passes of the print head. 'eps9mid' is a special |
25 | | * mode for 9 pin printers too, scan lines are interleaved but with next |
26 | | * vertical line. 'ibmpro' is for the IBM ProPrinter, which has slightly |
27 | | * (but only slightly) different control codes. |
28 | | * |
29 | | * Thanks to: |
30 | | * David Wexelblat (dwex@mtgzfs3.att.com) for the 'eps9high' code; |
31 | | * Guenther Thomsen (thomsen@cs.tu-berlin.de) for the 'eps9mid' code; |
32 | | * James W. Birdsall (jwbirdsa@picarefy.picarefy.com) for the |
33 | | * 'ibmpro' modifications; |
34 | | * Russell J. Lang (rjl@aladdin.com) for the 180x60 and 240x180 dpi |
35 | | * enhancements. |
36 | | */ |
37 | | #include "gdevprn.h" |
38 | | |
39 | | /* |
40 | | * Define whether the printer is archaic -- so old that it doesn't |
41 | | * support settable tabs, pitch, or left margin. (This should be a |
42 | | * run-time property....) Note: the IBM ProPrinter is archaic. |
43 | | */ |
44 | | /*#define ARCHAIC 1*/ |
45 | | |
46 | | /* |
47 | | * Define whether the printer is a Panasonic 9-pin printer, |
48 | | * which sometimes doesn't recognize a horizontal tab command |
49 | | * when a line contains a lot of graphics commands, |
50 | | * requiring a "backspace, space" sequence before a tab. |
51 | | */ |
52 | | /*#define TAB_HICCUP 1*/ |
53 | | |
54 | | /* |
55 | | * Define the minimum distance for which it's worth converting white space |
56 | | * into a tab. This can be specified in pixels (to save transmission time), |
57 | | * in tenths of an inch (for printers where tabs provoke actual head motion), |
58 | | * or both. The distance must meet BOTH criteria for the driver to tab, |
59 | | * so an irrelevant criterion should be set to 0 rather than infinite. |
60 | | */ |
61 | | #define MIN_TAB_PIXELS 10 |
62 | 0 | #define MIN_TAB_10THS 15 |
63 | | |
64 | | /* |
65 | | * Valid values for X_DPI: |
66 | | * |
67 | | * For 9-pin printers: 60, 120, 240 |
68 | | * For 24-pin printers: 60, 120, 180, 240, 360 |
69 | | * |
70 | | * The value specified at compile time is the default value used if the |
71 | | * user does not specify a resolution at runtime. |
72 | | */ |
73 | | #ifndef X_DPI |
74 | | # define X_DPI 240 |
75 | | #endif |
76 | | |
77 | | /* |
78 | | * For Y_DPI, a given printer will support a base resolution of 60 or 72; |
79 | | * check the printer manual. The Y_DPI value must be a multiple of this |
80 | | * base resolution. Valid values for Y_DPI: |
81 | | * |
82 | | * For 9-pin printers: 1*base_res |
83 | | * For 24-pin printers: 1*base_res, 3*base_res |
84 | | * |
85 | | * The value specified at compile time is the default value used if the |
86 | | * user does not specify a resolution at runtime. |
87 | | */ |
88 | | |
89 | | #ifndef Y_BASERES |
90 | | # define Y_BASERES 72 |
91 | | #endif |
92 | | #ifndef Y_DPI |
93 | | # define Y_DPI (1*Y_BASERES) |
94 | | #endif |
95 | | |
96 | | /* The device descriptors */ |
97 | | static dev_proc_print_page(epson_print_page); |
98 | | static dev_proc_print_page(eps9mid_print_page); |
99 | | static dev_proc_print_page(eps9high_print_page); |
100 | | static dev_proc_print_page(ibmpro_print_page); |
101 | | |
102 | | /* Standard Epson device */ |
103 | | const gx_device_printer far_data gs_epson_device = |
104 | | prn_device(prn_bg_procs, "epson", /* The print_page proc is compatible with allowing bg printing */ |
105 | | DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, |
106 | | X_DPI, Y_DPI, |
107 | | 0.25, 0.02, 0.25, 0.4, /* margins */ |
108 | | 1, epson_print_page); |
109 | | |
110 | | /* Mid-res (interleaved, 1 pass per line) 9-pin device */ |
111 | | const gx_device_printer far_data gs_eps9mid_device = |
112 | | prn_device(prn_bg_procs, "eps9mid", /* The print_page proc is compatible with allowing bg printing */ |
113 | | DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, |
114 | | X_DPI, 3*Y_BASERES, |
115 | | 0.2, 0.0, 0, 0.0, /* margins */ |
116 | | 1, eps9mid_print_page); |
117 | | |
118 | | /* High-res (interleaved) 9-pin device */ |
119 | | const gx_device_printer far_data gs_eps9high_device = |
120 | | prn_device(prn_bg_procs, "eps9high", /* The print_page proc is compatible with allowing bg printing */ |
121 | | DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, |
122 | | X_DPI, 3*Y_BASERES, |
123 | | 0.2, 0.0, 0.0, 0.0, /* margins */ |
124 | | 1, eps9high_print_page); |
125 | | |
126 | | /* IBM ProPrinter device */ |
127 | | const gx_device_printer far_data gs_ibmpro_device = |
128 | | prn_device(prn_bg_procs, "ibmpro", /* The print_page proc is compatible with allowing bg printing */ |
129 | | DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, |
130 | | X_DPI, Y_DPI, |
131 | | 0.2, 0.0, 0.0, 0.0, /* margins */ |
132 | | 1, ibmpro_print_page); |
133 | | |
134 | | /* ------ Driver procedures ------ */ |
135 | | |
136 | | /* Forward references */ |
137 | | static void eps_output_run(byte *, int, int, char, gp_file *, int); |
138 | | |
139 | | /* Send the page to the printer. */ |
140 | 0 | #define DD 0x40 /* double density flag */ |
141 | | static int |
142 | | eps_print_page(gx_device_printer *pdev, gp_file *prn_stream, int y_9pin_high, |
143 | | const char *init_string, int init_length, const char *end_string, |
144 | | int archaic, int tab_hiccup) |
145 | 0 | { |
146 | 0 | static const char graphics_modes_9[5] = |
147 | 0 | { |
148 | 0 | -1, 0 /*60*/, 1 /*120*/, 7 /*180*/, DD+3 /*240*/ |
149 | 0 | }; |
150 | |
|
151 | 0 | static const char graphics_modes_24[7] = |
152 | 0 | { |
153 | 0 | -1, 32 /*60*/, 33 /*120*/, 39 /*180*/, |
154 | 0 | DD+35 /*240*/, -1, DD+40 /*360*/ |
155 | 0 | }; |
156 | |
|
157 | 0 | int y_24pin = (y_9pin_high ? 0 : pdev->y_pixels_per_inch > 72); |
158 | 0 | int in_y_mult = ((y_24pin | y_9pin_high) ? 3 : 1); |
159 | 0 | int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev); |
160 | | /* Note that in_size is a multiple of 8. */ |
161 | 0 | int in_size = line_size * (8 * in_y_mult); |
162 | 0 | byte *buf1 = NULL; |
163 | 0 | byte *buf2 = NULL; |
164 | 0 | byte *in; |
165 | 0 | byte *out; |
166 | 0 | int out_y_mult = (y_24pin ? 3 : 1); |
167 | 0 | int x_dpi = (int)pdev->x_pixels_per_inch; |
168 | 0 | int y_passes = (y_9pin_high ? 3 : 1); |
169 | 0 | int dots_per_space = x_dpi / 10; /* pica space = 1/10" */ |
170 | 0 | int bytes_per_space = dots_per_space * out_y_mult; |
171 | 0 | int tab_min_pixels = x_dpi * MIN_TAB_10THS / 10; |
172 | 0 | int skip = 0, lnum = 0, pass, ypass; |
173 | 0 | int code = 0; |
174 | | |
175 | 0 | char start_graphics; |
176 | 0 | int first_pass; |
177 | 0 | int last_pass; |
178 | |
|
179 | 0 | if (y_24pin) { |
180 | 0 | if (x_dpi / 60 >= sizeof(graphics_modes_24) / sizeof(graphics_modes_24[0])) { |
181 | 0 | return_error(gs_error_rangecheck); |
182 | 0 | } |
183 | 0 | start_graphics = graphics_modes_24[x_dpi / 60]; |
184 | 0 | } |
185 | 0 | else { |
186 | 0 | if (x_dpi / 60 >= sizeof(graphics_modes_9) / sizeof(graphics_modes_9[0])) { |
187 | 0 | return_error(gs_error_rangecheck); |
188 | 0 | } |
189 | 0 | start_graphics = graphics_modes_9[x_dpi / 60]; |
190 | 0 | } |
191 | 0 | first_pass = (start_graphics & DD ? 1 : 0); |
192 | 0 | last_pass = first_pass * (y_9pin_high == 2 ? 1 : 2); |
193 | |
|
194 | 0 | if (bytes_per_space == 0) { |
195 | | /* This avoids divide by zero later on, bug 701843. */ |
196 | 0 | return_error(gs_error_rangecheck); |
197 | 0 | } |
198 | | |
199 | 0 | buf1 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf1)"); |
200 | 0 | buf2 = (byte *)gs_malloc(pdev->memory, in_size, 1, "eps_print_page(buf2)"); |
201 | 0 | in = buf1; |
202 | 0 | out = buf2; |
203 | | |
204 | | |
205 | | /* Check allocations */ |
206 | 0 | if ( buf1 == 0 || buf2 == 0 ) { |
207 | 0 | code = gs_error_VMerror; |
208 | 0 | goto xit; |
209 | 0 | } |
210 | | |
211 | | /* Initialize the printer and reset the margins. */ |
212 | 0 | gp_fwrite(init_string, 1, init_length, prn_stream); |
213 | 0 | if ( init_string[init_length - 1] == 'Q' ) |
214 | 0 | gp_fputc((int)(pdev->width / pdev->x_pixels_per_inch * 10) + 2, |
215 | 0 | prn_stream); |
216 | | |
217 | | /* Calculate the minimum tab distance. */ |
218 | 0 | if ( tab_min_pixels < max(MIN_TAB_PIXELS, 3) ) |
219 | 0 | tab_min_pixels = max(MIN_TAB_PIXELS, 3); |
220 | 0 | tab_min_pixels -= tab_min_pixels % 3; /* simplify life */ |
221 | | |
222 | | /* Print lines of graphics */ |
223 | 0 | while ( lnum < pdev->height ) |
224 | 0 | { |
225 | 0 | byte *in_data; |
226 | 0 | byte *inp; |
227 | 0 | byte *in_end; |
228 | 0 | byte *out_end = NULL; |
229 | 0 | byte *out_blk; |
230 | 0 | register byte *outp; |
231 | 0 | int lcnt; |
232 | | |
233 | | /* Copy 1 scan line and test for all zero. */ |
234 | 0 | code = gdev_prn_get_bits(pdev, lnum, in, &in_data); |
235 | 0 | if (code < 0) |
236 | 0 | goto xit; |
237 | 0 | if ( in_data[0] == 0 && |
238 | 0 | !memcmp((char *)in_data, (char *)in_data + 1, line_size - 1) |
239 | 0 | ) |
240 | 0 | { |
241 | 0 | lnum++; |
242 | 0 | skip += 3 / in_y_mult; |
243 | 0 | continue; |
244 | 0 | } |
245 | | |
246 | | /* Vertical tab to the appropriate position. */ |
247 | 0 | while ( skip > 255 ) |
248 | 0 | { |
249 | 0 | gp_fputs("\033J\377", prn_stream); |
250 | 0 | skip -= 255; |
251 | 0 | } |
252 | 0 | if ( skip ) |
253 | 0 | { |
254 | 0 | gp_fprintf(prn_stream, "\033J%c", skip); |
255 | 0 | } |
256 | | |
257 | | /* Copy the the scan lines. */ |
258 | 0 | code = lcnt = gdev_prn_copy_scan_lines(pdev, lnum, in, in_size); |
259 | 0 | if (code < 0) |
260 | 0 | goto xit; |
261 | 0 | if ( lcnt < 8 * in_y_mult ) |
262 | 0 | { /* Pad with lines of zeros. */ |
263 | 0 | memset(in + lcnt * line_size, 0, |
264 | 0 | in_size - lcnt * line_size); |
265 | 0 | } |
266 | |
|
267 | 0 | if ( y_9pin_high == 2 ) |
268 | 0 | { /* Force printing of every dot in one pass */ |
269 | | /* by reducing vertical resolution */ |
270 | | /* (ORing with the next line of data). */ |
271 | | /* This is necessary because some Epson compatibles */ |
272 | | /* can't print neighboring dots. */ |
273 | 0 | int i; |
274 | 0 | for ( i = 0; i < line_size * in_y_mult; ++i ) |
275 | 0 | in[i] |= in[i + line_size]; |
276 | 0 | } |
277 | |
|
278 | 0 | if ( y_9pin_high ) |
279 | 0 | { /* Shuffle the scan lines */ |
280 | 0 | byte *p; |
281 | 0 | int i; |
282 | 0 | static const char index[] = |
283 | 0 | { 0, 8, 16, 1, 9, 17, |
284 | 0 | 2, 10, 18, 3, 11, 19, |
285 | 0 | 4, 12, 20, 5, 13, 21, |
286 | 0 | 6, 14, 22, 7, 15, 23 |
287 | 0 | }; |
288 | |
|
289 | 0 | for ( i = 0; i < 24; i++ ) |
290 | 0 | { |
291 | 0 | memcpy(out+(index[i]*line_size), |
292 | 0 | in+(i*line_size), line_size); |
293 | 0 | } |
294 | 0 | p = in; |
295 | 0 | in = out; |
296 | 0 | out = p; |
297 | 0 | } |
298 | |
|
299 | 0 | for ( ypass = 0; ypass < y_passes; ypass++ ) |
300 | 0 | { |
301 | 0 | for ( pass = first_pass; pass <= last_pass; pass++ ) |
302 | 0 | { |
303 | | /* We have to 'transpose' blocks of 8 pixels x 8 lines, */ |
304 | | /* because that's how the printer wants the data. */ |
305 | | /* If we are in a 24-pin mode, we have to transpose */ |
306 | | /* groups of 3 lines at a time. */ |
307 | |
|
308 | 0 | if ( pass == first_pass ) |
309 | 0 | { |
310 | 0 | out_end = out; |
311 | 0 | inp = in; |
312 | 0 | in_end = inp + line_size; |
313 | |
|
314 | 0 | if ( y_24pin ) |
315 | 0 | { |
316 | 0 | for ( ; inp < in_end; inp++, out_end += 24 ) |
317 | 0 | { |
318 | 0 | gdev_prn_transpose_8x8(inp, line_size, out_end, 3); |
319 | 0 | gdev_prn_transpose_8x8(inp + line_size * 8, |
320 | 0 | line_size, out_end + 1, 3); |
321 | 0 | gdev_prn_transpose_8x8(inp + line_size * 16, |
322 | 0 | line_size, out_end + 2, 3); |
323 | 0 | } |
324 | | /* Remove trailing 0s. */ |
325 | 0 | while ( out_end > out && out_end[-1] == 0 && |
326 | 0 | out_end[-2] == 0 && out_end[-3] == 0) |
327 | 0 | { |
328 | 0 | out_end -= 3; |
329 | 0 | } |
330 | 0 | } |
331 | 0 | else |
332 | 0 | { |
333 | 0 | for ( ; inp < in_end; inp++, out_end += 8 ) |
334 | 0 | { |
335 | 0 | gdev_prn_transpose_8x8(inp + (ypass * 8*line_size), |
336 | 0 | line_size, out_end, 1); |
337 | 0 | } |
338 | | /* Remove trailing 0s. */ |
339 | 0 | while ( out_end > out && out_end[-1] == 0 ) |
340 | 0 | { |
341 | 0 | out_end--; |
342 | 0 | } |
343 | 0 | } |
344 | 0 | } |
345 | |
|
346 | 0 | for ( out_blk = outp = out; outp < out_end; ) |
347 | 0 | { |
348 | | /* Skip a run of leading 0s. At least */ |
349 | | /* tab_min_pixels are needed to make tabbing */ |
350 | | /* worth it. We do everything by 3's to */ |
351 | | /* avoid having to make different cases */ |
352 | | /* for 9- and 24-pin. */ |
353 | 0 | if ( !archaic && |
354 | 0 | *outp == 0 && out_end - outp >= tab_min_pixels && |
355 | 0 | (outp[1] | outp[2]) == 0 && |
356 | 0 | !memcmp((char *)outp, (char *)outp + 3, |
357 | 0 | tab_min_pixels - 3) |
358 | 0 | ) |
359 | 0 | { |
360 | 0 | byte *zp = outp; |
361 | 0 | int tpos; |
362 | 0 | byte *newp; |
363 | |
|
364 | 0 | outp += tab_min_pixels; |
365 | 0 | while ( outp + 3 <= out_end && |
366 | 0 | *outp == 0 && |
367 | 0 | outp[1] == 0 && outp[2] == 0 ) |
368 | 0 | { |
369 | 0 | outp += 3; |
370 | 0 | } |
371 | 0 | tpos = (outp - out) / bytes_per_space; |
372 | 0 | newp = out + tpos * bytes_per_space; |
373 | 0 | if ( newp > zp + 10 ) |
374 | 0 | { |
375 | | /* Output preceding bit data.*/ |
376 | 0 | if ( zp > out_blk ) |
377 | 0 | { |
378 | | /* only false at beginning of line */ |
379 | 0 | eps_output_run(out_blk, (int)(zp - out_blk), |
380 | 0 | out_y_mult, start_graphics, |
381 | 0 | prn_stream, |
382 | 0 | (y_9pin_high == 2 ? |
383 | 0 | (1 + ypass) & 1 : pass)); |
384 | 0 | } |
385 | | /* Tab over to the appropriate position. */ |
386 | 0 | if ( tab_hiccup ) |
387 | 0 | gp_fputs("\010 ", prn_stream); /* bksp, space */ |
388 | | /* The following statement is broken up */ |
389 | | /* to work around a bug in emx/gcc. */ |
390 | 0 | gp_fprintf(prn_stream, "\033D%c", tpos); |
391 | 0 | gp_fputc(0, prn_stream); |
392 | 0 | gp_fputc('\t', prn_stream); |
393 | 0 | out_blk = outp = newp; |
394 | 0 | } |
395 | 0 | } |
396 | 0 | else |
397 | 0 | { |
398 | 0 | outp += out_y_mult; |
399 | 0 | } |
400 | 0 | } |
401 | 0 | if ( outp > out_blk ) |
402 | 0 | { |
403 | 0 | eps_output_run(out_blk, (int)(outp - out_blk), |
404 | 0 | out_y_mult, start_graphics, |
405 | 0 | prn_stream, |
406 | 0 | (y_9pin_high == 2 ? (1 + ypass) & 1 : pass)); |
407 | 0 | } |
408 | |
|
409 | 0 | gp_fputc('\r', prn_stream); |
410 | 0 | } |
411 | 0 | if ( ypass < y_passes - 1 ) |
412 | 0 | gp_fputs("\033J\001", prn_stream); |
413 | 0 | } |
414 | 0 | skip = 24 - y_passes + 1; /* no skip on last Y pass */ |
415 | 0 | lnum += 8 * in_y_mult; |
416 | 0 | } |
417 | | |
418 | | /* Eject the page and reinitialize the printer */ |
419 | 0 | gp_fputs(end_string, prn_stream); |
420 | 0 | gp_fflush(prn_stream); |
421 | |
|
422 | 0 | xit: |
423 | 0 | if ( buf1 ) |
424 | 0 | gs_free(pdev->memory, (char *)buf1, in_size, 1, "eps_print_page(buf1)"); |
425 | 0 | if ( buf2 ) |
426 | 0 | gs_free(pdev->memory, (char *)buf2, in_size, 1, "eps_print_page(buf2)"); |
427 | 0 | if (code < 0) |
428 | 0 | return_error(code); |
429 | 0 | return code; |
430 | 0 | } |
431 | | |
432 | | /* Output a single graphics command. */ |
433 | | /* pass=0 for all columns, 1 for even columns, 2 for odd columns. */ |
434 | | static void |
435 | | eps_output_run(byte *data, int count, int y_mult, |
436 | | char start_graphics, gp_file *prn_stream, int pass) |
437 | 0 | { |
438 | 0 | int xcount = count / y_mult; |
439 | |
|
440 | 0 | gp_fputc(033, prn_stream); |
441 | 0 | if ( !(start_graphics & ~3) ) |
442 | 0 | { |
443 | 0 | gp_fputc("KLYZ"[(int)start_graphics], prn_stream); |
444 | 0 | } |
445 | 0 | else |
446 | 0 | { |
447 | 0 | gp_fputc('*', prn_stream); |
448 | 0 | gp_fputc(start_graphics & ~DD, prn_stream); |
449 | 0 | } |
450 | 0 | gp_fputc(xcount & 0xff, prn_stream); |
451 | 0 | gp_fputc(xcount >> 8, prn_stream); |
452 | 0 | if ( !pass ) |
453 | 0 | { |
454 | 0 | gp_fwrite(data, 1, count, prn_stream); |
455 | 0 | } |
456 | 0 | else |
457 | 0 | { |
458 | | /* Only write every other column of y_mult bytes. */ |
459 | 0 | int which = pass; |
460 | 0 | register byte *dp = data; |
461 | 0 | register int i, j; |
462 | |
|
463 | 0 | for ( i = 0; i < xcount; i++, which++ ) |
464 | 0 | { |
465 | 0 | for ( j = 0; j < y_mult; j++, dp++ ) |
466 | 0 | { |
467 | 0 | gp_fputc(((which & 1) ? *dp : 0), prn_stream); |
468 | 0 | } |
469 | 0 | } |
470 | 0 | } |
471 | 0 | } |
472 | | |
473 | | /* The print_page procedures are here, to avoid a forward reference. */ |
474 | | #ifndef ARCHAIC |
475 | 0 | # define ARCHAIC 0 |
476 | | #endif |
477 | | #ifndef TAB_HICCUP |
478 | 0 | # define TAB_HICCUP 0 |
479 | | #endif |
480 | | |
481 | 0 | #define ESC 0x1b |
482 | | static const char eps_init_string[] = { |
483 | | #if ARCHAIC |
484 | | ESC, '@', 022 /*^R*/, ESC, 'Q' |
485 | | #else |
486 | | ESC, '@', ESC, 'P', ESC, 'l', 0, '\r', ESC, 'Q' |
487 | | #endif |
488 | | }; |
489 | | |
490 | | static int |
491 | | epson_print_page(gx_device_printer *pdev, gp_file *prn_stream) |
492 | 0 | { |
493 | 0 | return eps_print_page(pdev, prn_stream, 0, eps_init_string, |
494 | 0 | sizeof(eps_init_string), "\f\033@", |
495 | 0 | ARCHAIC, TAB_HICCUP); |
496 | 0 | } |
497 | | |
498 | | static int |
499 | | eps9high_print_page(gx_device_printer *pdev, gp_file *prn_stream) |
500 | 0 | { |
501 | 0 | return eps_print_page(pdev, prn_stream, 1, eps_init_string, |
502 | 0 | sizeof(eps_init_string), "\f\033@", |
503 | 0 | ARCHAIC, TAB_HICCUP); |
504 | 0 | } |
505 | | |
506 | | static int |
507 | | eps9mid_print_page(gx_device_printer *pdev, gp_file *prn_stream) |
508 | 0 | { |
509 | 0 | return eps_print_page(pdev, prn_stream, 2, eps_init_string, |
510 | 0 | sizeof(eps_init_string), "\f\033@", |
511 | 0 | ARCHAIC, TAB_HICCUP); |
512 | 0 | } |
513 | | |
514 | | static int |
515 | | ibmpro_print_page(gx_device_printer *pdev, gp_file *prn_stream) |
516 | 0 | { |
517 | | /* |
518 | | * IBM Proprinter Guide to Operations, p. 4-5: "DC1: Select Printer: Sets |
519 | | * the printer to accept data from your computer." Prevents printer from |
520 | | * interpreting first characters as literal text. |
521 | | */ |
522 | 0 | #define DC1 0x11 |
523 | 0 | static const char ibmpro_init_string[] = { |
524 | 0 | DC1, ESC, '3', 0x30 |
525 | 0 | }; |
526 | 0 | #undef DC1 |
527 | 0 | return eps_print_page(pdev, prn_stream, 0, ibmpro_init_string, |
528 | 0 | sizeof(ibmpro_init_string), "\f", 1, 0); |
529 | 0 | } |