1 /* COPYRIGHT (C) 1990, 1992 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4 This file is part of Ghostscript.
5
6 Ghostscript is distributed in the hope that it will be useful, but
7 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8 to anyone for the consequences of using it or for whether it serves any
9 particular purpose or works at all, unless he says so in writing. Refer
10 to the Ghostscript General Public License for full details.
11
12 Everyone is granted permission to copy, modify and redistribute
13 Ghostscript, but only under the conditions described in the Ghostscript
14 General Public License. A copy of this license is supposed to have been
15 given to you along with Ghostscript so you can know your rights and
16 responsibilities. It should be in a file named COPYING. Among other
17 things, the copyright notice and this notice must be preserved on all
18 copies. */
19
20 /* gdevdmpr.c
21 *
22 * Dot matrix printer driver for Ghostscript
23 *
24 * The first version written by ... K.Asayama Nov 1992
25 * NEC PC-H98 high resolution mode supported by ... OkI Dec 1992
26 * IBM PC AT/Compatible machines supported by ... hero.h Mar 1993
27 * Modified for 386BSD by ... FKR Mar 1993
28 * Modified for Ghostscript version 2.5.2 by ... K.Asayama Mar 1993
29 * Modified for Ghostscript version 2.6.1 by ... K.Asayama Oct 1993
30 * Modified for Ghostscript version 4.03 by ... K.Asayama May 1997
31 */
32
33 #include "gdevprn.h"
34 #include "gp.h"
35 #include "psi/ierrors.h"
36 #include "gsparam.h"
37 #include "gsstate.h"
38 #include "math_.h"
39 #include "malloc_.h"
40
41 /* include library header. */
42 #include "dviprlib.h"
43
44 #define LOCAL_DEBUG 0
45
46 #define DEVICE_NAME "dmprt"
47 #define DEVICE_VERSION 201 /* 2.01 */
48
49 typedef struct gx_device_dmprt_local_s gx_device_dmprt_local;
50 struct gx_device_dmprt_local_s {
51 int orig_x_dpi;
52 int orig_y_dpi;
53
54 int x_offset;
55 int y_offset;
56
57 int spec_width;
58 int spec_height;
59 int max_width;
60 int max_height;
61 int dev_margin[4]; /* left bottom right top */
62
63 int prtcfg_init_f;
64 int verbose_f;
65 int debug_f;
66 dviprt_cfg_t prtcfg;
67 dviprt_print prtinfo;
68 };
69
70 /* declaration of the structure to describe `DMPRT' device driver */
71 typedef struct gx_device_dmprt_s gx_device_dmprt;
72 struct gx_device_dmprt_s {
73 gx_device_common;
74 gx_prn_device_common;
75
76 gx_device_dmprt_local dmprt;
77 };
78
79 /* declarations of main functions */
80 static dev_proc_get_params(gdev_dmprt_get_params);
81 static dev_proc_put_params(gdev_dmprt_put_params);
82 static dev_proc_get_initial_matrix(gdev_dmprt_get_initial_matrix);
83 static dev_proc_open_device(gdev_dmprt_open);
84 static dev_proc_print_page(gdev_dmprt_print_page);
85 static dev_proc_close_device(gdev_dmprt_close);
86
87 /* declarations of sub functions to get printer properties. */
88 static void gdev_dmprt_init_printer_props(gx_device_dmprt *);
89 static int gdev_dmprt_get_printer_props(gx_device_dmprt *,char *);
90 static int gdev_dmprt_check_code_props(byte * ,int );
91 static FILE *gdev_dmprt_dviprt_lib_fopen(const char *,char *);
92
93 static int gdev_dmprt_error_no_dviprt_to_gs(int );
94
95 /* The device descriptor */
96 gx_device_procs prn_dmprt_procs = {
97 gdev_dmprt_open,
98 gdev_dmprt_get_initial_matrix,
99 0, /* sync_output */
100 gdev_prn_output_page,
101 gdev_dmprt_close,
102 gdev_prn_map_rgb_color,
103 gdev_prn_map_color_rgb,
104 0, /* fill_rectangle */
105 0, /* tile_rectangle */
106 0, /* copy_mono */
107 0, /* copy_color */
108 0, /* draw_line */
109 0, /* get_bits */
110 gdev_dmprt_get_params,
111 gdev_dmprt_put_params,
112 gx_default_map_cmyk_color,
113 0,
114 };
115
116 #define DEFAULT_DPI 180
117 #define DEFAULT_WIDTH 8.3
118 #define DEFAULT_HEIGHT 11.7
119
120 gx_device_dmprt gs_dmprt_device = {
121 prn_device_body(gx_device_dmprt, prn_dmprt_procs, DEVICE_NAME,
122 DEFAULT_WIDTH*10, /* width 10'th */
123 DEFAULT_HEIGHT*10, /* height 10'th */
124 DEFAULT_DPI, /* X resolution */
125 DEFAULT_DPI, /* Y resolution */
126 0,0,0,0, /* margins (top,left,bottom,right) */
127 1,1,1,1,2,2, /* color info. */
128 gdev_dmprt_print_page),
129
130 {
131 DEFAULT_DPI, DEFAULT_DPI,
132 0, 0, /* offset */
133 DEFAULT_DPI*DEFAULT_WIDTH, /* specified width */
134 DEFAULT_DPI*DEFAULT_HEIGHT, /* specified height */
135 -1,-1, /* maximal width,height */
136 { 0,0,0,0 }, /* margins */
137
138 /* status of the device */
139 0, /* printer configuration is not initialized */
140 0, /* verbose mode */
141 0, /* debug flag */
142 },
143 };
144
145 #define ppdev ((gx_device_printer *)pdev)
146 #define pddev ((gx_device_dmprt *)pdev)
147
148 typedef struct {
149 char *name;
150 int no;
151 } dmprt_encoding;
152 static dmprt_encoding gdev_dmprt_encode_list[] = {
153 {"Null",CFG_ENCODE_NULL},
154 {"AsciiHex",CFG_ENCODE_HEX },
155 {"CCITTFax",CFG_ENCODE_FAX },
156 {"PCLMode1Compress",CFG_ENCODE_PCL1 },
157 {"PCLMode2Compress",CFG_ENCODE_PCL2 },
158 {0},
159 };
160
161 /* --- Get properties of printer device. --- */
162 static int gdev_dmprt_get_dmprt_params(gx_device *pdev, gs_param_list *plist);
163 static int
164 gdev_dmprt_get_dviprt_params(gx_device *pdev, gs_param_list *plist);
165
166 static int
gdev_dmprt_get_params(gx_device * pdev,gs_param_list * plist)167 gdev_dmprt_get_params(gx_device *pdev, gs_param_list *plist)
168 {
169 int code;
170 gs_param_dict dict;
171 const char *param_name;
172
173 if (!pddev->dmprt.prtcfg_init_f)
174 gdev_dmprt_init_printer_props(pddev);
175
176 dict.size = 30;
177 code = param_begin_write_dict(plist, (param_name = "DmprtParams"),
178 &dict, false);
179 if (code < 0) return code;
180 if (code == 0) {
181 code = gdev_dmprt_get_dmprt_params(pdev, dict.list);
182 param_end_write_dict(plist, param_name, &dict);
183 if (code < 0) return code;
184 }
185
186 dict.size = 30;
187 code = param_begin_write_dict(plist, (param_name = "DviprtParams"),
188 &dict, false);
189 if (code < 0) return code;
190 if (code == 0) {
191 code = gdev_dmprt_get_dviprt_params(pdev, dict.list);
192 param_end_write_dict(plist, param_name, &dict);
193 if (code < 0) return code;
194 }
195
196 {
197 int w = pddev->width;
198 int h = pddev->height;
199 pddev->width = pddev->dmprt.spec_width;
200 pddev->height = pddev->dmprt.spec_height;
201 code = gdev_prn_get_params(pdev, plist);
202 pddev->width = w;
203 pddev->height = h;
204 }
205
206 return code;
207 }
208
209 /* internal routines for get_params */
210 static int
gdev_dmprt_get_dmprt_params(gx_device * pdev,gs_param_list * plist)211 gdev_dmprt_get_dmprt_params(gx_device *pdev, gs_param_list *plist)
212 {
213 int code;
214 long vlong;
215 bool vbool;
216 gs_param_int_array vaint;
217 int int_data[4];
218
219 vlong = DEVICE_VERSION;
220 code = param_write_long(plist, "Version", &vlong);
221 if (code < 0) return code;
222
223 vbool = pddev->dmprt.debug_f;
224 code = param_write_bool(plist, "Debug", &vbool);
225 if (code < 0) return code;
226
227 vbool = pddev->dmprt.verbose_f;
228 code = param_write_bool(plist, "Verbose", &vbool);
229 if (code < 0) return code;
230
231 vaint.size = 2;
232 vaint.data = int_data;
233 vaint.persistent = false;
234 int_data[0] = pddev->dmprt.max_width;
235 int_data[1] = pddev->dmprt.max_height;
236 code = param_write_int_array(plist, "MaxSize", &vaint);
237 if (code < 0) return code;
238
239 vaint.size = 2;
240 vaint.data = int_data;
241 vaint.persistent = false;
242 int_data[0] = pddev->dmprt.x_offset;
243 int_data[1] = pddev->dmprt.y_offset;
244 code = param_write_int_array(plist, "Offsets", &vaint);
245 if (code < 0) return code;
246
247 vaint.size = 4;
248 vaint.data = int_data;
249 vaint.persistent = false;
250 { int i;
251 for (i=0;i<4;i++) int_data[i] = pddev->dmprt.dev_margin[i];
252 }
253 code = param_write_int_array(plist, "Margins", &vaint);
254 if (code < 0) return code;
255
256 return code;
257 }
258
259 static int
gdev_dmprt_get_dviprt_params(gx_device * pdev,gs_param_list * plist)260 gdev_dmprt_get_dviprt_params(gx_device *pdev, gs_param_list *plist)
261 {
262 dviprt_cfg_t *pprt = &pddev->dmprt.prtcfg;
263 long vlong;
264 bool vbool;
265 gs_param_string vstr;
266 const char *vchar;
267 int code;
268 int i;
269
270 vlong = pprt->integer[CFG_PINS] * 8;
271 code = param_write_long(plist,"Pins", &vlong);
272 if (code < 0) return code;
273 code = param_write_long(plist, "MinimalUnit",
274 pprt->integer+CFG_MINIMAL_UNIT);
275 if (code < 0) return code;
276 code = param_write_long(plist,"MaximalUnit",
277 pprt->integer+CFG_MAXIMAL_UNIT);
278 if (code < 0) return code;
279 code = param_write_int(plist,"HDpi" , &pddev->dmprt.orig_x_dpi);
280 if (code < 0) return code;
281 code = param_write_int(plist,"VDpi", &pddev->dmprt.orig_y_dpi);
282 if (code < 0) return code;
283 code = param_write_long(plist,"Constant", pprt->integer+CFG_CONSTANT);
284 if (code < 0) return code;
285
286 vbool = pprt->integer[CFG_UPPER_POS] & CFG_NON_TRANSPOSE_BIT ? 0 : 1;
287 code = param_write_bool(plist,"Transpose", &vbool);
288 if (code < 0) return code;
289 vbool = pprt->integer[CFG_UPPER_POS] & CFG_REVERSE_BIT ? 1 : 0;
290 code = param_write_bool(plist,"Reverse", &vbool);
291 if (code < 0) return code;
292 vbool = (pprt->integer[CFG_UPPER_POS] & CFG_NON_MOVING) ? 1 : 0;
293 code = param_write_bool(plist,"NonMoving", &vbool);
294 if (code < 0) return code;
295
296 vchar = pprt->strings[CFG_NAME] ? (const char*)pprt->strings[CFG_NAME] : "";
297 param_string_from_string(vstr, vchar);
298 code = param_write_string(plist, "Name", &vstr);
299 if (code < 0) return code;
300
301 for (i=0;gdev_dmprt_encode_list[i].name;i++) {
302 if (pprt->integer[CFG_ENCODE] == gdev_dmprt_encode_list[i].no)
303 break;
304 }
305 if (gdev_dmprt_encode_list[i].name == 0) i = 0;
306 param_string_from_string(vstr, gdev_dmprt_encode_list[i].name);
307 code = param_write_string(plist, "Encoding", &vstr);
308 if (code < 0) return code;
309
310 #define param_string_from_prt(ps, pprt, n) \
311 ((ps).data = pprt->prtcode[n] ? pprt->prtcode[n] : (const byte*)"", \
312 (ps).size = pprt->prtcode[n] ? pprt->prtcode_size[n] : 0, \
313 (ps).persistent = true)
314 #define param_write_prt(plist, name, pprt, n) \
315 (param_string_from_prt(vstr, pprt, n), \
316 param_write_string(plist, name, &vstr))
317
318 code = param_write_prt(plist, "BitImageMode",
319 pprt, CFG_BIT_IMAGE_MODE);
320 if (code < 0) return code;
321 code = param_write_prt(plist, "SendBitImage",
322 pprt, CFG_SEND_BIT_IMAGE);
323 if (code < 0) return code;
324 code = param_write_prt(plist, "BitRowHeader",
325 pprt, CFG_BIT_ROW_HEADER);
326 if (code < 0) return code;
327 code = param_write_prt(plist, "AfterBitImage",
328 pprt, CFG_AFTER_BIT_IMAGE);
329 if (code < 0) return code;
330 code = param_write_prt(plist, "LineFeed", pprt, CFG_LINE_FEED);
331 if (code < 0) return code;
332 code = param_write_prt(plist, "FormFeed", pprt, CFG_FORM_FEED);
333 if (code < 0) return code;
334 code = param_write_prt(plist, "NormalMode", pprt, CFG_NORMAL_MODE);
335 if (code < 0) return code;
336 code = param_write_prt(plist, "SkipSpaces", pprt, CFG_SKIP_SPACES);
337 if (code < 0) return code;
338
339 return code;
340 }
341 /* end of internal routines for get_params */
342
343 /* --- Put properties of printer device. --- */
344 static int gdev_dmprt_put_dmprt_params(gx_device *pdev, gs_param_list *plist);
345 static int
346 gdev_dmprt_put_dviprt_params(gx_device *pdev, gs_param_list *plist);
347 static int gdev_dmprt_put_prt_code_param(gs_param_list *plist,
348 dviprt_cfg_t *pprt,
349 const char* name, int idx);
350 static int
351 gdev_dmprt_put_prt_string_param(gs_param_list *plist,
352 dviprt_cfg_t *pprt, const char* name, int idx);
353
354 static int
gdev_dmprt_put_params(gx_device * pdev,gs_param_list * plist)355 gdev_dmprt_put_params(gx_device *pdev, gs_param_list *plist)
356 {
357 int code = 0;
358 const char *param_name;
359 gs_param_dict dict;
360
361 if (!pddev->dmprt.prtcfg_init_f)
362 gdev_dmprt_init_printer_props(pddev);
363
364 /* dmprt parameters */
365 code = param_begin_read_dict(plist, (param_name = "DmprtParams"),
366 &dict, false);
367 if (code < 0) return code;
368 if (code == 0) {
369 code = gdev_dmprt_put_dmprt_params(pdev, dict.list);
370 param_end_read_dict(plist, param_name, &dict);
371 if (code < 0) return code;
372 }
373
374 /* dviprt parameters */
375 code = param_begin_read_dict(plist, (param_name = "DviprtParams"),
376 &dict, false);
377 if (code < 0) return code;
378 if (code == 0) {
379 code = gdev_dmprt_put_dviprt_params(pdev, dict.list);
380 param_end_read_dict(plist, param_name, &dict);
381 if (code < 0) return code;
382 }
383
384 if (pdev->is_open && code) {
385 int ccode = gs_closedevice(pdev);
386 if (ccode < 0) return ccode;
387 }
388
389 pddev->width = pddev->dmprt.spec_width;
390 pddev->height = pddev->dmprt.spec_height;
391 code = gdev_prn_put_params(pdev, plist);
392 pddev->dmprt.spec_width = pddev->width;
393 pddev->dmprt.spec_height = pddev->height;
394 pddev->width -= (pddev->dmprt.dev_margin[0] + pddev->dmprt.dev_margin[2]);
395 pddev->height -= (pddev->dmprt.dev_margin[1] + pddev->dmprt.dev_margin[3]);
396 if (code < 0) return code;
397
398 if (pddev->dmprt.max_width>0 && pddev->dmprt.max_width<pddev->width)
399 pddev->width = pddev->dmprt.max_width;
400 if (pddev->dmprt.max_height>0 && pddev->dmprt.max_height<pddev->height)
401 pddev->height = pddev->dmprt.max_height;
402
403 return code;
404 }
405
406 /* internal routines for put_params */
407
408 static int
gdev_dmprt_put_dmprt_params(gx_device * pdev,gs_param_list * plist)409 gdev_dmprt_put_dmprt_params(gx_device *pdev, gs_param_list *plist)
410 {
411 int code;
412 long vlong;
413 bool vbool;
414 gs_param_int_array vaint;
415
416 /* debug flag */
417 code = param_read_bool(plist, "Debug", &vbool);
418 if (code < 0) return code;
419 if (code == 0) pddev->dmprt.debug_f = vbool;
420
421 code = param_read_bool(plist, "Verbose", &vbool);
422 if (code < 0) return code;
423 pddev->dmprt.verbose_f = vbool;
424
425 /* dummy */
426 code = param_read_long(plist, "Version", &vlong);
427 if (code < 0) return code;
428
429 code = param_read_int_array(plist, "MaxSize", &vaint);
430 if (code < 0) return code;
431 if (code == 0) {
432 if (vaint.size != 2) return e_typecheck;
433 pddev->dmprt.max_width = vaint.data[0];
434 pddev->dmprt.max_height = vaint.data[1];
435 }
436
437 code = param_read_int_array(plist, "Offsets", &vaint);
438 if (code < 0) return code;
439 if (code == 0) {
440 if (vaint.size != 2) return e_typecheck;
441 pddev->dmprt.x_offset = vaint.data[0];
442 pddev->dmprt.y_offset = vaint.data[1];
443 }
444
445 code = param_read_int_array(plist, "Margins", &vaint);
446 if (code < 0) return code;
447 if (code == 0) {
448 int i;
449 if (vaint.size != 4) return e_typecheck;
450 for (i=0;i<4;i++) pddev->dmprt.dev_margin[i] = vaint.data[i];
451 }
452
453 return code;
454 }
455
456 static int
gdev_dmprt_put_dviprt_params(gx_device * pdev,gs_param_list * plist)457 gdev_dmprt_put_dviprt_params(gx_device *pdev, gs_param_list *plist)
458 {
459 int code;
460 dviprt_cfg_t *pprt = &pddev->dmprt.prtcfg;
461 gs_param_string vstr;
462 long vlong;
463 bool vbool;
464
465 /* load .cfg/.src file */
466 code = param_read_string(plist, "FileName", &vstr);
467 if (code < 0) return code;
468 if (code == 0) {
469 char *filename = gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), vstr.size + 1, 1,
470 "gdev_dmprt_put_props(filename)");
471 int ccode;
472 if (filename == 0) return e_VMerror;
473 strncpy(filename, (const char*)vstr.data, vstr.size);
474 filename[vstr.size] = '\0';
475 ccode = gdev_dmprt_get_printer_props(pddev,filename);
476 gs_free(gs_lib_ctx_get_non_gc_memory_t(), filename, vstr.size+1, 1, "gdev_dmprt_put_props(filename)");
477 if (ccode < 0) return ccode;
478 }
479
480 code = param_read_long(plist, "Pins", &vlong);
481 if (code < 0) return code;
482 if (code == 0) pprt->integer[CFG_PINS] = vlong / 8;
483
484 code = param_read_long(plist, "MinimalUnit", &vlong);
485 if (code < 0) return code;
486 if (code == 0) pprt->integer[CFG_MINIMAL_UNIT] = vlong;
487
488 code = param_read_long(plist, "MaximalUnit", &vlong);
489 if (code < 0) return code;
490 if (code == 0) pprt->integer[CFG_MAXIMAL_UNIT] = vlong;
491
492 code = param_read_long(plist, "HDpi", &vlong);
493 if (code < 0) return code;
494 if (code == 0) pddev->dmprt.orig_x_dpi = vlong;
495
496 code = param_read_long(plist, "VDpi", &vlong);
497 if (code < 0) return code;
498 if (code == 0) pddev->dmprt.orig_y_dpi = vlong;
499
500 code = param_read_long(plist, "Constant", &vlong);
501 if (code < 0) return code;
502 if (code == 0) pprt->integer[CFG_CONSTANT] = vlong;
503
504 {
505 long tr = pprt->integer[CFG_UPPER_POS] & CFG_NON_TRANSPOSE_BIT;
506 long rv = pprt->integer[CFG_UPPER_POS] & CFG_REVERSE_BIT;
507 long nm = pprt->integer[CFG_UPPER_POS] & CFG_NON_MOVING;
508 param_read_bool(plist,"Transpose", &vbool);
509 if (code < 0) return code;
510 if (code == 0) tr = vbool ? 0 : CFG_NON_TRANSPOSE_BIT;
511 param_read_bool(plist,"Reverse", &vbool);
512 if (code < 0) return code;
513 if (code == 0) rv = vbool ? CFG_REVERSE_BIT : 0;
514 param_read_bool(plist,"NonMoving", &vbool);
515 if (code < 0) return code;
516 if (code == 0) nm = vbool ? CFG_NON_MOVING : 0;
517 pprt->integer[CFG_UPPER_POS] = tr | rv | nm;
518 }
519
520 code = gdev_dmprt_put_prt_code_param(plist, pprt, "BitImageMode",
521 CFG_BIT_IMAGE_MODE);
522 if (code < 0) return code;
523 code = gdev_dmprt_put_prt_code_param(plist, pprt, "SendBitImage",
524 CFG_SEND_BIT_IMAGE);
525 if (code < 0) return code;
526 code = gdev_dmprt_put_prt_code_param(plist, pprt, "BitRowHeader",
527 CFG_BIT_ROW_HEADER);
528 if (code < 0) return code;
529 code = gdev_dmprt_put_prt_code_param(plist, pprt, "AfterBitImage",
530 CFG_AFTER_BIT_IMAGE);
531 if (code < 0) return code;
532 code = gdev_dmprt_put_prt_code_param(plist, pprt, "LineFeed",
533 CFG_LINE_FEED);
534 if (code < 0) return code;
535 code = gdev_dmprt_put_prt_code_param(plist, pprt, "FormFeed",
536 CFG_FORM_FEED);
537 if (code < 0) return code;
538 code = gdev_dmprt_put_prt_code_param(plist, pprt, "NormalMode",
539 CFG_NORMAL_MODE);
540 if (code < 0) return code;
541 code = gdev_dmprt_put_prt_code_param(plist, pprt, "SkipSpaces",
542 CFG_SKIP_SPACES);
543 if (code < 0) return code;
544
545 code = gdev_dmprt_put_prt_string_param(plist, pprt, "Name",
546 CFG_NAME);
547 if (code < 0) return code;
548
549 code = param_read_string(plist, "Encoding", &vstr);
550 if (code < 0) return code;
551 if (code == 0) {
552 int i;
553 for (i=0; gdev_dmprt_encode_list[i].name ; i++) {
554 if (strlen(gdev_dmprt_encode_list[i].name) == vstr.size) {
555 if (strncmp(gdev_dmprt_encode_list[i].name,
556 vstr.data, vstr.size) == 0) {
557 pprt->integer[CFG_ENCODE] = gdev_dmprt_encode_list[i].no;
558 break;
559 }
560 }
561 }
562 if (gdev_dmprt_encode_list[i].name == 0)
563 return e_rangecheck;
564 }
565
566 return code;
567 }
568
569 static int
gdev_dmprt_put_prt_code_param(gs_param_list * plist,dviprt_cfg_t * pprt,const char * name,int idx)570 gdev_dmprt_put_prt_code_param(gs_param_list *plist,
571 dviprt_cfg_t *pprt, const char* name, int idx)
572 {
573 gs_param_string vstr;
574
575 int code = param_read_string(plist, name, &vstr);
576 if (code == 0) {
577 int ccode = gdev_dmprt_check_code_props(vstr.data, vstr.size);
578 byte *pbyte;
579 if (ccode < 0) return e_rangecheck;
580 pbyte = (byte *)malloc(vstr.size+1);
581 if (pbyte == 0) return e_VMerror;
582 memcpy(pbyte, vstr.data, vstr.size);
583 pbyte[vstr.size] = 0;
584 pprt->prtcode[idx] = pbyte;
585 pprt->prtcode_size[idx] = vstr.size;
586 if (code == 0) code = 1;
587 }
588 return code;
589 }
590
591 static int
gdev_dmprt_put_prt_string_param(gs_param_list * plist,dviprt_cfg_t * pprt,const char * name,int idx)592 gdev_dmprt_put_prt_string_param(gs_param_list *plist,
593 dviprt_cfg_t *pprt, const char* name, int idx)
594 {
595 gs_param_string vstr;
596
597 int code = param_read_string(plist, name, &vstr);
598 if (code == 0) {
599 byte *pbyte;
600 pbyte = (byte *)malloc(vstr.size+1);
601 if (pbyte == 0) return e_VMerror;
602 memcpy(pbyte, vstr.data, vstr.size);
603 pbyte[vstr.size] = 0;
604 pprt->strings[idx] = pbyte;
605 if (code == 0) code = 1;
606 }
607 return code;
608 }
609 /* end of internal routines for put_params */
610
611 /* --- Get initial matrix. --- */
612 static void
gdev_dmprt_get_initial_matrix(gx_device * pdev,gs_matrix * pmat)613 gdev_dmprt_get_initial_matrix(gx_device *pdev, gs_matrix *pmat)
614 {
615 gx_default_get_initial_matrix(pdev,pmat);
616 pmat->tx += (pddev->dmprt.x_offset - pddev->dmprt.dev_margin[0]);
617 pmat->ty += (pddev->dmprt.y_offset + pddev->dmprt.dev_margin[3]);
618 }
619
620 /* --- Open printer device. --- */
621 static int
gdev_dmprt_open(gx_device * pdev)622 gdev_dmprt_open(gx_device *pdev)
623 {
624 int code;
625 dviprt_cfg_t *pcfg;
626 dviprt_print *pprint;
627
628 pprint = &pddev->dmprt.prtinfo;
629 pcfg = &pddev->dmprt.prtcfg;
630
631 if ((code = gdev_prn_open(pdev)) < 0)
632 return code;
633 pcfg->integer[CFG_DPI] = (int)ppdev->x_pixels_per_inch;
634 pcfg->integer[CFG_Y_DPI] = (int)ppdev->y_pixels_per_inch;
635 code = dviprt_initlibrary(pprint,pcfg,gdev_prn_raster(pdev),pdev->height);
636 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
637 code = dviprt_setbuffer(pprint,NULL);
638 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
639
640 return 0;
641 }
642
643 /* --- Close printer device. --- */
644 static int
gdev_dmprt_close(gx_device * pdev)645 gdev_dmprt_close(gx_device *pdev)
646 {
647 int code;
648 dviprt_print *pprint;
649
650 pprint = &pddev->dmprt.prtinfo;
651
652 if (!strchr(pddev->fname,'%')) {
653 code = dviprt_endbitmap(pprint);
654 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
655 }
656 if (pddev->dmprt.verbose_f && pddev->PageCount>0) {
657 emprintf2(pdev->memory,
658 "%s: Total %lu bytes output.\n",
659 pddev->dname,
660 dviprt_getoutputbytes(pprint));
661 }
662 code = dviprt_unsetbuffer(pprint);
663 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
664 return gdev_prn_close(pdev);
665 }
666
667 /* Output the PAGE. */
668 static int
gdev_dmprt_print_page(gx_device_printer * pdev,FILE * prn_stream)669 gdev_dmprt_print_page(gx_device_printer *pdev, FILE *prn_stream)
670 {
671 int code = 0;
672 dviprt_print *pprint = &pddev->dmprt.prtinfo;
673 int line_size = gdev_prn_raster((gx_device *)pdev);
674 int pins = dviprt_getscanlines(pprint);
675 int i_buf_size = pins * line_size;
676 int lnum = 0;
677 ulong prev_bytes;
678 byte *in;
679
680 /* get work buffer */
681 in = (byte *)gs_malloc(pdev->memory->non_gc_memory, 1, i_buf_size ,"gdev_dmprt_print_page(in)");
682 if ( in == 0 )
683 return e_VMerror;
684
685 /* Initialize this printer driver */
686 if (pdev->file_is_new) {
687 code = dviprt_setstream(pprint,NULL,prn_stream);
688 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
689 }
690 if (pddev->dmprt.verbose_f) {
691 if (pddev->PageCount == 1)
692 emprintf2(pdev->memory,
693 "%s: %s\n",
694 pddev->dname,
695 pddev->dmprt.prtcfg.strings[CFG_NAME]);
696 emprintf2(pdev->memory,
697 "%s: [%ld]",
698 pddev->dname,
699 pddev->PageCount);
700 }
701 prev_bytes = dviprt_getoutputbytes(pprint);
702 code = dviprt_beginpage(pprint);
703 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
704
705 /* Transfer pixels to printer */
706 while ( lnum < pdev->height ) {
707 int num_lines;
708
709 num_lines = pdev->height-lnum;
710 if (num_lines > pins)
711 num_lines = pins;
712
713 code = gdev_prn_copy_scan_lines(pdev,lnum,in,line_size*num_lines);
714 if (code < 0) goto error_ex;
715
716 lnum += num_lines;
717 if (num_lines < pins) {
718 memset(in+line_size*num_lines,0,line_size*(pins-num_lines));
719 }
720
721 code = dviprt_outputscanlines(pprint,in);
722 if (code < 0) {
723 code = gdev_dmprt_error_no_dviprt_to_gs(code);
724 goto error_ex;
725 }
726 }
727
728 /* Eject the page and set printer normal mode. */
729 if (strchr(pdev->fname,'%')) {
730 code = dviprt_endbitmap(pprint);
731 if (code < 0) return gdev_dmprt_error_no_dviprt_to_gs(code);
732 }
733 fflush(pddev->file);
734 if (pddev->dmprt.verbose_f) {
735 emprintf1(pdev->memory,
736 " %lu bytes\n",
737 dviprt_getoutputbytes(pprint)-prev_bytes);
738 }
739 error_ex:
740 gs_free(pdev->memory->non_gc_memory, (char *)in, 1, i_buf_size,"gdev_dmprt_print_page(in)");
741
742 return code;
743 }
744
745 /************************** Internal Routines **************************/
746
747 /************************ Get printer properties. ***********************/
748 static int
gdev_dmprt_check_code_props(byte * str,int len)749 gdev_dmprt_check_code_props(byte *str,int len)
750 {
751 byte *end = str+len;
752 while (str < end) {
753 byte fmt = *str++;
754 if (fmt & CFG_FMT_BIT) {
755 int s = *str++;
756 str += s;
757 if (str > end) return e_rangecheck;
758 if ((fmt & CFG_FMT_FORMAT_BIT) == CFG_FMT_STRINGS) {
759 s = *str++;
760 str += s;
761 if (str > end) return e_rangecheck;
762 }
763 }
764 else {
765 str += fmt;
766 if (str > end) return e_rangecheck;
767 }
768 }
769 return str == end ? 0 : e_rangecheck;
770 }
771
772 static void
gdev_dmprt_init_printer_props(gx_device_dmprt * pdev)773 gdev_dmprt_init_printer_props(gx_device_dmprt *pdev)
774 {
775 dviprt_cfg_t *pprt;
776 int i;
777
778 pprt = &pdev->dmprt.prtcfg;
779
780 for (i=0;i<CFG_INTEGER_TYPE_COUNT;i++)
781 pprt->integer[i] = 0;
782 for (i=0;i<CFG_STRINGS_TYPE_COUNT;i++)
783 pprt->strings[i] = 0;
784 for (i=0;i<CFG_PRTCODE_TYPE_COUNT;i++) {
785 pprt->prtcode[i] = 0;
786 pprt->prtcode_size[i] = 0;
787 }
788 pdev->dmprt.prtcfg_init_f = 1;
789 }
790
791 static int
gdev_dmprt_get_printer_props(gx_device_dmprt * pdev,char * fnamebase)792 gdev_dmprt_get_printer_props(gx_device_dmprt *pdev,char *fnamebase)
793 {
794 int code;
795 FILE *fp;
796 dviprt_cfg_t cfg;
797 char *fname;
798
799 fname = gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), 256,1,"dviprt_lib_fname");
800 if (fname == NULL) return e_VMerror;
801
802 fp = gdev_dmprt_dviprt_lib_fopen(fnamebase,fname);
803 if (fp == NULL) {
804 return e_undefinedfilename;
805 }
806 if (fseek(fp,18,0) < 0)
807 return e_ioerror;
808 code = fgetc(fp);
809 fclose(fp);
810
811 if (code == EOF)
812 code = e_ioerror;
813 else if (code == 0xff) {
814 code = dviprt_readcfg(fname,&cfg,NULL,0,NULL,0);
815 }
816 else {
817 code = dviprt_readsrc(fname,&cfg,NULL,0,NULL,0);
818 }
819
820 if (code < 0) {
821 code = gdev_dmprt_error_no_dviprt_to_gs(code);
822 }
823 else { /* success */
824 memcpy(&pdev->dmprt.prtcfg,&cfg,sizeof(dviprt_cfg_t));
825 pddev->dmprt.orig_x_dpi = cfg.integer[CFG_DPI];
826 pddev->dmprt.orig_y_dpi =
827 cfg.integer[CFG_Y_DPI] > 0 ? cfg.integer[CFG_Y_DPI] : pddev->dmprt.orig_x_dpi;
828 }
829
830 gs_free(gs_lib_ctx_get_non_gc_memory_t(), fname,256,1,"dviprt_lib_fname");
831
832 return code;
833 }
834
835 static const char * gp_file_name_concat_string(const char *, unsigned);
836 static FILE *
gdev_dmprt_dviprt_lib_fopen(const char * fnamebase,char * fname)837 gdev_dmprt_dviprt_lib_fopen(const char *fnamebase,char *fname)
838 {
839 FILE *fp;
840 char *env;
841
842 strcpy(fname,fnamebase);
843 fp = fopen(fname,"r");
844 if (fp == NULL) {
845 env = getenv("TEXCFG");
846 if (env) {
847 strcpy(fname,env);
848 strcat(fname, gp_file_name_concat_string(env,strlen(env)));
849 fp = fopen(fname,gp_fmode_rb);
850 }
851 }
852 return fp;
853 }
854
855 /* Misc. */
856 static int
gdev_dmprt_error_no_dviprt_to_gs(int code)857 gdev_dmprt_error_no_dviprt_to_gs(int code)
858 {
859 switch (code) {
860 case CFG_ERROR_MEMORY:
861 return e_VMerror;
862 case CFG_ERROR_FILE_OPEN:
863 case CFG_ERROR_OUTPUT:
864 return e_ioerror;
865 default:
866 return -1;
867 }
868 }
869
870 /* Answer the string to be used for combining a directory/device prefix */
871 /* with a base file name. The prefix directory/device is examined to */
872 /* determine if a separator is needed and may return an empty string */
873 static const char *
gp_file_name_concat_string(const char * prefix,unsigned plen)874 gp_file_name_concat_string(const char *prefix, unsigned plen)
875 {
876 if (plen > 0 && prefix[plen - 1] == '/')
877 return "";
878 return "/";
879 }
880