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