1 /*
2  *
3  *   Print plug-in CANON BJL driver for the GIMP.
4  *
5  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com),
6  *	Robert Krawitz (rlk@alum.mit.edu) and
7  *      Andy Thaller (thaller@ph.tum.de)
8  *
9  *   Copyright (c) 2006 - 2007 Sascha Sommer (saschasommer@freenet.de)
10  *
11  *   This program is free software; you can redistribute it and/or modify it
12  *   under the terms of the GNU General Public License as published by the Free
13  *   Software Foundation; either version 2 of the License, or (at your option)
14  *   any later version.
15  *
16  *   This program is distributed in the hope that it will be useful, but
17  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19  *   for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
23  */
24 
25 /*
26  * This file must include only standard C header files.  The core code must
27  * compile on generic platforms that don't support glib, gimp, gtk, etc.
28  */
29 
30 /*
31  * Large parts of this file (mainly the ink handling) is based on
32  * print-escp2.c -- refer to README.new-printer on how to adjust the colors
33  * for a certain model.
34  */
35 
36 /* TODO-LIST
37  *
38  *   * adjust the colors of all supported models
39  *
40  */
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 #include <gutenprint/gutenprint.h>
45 #include "gutenprint-internal.h"
46 #include <gutenprint/gutenprint-intl-internal.h>
47 #include <string.h>
48 #include <stdio.h>
49 #if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
50 #include <varargs.h>
51 #else
52 #include <stdarg.h>
53 #endif
54 #ifdef HAVE_LIMITS_H
55 #include <limits.h>
56 #endif
57 #include <math.h>
58 
59 #include "print-canon.h"
60 
61 #ifndef MIN
62 #  define MIN(a,b) (((a)<(b)) ? (a) : (b))
63 #endif /* !MIN */
64 #ifndef MAX
65 #  define MAX(a, b) ((a) > (b) ? (a) : (b))
66 #endif /* !MAX */
67 
68 /* 5 3-level pixels into 1 byte */
69 static int
pack_pixels(unsigned char * buf,int len)70 pack_pixels(unsigned char* buf,int len)
71 {
72   int read_pos = 0;
73   int write_pos = 0;
74   int shift = 6;
75   while(read_pos < len)
76   {
77     /* read 5pixels at 2 bit */
78     unsigned short value = buf[read_pos] << 8;
79     if(read_pos+1 < len)
80       value += buf[read_pos + 1];
81     if(shift)       /*6,4,2,0*/
82       value >>= shift;
83     /* write 8bit value representing the 10 bit pixel combination */
84     buf[write_pos] = tentoeight[value & 1023];
85     ++write_pos;
86     if(shift == 0)
87     {
88       shift = 6;
89       read_pos += 2;
90     }
91     else
92     {
93       shift -= 2;
94       ++read_pos;
95     }
96   }
97   return write_pos;
98 }
99 
100 /* 3 4-bit-per-pixel  5-level pixels into 1 byte */
101 static int
pack_pixels3_5(unsigned char * buf,int len)102 pack_pixels3_5(unsigned char* buf,int len)
103 {
104   int read_pos = 0;
105   int write_pos = 0;
106   int shift = 4;
107   while(read_pos < len)
108   {
109     /* read 3pixels at 4 bit */
110     unsigned short value = buf[read_pos] << 8;
111     if(read_pos+1 < len)
112       value += buf[read_pos + 1];
113     if(shift)       /*4,0*/
114       value >>= shift;
115     /* write 8bit value representing the 12 bit pixel combination */
116     buf[write_pos] = twelve2eight[value & 4095];
117     ++write_pos;
118     if(shift == 0)
119     {
120       shift = 4;
121       read_pos += 2;
122     }
123     else
124     {
125       shift -= 4;
126       ++read_pos;
127     }
128   }
129   return write_pos;
130 }
131 
132 /* 3 4-bit-per-pixel 6-level pixels into 1 byte */
133 static int
pack_pixels3_6(unsigned char * buf,int len)134 pack_pixels3_6(unsigned char* buf,int len)
135 {
136   int read_pos = 0;
137   int write_pos = 0;
138   int shift = 4;
139   while(read_pos < len)
140   {
141     /* read 3pixels at 4 bit */
142     unsigned short value = buf[read_pos] << 8;
143     if(read_pos+1 < len)
144       value += buf[read_pos + 1];
145     if(shift)       /*4,0*/
146       value >>= shift;
147     /* write 8bit value representing the 12 bit pixel combination */
148     buf[write_pos] = twelve2eight2[value & 4095];
149     ++write_pos;
150     if(shift == 0)
151     {
152       shift = 4;
153       read_pos += 2;
154     }
155     else
156     {
157       shift -= 4;
158       ++read_pos;
159     }
160   }
161   return write_pos;
162 }
163 
164 /* model peculiarities */
165 #define CANON_CAP_MSB_FIRST  0x02ul    /* how to send data           */
166 #define CANON_CAP_a          0x04ul
167 #define CANON_CAP_b          0x08ul
168 #define CANON_CAP_q          0x10ul
169 #define CANON_CAP_m          0x20ul
170 #define CANON_CAP_d          0x40ul
171 #define CANON_CAP_t          0x80ul
172 #define CANON_CAP_c          0x100ul
173 #define CANON_CAP_p          0x200ul
174 #define CANON_CAP_l          0x400ul
175 #define CANON_CAP_r          0x800ul
176 #define CANON_CAP_g          0x1000ul
177 #define CANON_CAP_px         0x2000ul
178 #define CANON_CAP_rr         0x4000ul
179 #define CANON_CAP_I          0x8000ul
180 #define CANON_CAP_T          0x10000ul /* cartridge selection for PIXMA printers with Black and Color carts */
181 #define CANON_CAP_P          0x20000ul /* related to media type selection */
182 #define CANON_CAP_DUPLEX     0x40000ul /* duplex printing */
183 #define CANON_CAP_XML        0x80000ul /* use of XML at start and end of print data */
184 #define CANON_CAP_CARTRIDGE  0x100000ul /* not sure of this yet */
185 #define CANON_CAP_M          0x200000ul /* not sure of this yet */
186 #define CANON_CAP_S          0x400000ul /* not sure of this yet */
187 #define CANON_CAP_cart       0x800000ul /* BJC printers with Color, Black, Photo options */
188 #define CANON_CAP_BORDERLESS 0x1000000ul /* borderless (fullbleed) printing */
189 #define CANON_CAP_NOBLACK    0x2000000ul /* no Black cartridge selection */
190 #define CANON_CAP_v          0x4000000ul /* not sure of this yet */
191 #define CANON_CAP_w          0x8000000ul /* related to media type selection */
192 #define CANON_CAP_s          0x10000000ul /* not sure of this yet: duplex-related? */
193 #define CANON_CAP_u          0x20000000ul /* not sure of this yet: duplex-related? */
194 
195 #define CANON_CAP_STD0 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|\
196                         CANON_CAP_l|CANON_CAP_q|CANON_CAP_t)
197 
198 #define CANON_CAP_STD1 (CANON_CAP_b|CANON_CAP_c|CANON_CAP_d|CANON_CAP_l|\
199                         CANON_CAP_m|CANON_CAP_p|CANON_CAP_q|CANON_CAP_t)
200 
201 #include "canon-inks.h"
202 #include "canon-modes.h"
203 #include "canon-media.h"
204 #include "canon-media-mode.h"
205 #include "canon-printers.h"
206 
207 typedef struct {
208     char name;
209     const canon_ink_t* props;
210     unsigned char* buf;
211     unsigned char* comp_buf_offset;
212     unsigned int buf_length;
213     unsigned int delay;
214 } canon_channel_t;
215 
216 typedef struct
217 {
218   const canon_mode_t* mode;
219   const canon_slot_t* slot;
220   const canon_paper_t *pt;
221   /* cartridge selection for CANON_CAP_T and CANON_CAP_cart */
222   const char *ink_set;
223   const canon_modeuse_t* modeuse;
224   /* final inks used for output, after selection process completed */
225   unsigned int used_inks;
226   int num_channels;
227   int quality;
228   canon_channel_t* channels;
229   char* channel_order;
230   const canon_cap_t *caps;
231   unsigned char *comp_buf;
232   unsigned char *fold_buf;
233   int delay_max;
234   int buf_length_max;
235   int length;
236   int out_width;
237   int out_height;
238   int page_width;
239   int page_height;
240   int top;
241   int left;
242   int emptylines;
243   int ncolors; /* number of colors to print with */
244   int physical_xdpi, nozzle_ydpi, stepper_ydpi;
245   int nozzles;   /* count of inkjets for one pass */
246   int nozzle_separation;
247   int horizontal_passes;
248   int vertical_passes;
249   int vertical_oversample;
250   int *head_offset;
251   int last_pass_offset;
252   int bidirectional; /* tells us if we are allowed to print bidirectional */
253   int direction;     /* stores the last direction of the print head */
254   int weave_bits[4];
255   const char *duplex_str;
256   int is_first_page;
257   double cd_inner_radius;
258   double cd_outer_radius;
259 } canon_privdata_t;
260 
261 static const canon_modeuse_t* select_media_modes(stp_vars_t *v, const canon_paper_t* media_type,const canon_modeuselist_t* mlist);
262 static int compare_mode_valid(stp_vars_t *v,const canon_mode_t* mode,const canon_modeuse_t* muse, const canon_modeuselist_t* mlist);
263 static const canon_mode_t* suitable_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
264 static const canon_mode_t* find_first_matching_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
265 static const canon_mode_t* find_first_matching_mode(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
266 static const canon_mode_t* suitable_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
267 static const canon_mode_t* find_first_matching_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
268 static const canon_mode_t* suitable_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
269 static const canon_mode_t* find_first_matching_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode);
270 static const canon_mode_t* suitable_mode_general(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode);
271 static const char* find_ink_type(stp_vars_t *v,const canon_mode_t* mode,const char *printing_mode);
272 static const canon_mode_t* canon_check_current_mode(stp_vars_t *v);
273 
274 static void canon_write_line(stp_vars_t *v);
275 
276 static void canon_advance_paper(stp_vars_t *, int);
277 static void canon_flush_pass(stp_vars_t *, int, int);
278 static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y);
279 
280 static void fix_papersize(unsigned char arg_ESCP_1, int *paper_width, int *paper_length);
281 
282 static const stp_parameter_t the_parameters[] =
283 {
284   {
285     "PageSize", N_("Page Size"), "Color=No,Category=Basic Printer Setup",
286     N_("Size of the paper being printed to"),
287     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
288     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
289   },
290   {
291     "MediaType", N_("Media Type"), "Color=Yes,Category=Basic Printer Setup",
292     N_("Type of media (plain paper, photo paper, etc.)"),
293     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
294     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
295   },
296   {
297     "InputSlot", N_("Media Source"), "Color=No,Category=Basic Printer Setup",
298     N_("Source (input slot) of the media"),
299     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
300     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
301   },
302   {
303     "CassetteTray", N_("Cassette Tray"), "Color=No,Category=Basic Printer Setup",
304     N_("Tray selection for cassette media source"),
305     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
306     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
307   },
308   {
309     "CDInnerRadius", N_("CD Hub Size"), "Color=No,Category=Basic Printer Setup",
310     N_("Print only outside of the hub of the CD, or all the way to the hole"),
311     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
312     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
313   },
314   {
315     "CDOuterDiameter", N_("CD Size (Custom)"), "Color=No,Category=Basic Printer Setup",
316     N_("Variable adjustment for the outer diameter of CD"),
317     STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
318     STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
319   },
320   {
321     "CDInnerDiameter", N_("CD Hub Size (Custom)"), "Color=No,Category=Basic Printer Setup",
322     N_("Variable adjustment to the inner hub of the CD"),
323     STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
324     STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
325   },
326   {
327     "CDXAdjustment", N_("CD Horizontal Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
328     N_("Fine adjustment to horizontal position for CD printing"),
329     STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
330     STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
331   },
332   {
333     "CDYAdjustment", N_("CD Vertical Fine Adjustment"), "Color=No,Category=Advanced Printer Setup",
334     N_("Fine adjustment to horizontal position for CD printing"),
335     STP_PARAMETER_TYPE_DIMENSION, STP_PARAMETER_CLASS_FEATURE,
336     STP_PARAMETER_LEVEL_ADVANCED, 1, 1, STP_CHANNEL_NONE, 1, 0
337   },
338   {
339     "Resolution", N_("Resolution"), "Color=Yes,Category=Basic Printer Setup",
340     N_("Resolution and quality of the print"),
341     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
342     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
343   },
344   /*
345    * Don't check this parameter.  We may offer different settings for
346    * different ink sets, but we need to be able to handle settings from PPD
347    * files that don't have constraints set up.
348    */
349   {
350     "InkType", N_("Ink Type"), "Color=Yes,Category=Advanced Printer Setup",
351     N_("Type of ink in the printer"),
352     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
353     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
354   },
355   {
356     "InkChannels", N_("Ink Channels"), "Color=Yes,Category=Advanced Printer Functionality",
357     N_("Ink Channels"),
358     STP_PARAMETER_TYPE_INT, STP_PARAMETER_CLASS_FEATURE,
359     STP_PARAMETER_LEVEL_INTERNAL, 0, 0, STP_CHANNEL_NONE, 0, 0
360   },
361   /*
362    * Don't check this parameter.  We may offer different settings for
363    * different ink sets, but we need to be able to handle settings from PPD
364    * files that don't have constraints set up.
365    */
366   {
367     "PrintingMode", N_("Printing Mode"), "Color=Yes,Category=Core Parameter",
368     N_("Printing Output Mode"),
369     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
370     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
371   },
372   /*
373    * Don't check this parameter.  We may offer different settings for
374    * different ink sets, but we need to be able to handle settings from PPD
375    * files that don't have constraints set up.
376    */
377   {
378     "InkSet", N_("Ink Set"), "Color=Yes,Category=Basic Printer Setup",
379     N_("Type of inkset in the printer"),
380     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
381     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
382   },
383   {
384     "FullBleed", N_("Borderless"), "Color=No,Category=Basic Printer Setup",
385     N_("Print without borders"),
386     STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
387     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
388   },
389   {
390     "Duplex", N_("Double-Sided Printing"), "Color=No,Category=Basic Printer Setup",
391     N_("Duplex/Tumble Setting"),
392     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
393     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0
394   },
395   {
396     "Quality", N_("Print Quality"), "Color=Yes,Category=Basic Output Adjustment",
397     N_("Print Quality"),
398     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
399     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 0, 0
400   },
401   {
402     "Orientation", N_("Orientation"), "Color=No,Category=Basic Printer Setup",
403     N_("Orientation, Portrait, Landscape, Upside Down, Seascape"),
404     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
405     STP_PARAMETER_LEVEL_BASIC, 1, 1, STP_CHANNEL_NONE, 1, 0,
406   },
407 };
408 
409 static const int the_parameter_count =
410 sizeof(the_parameters) / sizeof(const stp_parameter_t);
411 
412 typedef struct
413 {
414   const stp_parameter_t param;
415   double min;
416   double max;
417   double defval;
418   int color_only;
419 } float_param_t;
420 
421 static const float_param_t float_parameters[] =
422 {
423   {
424     {
425       "CyanDensity", N_("Cyan Density"), "Color=Yes,Category=Output Level Adjustment",
426       N_("Adjust the cyan density"),
427       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
428       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
429     }, 0.0, 2.0, 1.0, 1
430   },
431   {
432     {
433       "MagentaDensity", N_("Magenta Density"), "Color=Yes,Category=Output Level Adjustment",
434       N_("Adjust the magenta density"),
435       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
436       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
437     }, 0.0, 2.0, 1.0, 1
438   },
439   {
440     {
441       "YellowDensity", N_("Yellow Density"), "Color=Yes,Category=Output Level Adjustment",
442       N_("Adjust the yellow density"),
443       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
444       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
445     }, 0.0, 2.0, 1.0, 1
446   },
447   {
448     {
449       "BlackDensity", N_("Black Density"), "Color=Yes,Category=Output Level Adjustment",
450       N_("Adjust the black density"),
451       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
452       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
453     }, 0.0, 2.0, 1.0, 1
454   },
455   {
456     {
457       "LightCyanTrans", N_("Light Cyan Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
458       N_("Light Cyan Transition"),
459       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
460       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
461     }, 0.0, 5.0, 1.0, 1
462   },
463   {
464     {
465       "LightMagentaTrans", N_("Light Magenta Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
466       N_("Light Magenta Transition"),
467       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
468       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
469     }, 0.0, 5.0, 1.0, 1
470   },
471  {
472     {
473       "LightYellowTrans", N_("Light Yellow Transition"), "Color=Yes,Category=Advanced Ink Adjustment",
474       N_("Light Yellow Transition"),
475       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
476       STP_PARAMETER_LEVEL_ADVANCED4, 0, 1, STP_CHANNEL_NONE, 1, 0
477     }, 0.0, 5.0, 1.0, 1
478   },
479 };
480 
481 static const int float_parameter_count =
482 sizeof(float_parameters) / sizeof(const float_param_t);
483 
484 /*
485  * Duplex support - modes available
486  * Note that the internal names MUST match those in cups/genppd.c else the
487  * PPD files will not be generated correctly
488  */
489 
490 static const stp_param_string_t duplex_types[] =
491 {
492   { "None",             N_ ("Off") },
493   { "DuplexNoTumble",   N_ ("Long Edge (Standard)") },
494   { "DuplexTumble",     N_ ("Short Edge (Flip)") }
495 };
496 #define NUM_DUPLEX (sizeof (duplex_types) / sizeof (stp_param_string_t))
497 
498 /*
499  * Orientation support - modes available
500  * Note that the internal names MUST match those in cups/genppd.c else the
501  * PPD files will not be generated correctly
502  */
503 
504 static const stp_param_string_t orientation_types[] = {
505   {"Portrait", N_("Portrait")},
506   {"Landscape", N_("Landscape")},
507   {"UpsideDown", N_("Reverse Portrait")},
508   {"Seascape", N_("Reverse Landscape")},
509 };
510 #define NUM_ORIENTATION (sizeof (orientation_types) / sizeof (stp_param_string_t))
511 
512 static const canon_paper_t *
get_media_type(const canon_cap_t * caps,const char * name)513 get_media_type(const canon_cap_t* caps,const char *name)
514 {
515   int i;
516   if (name && caps->paperlist)
517     {
518       for (i = 0; i < caps->paperlist->count; i++)
519         {
520 	  /* translate paper_t.name */
521 	  if (!strcmp(name, caps->paperlist->papers[i].name))
522 	    return &(caps->paperlist->papers[i]);
523         }
524       return &(caps->paperlist->papers[0]);
525     }
526   return NULL;
527 }
528 
529 static const char* canon_families[] = {
530  "", /* the old BJC printers */
531  "S",         /*  1 */
532  "i",         /*  2 */
533  "PIXMA iP",  /*  3 */
534  "PIXMA iX",  /*  4 */
535  "PIXMA MP",  /*  5 */
536  "PIXUS",     /*  6 */
537  "PIXMA Pro", /*  7 */
538  "PIXMA MG",  /*  8 */
539  "PIXMA MX",  /*  9 */
540  "SELPHY DS", /* 10 */
541  "PIXMA mini",/* 11 */
542  "PIXMA E",   /* 12 */
543  "PIXMA P",   /* 13 */
544  "MAXIFY iB", /* 14 */
545  "MAXIFY MB", /* 15 */
546  "PIXMA MPC", /* 16 */
547  "PIXMA G",   /* 17 */
548  "PIXMA TS",  /* 18 */
549  "PIXMA TR",  /* 19 */
550  "PIXMA XK",  /* 20 */
551 };
552 
553 /* canon model ids look like the following
554    FFMMMMMM
555    FF: family is the offset in the canon_families struct
556    MMMMMM: model nr
557 */
canon_get_printername(const stp_vars_t * v)558 static char* canon_get_printername(const stp_vars_t* v)
559 {
560   unsigned int model = stp_get_model_id(v);
561   unsigned int family = model / 1000000;
562   unsigned int nr = model - family * 1000000;
563   char* name;
564   size_t len;
565   if(family >= sizeof(canon_families) / sizeof(canon_families[0])){
566     stp_eprintf(v,"canon_get_printername: no family %i using default BJC\n", family);
567     family = 0;
568   }
569   len = strlen(canon_families[family]) + 7; /* max model nr. + terminating 0 */
570   name = stp_zalloc(len);
571   snprintf(name,len,"%s%u",canon_families[family],nr);
572   stp_dprintf(STP_DBG_CANON, v,"canon_get_printername: current printer name: %s\n", name);
573   return name;
574 }
575 
canon_get_model_capabilities(const stp_vars_t * v)576 static const canon_cap_t * canon_get_model_capabilities(const stp_vars_t*v)
577 {
578   int i;
579   char* name = canon_get_printername(v);
580   int models= sizeof(canon_model_capabilities) / sizeof(canon_cap_t);
581   for (i=0; i<models; i++) {
582     if (!strcmp(canon_model_capabilities[i].name,name)) {
583       stp_free(name);
584       return &(canon_model_capabilities[i]);
585     }
586   }
587   stp_eprintf(v,"canon: model %s not found in capabilities list=> using default\n",name);
588   stp_free(name);
589   return &(canon_model_capabilities[0]);
590 }
591 
592 static const canon_slot_t *
canon_source_type(const char * name,const canon_cap_t * caps)593 canon_source_type(const char *name, const canon_cap_t * caps)
594 {
595     if(name){
596         int i;
597         for(i=0; i<caps->slotlist->count; i++){
598             if( !strcmp(name,caps->slotlist->slots[i].name))
599                  return &(caps->slotlist->slots[i]);
600         }
601     }
602     return &(caps->slotlist->slots[0]);
603 }
604 
605 /* function returns the current set printmode (specified by resolution) */
606 /* if no mode is set the default mode will be returned */
canon_get_current_mode(const stp_vars_t * v)607 static const canon_mode_t* canon_get_current_mode(const stp_vars_t *v){
608 #if 0
609     const char* input_slot = stp_get_string_parameter(v, "InputSlot");
610     const char *quality = stp_get_string_parameter(v, "Quality");
611 #endif
612     const char *resolution = stp_get_string_parameter(v, "Resolution");
613     const canon_cap_t * caps = canon_get_model_capabilities(v);
614     const canon_mode_t* mode = NULL;
615     const char *ink_type = stp_get_string_parameter(v, "InkType");/*debug*/
616     const char *ink_set = stp_get_string_parameter(v, "InkSet");/*debug*/
617     int i;
618 
619     stp_dprintf(STP_DBG_CANON, v,"Entered canon_get_current_mode\n");
620 
621     if (ink_set)
622       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkSet value (high priority): '%s'\n",ink_set);
623     else
624       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkSet value is NULL\n");
625 
626     if (ink_type)
627       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkType value (low priority): '%s'\n",ink_type);
628     else
629       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: InkType value is NULL\n");
630 
631     if(resolution){
632       for(i=0;i<caps->modelist->count;i++){
633             if(!strcmp(resolution,caps->modelist->modes[i].name)){
634                 mode = &caps->modelist->modes[i];
635                 break;
636             }
637         }
638     }
639 #if 0
640     if(!mode)
641         mode = &caps->modelist->modes[caps->modelist->default_mode];
642 #endif
643 
644 #if 0
645     if(quality && strcmp(quality, "None") == 0)
646         quality = "Standard";
647 
648     if(quality && !strcmp(quality,"Standard")){
649         return &caps->modelist->modes[caps->modelist->default_mode];
650     }
651 #endif
652 
653 #if 0
654     /* only some modes can print to cd */
655     if(input_slot && !strcmp(input_slot,"CD") && !(mode->flags & MODE_FLAG_CD)){
656         for(i=0;i<caps->modelist->count;i++){
657             if(caps->modelist->modes[i].flags & MODE_FLAG_CD){
658                 mode = &caps->modelist->modes[i];
659                 break;
660             }
661         }
662     }
663 #endif
664 
665     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: current mode is '%s'\n",resolution);
666 
667     return mode;
668 }
669 
select_media_modes(stp_vars_t * v,const canon_paper_t * media_type,const canon_modeuselist_t * mlist)670 const canon_modeuse_t* select_media_modes(stp_vars_t *v, const canon_paper_t* media_type,const canon_modeuselist_t* mlist){
671   const canon_modeuse_t* muse = NULL;
672   int i;
673   for(i=0;i<mlist->count;i++){
674     if(!strcmp(media_type->name,mlist->modeuses[i].name)){
675       muse = &mlist->modeuses[i];
676       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: assigned media '%s'\n",mlist->name);
677       break;
678     }
679   }
680   return muse;
681 }
682 
compare_mode_valid(stp_vars_t * v,const canon_mode_t * mode,const canon_modeuse_t * muse,const canon_modeuselist_t * mlist)683 int compare_mode_valid(stp_vars_t *v,const canon_mode_t* mode,const canon_modeuse_t* muse, const canon_modeuselist_t* mlist){
684   int i=0;
685   int modecheck=1;
686   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: assigned mode-media '%s'\n",mlist->name);
687   while (muse->mode_name_list[i]!=NULL){
688     if(!strcmp(mode->name,muse->mode_name_list[i])){
689       modecheck=0;
690       break;
691     }
692     i++;
693   }
694   return modecheck;
695 }
696 
suitable_mode_monochrome(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)697 const canon_mode_t* suitable_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
698   const canon_mode_t* mode=NULL;
699   int i=0;
700   int j;
701   int modefound=0;
702 
703   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_monochrome\n");
704 
705   while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
706     for(j=0;j<caps->modelist->count;j++){
707       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
708 	if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
709 	  /* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
710 	  if ( (caps->modelist->modes[j].quality >= quality) && (caps->modelist->modes[j].flags & MODE_FLAG_BLACK) ){
711 	    /* keep setting the mode until lowest matching quality is found */
712 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
713 	      /* duplex check -- rare for monochrome, cannot remember any such case */
714 	      mode = &caps->modelist->modes[j];
715 	      modefound=1;
716 	    }
717 	  }
718 	  break; /* go to next mode in muse list */
719 	}
720 	else { /* no special replacement modes for black inkset */
721 	  if ( (caps->modelist->modes[j].quality >= quality) ){
722 	    /* keep setting the mode until lowest matching quality is found */
723 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
724 	      /* duplex check -- rare for monochrome, cannot remember any such case */
725 	      mode = &caps->modelist->modes[j];
726 	      modefound=1;
727 	    }
728 	  }
729 	  break; /* go to next mode in muse list */
730 	}
731       }
732     }
733     i++;
734   }
735   return mode;
736 }
737 
find_first_matching_mode_monochrome(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)738 const canon_mode_t* find_first_matching_mode_monochrome(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
739   const canon_mode_t* mode=NULL;
740   /* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
741   int i=0;
742   int modefound=0;
743   int j;
744 
745   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_monochrome\n");
746 
747   while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
748     /* pick first mode with MODE_FLAG_BLACK */
749     for(j=0;j<caps->modelist->count;j++){
750       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
751 	/* only look at modes with MODE_FLAG_BLACK if INKSET_BLACK_MODEREPL is in force */
752 	if ( (caps->modelist->modes[j].flags & MODE_FLAG_BLACK) ) {
753 	  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
754 	    /* duplex check -- rare for monochrome, cannot remember any such case */
755 	    mode = &caps->modelist->modes[j];
756 	    modefound=1;
757 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_monochrome): picked monochrome mode (%s)\n",mode->name);
758 	  }
759 	}
760 	break; /* go to next mode in muse list */
761       }
762     }
763     i++;
764   }
765   return mode;
766 }
767 
find_first_matching_mode(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)768 const canon_mode_t* find_first_matching_mode(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
769   const canon_mode_t* mode=NULL;
770   int i=0;
771   int modefound=0;
772   int j;
773 
774   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode\n");
775 
776   while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
777     for(j=0;j<caps->modelist->count;j++){
778       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
779 	if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
780 	  /* duplex check */
781 	  mode = &caps->modelist->modes[j];
782 	  modefound=1;
783 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode): picked mode without inkset limitation (%s)\n",mode->name);
784 	}
785 	break; /* go to next mode in muse list */
786       }
787     }
788     i++;
789   }
790   return mode;
791 }
792 
suitable_mode_color(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)793 const canon_mode_t* suitable_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
794   const canon_mode_t* mode=NULL;
795   int i=0;
796   int j;
797   int modefound=0;
798 
799   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_color\n");
800 
801   while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
802     for(j=0;j<caps->modelist->count;j++){
803       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
804 	if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
805 	  /* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
806 	  if ( (caps->modelist->modes[j].quality >= quality)  && (caps->modelist->modes[j].flags & MODE_FLAG_COLOR) ) {
807 	    /* keep setting the mode until lowest matching quality is found */
808 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
809 	      /* duplex check */
810 	      mode = &caps->modelist->modes[j];
811 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_color): picked mode with special replacement inkset (%s)\n",mode->name);
812 	      modefound=1;
813 	    }
814 	  }
815 	  break; /* go to next mode in muse list */
816 	}
817 	else { /* no special replacement modes for color inkset */
818 	  if ( (caps->modelist->modes[j].quality >= quality) ){
819 	    /* keep setting the mode until lowest matching quality is found */
820 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
821 	      /* duplex check */
822 	      mode = &caps->modelist->modes[j];
823 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_color): picked mode without any special replacement inkset (%s)\n",mode->name);
824 	      modefound=1;
825 	    }
826 	  }
827 	  break; /* go to next mode in muse list */
828 	}
829       }
830     }
831     i++;
832   }
833   return mode;
834 }
835 
find_first_matching_mode_color(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)836 const canon_mode_t* find_first_matching_mode_color(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
837   const canon_mode_t* mode=NULL;
838   /* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
839   int i=0;
840   int modefound=0;
841   int j;
842 
843   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_color\n");
844 
845   while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
846     /* pick first mode with MODE_FLAG_COLOR */
847     for(j=0;j<caps->modelist->count;j++){
848       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
849 	/* only look at modes with MODE_FLAG_COLOR if INKSET_COLOR_MODEREPL is in force */
850 	if ( (caps->modelist->modes[j].flags & MODE_FLAG_COLOR) ) {
851 	  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
852 	    /* duplex check */
853 	    mode = &caps->modelist->modes[j];
854 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_color): picked first mode with special replacement inkset (%s)\n",mode->name);
855 	    modefound=1;
856 	  }
857 	}
858 	break; /* go to next mode in muse list */
859       }
860     }
861     i++;
862   }
863   return mode;
864 }
865 
suitable_mode_photo(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)866 const canon_mode_t* suitable_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
867   const canon_mode_t* mode=NULL;
868   int i=0;
869   int j;
870   int modefound=0;
871 
872   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_photo\n");
873 
874   while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
875     for(j=0;j<caps->modelist->count;j++){
876       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
877 	if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
878 	  /* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
879 	  if ( (caps->modelist->modes[j].quality >= quality)  && (caps->modelist->modes[j].flags & MODE_FLAG_PHOTO) ) {
880 	    /* keep setting the mode until lowest matching quality is found */
881 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
882 	      /* duplex check */
883 	      mode = &caps->modelist->modes[j];
884 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_photo): picked first mode with special replacement inkset (%s)\n",mode->name);
885 	      modefound=1;
886 	    }
887 	  }
888 	  break; /* go to next mode in muse list */
889 	}
890 	else { /* if no special replacement modes for photo inkset */
891 	  if ( (caps->modelist->modes[j].quality >= quality) ){
892 	    /* keep setting the mode until lowest matching quality is found */
893 	    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
894 	      /* duplex check */
895 	      mode = &caps->modelist->modes[j];
896 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_photo): picked first mode with photo inkset (%s)\n",mode->name);
897 	      modefound=1;
898 	    }
899 	  }
900 	  break; /* go to next mode in muse list */
901 	}
902       }
903     }
904     i++;
905   }
906   return mode;
907 }
908 
find_first_matching_mode_photo(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,const char * duplex_mode)909 const canon_mode_t* find_first_matching_mode_photo(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,const char *duplex_mode) {
910   const canon_mode_t* mode=NULL;
911   /* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
912   int i=0;
913   int modefound=0;
914   int j;
915 
916   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_first_matching_mode_photo\n");
917 
918   while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
919     /* pick first mode with MODE_FLAG_PHOTO */
920     for(j=0;j<caps->modelist->count;j++){
921       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
922 	/* only look at modes with MODE_FLAG_PHOTO if INKSET_PHOTO_MODEREPL is in force */
923 	if ( (caps->modelist->modes[j].flags & MODE_FLAG_PHOTO) ) {
924 	  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
925 	    /* duplex check */
926 	    mode = &caps->modelist->modes[j];
927 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (find_first_matching_mode_photo): picked first mode with photo inkset (%s)\n",mode->name);
928 	    modefound=1;
929 	  }
930 	}
931 	break; /* go to next mode in muse list */
932       }
933     }
934     i++;
935   }
936   return mode;
937 }
938 
suitable_mode_general(stp_vars_t * v,const canon_modeuse_t * muse,const canon_cap_t * caps,int quality,const char * duplex_mode)939 const canon_mode_t* suitable_mode_general(stp_vars_t *v,const canon_modeuse_t* muse,const canon_cap_t *caps,int quality,const char *duplex_mode) {
940   const canon_mode_t* mode=NULL;
941   int i=0;
942   int j;
943   int modefound=0;
944 
945   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered suitable_mode_general\n");
946 
947 
948   while ((muse->mode_name_list[i]!=NULL) && (modefound != 1)){
949     for(j=0;j<caps->modelist->count;j++){
950       if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
951 	if ( (caps->modelist->modes[j].quality >= quality) ) {
952 	  /* keep setting the mode until lowest matching quality is found */
953 	  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
954 	    /* duplex check */
955 	    mode = &caps->modelist->modes[j];
956 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (suitable_mode_general): picked first mode with lowest matching quality (%s)\n",mode->name);
957 	    modefound=1;
958 	  }
959 	}
960 	break; /* go to next mode in muse list */
961       }
962     }
963     i++;
964   }
965   return mode;
966 }
967 
find_ink_type(stp_vars_t * v,const canon_mode_t * mode,const char * printing_mode)968 const char* find_ink_type(stp_vars_t *v,const canon_mode_t* mode,const char *printing_mode) {
969   int i,inkfound;
970   const char *ink_type = stp_get_string_parameter(v, "InkType");
971 
972   stp_dprintf(STP_DBG_CANON, v,"DEBUG: Entered find_ink_type\n");
973 
974   /* if InkType does not match that of mode, change InkType to match it */
975   /* choose highest color as default, as there is only one option for Black */
976   /* if InkType does not match that of mode, change InkType to match it */
977   /* choose highest color as default, as there is only one option for Black */
978   if (printing_mode && !strcmp(printing_mode,"BW")) {
979     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
980     stp_set_string_parameter(v, "InkType", "Gray");
981     ink_type = stp_get_string_parameter(v, "InkType");
982   } else {
983     inkfound=0;
984     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
985     for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
986       if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
987 	if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
988 	  inkfound=1;
989 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
990 	  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
991 	  ink_type = stp_get_string_parameter(v, "InkType");
992 	  break;
993 	}
994       }
995     }
996     /* if no match found choose first available inkset */
997     if (inkfound==0) {
998       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
999 	if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1000 	  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1001 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1002 	    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1003 	    ink_type = stp_get_string_parameter(v, "InkType");
1004 	    inkfound=1; /* set */
1005 	    break;
1006 	  }
1007 	}
1008       }
1009     }
1010   }
1011   return ink_type;
1012 }
1013 
1014 /* function checks printmode (specified by resolution) */
1015 /* and substitutes a mode if needed. NULL is returned for now */
canon_check_current_mode(stp_vars_t * v)1016 const canon_mode_t* canon_check_current_mode(stp_vars_t *v){
1017 #if 0
1018   const char* input_slot = stp_get_string_parameter(v, "InputSlot");
1019   const char *quality = stp_get_string_parameter(v, "Quality");
1020 #endif
1021   const char *resolution = stp_get_string_parameter(v, "Resolution");
1022   const char *ink_set = stp_get_string_parameter(v, "InkSet");
1023   const char *duplex_mode = stp_get_string_parameter(v, "Duplex");
1024   const char *ink_type = stp_get_string_parameter(v, "InkType");
1025   const char *printing_mode = stp_get_string_parameter(v, "PrintingMode");
1026   const canon_cap_t * caps = canon_get_model_capabilities(v);
1027   const canon_mode_t* mode = NULL;
1028   const canon_modeuselist_t* mlist = caps->modeuselist;
1029   const canon_modeuse_t* muse = NULL;
1030   const canon_paper_t* media_type = get_media_type(caps,stp_get_string_parameter(v, "MediaType"));
1031   int i,j;
1032   int modecheck, quality, modefound;
1033 #if 0
1034   int inkfound;
1035 #endif
1036 
1037   stp_dprintf(STP_DBG_CANON, v,"Entered canon_check_current_mode: got PrintingMode %s\n",printing_mode);
1038 
1039   /* Logic: priority of options
1040      1. Media --- always present for final selection.
1041      2. InkSet (cartridge selection) --- optional as only some printers offer this.
1042      3. PrintingMode --- for printers which have K-only monochrome modes can choose BW.
1043      4. Duplex --- for printers that have special duplex modes need to skip non-duplex modes.
1044      5. InkType --- suggestion only, since modes are tied to ink types in most Canon printers.
1045      6. Quality --- suggestion, based on initially-selected mode.
1046      7. Mode --- once chosen, InkType is selected based on quality, inkset, printing mode.
1047   */
1048 
1049   /*
1050     canon-mode-media:
1051     INKSET_BLACK_SUPPORT: media type supports black-only cartridge
1052     INKSET_COLOR_SUPPORT: media type supports color-only cartridge
1053     INKSET_BLACK_MODEREPL: media type has special modes for black-only cartridge
1054     INKSET_COLOR_MODEREPL: media type has special modes for black-only cartridge
1055     INKSET_PHOTO_SUPPORT: media type supports special photo cartridge
1056     DUPLEX_MODEREPL: media type has (a) special mode(s) for duplex
1057     canon-modes.h:
1058     MODE_FLAG_BLACK: mode can be used for supporting black-only cartridge
1059     MODE_FLAG_COLOR: mode can be used for supporting color-only cartridge
1060     MODE_FLAG_PHOTO: mode can be used for supporting photo cartridge
1061     MODE_FLAG_NOPDUPLEX: mode cannot be used for duplex, must be skipped
1062   */
1063 
1064   if(resolution){
1065     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- (Initial) Resolution already known: '%s'\n",resolution);
1066     for(i=0;i<caps->modelist->count;i++){
1067       if(!strcmp(resolution,caps->modelist->modes[i].name)){
1068 	mode = &caps->modelist->modes[i];
1069 	break;
1070       }
1071     }
1072   }
1073   else {
1074     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- (Initial) Resolution not yet known \n");
1075   }
1076 
1077   if (ink_set)
1078     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkSet value (high priority): '%s'\n",ink_set);
1079   else
1080     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkSet value is NULL\n");
1081 
1082   if (ink_type)
1083     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkType value (low priority): '%s'\n",ink_type);
1084   else
1085     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: (Initial) InkType value is NULL\n");
1086 
1087   /* beginning of mode replacement code */
1088   if (media_type && resolution && mode) {
1089     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- Resolution, Media, Mode all known \n");
1090     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: media type selected: '%s'\n",media_type->name);
1091     stp_dprintf(STP_DBG_CANON, v,"DEBUG: (Initial) Gutenprint: mode initially active: '%s'\n",mode->name);
1092 
1093     /* scroll through modeuse list to find media */
1094     muse = select_media_modes(v,media_type,mlist);
1095 
1096     /* now scroll through to find if the mode is in the modeuses list */
1097     modecheck=compare_mode_valid(v,mode,muse,mlist);
1098 
1099     stp_dprintf(STP_DBG_CANON, v,"DEBUG: (mode replacement) Gutenprint: modecheck value: '%i'\n",modecheck);
1100 
1101     /* if we did not find a valid mode, need to replace it */
1102     if (modecheck!=0) {
1103 
1104       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode): no suitable mode exists, need to find a mode\n");
1105 
1106       quality = mode->quality;
1107       /* Black InkSet */
1108       if (ink_set && !strcmp(ink_set,"Black"))  {
1109 	stp_set_string_parameter(v, "PrintingMode","BW");
1110 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
1111 	if (!(mode->ink_types & CANON_INK_K)) {
1112 
1113 	  /* need a new mode:
1114 	     loop through modes in muse list searching for a matching inktype, comparing quality
1115 	  */
1116 	  mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1117 	  if (!mode)
1118 	    modefound=0;
1119 	  else
1120 	    modefound=1;
1121 
1122 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media matching the InkSet limitation */
1123 	    if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1124 	      mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1125 	    }
1126 	    else {  /* no special replacement modes for black inkset */
1127 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1128 	      stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K but did no special conditions, so first match taken: '%s'\n",mode->name);
1129 	    }
1130 	  }
1131 	  if (!mode)
1132 	    modefound=0;
1133 	  else
1134 	    modefound=1;
1135 
1136 	  /* set InkType for the mode found */
1137 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1138 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1139 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1140 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1141 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1142 		ink_type = stp_get_string_parameter(v, "InkType");
1143 		break;
1144 	      }
1145 	    }
1146 	  }
1147 	}
1148 	else {
1149 	  /* mode is fine */
1150 	  /* matched expected K inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1151 	  mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1152 	  stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K and mode already fits (but need to check for duplex condition): '%s'\n",mode->name);
1153 	  if (!mode)
1154 	    modefound=0;
1155 	  else
1156 	    modefound=1;
1157 
1158 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media matching the InkSet limitation */
1159 	    if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1160 	    mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1161 	    stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K, pick first one matching condition for black mode replacement: '%s'\n",mode->name);
1162 	    }
1163 	    else {  /* no special replacement modes for black inkset */
1164 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1165 	      stp_dprintf(STP_DBG_CANON, v,"Gutenprint (check_current_mode): Ink set is set to CANON_INK_K, pick first one matching condition without mode replacement needed: '%s'\n",mode->name);
1166 	    }
1167 	  }
1168 
1169 	  ink_type=find_ink_type(v,mode,printing_mode);
1170 #if 0
1171 	  /* if InkType does not match that of mode, change InkType to match it */
1172 	  /* choose highest color as default, as there is only one option for Black */
1173 	  /* if InkType does not match that of mode, change InkType to match it */
1174 	  /* choose highest color as default, as there is only one option for Black */
1175 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1176 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1177 	    stp_set_string_parameter(v, "InkType", "Gray");
1178 	    ink_type = stp_get_string_parameter(v, "InkType");
1179 	  } else {
1180 	    inkfound=0;
1181 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1182 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1183 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1184 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1185 		  inkfound=1;
1186 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1187 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1188 		  ink_type = stp_get_string_parameter(v, "InkType");
1189 		  break;
1190 		}
1191 	      }
1192 	    }
1193 	    /* if no match found choose first available inkset */
1194 	    if (inkfound==0) {
1195 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1196 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1197 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1198 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1199 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1200 		    ink_type = stp_get_string_parameter(v, "InkType");
1201 		    inkfound=1; /* set */
1202 		    break;
1203 		  }
1204 		}
1205 	      }
1206 	    }
1207 	  }
1208 #endif
1209 
1210 #if 0
1211 	  /* set InkType for the mode found */
1212 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1213 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1214 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1215 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1216 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1217 		ink_type = stp_get_string_parameter(v, "InkType");
1218 		break;
1219 	      }
1220 	    }
1221 	  }
1222 #endif
1223 
1224 	}
1225       } /* End of Black Inkset */
1226       /*-------------------------------------------------------------------------------------------------*/
1227       /* Color InkSet */
1228       /* Added limitation: "Color" for BJC corresponds to "Both" on other types */
1229       else if ( (ink_set && !strcmp(ink_set,"Color")) && (caps->features & CANON_CAP_T) ) {
1230 	stp_set_string_parameter(v, "PrintingMode","Color");
1231 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
1232 	if (!(mode->ink_types & CANON_INK_CMY)) {
1233 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset incorrect for Color cartridge---need new mode\n");
1234 	  /* need a new mode
1235 	     loop through modes in muse list searching for a matching inktype, comparing quality
1236 	  */
1237 	  mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1238 	  if (!mode)
1239 	    modefound=0;
1240 	  else
1241 	    modefound=1;
1242 
1243 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1244 	    if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1245 	      mode=find_first_matching_mode_color(v,muse,caps,duplex_mode);
1246 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1247 	    }
1248 	    else {  /* no special replacement modes for color inkset */
1249 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1250 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1251 	    }
1252 	  }
1253 	  if (!mode)
1254 	    modefound=0;
1255 	  else
1256 	    modefound=1;
1257 
1258 	  ink_type=find_ink_type(v,mode,printing_mode);
1259 #if 0
1260 	  /* if InkType does not match that of mode, change InkType to match it */
1261 	  /* choose highest color as default, as there is only one option for Black */
1262 	  /* if InkType does not match that of mode, change InkType to match it */
1263 	  /* choose highest color as default, as there is only one option for Black */
1264 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1265 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1266 	    stp_set_string_parameter(v, "InkType", "Gray");
1267 	    ink_type = stp_get_string_parameter(v, "InkType");
1268 	  } else {
1269 	    inkfound=0;
1270 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1271 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1272 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1273 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1274 		  inkfound=1;
1275 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1276 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1277 		  ink_type = stp_get_string_parameter(v, "InkType");
1278 		  break;
1279 		}
1280 	      }
1281 	    }
1282 	    /* if no match found choose first available inkset */
1283 	    if (inkfound==0) {
1284 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1285 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1286 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1287 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1288 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1289 		    ink_type = stp_get_string_parameter(v, "InkType");
1290 		    inkfound=1; /* set */
1291 		    break;
1292 		  }
1293 		}
1294 	      }
1295 	    }
1296 	  }
1297 #endif
1298 #if 0
1299 	  /* set InkType for the mode found */
1300 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1301 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1302 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1303 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1304 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1305 		ink_type = stp_get_string_parameter(v, "InkType");
1306 		break;
1307 	      }
1308 	    }
1309 	  }
1310 #endif
1311 
1312 	}
1313 	else {
1314 	  /* mode is fine */
1315 	  /* matched expected RGB inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1316 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset OK but need to check other parameters\n");
1317 	  mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1318 	  if (!mode)
1319 	    modefound=0;
1320 	  else
1321 	    modefound=1;
1322 
1323 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1324 	    if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1325 	      mode=find_first_matching_mode_color(v,muse,caps,duplex_mode);
1326 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1327 	    }
1328 	    else {  /* no special replacement modes for color inkset */
1329 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1330 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1331 	    }
1332 	  }
1333 	  if (!mode)
1334 	    modefound=0;
1335 	  else
1336 	    modefound=1;
1337 
1338 	  ink_type=find_ink_type(v,mode,printing_mode);
1339 #if 0
1340 	  /* if InkType does not match that of mode, change InkType to match it */
1341 	  /* choose highest color as default, as there is only one option for Black */
1342 	  /* if InkType does not match that of mode, change InkType to match it */
1343 	  /* choose highest color as default, as there is only one option for Black */
1344 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1345 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1346 	    stp_set_string_parameter(v, "InkType", "Gray");
1347 	    ink_type = stp_get_string_parameter(v, "InkType");
1348 	  } else {
1349 	    inkfound=0;
1350 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1351 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1352 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1353 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1354 		  inkfound=1;
1355 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1356 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1357 		  ink_type = stp_get_string_parameter(v, "InkType");
1358 		  break;
1359 		}
1360 	      }
1361 	    }
1362 	    /* if no match found choose first available inkset */
1363 	    if (inkfound==0) {
1364 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1365 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1366 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1367 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1368 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1369 		    ink_type = stp_get_string_parameter(v, "InkType");
1370 		    inkfound=1; /* set */
1371 		    break;
1372 		  }
1373 		}
1374 	      }
1375 	    }
1376 	  }
1377 #endif
1378 #if 0
1379 	  /* set InkType for the mode found */
1380 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1381 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1382 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1383 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1384 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1385 		ink_type = stp_get_string_parameter(v, "InkType");
1386 		break;
1387 	      }
1388 	    }
1389 	  }
1390 #endif
1391 
1392 	}
1393       }  /* end of Color InkSet */
1394       /*-------------------------------------------------------------------------------------------------*/
1395       /* Photo cartridge selection: only use modes that support it */
1396       else if (ink_set && !strcmp(ink_set,"Photo")) {
1397 	/* Photo cartridge printing does not seem to have any monochrome option */
1398 	stp_set_string_parameter(v, "PrintingMode","Color");
1399 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
1400 	/* need to match photo cartridge mode flag */
1401 	if (!(mode->flags & MODE_FLAG_PHOTO)) {
1402 	  /* need a new mode
1403 	     loop through modes in muse list searching for a matching inkset, comparing quality
1404 	  */
1405 	  mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
1406 	  if (!mode)
1407 	    modefound=0;
1408 	  else
1409 	    modefound=1;
1410 
1411 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1412 	    if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
1413 	      mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
1414 	    }
1415 	    else {  /* no special replacement modes for photo inkset */
1416 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1417 	    }
1418 	  }
1419 	  if (!mode)
1420 	    modefound=0;
1421 	  else
1422 	    modefound=1;
1423 
1424 	  ink_type=find_ink_type(v,mode,printing_mode);
1425 #if 0
1426 	  /* if InkType does not match that of mode, change InkType to match it */
1427 	  /* choose highest color as default, as there is only one option for Black */
1428 	  /* if InkType does not match that of mode, change InkType to match it */
1429 	  /* choose highest color as default, as there is only one option for Black */
1430 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1431 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1432 	    stp_set_string_parameter(v, "InkType", "Gray");
1433 	    ink_type = stp_get_string_parameter(v, "InkType");
1434 	  } else {
1435 	    inkfound=0;
1436 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1437 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1438 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1439 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1440 		  inkfound=1;
1441 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1442 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1443 		  ink_type = stp_get_string_parameter(v, "InkType");
1444 		  break;
1445 		}
1446 	      }
1447 	    }
1448 	    /* if no match found choose first available inkset */
1449 	    if (inkfound==0) {
1450 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1451 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1452 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1453 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1454 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1455 		    ink_type = stp_get_string_parameter(v, "InkType");
1456 		    inkfound=1; /* set */
1457 		    break;
1458 		  }
1459 		}
1460 	      }
1461 	    }
1462 	  }
1463 #endif
1464 #if 0
1465 	  /* set InkType for the mode found */
1466 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1467 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1468 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1469 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1470 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1471 		ink_type = stp_get_string_parameter(v, "InkType");
1472 		break;
1473 	      }
1474 	    }
1475 	  }
1476 #endif
1477 
1478 	}
1479 	else {
1480 	  /* mode is fine */
1481 	  /* matched expected inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1482 	  mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
1483 	  if (!mode)
1484 	    modefound=0;
1485 	  else
1486 	    modefound=1;
1487 
1488 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1489 	    if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
1490 	      mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
1491 	    }
1492 	    else {  /* no special replacement modes for photo inkset */
1493 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1494 	    }
1495 	  }
1496 	  if (!mode)
1497 	    modefound=0;
1498 	  else
1499 	    modefound=1;
1500 
1501 	  ink_type=find_ink_type(v,mode,printing_mode);
1502 #if 0
1503 	  /* if InkType does not match that of mode, change InkType to match it */
1504 	  /* choose highest color as default, as there is only one option for Black */
1505 	  /* if InkType does not match that of mode, change InkType to match it */
1506 	  /* choose highest color as default, as there is only one option for Black */
1507 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1508 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1509 	    stp_set_string_parameter(v, "InkType", "Gray");
1510 	    ink_type = stp_get_string_parameter(v, "InkType");
1511 	  } else {
1512 	    inkfound=0;
1513 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1514 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1515 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1516 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1517 		  inkfound=1;
1518 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1519 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1520 		  ink_type = stp_get_string_parameter(v, "InkType");
1521 		  break;
1522 		}
1523 	      }
1524 	    }
1525 	    /* if no match found choose first available inkset */
1526 	    if (inkfound==0) {
1527 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1528 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1529 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1530 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1531 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1532 		    ink_type = stp_get_string_parameter(v, "InkType");
1533 		    inkfound=1; /* set */
1534 		    break;
1535 		  }
1536 		}
1537 	      }
1538 	    }
1539 	  }
1540 #endif
1541 #if 0
1542 	  /* set InkType for the mode found */
1543 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1544 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1545 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1546 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1547 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1548 		ink_type = stp_get_string_parameter(v, "InkType");
1549 		break;
1550 	      }
1551 	    }
1552 	  }
1553 
1554 #endif
1555 
1556 	}
1557       } /* end of Photo Inkset  */
1558       /*-------------------------------------------------------------------------------------------------*/
1559       /* no restrictions for InkSet "Both" (non-BJC) or "Color" (BJC) or if no InkSet set yet --- do not worry about InkSet at all */
1560       else {
1561 	if (printing_mode && !strcmp(printing_mode,"Color")) {
1562 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode Color\n");
1563 	  /* must skip K-only inksets if they exist: they only exist if the option "BW" is also declared but we cannot check if an option exists or not */
1564 	  i=0;
1565 	  quality = mode->quality;
1566 	  modefound=0;
1567 	  while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
1568 	    for(j=0;j<caps->modelist->count;j++){
1569 	      if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1570 		if ( (caps->modelist->modes[j].quality >= quality) ) {
1571 		  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1572 		    /* duplex check */
1573 		    if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
1574 		      mode = &caps->modelist->modes[j];
1575 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode color): picked first mode with color inkset (%s)\n",mode->name);
1576 		      modefound=1;
1577 		    }
1578 		  }
1579 		}
1580 		break; /* go to next mode in muse list */
1581 	      }
1582 	    }
1583 	    i++;
1584 	  }
1585 	}
1586 	else if (printing_mode && !strcmp(printing_mode,"BW")) {
1587 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode BW\n");
1588 	  /* need to find K-only inksets: they must exist since we declared the printer to have this capability! */
1589 	  i=0;
1590 	  quality = mode->quality;
1591 	  modefound=0;
1592 	  while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
1593 	    for(j=0;j<caps->modelist->count;j++){
1594 	      if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1595 		if ( (caps->modelist->modes[j].quality >= quality) ) {
1596 		  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1597 		    /* duplex check */
1598 		    if (caps->modelist->modes[j].ink_types & CANON_INK_K) { /* AND means support for CANON_IN_K is included */
1599 		      mode = &caps->modelist->modes[j];
1600 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode BW): picked first mode with mono inkset (%s)\n",mode->name);
1601 		      modefound=1;
1602 		    }
1603 		  }
1604 		}
1605 		break; /* go to next mode in muse list */
1606 	      }
1607 	    }
1608 	    i++;
1609 	  }
1610 	}
1611 	else { /* no restriction from PrintingMode if not set yet */
1612 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet\n");
1613 	  /* if mode is not a matching duplex mode, need to find a new one */
1614 	  i=0;
1615 	  quality = mode->quality;
1616 	  modefound=0;
1617 	  while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
1618 	    for(j=0;j<caps->modelist->count;j++){
1619 	      if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1620 		if ( (caps->modelist->modes[j].quality >= quality) ) {
1621 		  if ( !(duplex_mode) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1622 		    /* duplex check */
1623 		    mode = &caps->modelist->modes[j];
1624 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, printmode unset): picked first mode with quality match (%s)\n",mode->name);
1625 		    modefound=1;
1626 		  }
1627 		}
1628 		break; /* go to next mode in muse list */
1629 	      }
1630 	    }
1631 	    i++;
1632 	  }
1633 	}
1634 	/* if no mode was found yet, repeat with no restrictions --- since some media may not allow PrintingMode to be what was selected */
1635 	if (modefound==0) {
1636 	  i=0;
1637 	  quality = mode->quality;
1638 	  while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
1639 	    for(j=0;j<caps->modelist->count;j++){
1640 	      if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
1641 		if ( (caps->modelist->modes[j].quality >= quality) ) {
1642 		  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
1643 		    /* duplex check */
1644 		    mode = &caps->modelist->modes[j];
1645 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode, Both/Color, no printmode): picked first mode with quality match (%s)\n",mode->name);
1646 		    modefound=1;
1647 		    /* set PrintingMode to whatever the mode is capable of */
1648 		    if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
1649 		      stp_set_string_parameter(v,"PrintingMode","Color");
1650 		      printing_mode = stp_get_string_parameter(v, "PrintingMode");
1651 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to Color\n");
1652 		    } else {
1653 		      stp_set_string_parameter(v,"PrintingMode","BW");
1654 		      printing_mode = stp_get_string_parameter(v, "PrintingMode");
1655 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to BW\n");
1656 		    }
1657 		  }
1658 		}
1659 		break; /* go to next mode in muse list */
1660 	      }
1661 	    }
1662 	    i++;
1663 	  }
1664 	}
1665 
1666 	ink_type=find_ink_type(v,mode,printing_mode);
1667 #if 0
1668 	/* if InkType does not match that of mode, change InkType to match it */
1669 	/* choose highest color as default, as there is only one option for Black */
1670 	/* if InkType does not match that of mode, change InkType to match it */
1671 	/* choose highest color as default, as there is only one option for Black */
1672 	if (printing_mode && !strcmp(printing_mode,"BW")) {
1673 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1674 	  stp_set_string_parameter(v, "InkType", "Gray");
1675 	  ink_type = stp_get_string_parameter(v, "InkType");
1676 	} else {
1677 	  inkfound=0;
1678 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1679 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1680 	    if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1681 	      if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1682 		inkfound=1;
1683 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1684 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1685 		ink_type = stp_get_string_parameter(v, "InkType");
1686 		break;
1687 	      }
1688 	    }
1689 	  }
1690 	  /* if no match found choose first available inkset */
1691 	  if (inkfound==0) {
1692 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1693 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1694 		if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1695 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---choosing first available. InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1696 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1697 		  ink_type = stp_get_string_parameter(v, "InkType");
1698 		  inkfound=1; /* set */
1699 		  break;
1700 		}
1701 	      }
1702 	    }
1703 	  }
1704 	}
1705 #endif
1706 
1707 	/* end of cartridge option block */
1708 
1709 	stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: mode searching: replaced mode with: '%s'\n",mode->name);
1710 
1711 #if 0
1712 	/* set InkType for the mode decided upon */
1713 	for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1714 	  if (mode->ink_types & canon_inktypes[i].ink_type) {
1715 	    if (strcmp(ink_type,canon_inktypes[i].name)) {
1716 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (Mode found): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1717 	      stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1718 	      ink_type = stp_get_string_parameter(v, "InkType");
1719 	      break;
1720 	    }
1721 	  }
1722 	}
1723 #endif
1724 
1725       }
1726     }
1727     /* -------------------------------------- modecheck returned 0 for compare_mode_valid ------------------------------------------*/
1728     else { /* we did find the mode in the list for media, so it should take precedence over other settings, as it is more specific. */
1729 
1730       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (check_current_mode):  mode exists, need to check for consistency (%s)\n",mode->name);
1731       quality = mode->quality;
1732       /* Black InkSet */
1733       if (ink_set && !strcmp(ink_set,"Black")) {
1734 	stp_set_string_parameter(v, "PrintingMode","BW");
1735 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
1736 	if (!(mode->ink_types & CANON_INK_K)) {
1737 	  /* need a new mode:
1738 	     loop through modes in muse list searching for a matching inktype, comparing quality
1739 	  */
1740 	  mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1741 	  if (!mode)
1742 	    modefound=0;
1743 	  else
1744 	    modefound=1;
1745 
1746 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1747 	    if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1748 	      mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1749 	    }
1750 	    else {  /* no special replacement modes for black inkset */
1751 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1752 	    }
1753 	  }
1754 	  if (!mode)
1755 	    modefound=0;
1756 	  else
1757 	    modefound=1;
1758 
1759 	  ink_type=find_ink_type(v,mode,printing_mode);
1760 #if 0
1761 	  /* if InkType does not match that of mode, change InkType to match it */
1762 	  /* choose highest color as default, as there is only one option for Black */
1763 	  /* if InkType does not match that of mode, change InkType to match it */
1764 	  /* choose highest color as default, as there is only one option for Black */
1765 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1766 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1767 	    stp_set_string_parameter(v, "InkType", "Gray");
1768 	    ink_type = stp_get_string_parameter(v, "InkType");
1769 	  } else {
1770 	    inkfound=0;
1771 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1772 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1773 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1774 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1775 		  inkfound=1;
1776 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1777 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1778 		  ink_type = stp_get_string_parameter(v, "InkType");
1779 		  break;
1780 		}
1781 	      }
1782 	    }
1783 	    /* if no match found choose first available inkset */
1784 	    if (inkfound==0) {
1785 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1786 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1787 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1788 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1789 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1790 		    ink_type = stp_get_string_parameter(v, "InkType");
1791 		    inkfound=1; /* set */
1792 		    break;
1793 		  }
1794 		}
1795 	      }
1796 	    }
1797 	  }
1798 #endif
1799 #if 0
1800 	  /* set InkType for the mode found */
1801 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1802 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1803 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1804 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1805 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1806 		ink_type = stp_get_string_parameter(v, "InkType");
1807 		break;
1808 	      }
1809 	    }
1810 	  }
1811 #endif
1812 
1813 	}
1814 	else {
1815 	  /* mode is fine */
1816 	  /* matched expected K inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1817 	  mode=suitable_mode_monochrome(v,muse,caps,quality,duplex_mode);
1818 	  if (!mode)
1819 	    modefound=0;
1820 	  else
1821 	    modefound=1;
1822 
1823 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1824 	    if ( (muse->use_flags & INKSET_BLACK_MODEREPL) ) {
1825 	      mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1826 	    }
1827 	    else {  /* no special replacement modes for black inkset */
1828 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1829 	    }
1830 	  }
1831 	  if (!mode)
1832 	    modefound=0;
1833 	  else
1834 	    modefound=1;
1835 
1836 	  ink_type=find_ink_type(v,mode,printing_mode);
1837 #if 0
1838 	  /* if InkType does not match that of mode, change InkType to match it */
1839 	  /* choose highest color as default, as there is only one option for Black */
1840 	  /* if InkType does not match that of mode, change InkType to match it */
1841 	  /* choose highest color as default, as there is only one option for Black */
1842 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1843 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1844 	    stp_set_string_parameter(v, "InkType", "Gray");
1845 	    ink_type = stp_get_string_parameter(v, "InkType");
1846 	  } else {
1847 	    inkfound=0;
1848 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1849 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1850 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1851 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1852 		  inkfound=1;
1853 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1854 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1855 		  ink_type = stp_get_string_parameter(v, "InkType");
1856 		  break;
1857 		}
1858 	      }
1859 	    }
1860 	    /* if no match found choose first available inkset */
1861 	    if (inkfound==0) {
1862 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1863 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1864 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1865 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1866 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1867 		    ink_type = stp_get_string_parameter(v, "InkType");
1868 		    inkfound=1; /* set */
1869 		    break;
1870 		  }
1871 		}
1872 	      }
1873 	    }
1874 	  }
1875 #endif
1876 #if 0
1877 	  /* set InkType for the mode found */
1878 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1879 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1880 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1881 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Black): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1882 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1883 		ink_type = stp_get_string_parameter(v, "InkType");
1884 		break;
1885 	      }
1886 	    }
1887 	  }
1888 #endif
1889 
1890 	}
1891       } /* End of Black Inkset */
1892       /*-------------------------------------------------------------------------------------------------*/
1893       /* InkSet Color */
1894       else if ( (ink_set && !strcmp(ink_set,"Color")) && (caps->features & CANON_CAP_T) ) {
1895 	stp_set_string_parameter(v, "PrintingMode","Color");
1896 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
1897 	if (!(mode->ink_types & CANON_INK_CMY)) { /* Color InkSet */
1898 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset incorrect for Color cartridge---need new mode\n");
1899 	  /* need a new mode
1900 	     loop through modes in muse list searching for a matching inktype, comparing quality
1901 	  */
1902 	  mode=suitable_mode_color(v,muse,caps,quality,duplex_mode);
1903 
1904 	  if (!mode)
1905 	    modefound=0;
1906 	  else
1907 	    modefound=1;
1908 
1909 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1910 	    if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1911 	      mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1912 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1913 	    }
1914 	    else {  /* no special replacement modes for color inkset */
1915 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1916 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1917 	    }
1918 	  }
1919 	  if (!mode)
1920 	    modefound=0;
1921 	  else
1922 	    modefound=1;
1923 
1924 	  ink_type=find_ink_type(v,mode,printing_mode);
1925 #if 0
1926 	  /* if InkType does not match that of mode, change InkType to match it */
1927 	  /* choose highest color as default, as there is only one option for Black */
1928 	  /* if InkType does not match that of mode, change InkType to match it */
1929 	  /* choose highest color as default, as there is only one option for Black */
1930 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
1931 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
1932 	    stp_set_string_parameter(v, "InkType", "Gray");
1933 	    ink_type = stp_get_string_parameter(v, "InkType");
1934 	  } else {
1935 	    inkfound=0;
1936 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
1937 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1938 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1939 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
1940 		  inkfound=1;
1941 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1942 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1943 		  ink_type = stp_get_string_parameter(v, "InkType");
1944 		  break;
1945 		}
1946 	      }
1947 	    }
1948 	    /* if no match found choose first available inkset */
1949 	    if (inkfound==0) {
1950 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1951 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
1952 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
1953 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1954 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1955 		    ink_type = stp_get_string_parameter(v, "InkType");
1956 		    inkfound=1; /* set */
1957 		    break;
1958 		  }
1959 		}
1960 	      }
1961 	    }
1962 	  }
1963 #endif
1964 #if 0
1965 	  /* set InkType for the mode found */
1966 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
1967 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
1968 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
1969 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
1970 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
1971 		ink_type = stp_get_string_parameter(v, "InkType");
1972 		break;
1973 	      }
1974 	    }
1975 	  }
1976 #endif
1977 
1978 	}
1979 	else {
1980 	  /* mode is fine */
1981 	  /* matched expected RGB inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
1982 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): inkset OK but need to check other parameters\n");
1983 	  mode=suitable_mode_color(v,muse,caps,quality,duplex_mode); /* something wrong here!!! */
1984 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): returned mode for color inkset: %s\n",mode->name);
1985 	  if (!mode)
1986 	    modefound=0;
1987 	  else
1988 	    modefound=1;
1989 
1990 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
1991 	    if ( (muse->use_flags & INKSET_COLOR_MODEREPL) ) {
1992 	      mode=find_first_matching_mode_monochrome(v,muse,caps,duplex_mode);
1993 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode for color inkset (%s)\n",mode->name);
1994 	    }
1995 	    else {  /* no special replacement modes for color inkset */
1996 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
1997 	      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): Decided on first matching mode with no special replacement modes for color inkset (%s)\n",mode->name);
1998 	    }
1999 	  }
2000 	  if (!mode)
2001 	    modefound=0;
2002 	  else
2003 	    modefound=1;
2004 
2005 	  ink_type=find_ink_type(v,mode,printing_mode);
2006 #if 0
2007 	  /* if InkType does not match that of mode, change InkType to match it */
2008 	  /* choose highest color as default, as there is only one option for Black */
2009 	  /* if InkType does not match that of mode, change InkType to match it */
2010 	  /* choose highest color as default, as there is only one option for Black */
2011 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
2012 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2013 	    stp_set_string_parameter(v, "InkType", "Gray");
2014 	    ink_type = stp_get_string_parameter(v, "InkType");
2015 	  } else {
2016 	    inkfound=0;
2017 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2018 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2019 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2020 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2021 		  inkfound=1;
2022 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2023 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2024 		  ink_type = stp_get_string_parameter(v, "InkType");
2025 		  break;
2026 		}
2027 	      }
2028 	    }
2029 	    /* if no match found choose first available inkset */
2030 	    if (inkfound==0) {
2031 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2032 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2033 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2034 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2035 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2036 		    ink_type = stp_get_string_parameter(v, "InkType");
2037 		    inkfound=1; /* set */
2038 		    break;
2039 		  }
2040 		}
2041 	      }
2042 	    }
2043 	  }
2044 #endif
2045 #if 0
2046 	  /* set InkType for the mode found */
2047 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2048 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
2049 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2050 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2051 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2052 		ink_type = stp_get_string_parameter(v, "InkType");
2053 		break;
2054 	      }
2055 	    }
2056 	  }
2057 #endif
2058 
2059 	}
2060       } /* End of Color Inkset */
2061       /*-------------------------------------------------------------------------------------------------*/
2062       /* Photo cartridge selection: only use modes that support it */
2063       else if (ink_set && !strcmp(ink_set,"Photo")) {
2064 	/* Photo cartridge printing does not seem to have any monochrome option */
2065 	stp_set_string_parameter(v, "PrintingMode","Color");
2066 	printing_mode = stp_get_string_parameter(v, "PrintingMode");
2067 	/* need to match photo cartridge mode flag */
2068 	if (!(mode->flags & MODE_FLAG_PHOTO)) {
2069 	  /* need a new mode
2070 	     loop through modes in muse list searching for a matching inkset, comparing quality
2071 	  */
2072 	  mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
2073 	  if (!mode)
2074 	    modefound=0;
2075 	  else
2076 	    modefound=1;
2077 
2078 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
2079 	    if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
2080 	      mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
2081 	    }
2082 	    else {  /* no special replacement modes for photo inkset */
2083 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
2084 	    }
2085 	  }
2086 	  if (!mode)
2087 	    modefound=0;
2088 	  else
2089 	    modefound=1;
2090 
2091 	  ink_type=find_ink_type(v,mode,printing_mode);
2092 #if 0
2093 	  /* if InkType does not match that of mode, change InkType to match it */
2094 	  /* choose highest color as default, as there is only one option for Black */
2095 	  /* if InkType does not match that of mode, change InkType to match it */
2096 	  /* choose highest color as default, as there is only one option for Black */
2097 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
2098 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2099 	    stp_set_string_parameter(v, "InkType", "Gray");
2100 	    ink_type = stp_get_string_parameter(v, "InkType");
2101 	  } else {
2102 	    inkfound=0;
2103 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2104 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2105 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2106 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2107 		  inkfound=1;
2108 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2109 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2110 		  ink_type = stp_get_string_parameter(v, "InkType");
2111 		  break;
2112 		}
2113 	      }
2114 	    }
2115 	    /* if no match found choose first available inkset */
2116 	    if (inkfound==0) {
2117 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2118 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2119 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2120 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2121 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2122 		    ink_type = stp_get_string_parameter(v, "InkType");
2123 		    inkfound=1; /* set */
2124 		    break;
2125 		  }
2126 		}
2127 	      }
2128 	    }
2129 	  }
2130 #endif
2131 #if 0
2132 	  /* set InkType for the mode found */
2133 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2134 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
2135 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2136 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2137 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2138 		ink_type = stp_get_string_parameter(v, "InkType");
2139 		break;
2140 	      }
2141 	    }
2142 	  }
2143 #endif
2144 
2145 	}
2146 	else {
2147 	  /* mode is fine */
2148 	  /* matched expected inkset, but need to check if Duplex matches, and if not, get a new mode with right inkset */
2149 	  mode=suitable_mode_photo(v,muse,caps,quality,duplex_mode);
2150 	  if (!mode)
2151 	    modefound=0;
2152 	  else
2153 	    modefound=1;
2154 
2155 	  if (modefound == 0) { /* still did not find a mode: pick first one for that media */
2156 	    if ( (muse->use_flags & INKSET_PHOTO_MODEREPL) ) {
2157 	      mode=find_first_matching_mode_photo(v,muse,caps,duplex_mode);
2158 	    }
2159 	    else {  /* no special replacement modes for photo inkset */
2160 	      mode=find_first_matching_mode(v,muse,caps,duplex_mode);
2161 	    }
2162 	  }
2163 	  if (!mode)
2164 	    modefound=0;
2165 	  else
2166 	    modefound=1;
2167 
2168 	  ink_type=find_ink_type(v,mode,printing_mode);
2169 #if 0
2170 	  /* if InkType does not match that of mode, change InkType to match it */
2171 	  /* choose highest color as default, as there is only one option for Black */
2172 	  /* if InkType does not match that of mode, change InkType to match it */
2173 	  /* choose highest color as default, as there is only one option for Black */
2174 	  if (printing_mode && !strcmp(printing_mode,"BW")) {
2175 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2176 	    stp_set_string_parameter(v, "InkType", "Gray");
2177 	    ink_type = stp_get_string_parameter(v, "InkType");
2178 	  } else {
2179 	    inkfound=0;
2180 	    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2181 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2182 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2183 		if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2184 		  inkfound=1;
2185 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2186 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2187 		  ink_type = stp_get_string_parameter(v, "InkType");
2188 		  break;
2189 		}
2190 	      }
2191 	    }
2192 	    /* if no match found choose first available inkset */
2193 	    if (inkfound==0) {
2194 	      for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2195 		if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2196 		  if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2197 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2198 		    stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2199 		    ink_type = stp_get_string_parameter(v, "InkType");
2200 		    inkfound=1; /* set */
2201 		    break;
2202 		  }
2203 		}
2204 	      }
2205 	    }
2206 	  }
2207 #endif
2208 #if 0
2209 	  /* set InkType for the mode found */
2210 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2211 	    if (mode->ink_types & canon_inktypes[i].ink_type) {
2212 	      if (strcmp(ink_type,canon_inktypes[i].name)) { /* if InkType does not match selected mode ink type*/
2213 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Color): InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2214 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2215 		ink_type = stp_get_string_parameter(v, "InkType");
2216 		break;
2217 	      }
2218 	    }
2219 	  }
2220 #endif
2221 
2222 	}
2223       } /* end of Photo Inkset  */
2224       /*-------------------------------------------------------------------------------------------------*/
2225       /* no restrictions for InkSet "Both" (non-BJC) or "Color" (BJC) or if no InkSet set yet */
2226       else {
2227 	if (printing_mode && !strcmp(printing_mode,"Color")) {
2228 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode Color\n");
2229 	  /* must skip K-only inksets if they exist: they only exist if the option "BW" is also declared but we cannot check if an option exists or not */
2230 	    i=0;
2231 	    quality = mode->quality;
2232 	    modefound=0;
2233 	    while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
2234 	      for(j=0;j<caps->modelist->count;j++){
2235 		if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2236 		  if ( (caps->modelist->modes[j].quality >= quality) ) {
2237 		    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2238 		      /* duplex check */
2239 		      if (caps->modelist->modes[j].ink_types > CANON_INK_K) {
2240 			if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2241 			  mode = &caps->modelist->modes[j];
2242 			  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) Color: Decided on mode (%s)\n",mode->name);
2243 			  modefound=1;
2244 			}
2245 		      }
2246 		    }
2247 		  }
2248 		  break; /* go to next mode in muse list */
2249 		}
2250 	      }
2251 	      i++;
2252 	    }
2253 	}
2254 	else if (printing_mode && !strcmp(printing_mode,"BW")) {
2255 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode BW\n");
2256 	  /* need to find K-only inksets: they must exist since we declared the printer to have this capability! */
2257 	    i=0;
2258 	    quality = mode->quality;
2259 	    modefound=0;
2260 	    while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
2261 	      for(j=0;j<caps->modelist->count;j++){
2262 		if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2263 		  if ( (caps->modelist->modes[j].quality >= quality) ) {
2264 		    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2265 		      /* duplex check */
2266 		      if (caps->modelist->modes[j].ink_types & CANON_INK_K) { /* AND means CANON_INK_K is included in the support */
2267 			if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2268 			  mode = &caps->modelist->modes[j];
2269 			  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) BW: Decided on mode (%s)\n",mode->name);
2270 			  modefound=1;
2271 			}
2272 		      }
2273 		    }
2274 		  }
2275 		  break; /* go to next mode in muse list */
2276 		}
2277 	      }
2278 	      i++;
2279 	    }
2280 	}
2281 	else { /* no restriction from PrintingMode if not set yet */
2282 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet\n");
2283 	    i=0;
2284 	    quality = mode->quality;
2285 	    modefound=0;
2286 	    while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
2287 	      for(j=0;j<caps->modelist->count;j++){
2288 		if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2289 		  if ( (caps->modelist->modes[j].quality >= quality) ) {
2290 		    if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2291 		      /* duplex check */
2292 		      if (!strcmp(mode->name,caps->modelist->modes[j].name)) {
2293 			mode = &caps->modelist->modes[j];
2294 			stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode not set yet: Decided on first matching mode with quality match (%s)\n",mode->name);
2295 			modefound=1;
2296 		      }
2297 		    }
2298 		  }
2299 		  break; /* go to next mode in muse list */
2300 		}
2301 	      }
2302 	      i++;
2303 	    }
2304 	}
2305 	/* if no mode was found yet, repeat with no restrictions --- since some media may not allow PrintingMode to be what was selected */
2306 	if (modefound==0) {
2307 	  i=0;
2308 	  quality = mode->quality;
2309 	  while ( (muse->mode_name_list[i]!=NULL)  && (modefound != 1) ) {
2310 	    for(j=0;j<caps->modelist->count;j++){
2311 	      if(!strcmp(muse->mode_name_list[i],caps->modelist->modes[j].name)){/* find right place in canon-modes list */
2312 		if ( (caps->modelist->modes[j].quality >= quality) ) {
2313 		  if ( (duplex_mode && strncmp(duplex_mode,"Duplex",6)) || !(muse->use_flags & DUPLEX_SUPPORT) || !(caps->modelist->modes[j].flags & MODE_FLAG_NODUPLEX) ) {
2314 		    /* duplex check */
2315 		    mode = &caps->modelist->modes[j];
2316 		    stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) No mode previously found---catch-all: Decided on first matching mode (%s)\n",mode->name);
2317 		    modefound=1;
2318 		    /* set PrintingMode to whatever the mode is capable of */
2319 		    if (caps->modelist->modes[j].ink_types > CANON_INK_K){
2320 		      stp_set_string_parameter(v,"PrintingMode","Color");
2321 		      printing_mode = stp_get_string_parameter(v, "PrintingMode");
2322 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to Color\n");
2323 		    } else {
2324 		      stp_set_string_parameter(v,"PrintingMode","BW");
2325 		      printing_mode = stp_get_string_parameter(v, "PrintingMode");
2326 		      stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both) PrintingMode set to BW\n");
2327 		    }
2328 		  }
2329 		}
2330 		break; /* go to next mode in muse list */
2331 	      }
2332 	    }
2333 	    i++;
2334 	  }
2335 	}
2336 
2337 	ink_type=find_ink_type(v,mode,printing_mode);
2338 #if 0
2339 	/* if InkType does not match that of mode, change InkType to match it */
2340 	/* choose highest color as default, as there is only one option for Black */
2341 	/* if InkType does not match that of mode, change InkType to match it */
2342 	/* choose highest color as default, as there is only one option for Black */
2343 	if (printing_mode && !strcmp(printing_mode,"BW")) {
2344 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType changed to %u (%s)\n",CANON_INK_K, "Gray");
2345 	  stp_set_string_parameter(v, "InkType", "Gray");
2346 	  ink_type = stp_get_string_parameter(v, "InkType");
2347 	} else {
2348 	  inkfound=0;
2349 	  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType of mode %s is currently set as %s\n",mode->name,ink_type);
2350 	  for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2351 	    if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2352 	      if ( !(strcmp(ink_type,canon_inktypes[i].name))) {
2353 		inkfound=1;
2354 		stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): InkType match found %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2355 		stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2356 		ink_type = stp_get_string_parameter(v, "InkType");
2357 		break;
2358 	      }
2359 	    }
2360 	  }
2361 	  /* if no match found choose first available inkset */
2362 	  if (inkfound==0) {
2363 	    for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2364 	      if (mode->ink_types & canon_inktypes[i].ink_type) { /* a mode can have several ink_types: must compare with ink_type if set */
2365 		if ((!ink_type) || (strcmp(ink_type,canon_inktypes[i].name))) { /* if InkType does not match selected mode ink type*/
2366 		  stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint (InkSet:Both): No match found---choosing first available. InkType changed to %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2367 		  stp_set_string_parameter(v, "InkType", canon_inktypes[i].name);
2368 		  ink_type = stp_get_string_parameter(v, "InkType");
2369 		  inkfound=1; /* set */
2370 		  break;
2371 		}
2372 	      }
2373 	    }
2374 	  }
2375 	}
2376 #endif
2377       }
2378     }
2379   }
2380   /* end of mode replacement code */
2381 
2382 
2383 #if 0
2384   if(quality && strcmp(quality, "None") == 0)
2385     quality = "Standard";
2386 
2387   if(quality && !strcmp(quality,"Standard")){
2388     return &caps->modelist->modes[caps->modelist->default_mode];
2389   }
2390 #endif
2391 
2392 #if 0
2393   /* only some modes can print to cd */
2394   if(input_slot && !strcmp(input_slot,"CD") && !(mode->flags & MODE_FLAG_CD)){
2395     for(i=0;i<caps->modelist->count;i++){
2396       if(caps->modelist->modes[i].flags & MODE_FLAG_CD){
2397 	mode = &caps->modelist->modes[i];
2398 	break;
2399       }
2400     }
2401   }
2402 #endif
2403 
2404 
2405   if (mode) {
2406     stp_set_string_parameter(v, "Resolution",mode->text);  /* check_current_mode checks resolution! */
2407     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- updated Resolution: '%s'\n",mode->name);
2408   }
2409 
2410   if (mode) {
2411     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- Final returned mode: '%s'\n",mode->name);
2412   }
2413   else {
2414     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  check_current_mode --- Final returned mode is NULL \n");
2415   }
2416 
2417   /* set PrintingMode in case of Inkset precedence */
2418   if (mode) { /* final mode takes precedence */
2419     if (mode->ink_types == CANON_INK_K)
2420       stp_set_string_parameter(v, "PrintingMode", "BW");
2421     else
2422       stp_set_string_parameter(v, "PrintingMode", "Color");
2423   }
2424   else if (ink_type) { /* mode not yet known, but InkType known. InkSet should have been handled together with InkType above */
2425     if (!strcmp(ink_type,"Gray"))
2426       stp_set_string_parameter(v, "PrintingMode", "BW");
2427     else
2428       stp_set_string_parameter(v, "PrintingMode", "Color");
2429   }
2430 
2431   if (printing_mode) {
2432     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final PrintingMode %s\n",printing_mode);
2433   } else { /* should not happen */
2434     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final PrintingMode is NULL\n");
2435   }
2436   if (ink_set) {
2437     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkSet value (high priority): '%s'\n",ink_set);
2438   } else {
2439     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkSet value is NULL\n");
2440   }
2441 
2442   if (ink_type) {
2443     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkType value (low priority): '%s'\n",ink_type);
2444   } else {
2445     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Final InkType value is NULL\n");
2446   }
2447 
2448   return mode;
2449 }
2450 
2451 /* function returns the best ink_type for the current mode */
2452 static unsigned int
canon_printhead_colors(const stp_vars_t * v)2453 canon_printhead_colors(const stp_vars_t*v)
2454 {
2455   int i,j;
2456   const canon_mode_t* mode;
2457   const canon_cap_t * caps = canon_get_model_capabilities(v);
2458   const char *print_mode = stp_get_string_parameter(v, "PrintingMode");
2459   const char *ink_type = stp_get_string_parameter(v, "InkType");
2460   const char *ink_set = stp_get_string_parameter(v, "InkSet");
2461 
2462   stp_dprintf(STP_DBG_CANON, v,"Entered canon_printhead_colors: got PrintingMode %s\n",print_mode);
2463 
2464   /* if a mode is available, use it. Else mode is NULL */
2465   stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from canon_printhead_colors\n");
2466   mode = canon_get_current_mode(v);
2467 
2468   /* get the printing mode again */
2469   print_mode = stp_get_string_parameter(v, "PrintingMode");
2470 
2471   /* if the printing mode was already selected as BW, accept it */
2472   if(print_mode && !strcmp(print_mode, "BW") && !(caps->features & CANON_CAP_NOBLACK) ){ /* workaround in case BW is a default */
2473     stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) Found InkType %u (CANON_INK_K)\n",CANON_INK_K);
2474     stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) NOBLACK? %lu\n",(caps->features & CANON_CAP_NOBLACK));
2475     return CANON_INK_K;
2476   }
2477   /* alternatively, if the cartridge selection is in force, and black cartridge is selected, accept it */
2478   if(ink_set && !strcmp(ink_set, "Black")){
2479     stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[BW]) Found InkSet black selection\n");
2480     return CANON_INK_K;
2481   }
2482 
2483   /* originally finds selected InkType of form: CANON_INK_<inks> */
2484   /* but this is incorrect, since it does not check media or mode */
2485   /* change: deal with mode set and mode not set cases */
2486 
2487   /* if mode was already set, then return the ink types for only that mode */
2488 
2489   if (mode) {
2490     /* if an inktype selected check what it is */
2491     if(ink_type){
2492       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2493 	if (mode->ink_types & canon_inktypes[i].ink_type) {
2494 	  stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[inktype]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2495 	  return canon_inktypes[i].ink_type;
2496 	}
2497       }
2498     }
2499     else {
2500       /* find the matching inks for the mode: chooses the first one found for a mode! */
2501       /* ink types are arranged in decreasing order so those with more meta inks are discovered first */
2502       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2503 	if(mode->ink_types & canon_inktypes[i].ink_type) {
2504 	  stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[mode]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2505 	  return canon_inktypes[i].ink_type;
2506 	}
2507       }
2508     }
2509   }
2510   else { /* mode not yet set */
2511     /* if an inktype selected check what it is */
2512     if(ink_type){
2513       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2514 	if(ink_type && !strcmp(canon_inktypes[i].name,ink_type)) {
2515 	  stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[inktype]) Found InkType %i(%s)\n",canon_inktypes[i].ink_type,canon_inktypes[i].name);
2516 	  return canon_inktypes[i].ink_type;
2517 	}
2518       }
2519     }
2520     else { /* no ink type selected yet */
2521       stp_dprintf(STP_DBG_CANON, v,"canon_printhead_colors: no mode and no inktype: we have to choose the highest one to return\n");
2522       /* loop through all modes, and return the highest inktype found */
2523       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2524 	for(j=0;j<caps->modelist->count;j++){
2525 	  if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2526 	    stp_dprintf(STP_DBG_CANON, v," highest inktype found ---  %s(%s)\n",canon_inktypes[i].name,canon_inktypes[i].text);
2527 	    return canon_inktypes[i].ink_type;
2528 	  }
2529 	}
2530       }
2531     }
2532 
2533   }
2534 
2535   /* originally as fallback choose CANON_INK_K */
2536   /* However, some Canon printers do not have monochrome mode at all, only color meta ink modes, like iP6000 series */
2537 #if 0
2538   stp_dprintf(STP_DBG_CANON, v,"(canon_printhead_colors[fall-through]) Returning InkType %i(CANON_INK_K)\n",CANON_INK_K);
2539   return CANON_INK_K;
2540 #endif
2541   /* new fallback: loop through ink type in reverse order, picking first one found, which if CANON_INK_K is supported will be that, else the lowest amount of color */
2542   for(i=((sizeof(canon_inktypes)/sizeof(canon_inktypes[0]))-1);i>=0;i--){
2543     for(j=0;j<caps->modelist->count;j++){
2544       if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2545 	stp_dprintf(STP_DBG_CANON, v," lowest inktype found ---  %s(%s)\n",canon_inktypes[i].name,canon_inktypes[i].text);
2546 	return canon_inktypes[i].ink_type;
2547       }
2548     }
2549   }
2550 
2551   /* if fails until here, return something reasonable in most situations */
2552   return CANON_INK_K;
2553 
2554 }
2555 
2556 static unsigned char
canon_size_type(const stp_vars_t * v,const canon_cap_t * caps)2557 canon_size_type(const stp_vars_t *v, const canon_cap_t * caps)
2558 {
2559   const stp_papersize_list_t *list = stpi_get_standard_papersize_list();
2560   const stp_papersize_t *pp = stpi_get_papersize_by_size(list,
2561 							stp_get_page_height(v),
2562 							stp_get_page_width(v));
2563 
2564   stp_dprintf(STP_DBG_CANON, v,"canon: entered canon_size_type\n");
2565 
2566   if (pp)
2567     {
2568       const char *name = pp->name;
2569       stp_dprintf(STP_DBG_CANON, v,"canon: in canon_size_type is pp->name: '%s'\n",name);
2570       /* used internally: do not translate */
2571       /* built ins:                                  Japanese driver notation */
2572       if (!strcmp(name,"A5"))          return 0x01;
2573       if (!strcmp(name,"A4"))          return 0x03;
2574       if (!strcmp(name,"A3"))          return 0x05;
2575       if (!strcmp(name,"B5"))          return 0x08;
2576       if (!strcmp(name,"B4"))          return 0x0a;
2577       if (!strcmp(name,"Letter"))      return 0x0d;
2578       if (!strcmp(name,"Legal"))       return 0x0f;
2579       if (!strcmp(name,"Tabloid"))     return 0x11; /* 11x17 inch */
2580       if (!strcmp(name,"w283h420"))    return 0x14; /* Hagaki */
2581       /*      if (!strcmp(name,"COM10"))       return 0x16;*/
2582       /*      if (!strcmp(name,"DL"))          return 0x17;*/
2583       if (!strcmp(name,"LetterExtra")) return 0x2a; /* Letter navi --- Letter+ */
2584       if (!strcmp(name,"A4Extra"))     return 0x2b; /* A4navi --- A4+ */
2585       if (!strcmp(name,"A3plus"))      return 0x2c; /* A3navi --- A3+ (13x19 inch) */
2586       if (!strcmp(name,"w288h144"))    return 0x2d; /* 4x2 inch labels */
2587       if (!strcmp(name,"COM10"))       return 0x2e; /* US Comm #10 Env */
2588       if (!strcmp(name,"DL"))          return 0x2f; /* Euro DL Env */
2589       if (!strcmp(name,"w297h666"))    return 0x30; /* Western Env #4 (you4) */
2590       if (!strcmp(name,"w277h538"))    return 0x31; /* Western Env #6 (you6) */
2591       if (!strcmp(name,"w252h360J"))   return 0x32; /* L --- similar to US 3.5x5 inch size */
2592       if (!strcmp(name,"w360h504J"))   return 0x33; /* 2L --- similar to US5x7 inch */
2593       if (!strcmp(name,"w288h432J"))   return 0x34; /* KG --- same size as US 4x6 inch */
2594       /* if (!strcmp(name,"CD5Inch"))  return 0x35; */ /* CD Custom Tray */
2595       if (!strcmp(name,"w155h257"))    return 0x36; /* Japanese Business Card 55mm x 91mm */
2596       if (!strcmp(name,"w360h504"))    return 0x37; /* US5x7 inch */
2597       if (!strcmp(name,"w420h567"))    return 0x39; /* Oufuku Hagaki --- but should be w567h420 */
2598       if (!strcmp(name,"w340h666"))    return 0x3a; /* Japanese Long Env #3 (chou3) */
2599       if (!strcmp(name,"w255h581"))    return 0x3b; /* Japanese Long Env #4 (chou4) */
2600       /* if (!strcmp(name,"CD5Inch"))  return 0x3f; */ /* CD Tray A */
2601       /* if (!strcmp(name,"CD5Inch"))  return 0x40; */ /* CD Tray B */
2602       if (!strcmp(name,"w155h244"))    return 0x41; /* Business/Credit Card 54mm x 86mm */
2603 
2604       /* Fine Art paper codes */
2605       /* iP6700D, iP7100, iP7500, iP8100, iP8600, iP9910 */
2606       /* iX7000 */
2607       /* MG6100, M6200, MG8100, MG8200 */
2608       /* MX7600 */
2609       /* MP950, MP960, MP970, MP980, MP990 */
2610       /* if (!strcmp(name,"A4"))       return 0x42; */ /* FineArt A4 35mm border --- iP7100: gap is 18 */
2611       /* if (!strcmp(name,"A3"))       return 0x43; */ /* FineArt A3 35mm border */
2612       /* if (!strcmp(name,"A3plus"))   return 0x44; */ /* FineArt A3plus 35mm border */
2613       /* if (!strcmp(name,"Letter"))   return 0x45; */ /* FineArt Letter 35mm border */
2614 
2615       if (!strcmp(name,"w288h576"))    return 0x46; /* US4x8 */
2616       if (!strcmp(name,"w1008h1224J")) return 0x47; /* HanKire --- 14in x 17 inch */
2617       if (!strcmp(name,"720h864J"))    return 0x48; /* YonKire --- 10in x 12 inch */
2618       if (!strcmp(name,"c8x10J"))      return 0x49; /* RokuKire --- same size as 8x10 inch */
2619 
2620       /* if (!strcmp(name,"CD5Inch"))  return 0x4a; */ /* CD Tray C */
2621       /* if (!strcmp(name,"CD5Inch"))  return 0x4b; */ /* CD Tray D */
2622       /* if (!strcmp(name,"CD5Inch"))  return 0x4c; */ /* CD Tray E */
2623 
2624       /* Fine Art paper codes */
2625       /* Pro series (9000, 9000 Mk.2, 9500, 9500 Mk.2, PRO-1) */
2626       /* if (!strcmp(name,"A4"))       return 0x4d; */ /* FineArt A4 35mm border */
2627       /* if (!strcmp(name,"A3"))       return 0x4e; */ /* FineArt A3 35mm border */
2628       /* if (!strcmp(name,"Letter"))   return 0x4f; */ /* FineArt Letter 35mm border */
2629       /* if (!strcmp(name,"A3plus"))   return 0x50; */ /* FineArt A3plus 35mm border */
2630 
2631       /* if (!strcmp(name,"CD5Inch"))  return 0x51; */ /* CD Tray F */
2632       if (!strcmp(name,"w288h512"))    return 0x52; /* Wide 101.6x180.6mm */
2633       /* w283h566 Wide postcard 100mm x 200mm */
2634 
2635       /* media size codes for CD (and other media depending on printer model */
2636 
2637       if (!strcmp(name,"CD5Inch"))     return 0x53; /* CD Tray G --- arbitrary choice here, modify in ESC (P command */
2638       /* if (!strcmp(name,"CD5Inch"))  return 0x56; */ /* CD Tray G-late */
2639       /* if (!strcmp(name,"CD5Inch"))  return 0x57; */ /* CD Tray H */
2640 
2641       /* Fine Art paper codes */
2642       /* MG6300, MG6500, MG6700, MG7100, MG7500 (only A4), MG6900, MG7700  */
2643       /* iP8700, iX6800 (A3 also) */
2644       /* if (!strcmp(name,"A4"))       return 0x58; */ /* FineArt A4 35mm border */
2645       /* if (!strcmp(name,"A3"))       return 0x59; */ /* FineArt A3 35mm border */
2646       /* if (!strcmp(name,"Letter"))   return 0x5a; */ /* FineArt Letter 35mm border */
2647       /* if (!strcmp(name,"A3plus"))   return 0x5d; */ /* FineArt A3plus 35mm border */
2648 
2649       /* if (!strcmp(name,"CD5Inch"))  return 0x5b; */ /* CD Tray J */
2650       /* if (!strcmp(name,"CD5Inch"))  return 0x62; */ /* CD Tray L */
2651 
2652       if (!strcmp(name,"A6"))          return 0x63;
2653 
2654       if (!strcmp(name,"LegalIndia"))  return 0x8d; /* Legal (India) */
2655       if (!strcmp(name,"Oficio"))      return 0x8e; /* Oficio */
2656       if (!strcmp(name,"M-Oficio"))    return 0x8f; /* Mexico Oficio */
2657 
2658       if (!strcmp(name,"w612h936"))    return 0x90; /* (American) Foolscap */
2659       if (!strcmp(name,"Executive"))   return 0x91;
2660 
2661       if (!strcmp(name,"C5"))          return 0x92; /* C5 Env */
2662       if (!strcmp(name,"Monarch"))     return 0x93; /* Monarch Env */
2663 
2664       if (!strcmp(name,"B-Oficio"))    return 0x94; /* Brazil Oficio */
2665 
2666       if (!strcmp(name,"w360h360"))    return 0xba; /* square 5x5 inch */
2667 
2668       /* custom */
2669 
2670       stp_dprintf(STP_DBG_CANON, v,"canon: Unknown paper size '%s' - using custom\n",name);
2671     } else {
2672       stp_dprintf(STP_DBG_CANON, v,"canon: Couldn't look up paper size %fx%f - "
2673 	      "using custom\n",stp_get_page_height(v), stp_get_page_width(v));
2674     }
2675   return 0;
2676 }
2677 
2678 /* fix paper_width and paper_length for known papersizes in ESC (p command */
fix_papersize(unsigned char arg_ESCP_1,int * paper_width,int * paper_length)2679 static void fix_papersize(unsigned char arg_ESCP_1, int *paper_width, int *paper_length){
2680 
2681   switch(arg_ESCP_1)
2682     {
2683     case 0x63: *paper_width = 2481; *paper_length = 3497; break;; /* A6 */
2684     case 0x01: *paper_width = 3497; *paper_length = 4961; break;; /* A5 */
2685     case 0x03: *paper_width = 4961; *paper_length = 7016; break;; /* A4 */
2686     case 0x05: *paper_width = 7016; *paper_length = 9922; break;; /* A3 */
2687     case 0x08: *paper_width = 4300; *paper_length = 6071; break;; /* B5 */
2688     case 0x0a: *paper_width = 6071; *paper_length = 8599; break;; /* B4 */
2689     case 0x0d: *paper_width = 5100; *paper_length = 6600; break;; /* Letter */
2690     case 0x0f: *paper_width = 5100; *paper_length = 8400; break;; /* Legal */
2691     case 0x8d: *paper_width = 5079; *paper_length = 8150; break;; /* Legal (India) */
2692     case 0x8e: *paper_width = 5100; *paper_length = 7500; break;; /* Oficio */
2693     case 0x94: *paper_width = 5103; *paper_length = 8386; break;; /* Brazil Oficio */
2694     case 0x8f: *paper_width = 5103; *paper_length = 8056; break;; /* Mexico Oficio */
2695     case 0x90: *paper_width = 5100; *paper_length = 7800; break;; /* (American) Foolscap */
2696     case 0x91: *paper_width = 4352; *paper_length = 6300; break;; /* Executive */
2697     case 0x11: *paper_width = 6600; *paper_length = 10200; break;; /* Tabloid : 11x17" */
2698       /* Letter+, A4+ only seem to be available in shrink-to-fit */
2699       /* case 0x2a: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* LetterExtra : Letter navi, Letter+ */
2700       /* case 0x2b: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* A4Extra : A4navi, A4+ */
2701     case 0x2c: *paper_width = 7772; *paper_length = 11410; break;; /* A3Extra : A3navi, A3+ (13x19") */
2702       /* case 0x2d: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */ /* w288h144 : 4x2" labels */
2703       /* Hagaki media */
2704     case 0x14: *paper_width = 2363; *paper_length = 3497; break;; /* w283h420 : Hagaki */
2705       /* Oufuku Hagaki should be swapped: w567h420, same height as Hagaki */
2706       /* case 0x39: paper_width = 4725;  l: 3497 */
2707       /* w420h567 : Oufuku Hagaki */
2708       /* case 0x39: paper_width=(init->page_width + border_left + border_right) * unit / 72; break;;*/ /* leave untouched since orientation wrong */
2709     case 0x52: *paper_width = 2400; *paper_length = 4267; break;; /* w288h512 : Wide101.6x180.6mm */
2710       /* Envelope media */
2711     case 0x16: *paper_width = 2475; *paper_length = 5700; break;; /* COM10 : US Commercial #10 */
2712     case 0x17: *paper_width = 2599; *paper_length = 5197; break;; /* DL : Euro DL */
2713     case 0x2e: *paper_width = 2475; *paper_length = 5700; break;; /* COM10 : US Commercial #10 */
2714     case 0x2f: *paper_width = 2599; *paper_length = 5197; break;; /* DL : Euro DL */
2715     case 0x30: *paper_width = 2481; *paper_length = 5552; break;; /* w297xh666 : Western Env #4 (you4) */
2716     case 0x31: *paper_width = 2155; *paper_length = 4489;  break;; /* w277xh538 : Western Env #6 (you6) */
2717     case 0x3a: *paper_width = 2835; *paper_length = 5552; break;; /* w340xh666 : Japanese Long Env #3 (chou3) */
2718     case 0x3b: *paper_width = 2126; *paper_length = 4843; break;; /* w255xh581 : Japanese Long Env #4 (chou4) */
2719     case 0x92: *paper_width = 3827; *paper_length = 5410; break;; /* C5 */
2720     case 0x93: *paper_width = 2325; *paper_length = 4500; break;; /* Monarch */
2721       /* Photo media */
2722     case 0x32: *paper_width = 2103; *paper_length = 3000; break;; /* w252h360 : L --- similar to US 3.5x5" */
2723     case 0x33: *paper_width = 3000; *paper_length = 4205; break;; /* w360h504 : 2L --- similar to US 5x7" */
2724     case 0x37: *paper_width = 3000; *paper_length = 4200; break;; /* w360h504 : US 5x7" */
2725     case 0x34: *paper_width = 2400; *paper_length = 3600; break;; /* w288h432J : KG --- same as US 4x6" */
2726     case 0x46: *paper_width = 2400; *paper_length = 4800; break;; /* w288h576 : US 4x8" */
2727     case 0xba: *paper_width = 3000; *paper_length = 3000; break;; /* w360h360 : square 5x5" */
2728       /* CD media */
2729     case 0x35: *paper_width = 3207; *paper_length = 6041; break;;  /* CD5Inch : CD Custom Tray */
2730     case 0x3f: *paper_width = 3378; *paper_length = 6206; break;;  /* CD5Inch : CD Tray A */
2731     case 0x40: *paper_width = 3095; *paper_length = 5640; break;;  /* CD5Inch : CD Tray B */
2732     case 0x4a: *paper_width = 3095; *paper_length = 5640; break;;  /* CD5Inch : CD Tray C */
2733     case 0x4b: *paper_width = 3095; *paper_length = 5640; break;;  /* CD5Inch : CD Tray D */
2734     case 0x4c: *paper_width = 4063; *paper_length = 6497; break;;  /* CD5Inch : CD Tray E */
2735     case 0x51: *paper_width = 3095; *paper_length = 5730; break;;  /* CD5Inch : CD Tray F */
2736     case 0x53: *paper_width = 3095; *paper_length = 6008; break;;  /* CD5Inch : CD Tray G */
2737     case 0x56: *paper_width = 3095; *paper_length = 6008; break;;  /* CD5Inch : CD Tray G late version */
2738     case 0x57: *paper_width = 3572; *paper_length = 8953; break;;  /* CD5Inch : CD Tray H */
2739     case 0x5b: *paper_width = 3071; *paper_length = 5311; break;;  /* CD5Inch : CD Tray J */
2740       /* no printer using Tray L yet supported */
2741       /* case 0x62: paper_width = ( init->page_width + border_left + border_right ) * unit / 72; break;; */  /* CD5Inch : CD Tray L */
2742     case 0xbc: *paper_width = 3494; *paper_length = 4928; break;;  /* CD5Inch : CD Tray M */
2743       /* Business/Credit Card media */
2744     case 0x36: *paper_width = 1300; *paper_length = 2150; break;; /* w155h257 : Japanese Business Card 55x91mm */
2745     case 0x41: *paper_width = 1276; *paper_length = 2032; break;; /* w155h244 : Business/Credit Card 54x86mm */
2746       /* Fine Art media */
2747     case 0x42: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2748     case 0x43: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2749     case 0x44: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2750     case 0x45: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2751     case 0x4d: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2752     case 0x4e: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2753     case 0x4f: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2754     case 0x50: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2755     case 0x58: *paper_width = 4961; *paper_length = 7016; break;; /* FineArt A4 35mm border */
2756     case 0x59: *paper_width = 7016; *paper_length = 9922; break;; /* FineArt A3 35mm border */
2757     case 0x5a: *paper_width = 5100; *paper_length = 6600; break;; /* FineArt Letter 35mm border */
2758     case 0x5d: *paper_width = 7772; *paper_length = 11410; break;; /* FineArt A3+ 35mm border */
2759       /* Other media */
2760     case 0x47: *paper_width = 8400; *paper_length = 10200; break;; /* w1008h1224J : HanKire --- 14x17" */
2761     case 0x48: *paper_width = 6000; *paper_length = 7200; break;; /* 720h864J : YonKire --- 10x12" */
2762     case 0x49: *paper_width = 4800; *paper_length = 6000; break;; /* c8x10J : RokuKire --- same as 8x10" */
2763       /* default */
2764       /* default: paper_width=(init->page_width + border_left + border_right) * unit / 72; break;; */ /* custom */
2765     }
2766 }
2767 
2768 static void
canon_describe_resolution(const stp_vars_t * v,stp_resolution_t * x,stp_resolution_t * y)2769 canon_describe_resolution(const stp_vars_t *v, stp_resolution_t *x, stp_resolution_t *y)
2770 {
2771   const canon_mode_t* mode = NULL;
2772   const canon_cap_t * caps = canon_get_model_capabilities(v);
2773 
2774   /* if mode is not yet set, it remains NULL */
2775   stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from canon_describe_resolution\n");
2776   mode = canon_get_current_mode(v);
2777 
2778   if(!mode)
2779     mode = &caps->modelist->modes[caps->modelist->default_mode];
2780 
2781   if (mode) {
2782     *x = mode->xdpi;
2783     *y = mode->ydpi;
2784   }
2785 }
2786 
2787 static const char *
canon_describe_output(const stp_vars_t * v)2788 canon_describe_output(const stp_vars_t *v)
2789 {
2790   unsigned int ink_type = canon_printhead_colors(v);
2791 
2792   if(ink_type & CANON_INK_CMYK_MASK)
2793     return "CMYK";
2794   if(ink_type & CANON_INK_CMY_MASK)
2795     return "CMY";
2796   /* Gernot added */
2797   /*if(ink_type & CANON_INK_cmy_MASK)
2798     return "cmy";*/
2799   return "Grayscale";
2800 }
2801 
2802 /*
2803  * 'canon_parameters()' - Return the parameter values for the given parameter.
2804  */
2805 
2806 static stp_parameter_list_t
canon_list_parameters(const stp_vars_t * v)2807 canon_list_parameters(const stp_vars_t *v)
2808 {
2809   stp_parameter_list_t *ret = stp_parameter_list_create();
2810   stp_parameter_list_t *tmp_list;
2811 
2812   int i;
2813 
2814   /* Set up dithering */
2815   tmp_list = stp_dither_list_parameters(v);
2816   stp_parameter_list_append(ret, tmp_list);
2817   stp_parameter_list_destroy(tmp_list);
2818 
2819   for (i = 0; i < the_parameter_count; i++)
2820     stp_parameter_list_add_param(ret, &(the_parameters[i]));
2821   for (i = 0; i < float_parameter_count; i++)
2822     stp_parameter_list_add_param(ret, &(float_parameters[i].param));
2823   return ret;
2824 }
2825 
2826 static void
canon_parameters(const stp_vars_t * v,const char * name,stp_parameter_t * description)2827 canon_parameters(const stp_vars_t *v, const char *name,
2828 		 stp_parameter_t *description)
2829 {
2830   int		i,j;
2831 
2832   const canon_cap_t * caps=
2833     canon_get_model_capabilities(v);
2834   description->p_type = STP_PARAMETER_TYPE_INVALID;
2835 
2836   if (name == NULL)
2837     return;
2838 
2839   for (i = 0; i < float_parameter_count; i++)
2840     if (strcmp(name, float_parameters[i].param.name) == 0)
2841       {
2842 	/* presumably need to return the maximum number of inks the printer can handle */
2843 	unsigned int ink_type = canon_printhead_colors(v);
2844 
2845 	stp_fill_parameter_settings(description,
2846 				    &(float_parameters[i].param));
2847 	description->deflt.dbl = float_parameters[i].defval;
2848 	description->bounds.dbl.upper = float_parameters[i].max;
2849 	description->bounds.dbl.lower = float_parameters[i].min;
2850 	if (ink_type != CANON_INK_K || !float_parameters[i].color_only)
2851 	  description->is_active = 1;
2852 	else
2853 	  description->is_active = 0;
2854 	return;
2855       }
2856 
2857   for (i = 0; i < the_parameter_count; i++)
2858     if (strcmp(name, the_parameters[i].name) == 0)
2859       {
2860 	stp_fill_parameter_settings(description, &(the_parameters[i]));
2861 	break;
2862       }
2863   if (strcmp(name, "PageSize") == 0)
2864     {
2865       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2866       unsigned int height_limit, width_limit;
2867       description->bounds.str = stp_string_list_create();
2868 
2869       width_limit = caps->max_width;
2870       height_limit = caps->max_height;
2871 
2872       if(input_slot && !strcmp(input_slot,"CD")){
2873         stp_string_list_add_string
2874           (description->bounds.str, "CD5Inch", _("CD - 5 inch"));
2875         stp_string_list_add_string
2876           (description->bounds.str, "CD3Inch", _("CD - 3 inch"));
2877         stp_string_list_add_string
2878           (description->bounds.str, "CDCustom", _("CD - Custom"));
2879       }else{
2880 	  const stp_papersize_list_t *paper_sizes =
2881 	    stpi_get_standard_papersize_list();
2882 	  const stp_papersize_list_item_t *ptli =
2883 	    stpi_papersize_list_get_start(paper_sizes);
2884 	  while (ptli)
2885 	    {
2886 	      const stp_papersize_t *pt = stpi_paperlist_item_get_data(ptli);
2887 	      if (pt->paper_size_type == PAPERSIZE_TYPE_STANDARD ||
2888 		  pt->paper_size_type == PAPERSIZE_TYPE_ENVELOPE) {
2889 		if (strlen(pt->name) > 0 &&
2890 		    pt->width <= width_limit && pt->height <= height_limit){
2891 		  stp_string_list_add_string(description->bounds.str,
2892 					     pt->name, gettext(pt->text));
2893 		}
2894 	      }
2895 	      ptli = stpi_paperlist_item_next(ptli);
2896 	    }
2897       }
2898       description->deflt.str =
2899         stp_string_list_param(description->bounds.str, 0)->name;
2900   }
2901   else if (strcmp(name, "CDInnerRadius") == 0 )
2902     {
2903       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2904       description->bounds.str = stp_string_list_create();
2905       if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2906          (!stp_get_string_parameter(v, "PageSize") ||
2907           strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") != 0) )
2908 	{
2909 	  stp_string_list_add_string
2910 	    (description->bounds.str, "None", _("Normal"));
2911 	  stp_string_list_add_string
2912 	    (description->bounds.str, "Small", _("Print To Hub"));
2913 	  description->deflt.str =
2914 	    stp_string_list_param(description->bounds.str, 0)->name;
2915 	}
2916       else
2917 	description->is_active = 0;
2918     }
2919   else if (strcmp(name, "CDInnerDiameter") == 0 )
2920     {
2921       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2922       description->bounds.dimension.lower = 16 * 10 * 72 / 254;
2923       description->bounds.dimension.upper = 43 * 10 * 72 / 254;
2924       description->deflt.dimension = 43 * 10 * 72 / 254;
2925       if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2926          (!stp_get_string_parameter(v, "PageSize") ||
2927          strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0) )
2928 	description->is_active = 1;
2929       else
2930 	description->is_active = 0;
2931     }
2932   else if (strcmp(name, "CDOuterDiameter") == 0 )
2933     {
2934       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2935       description->bounds.dimension.lower = 65 * 10 * 72 / 254;
2936       description->bounds.dimension.upper = 120 * 10 * 72 / 254;
2937       description->deflt.dimension = 329;
2938       if ( (!input_slot || !strcmp(input_slot,"CD")) &&
2939          (!stp_get_string_parameter(v, "PageSize") ||
2940           strcmp(stp_get_string_parameter(v, "PageSize"), "CDCustom") == 0) )
2941 	description->is_active = 1;
2942       else
2943 	description->is_active = 0;
2944     }
2945   else if (strcmp(name, "CDXAdjustment") == 0 ||
2946 	   strcmp(name, "CDYAdjustment") == 0)
2947     {
2948       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2949       description->bounds.dimension.lower = -15;
2950       description->bounds.dimension.upper = 15;
2951       description->deflt.dimension = 0;
2952       if (!input_slot || !strcmp(input_slot,"CD"))
2953 	description->is_active = 1;
2954       else
2955 	description->is_active = 0;
2956     }
2957   else if (strcmp(name, "Resolution") == 0)
2958   {
2959 #if 0
2960     const char* input_slot = stp_get_string_parameter(v, "InputSlot");
2961 #endif
2962     description->bounds.str= stp_string_list_create();
2963     description->deflt.str = NULL;
2964     for(i=0;i<caps->modelist->count;i++){
2965 #if 0
2966       if(!((!input_slot || !strcmp(input_slot,"CD")) && !(caps->modelist->modes[i].flags & MODE_FLAG_CD)))
2967 #endif
2968           stp_string_list_add_string(description->bounds.str,
2969 				     caps->modelist->modes[i].name, gettext(caps->modelist->modes[i].text));
2970         stp_dprintf(STP_DBG_CANON, v,"supports mode '%s'\n",
2971 		     caps->modelist->modes[i].name);
2972         if(i == caps->modelist->default_mode)
2973 	  description->deflt.str=caps->modelist->modes[i].name;
2974     }
2975   }
2976   else if (strcmp(name, "InkType") == 0)
2977   {
2978     const canon_mode_t* mode = NULL;
2979 
2980     stp_dprintf(STP_DBG_CANON, v,"Calling get_current_parameter from InkType block in canon_parameters\n");
2981     mode=canon_get_current_mode(v);
2982 
2983     description->bounds.str= stp_string_list_create();
2984     if (mode) {
2985       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2986 	if(mode->ink_types & canon_inktypes[i].ink_type){
2987           stp_string_list_add_string(description->bounds.str,canon_inktypes[i].name,_(canon_inktypes[i].text));
2988 	  stp_dprintf(STP_DBG_CANON, v," mode known --- Added InkType %s(%s) for mode %s (inktype %u)\n",canon_inktypes[i].name,canon_inktypes[i].text,mode->name,mode->ink_types);
2989 	}
2990       }
2991       description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name;
2992     }
2993     /* mode not defined yet --- needed for PPD generation */
2994     else {
2995       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
2996 	for(j=0;j<caps->modelist->count;j++){
2997 	  if(caps->modelist->modes[j].ink_types & canon_inktypes[i].ink_type){
2998 	    stp_string_list_add_string(description->bounds.str,canon_inktypes[i].name,_(canon_inktypes[i].text));
2999 	    stp_dprintf(STP_DBG_CANON, v," no mode --- Added InkType %s(%s) for mode (%s) inktypes %u\n",canon_inktypes[i].name,canon_inktypes[i].text,caps->modelist->modes[j].name,caps->modelist->modes[j].ink_types);
3000 	    break;
3001 	  }
3002 	}
3003       }
3004       /* default type must be deduced from the default mode */
3005       /* use color if available, so break after first (color) is found, since inkt types ordered with gray last */
3006       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3007 	if(caps->modelist->modes[caps->modelist->default_mode].ink_types & canon_inktypes[i].ink_type){
3008 	  description->deflt.str = canon_inktypes[i].name;
3009 	  break;
3010 	}
3011       }
3012     }
3013     /* default type must be deduced from the default mode */
3014     /*description->deflt.str = stp_string_list_param(description->bounds.str, 0)->name;*/
3015   }
3016   else if (strcmp(name, "InkChannels") == 0)
3017     {
3018       unsigned int ink_type = canon_printhead_colors(v);
3019       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3020 	if(ink_type == canon_inktypes[i].ink_type){
3021               description->deflt.integer = canon_inktypes[i].num_channels;
3022 	      stp_dprintf(STP_DBG_CANON, v,"Added %d InkChannels\n",canon_inktypes[i].num_channels);
3023 	}
3024       }
3025       description->bounds.integer.lower = -1;
3026       description->bounds.integer.upper = -1;
3027     }
3028   else if (strcmp(name, "MediaType") == 0)
3029   {
3030     const canon_paper_t * canon_paper_list = caps->paperlist->papers;
3031     int count = caps->paperlist->count;
3032     description->bounds.str= stp_string_list_create();
3033     description->deflt.str= canon_paper_list[0].name;
3034 
3035     for (i = 0; i < count; i ++) {
3036       stp_string_list_add_string(description->bounds.str,
3037 				canon_paper_list[i].name,
3038 				gettext(canon_paper_list[i].text));
3039 
3040       stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint:  Added Media Type: '%s'\n",canon_paper_list[i].name);
3041     }
3042   }
3043   else if (strcmp(name, "InputSlot") == 0)
3044   {
3045     const canon_slot_t * canon_slot_list = caps->slotlist->slots;
3046     int count = caps->slotlist->count;
3047     description->bounds.str= stp_string_list_create();
3048     description->deflt.str= canon_slot_list[0].name;
3049 
3050     for (i = 0; i < count; i ++)
3051       stp_string_list_add_string(description->bounds.str,
3052 				 canon_slot_list[i].name,
3053 				 gettext(canon_slot_list[i].text));
3054   }
3055   else if (strcmp(name, "CassetteTray") == 0)
3056   {
3057     description->bounds.str= stp_string_list_create();
3058     description->is_active = 0;
3059     if (caps->CassetteTray_Opts) {
3060       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3061       stp_string_list_add_string
3062 	(description->bounds.str, "Default", _("Driver-Controlled"));
3063       stp_string_list_add_string
3064 	(description->bounds.str, "Upper", _("Upper Tray/Cassette 1"));
3065       stp_string_list_add_string
3066 	(description->bounds.str, "Lower", _("Lower Tray/Cassette 2"));
3067       description->deflt.str =
3068 	stp_string_list_param(description->bounds.str, 0)->name;
3069       if (!input_slot || !strcmp(input_slot,"Cassette"))
3070 	description->is_active = 1;
3071     }
3072   }
3073   else if (strcmp(name, "PrintingMode") == 0)
3074   {
3075     int found_color, found_mono;
3076     const canon_mode_t* mode = NULL;
3077     /* mode remains NULL if not yet set */
3078 
3079     stp_dprintf(STP_DBG_CANON, v,"Calling get_current_mode from PrintingMode block in canon_parameter\n");
3080     mode = canon_get_current_mode(v);
3081 
3082     /* If mode is not set need to search ink types for all modes and
3083        see whether we have any color there
3084      */
3085 
3086     stp_dprintf(STP_DBG_CANON, v,"PrintingMode---entered enumeration block in canon_printers\n");
3087 
3088     description->bounds.str = stp_string_list_create();
3089 
3090     stp_dprintf(STP_DBG_CANON, v,"PrintingMode---created list\n");
3091 
3092     if (mode) {
3093       stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) what is the current mode inktype value: %i\n",mode->ink_types);
3094       /* e.g., ink_types is 21 = 16 + 4 + 1 */
3095       if (mode->ink_types > 1) {
3096 	stp_string_list_add_string
3097 	  (description->bounds.str, "Color", _("Color"));
3098 	stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added Color\n");
3099       }
3100       if (mode->ink_types & CANON_INK_K) {
3101 	stp_string_list_add_string
3102 	  (description->bounds.str, "BW", _("Black and White"));
3103 	stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added BW\n");
3104       }
3105     }
3106 #if 0
3107       /* original code */
3108       if (mode)
3109 	if (mode->ink_types != CANON_INK_K) {
3110 	  stp_string_list_add_string
3111 	    (description->bounds.str, "Color", _("Color"));
3112 	  stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode known) added Color\n");
3113 	}
3114 #endif
3115 
3116     else { /* mode not known yet --- needed for PPD generation */
3117       stp_dprintf(STP_DBG_CANON, v,"PrintingMode: entered mode not known conditional block\n");
3118       /* add code to find color inks */
3119       /* default type must be deduced from the default mode */
3120       /* use color if available, so break after first (color) is found, since ink types ordered with gray last */
3121       found_color=0;
3122       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3123 	for(j=0;j<caps->modelist->count;j++){
3124 	  if(caps->modelist->modes[j].ink_types > 1){
3125 	    stp_string_list_add_string
3126 	      (description->bounds.str, "Color", _("Color"));
3127 	    found_color=1;
3128 	    stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added Color\n");
3129 	    break;
3130 	  }
3131 	}
3132 	if (found_color==1)
3133 	  break;
3134       }
3135       found_mono=0;
3136       for(i=0;i<sizeof(canon_inktypes)/sizeof(canon_inktypes[0]);i++){
3137 	for(j=0;j<caps->modelist->count;j++){
3138 	  if(caps->modelist->modes[j].ink_types & CANON_INK_K){
3139 	    stp_string_list_add_string
3140 	      (description->bounds.str, "BW", _("Black and White"));
3141 	    found_mono=1;
3142 	    stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added BW\n");
3143 	    break;
3144 	  }
3145 	}
3146 	if (found_mono==1)
3147 	  break;
3148       }
3149 
3150 #if 0
3151       /* ink types for default mode*/
3152       if(caps->modelist->modes[caps->modelist->default_mode].ink_types > 1){
3153 	stp_string_list_add_string
3154 	  (description->bounds.str, "Color", _("Color"));
3155 	stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added Color\n");
3156       }
3157       if(caps->modelist->modes[caps->modelist->default_mode].ink_types & CANON_INK_K){
3158 	stp_string_list_add_string
3159 	(description->bounds.str, "BW", _("Black and White"));
3160 	stp_dprintf(STP_DBG_CANON, v,"PrintingMode: (mode not known) added BW\n");
3161       }
3162 #endif
3163 #if 0
3164       /* original code */
3165       stp_string_list_add_string
3166 	(description->bounds.str, "BW", _("Black and White"));
3167       stp_dprintf(STP_DBG_CANON, v,"PrintingMode: added BW\n");
3168 #endif
3169     }
3170 
3171     /* original code --- fine as is */
3172     description->deflt.str =
3173       stp_string_list_param(description->bounds.str, 0)->name;
3174   }
3175   else if (strcmp(name, "InkSet") == 0)
3176     {
3177       description->bounds.str= stp_string_list_create();
3178       if (caps->features & CANON_CAP_T) {
3179 	stp_string_list_add_string
3180 	  (description->bounds.str, "Both", _("Both"));
3181 	if (!(caps->features & CANON_CAP_NOBLACK)) {
3182 	    stp_string_list_add_string
3183 	      (description->bounds.str, "Black", _("Black"));
3184 	}
3185 	stp_string_list_add_string
3186 	  (description->bounds.str, "Color", _("Color"));
3187       } /* mutually exclusive */
3188       else if (caps->features & CANON_CAP_cart) {
3189 	stp_string_list_add_string
3190 	  (description->bounds.str, "Color", _("Color"));
3191 	stp_string_list_add_string
3192 	  (description->bounds.str, "Black", _("Black"));
3193 	stp_string_list_add_string
3194 	  (description->bounds.str, "Photo", _("Photo"));
3195       } else {
3196 	/* make sure to have at least a default value: no choice */
3197 	stp_string_list_add_string
3198 	  (description->bounds.str, "None", _("None"));
3199       }
3200       description->deflt.str =
3201 	stp_string_list_param(description->bounds.str, 0)->name;
3202     }
3203   /* Test implementation of borderless printing */
3204   else if (strcmp(name, "FullBleed") == 0)
3205     {
3206       const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3207       if (input_slot && !strcmp(input_slot,"CD"))
3208 	description->is_active = 0;
3209       else if (caps->features & CANON_CAP_BORDERLESS)
3210 	description->deflt.boolean = 0;
3211       else
3212 	description->is_active = 0;
3213     }
3214   else if (strcmp(name, "Duplex") == 0)
3215   {
3216     int offer_duplex=0;
3217 
3218     description->bounds.str = stp_string_list_create();
3219 
3220 /*
3221  * Don't offer the Duplex/Tumble options if the JobMode parameter is
3222  * set to "Page" Mode.
3223  * "Page" mode is set by the Gimp Plugin, which only outputs one page at a
3224  * time, so Duplex/Tumble is meaningless.
3225  */
3226 
3227     if (stp_get_string_parameter(v, "JobMode"))
3228         offer_duplex = strcmp(stp_get_string_parameter(v, "JobMode"), "Page");
3229     else
3230      offer_duplex=1;
3231 
3232     if (offer_duplex && (caps->features & CANON_CAP_DUPLEX))
3233     {
3234       description->deflt.str = duplex_types[0].name;
3235       for (i=0; i < NUM_DUPLEX; i++)
3236         {
3237           stp_string_list_add_string(description->bounds.str,
3238 				     duplex_types[i].name,gettext(duplex_types[i].text));
3239         }
3240     }
3241     else
3242       description->is_active = 0;
3243   }
3244   else if (strcmp(name, "Orientation") == 0)
3245   {
3246     description->bounds.str = stp_string_list_create();
3247     description->deflt.str = orientation_types[0].name;
3248     for (i=0; i < NUM_ORIENTATION; i++)
3249       {
3250         stp_string_list_add_string(description->bounds.str,
3251 				   orientation_types[i].name,gettext(orientation_types[i].text));
3252       }
3253   }
3254   else if (strcmp(name, "Quality") == 0)
3255   {
3256 #if 0
3257     int has_standard_quality = 0;
3258 #endif
3259     description->bounds.str = stp_string_list_create();
3260     stp_string_list_add_string(description->bounds.str, "None",
3261 			       _("Manual Control"));
3262     stp_string_list_add_string(description->bounds.str, "Standard",
3263 			       _("Standard"));
3264     description->deflt.str = "Standard";
3265   }
3266   /* Cartridge selection for those printers that have it */
3267   else if (strcmp(name, "Cartridge") == 0)
3268   {
3269 #if 0
3270     int offer_cartridge_selection = 0;
3271 #endif
3272     description->bounds.str = stp_string_list_create();
3273     stp_string_list_add_string(description->bounds.str, "Both",
3274 			       _("Both"));
3275     stp_string_list_add_string(description->bounds.str, "Color",
3276 			       _("Color"));
3277     stp_string_list_add_string(description->bounds.str, "Black",
3278 			       _("Black"));
3279 
3280     /* description->deflt.str = "Both"; */
3281     /* Note: not necessary set cartridge if Mono mode */
3282 
3283     if (caps->features & CANON_CAP_CARTRIDGE)
3284       {
3285 	description->deflt.str =
3286 	  stp_string_list_param(description->bounds.str, 0)->name;
3287       }
3288     else
3289       description->is_active = 0;
3290   }
3291 
3292 }
3293 
3294 
3295 /*
3296  * 'canon_imageable_area()' - Return the imageable area of the page.
3297  */
3298 
3299 static void
internal_imageable_area(const stp_vars_t * v,int use_paper_margins,int use_maximum_area,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3300 internal_imageable_area(const stp_vars_t *v,   /* I */
3301 			int  use_paper_margins,
3302 			int use_maximum_area,
3303 			stp_dimension_t  *left,	/* O - Left position in points */
3304 			stp_dimension_t  *right,	/* O - Right position in points */
3305 			stp_dimension_t  *bottom,	/* O - Bottom position in points */
3306 			stp_dimension_t  *top)	/* O - Top position in points */
3307 {
3308   stp_dimension_t width, length;	/* Size of page */
3309   int cd = 0;                           /* CD selected */
3310   const char *media_size = stp_get_string_parameter(v, "PageSize");
3311   stp_dimension_t left_margin = 0;
3312   stp_dimension_t right_margin = 0;
3313   stp_dimension_t bottom_margin = 0;
3314   stp_dimension_t top_margin = 0;
3315   const stp_papersize_t *pt = NULL;
3316   const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3317 
3318   const canon_cap_t * caps= canon_get_model_capabilities(v);
3319 
3320   if (media_size)
3321     pt = stp_describe_papersize(v, media_size);
3322 
3323   if(input_slot && !strcmp(input_slot,"CD"))
3324     cd = 1;
3325 
3326   stp_default_media_size(v, &width, &length);
3327 
3328   if (cd) {
3329     /* ignore printer margins for the cd print, margins get adjusted in do_print for now */
3330     if (pt) {
3331       /* move code from do_print here */
3332     }
3333     else {
3334       /* move code from do_print here */
3335     }
3336   }
3337   /* non-CD media */
3338   else {
3339     if (pt && use_paper_margins) {
3340       left_margin = pt->left;
3341       right_margin = pt->right;
3342       bottom_margin = pt->bottom;
3343       top_margin = pt->top;
3344     }
3345     /* limit to printer capabilities---without fullbleed */
3346     left_margin = MAX(left_margin, caps->border_left);
3347     right_margin = MAX(right_margin, caps->border_right);
3348     top_margin = MAX(top_margin, caps->border_top);
3349     bottom_margin = MAX(bottom_margin, caps->border_bottom);
3350   }
3351 
3352   /* temporarily limit to non-CD media until page size code moved here from do_print */
3353   /* Note: written below code to handle CD case as well */
3354   if(!cd){
3355     stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: about to enter the borderless condition block\n");
3356     stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: is borderless available? %016lx\n",caps->features & CANON_CAP_BORDERLESS);
3357     stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: is borderless selected? %d\n",stp_get_boolean_parameter(v, "FullBleed"));
3358 
3359     if ( (caps->features & CANON_CAP_BORDERLESS) &&
3360 	 (use_maximum_area || (!cd && stp_get_boolean_parameter(v, "FullBleed")))) {
3361 
3362       stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered borderless condition\n");
3363 
3364       if (pt) {
3365 
3366 	stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered pt condition\n");
3367 
3368 	if (pt->left <= 0 && pt->right <= 0 && pt->top <= 0 && pt->bottom <= 0) {
3369 
3370 	  stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: entered margin<=0 condition\n");
3371 
3372 	  if (use_paper_margins) {
3373 	    unsigned width_limit = caps->max_width;
3374 	    left_margin = -8;
3375 	    right_margin = -8;
3376 	    if (width - right_margin - 3 > width_limit)
3377 	      right_margin = width - width_limit - 3;
3378 	    top_margin = -6;
3379 	    bottom_margin = -15;
3380 
3381 	    stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: use_paper_margins so set margins all to -7\n");
3382 
3383 	  }
3384 	  else {
3385 	    left_margin = 0;
3386 	    right_margin = 0;
3387 	    top_margin = 0;
3388 	    bottom_margin = 0;
3389 
3390 	    stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: does not use paper margins so set margins all to 0\n");
3391 
3392 	  }
3393 	}
3394       }
3395     }
3396   }
3397 
3398   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: left_margin %f\n",left_margin);
3399   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: right_margin %f\n",right_margin);
3400   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: top_margin %f\n",top_margin);
3401   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: bottom_margin %f\n",bottom_margin);
3402 
3403   *left =	left_margin;
3404   *right =	width - right_margin;
3405   *top =	top_margin;
3406   *bottom =	length - bottom_margin;
3407 
3408   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_left %f\n",*left);
3409   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_right %f\n",*right);
3410   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_top %f\n",*top);
3411   stp_dprintf(STP_DBG_CANON, v,"internal_imageable_area: page_bottom %f\n",*bottom);
3412 
3413 }
3414 
3415 static void
canon_imageable_area(const stp_vars_t * v,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3416 canon_imageable_area(const stp_vars_t *v,   /* I */
3417                      stp_dimension_t  *left,	/* O - Left position in points */
3418                      stp_dimension_t  *right,	/* O - Right position in points */
3419                      stp_dimension_t  *bottom,	/* O - Bottom position in points */
3420                      stp_dimension_t  *top)		/* O - Top position in points */
3421 {
3422   internal_imageable_area(v, 1, 0, left, right, bottom, top);
3423 }
3424 
3425 static void
canon_maximum_imageable_area(const stp_vars_t * v,stp_dimension_t * left,stp_dimension_t * right,stp_dimension_t * bottom,stp_dimension_t * top)3426 canon_maximum_imageable_area(const stp_vars_t *v,   /* I */
3427                      stp_dimension_t  *left,	/* O - Left position in points */
3428                      stp_dimension_t  *right,	/* O - Right position in points */
3429                      stp_dimension_t  *bottom,	/* O - Bottom position in points */
3430                      stp_dimension_t  *top)		/* O - Top position in points */
3431 {
3432   internal_imageable_area(v, 1, 1, left, right, bottom, top);
3433 }
3434 
3435 static void
canon_limit(const stp_vars_t * v,stp_dimension_t * width,stp_dimension_t * height,stp_dimension_t * min_width,stp_dimension_t * min_height)3436 canon_limit(const stp_vars_t *v,  		/* I */
3437 	    stp_dimension_t *width,
3438 	    stp_dimension_t *height,
3439 	    stp_dimension_t *min_width,
3440 	    stp_dimension_t *min_height)
3441 {
3442   const canon_cap_t * caps=
3443     canon_get_model_capabilities(v);
3444   *width =	caps->max_width;
3445   *height =	caps->max_height;
3446   *min_width = 1;
3447   *min_height = 1;
3448 }
3449 
3450 /*
3451  * 'canon_cmd()' - Sends a command with variable args
3452  */
3453 static void
canon_cmd(const stp_vars_t * v,const char * ini,const char cmd,int num,...)3454 canon_cmd(const stp_vars_t *v, /* I - the printer         */
3455 	  const char *ini, /* I - 2 bytes start code  */
3456 	  const char cmd,  /* I - command code        */
3457 	  int  num,  /* I - number of arguments */
3458 	  ...        /* I - the args themselves */
3459 	  )
3460 {
3461   unsigned char *buffer = stp_zalloc(num + 1);
3462   int i;
3463   va_list ap;
3464 
3465   if (num)
3466     {
3467       va_start(ap, num);
3468       for (i=0; i<num; i++)
3469 	buffer[i]= (unsigned char) va_arg(ap, int);
3470       va_end(ap);
3471     }
3472 
3473   stp_zfwrite(ini,2,1,v);
3474   if (cmd)
3475     {
3476       stp_putc(cmd,v);
3477       stp_put16_le(num, v);
3478       if (num)
3479 	stp_zfwrite((const char *)buffer,num,1,v);
3480     }
3481   stp_free(buffer);
3482 }
3483 
3484 #define PUT(V,WHAT,VAL,RES) stp_dprintf(STP_DBG_CANON,V,"canon: "WHAT	\
3485 " is %04x =% 5d = %f\" = %f mm\n",(VAL),(VAL),(VAL)/(1.*RES),(VAL)/(RES/25.4))
3486 
3487 #define ESC28 "\033\050"
3488 #define ESC5b "\033\133"
3489 #define ESC40 "\033\100"
3490 
canon_control_cmd(const stp_vars_t * v,const char * cmd)3491 static void canon_control_cmd(const stp_vars_t*v,const char* cmd){
3492       canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x1f);
3493       stp_puts("BJLSTART\nControlMode=Common\n",v);
3494       stp_puts(cmd,v);
3495       stp_putc('\n',v);
3496       stp_puts("BJLEND\n",v);
3497 }
3498 
3499 
3500 /* ESC [K --  -- reset printer:
3501  */
3502 static void
canon_init_resetPrinter(const stp_vars_t * v,const canon_privdata_t * init)3503 canon_init_resetPrinter(const stp_vars_t *v, const canon_privdata_t *init)
3504 {
3505   if ( init->caps->control_cmdlist ){
3506     int i=0;
3507     while(init->caps->control_cmdlist[i]){
3508       canon_control_cmd(v,init->caps->control_cmdlist[i]);
3509       ++i;
3510     }
3511   }
3512   if(!strcmp(init->slot->name,"CD"))
3513     canon_control_cmd(v,"MediaDetection=ON");
3514   canon_cmd(v,ESC5b,0x4b, 2, 0x00,0x0f);
3515 }
3516 
3517 /* ESC ($ -- 0x24 -- cmdSetDuplex --:
3518  */
3519 static void
canon_init_setDuplex(const stp_vars_t * v,const canon_privdata_t * init)3520 canon_init_setDuplex(const stp_vars_t *v, const canon_privdata_t *init)
3521 {
3522   if (!(init->caps->features & CANON_CAP_DUPLEX))
3523     return;
3524   if (strncmp(init->duplex_str, "Duplex", 6)) {
3525     if ( !(strcmp(init->caps->name,"i860")) || !(strcmp(init->caps->name,"i865")) || !(strcmp(init->caps->name,"i950")) || !(strcmp(init->caps->name,"i960")) || !(strcmp(init->caps->name,"i990")) ) {
3526       /* i860, i865, i950, i960, i990 use ESC ($ command even for simplex mode */
3527       canon_cmd(v,ESC28,0x24,9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
3528       return;
3529     }
3530     else
3531       return;
3532   }
3533   /* The same command seems to be needed for both Duplex and DuplexTumble
3534      no idea about the meanings of the single bytes */
3535   canon_cmd(v,ESC28,0x24,9,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x02);
3536 }
3537 
3538 /* ESC (a -- 0x61 -- cmdSetPageMode --:
3539  */
3540 static void
canon_init_setPageMode(const stp_vars_t * v,const canon_privdata_t * init)3541 canon_init_setPageMode(const stp_vars_t *v, const canon_privdata_t *init)
3542 {
3543   if (!(init->caps->features & CANON_CAP_a))
3544     return;
3545 
3546   if (init->caps->features & CANON_CAP_a)
3547     canon_cmd(v,ESC28,0x61, 1, 0x01);
3548 }
3549 
3550 /* ESC (b -- 0x62 -- -- set data compression:
3551  */
3552 static void
canon_init_setDataCompression(const stp_vars_t * v,const canon_privdata_t * init)3553 canon_init_setDataCompression(const stp_vars_t *v, const canon_privdata_t *init)
3554 {
3555   if (!(init->caps->features & CANON_CAP_b))
3556     return;
3557 
3558   canon_cmd(v,ESC28,0x62, 1, 0x01);
3559 }
3560 
3561 /* ESC (c -- 0x63 -- cmdSetColor --:
3562  */
3563 static void
canon_init_setColor(const stp_vars_t * v,const canon_privdata_t * init)3564 canon_init_setColor(const stp_vars_t *v, const canon_privdata_t *init)
3565 {
3566   unsigned char
3567     numargs, arg_63[6];
3568 
3569   if (!(init->caps->features & CANON_CAP_c))
3570     return;
3571 
3572   numargs = 3;
3573   arg_63[0] = init->caps->model_id << 4; /* MODEL_ID */
3574 
3575   switch ( init->caps->model_id ) {
3576 
3577   	case 0:			/* very old 360 dpi series: BJC-800/820 */
3578 		break;		/*	tbd */
3579 
3580   	case 1:			/* 360 dpi series - BJC-4000, BJC-210, BJC-70 and their descendants */
3581 		if (init->used_inks == CANON_INK_K)
3582                             arg_63[0]|= 0x01;                                        /* PRINT_COLOUR */
3583 
3584 
3585 //		  if ( (!strcmp(init->caps->name,"85")) ||  (!strcmp(init->caps->name,"1000")) ) /* BJC-85, BJC-1000 */
3586 //		    arg_63[1] = (init->pt) ? init->pt->media_code_c : 0;                /* print media type */
3587 //		  else /* original, not sure which models follow this at all */
3588 		    arg_63[1] = ((init->pt ? init->pt->media_code_c : 0) << 4)                /* PRINT_MEDIA */
3589 		      + 1;	/* hardcode to High quality for now */		/* PRINT_QUALITY */
3590 
3591 		    if (!strcmp(init->caps->name,"2100")) { /* BJC-2100: ESC (c command length is 3 */
3592 		      if (!strcmp(init->mode->name,"720x360dpi"))
3593 			arg_63[1] = 0x00;
3594 		      else if (!strcmp(init->mode->name,"360x360dpi_draft"))
3595 			arg_63[1] = 0x00;
3596 		      else if (!strcmp(init->mode->name,"180x180dpi"))
3597 			arg_63[1] = 0x02;
3598 		      /* else keep at 01 hard-coded as above - logic unknown */
3599 		      canon_cmd(v,ESC28,0x63, 3, arg_63[0], arg_63[1], 0x00);
3600 		    } else /* length 2 in legacy code */
3601 		      canon_cmd(v,ESC28,0x63, 2, arg_63[0], arg_63[1]);
3602 		break;
3603 
3604 	case 2:			/* are any models using this? */
3605 		break;
3606 
3607 	case 3:			/* 720 dpi series - BJC-3000 and descendants */
3608 		if (init->used_inks == CANON_INK_K)
3609                             arg_63[0]|= 0x01;                                        /* colour mode */
3610 
3611                   arg_63[1] = (init->pt) ? init->pt->media_code_c : 0;                /* print media type */
3612 
3613                  if (!strcmp(init->caps->name,"S200")) /* S200 */
3614                    {
3615                      if ((init->mode->xdpi == 720) && (init->mode->ydpi == 720 ))
3616                        arg_63[2] = 1;
3617                      else
3618                        arg_63[2] = 4; /* hardcoded: quality 3  (may be 0...4) */
3619                      /* bidirectional is controlled via quality: 0..2 is bidi, 3 and 4 uni */
3620                      /* not every combination works, no idea about the principle */
3621                      if ( (init->mode->xdpi > 360) || (init->mode->ydpi > 360) )
3622                        {
3623                          numargs = 6;
3624                          arg_63[3] = 0x10; arg_63[4] = 6; arg_63[5] = 8; /* arg5 makes a vert. offset for K */
3625                          if (init->used_inks == CANON_INK_K)
3626                            arg_63[4] = 1;
3627                        }
3628                    }
3629 		 else if (!strcmp(init->caps->name,"4550")) /* BJC-4550 */
3630 		    {
3631 		      numargs = 3;
3632 		      arg_63[2] = 0; /* not used in Black and Color, no idea about PhotoColor yet */
3633 		      arg_63[1] = init->quality;     /* hardcode to whatever this means for now; quality, apparently */
3634 		    }
3635                  else
3636                    arg_63[2] = init->quality;        /* hardcode to whatever this means for now; quality, apparently */
3637 
3638                  stp_zprintf(v, "\033\050\143");
3639                  stp_put16_le(numargs, v);
3640                  stp_zfwrite((const char *)arg_63, numargs, 1, v);
3641 		break;
3642   	}
3643 
3644   return;
3645 }
3646 
3647 /* ESC (d -- 0x64 -- -- set raster resolution:
3648  */
3649 static void
canon_init_setResolution(const stp_vars_t * v,const canon_privdata_t * init)3650 canon_init_setResolution(const stp_vars_t *v, const canon_privdata_t *init)
3651 {
3652   if (!(init->caps->features & CANON_CAP_d))
3653     return;
3654 
3655    if (strcmp(init->caps->name,"S200") || (init->mode->xdpi <= 360))
3656   canon_cmd(v,ESC28,0x64, 4,
3657 	    (init->mode->ydpi >> 8 ), (init->mode->ydpi & 255),
3658 	    (init->mode->xdpi >> 8 ), (init->mode->xdpi & 255));
3659    else
3660      if (init->mode->xdpi < 2880)
3661        canon_cmd(v,ESC28,0x64, 4,
3662          (720 >> 8), (720 & 255),
3663          (720 >> 8), (720 & 255));
3664      else
3665        canon_cmd(v,ESC28,0x64, 4,
3666          (720 >> 8), (720 & 255),
3667          (2880 >> 8), (2880 & 255));
3668   }
3669 
3670 /* ESC (g -- 0x67 -- cmdSetPageMargins --:
3671  */
3672 static void
canon_init_setPageMargins(const stp_vars_t * v,const canon_privdata_t * init)3673 canon_init_setPageMargins(const stp_vars_t *v, const canon_privdata_t *init)
3674 {
3675   /* TOFIX: what exactly is to be sent?
3676    * Is it the printable length or the bottom border?
3677    * Is is the printable width or the right border?
3678    */
3679 
3680   int minlength= 0;
3681   int minwidth= 0;
3682   int length= init->page_height*5/36;
3683   int width= init->page_width*5/36;
3684 
3685   if (!(init->caps->features & CANON_CAP_g))
3686     return;
3687 
3688   if (minlength>length) length= minlength;
3689   if (minwidth>width) width= minwidth;
3690 
3691   canon_cmd(v,ESC28,0x67, 4, 0,
3692 	    (unsigned char)(length),1,
3693 	    (unsigned char)(width));
3694 
3695 }
3696 
3697 /* ESC (l -- 0x6c -- cmdSetTray --:
3698  */
3699 static void
canon_init_setTray(const stp_vars_t * v,const canon_privdata_t * init)3700 canon_init_setTray(const stp_vars_t *v, const canon_privdata_t *init)
3701 {
3702   unsigned char
3703     arg_6c_1 = 0x00,
3704     arg_6c_2 = 0x00, /* plain paper */
3705     arg_6c_3 = 0x00; /* special cases like iP7100 to be handled */
3706 
3707   if (!(init->caps->features & CANON_CAP_l))
3708     return;
3709 
3710   arg_6c_1 = init->caps->model_id << 4;
3711 
3712   arg_6c_1|= (init->slot->code & 0x0f);
3713 
3714   /* set gap for MP710/740 if thick media selected */
3715   if (!strcmp(init->slot->name,"AutoThick"))
3716     if ( (!strcmp(init->caps->name,"PIXMA MP710")) || (!strcmp(init->caps->name,"PIXMA MP740")) )
3717       arg_6c_3 = 0x10;
3718 
3719   switch ( init->caps->model_id ) {
3720   case 0:
3721     break;
3722   case 1:
3723     if (init->pt) arg_6c_2 = ((init->pt ? init->pt->media_code_l : 0) << 4);                /* PRINT_MEDIA */
3724     break;
3725   case 2:
3726     break;
3727   case 3:
3728     if (init->pt) arg_6c_2 = init->pt->media_code_l;                                        /* PRINT_MEDIA */
3729     break;
3730   }
3731 
3732   /* select between length 2 and 3 byte variations of command */
3733   /*if(init->caps->model_id >= 3)*/
3734   if(init->caps->ESC_l_len == 3)
3735     canon_cmd(v,ESC28,0x6c, 3, arg_6c_1, arg_6c_2, arg_6c_3); /* 3rd arg is "gap" */
3736   else /* else 2 bytes---no other option for now */
3737     canon_cmd(v,ESC28,0x6c, 2, arg_6c_1, arg_6c_2);
3738 }
3739 
3740 /* ESC (m -- 0x6d --  -- :
3741  */
3742 static void
canon_init_setPrintMode(const stp_vars_t * v,const canon_privdata_t * init)3743 canon_init_setPrintMode(const stp_vars_t *v, const canon_privdata_t *init)
3744 {
3745   unsigned char
3746     arg_6d_1 = 0x03, /* color printhead? */
3747     arg_6d_2 = 0x00, /* 00=color  02=b/w */
3748     arg_6d_3 = 0x00, /* only 01 for bjc8200 and S200*/
3749                      /* S200:for envelope and t-shirt transfer = 03 */
3750     arg_6d_a = 0x03, /* A4 paper */
3751     arg_6d_b = 0x00;
3752 
3753   if (!(init->caps->features & CANON_CAP_m))
3754     return;
3755 
3756   arg_6d_a= canon_size_type(v,init->caps);
3757   if (!arg_6d_a)
3758     arg_6d_b= 1;
3759 
3760   arg_6d_1= 0x04;
3761 
3762   if ((!strcmp(init->caps->name,"7000")) && (init->used_inks == CANON_INK_K || init->used_inks == CANON_INK_CcMmYK || init->used_inks == CANON_INK_CcMmYyK))
3763     arg_6d_1= 0x03;
3764 
3765   if (((!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200")) && init->used_inks == CANON_INK_K) || init->used_inks == CANON_INK_CMYK)
3766       arg_6d_1= 0x02;
3767 
3768   if(!strcmp(init->caps->name,"S200") && init->used_inks == CANON_INK_CMY)
3769       arg_6d_1= 0x02;
3770 
3771   if (init->used_inks == CANON_INK_K)
3772     arg_6d_2= 0x02;
3773 
3774   if (!strcmp(init->caps->name,"8200") || !strcmp(init->caps->name,"S200"))
3775     arg_6d_3= 0x01;
3776 
3777   canon_cmd(v,ESC28,0x6d,12, arg_6d_1,
3778 	    0xff,0xff,0x00,0x00,0x07,0x00,
3779 	    arg_6d_a,arg_6d_b,arg_6d_2,0x00,arg_6d_3);
3780 }
3781 
3782 /* ESC (M -- 0x4d --  -- :
3783  */
3784 static void
canon_init_setESC_M(const stp_vars_t * v,const canon_privdata_t * init)3785 canon_init_setESC_M(const stp_vars_t *v, const canon_privdata_t *init)
3786 {
3787   if (!(init->caps->features & CANON_CAP_M))
3788     return;
3789 
3790   canon_cmd(v,ESC28,0x4d, 3, 0x00, 0x00, 0x00);
3791 }
3792 
3793 /* ESC (p -- 0x70 -- cmdSetPageMargins2 --:
3794  */
3795 static void
canon_init_setPageMargins2(const stp_vars_t * v,canon_privdata_t * init)3796 canon_init_setPageMargins2(const stp_vars_t *v, canon_privdata_t *init)
3797 {
3798   unsigned char arg_70_1,arg_70_2,arg_70_3,arg_70_4;
3799 
3800   int border_left,border_right,border_top,border_bottom;
3801   int border_left2,border_top2;
3802   int border_right2;
3803   int border_bottom2;
3804   int area_right,area_top;
3805   int test_cd; /* variable for activating experimental adjustments */
3806   /* CD tray size adjustments for paper dimensions */
3807   int adjust_tray_custom_length, adjust_tray_custom_width;
3808   int adjust_tray_A_length, adjust_tray_A_width;
3809   int adjust_tray_BCD_length, adjust_tray_BCD_width;
3810   int adjust_tray_E_length, adjust_tray_E_width;
3811   int adjust_tray_F_length, adjust_tray_F_width;
3812   int adjust_tray_G_length, adjust_tray_G_width;
3813   int adjust_tray_H_length, adjust_tray_H_width;
3814   int adjust_tray_J_length, adjust_tray_J_width;
3815   int adjust_tray_L_length, adjust_tray_L_width;
3816   /* CD tray border adjustments */
3817   int adjust_tray_custom_left, adjust_tray_custom_right, adjust_tray_custom_top, adjust_tray_custom_bottom;
3818   int adjust_tray_A_left, adjust_tray_A_right, adjust_tray_A_top, adjust_tray_A_bottom;
3819   int adjust_tray_BCD_left, adjust_tray_BCD_right, adjust_tray_BCD_top, adjust_tray_BCD_bottom;
3820   int adjust_tray_E_left, adjust_tray_E_right, adjust_tray_E_top, adjust_tray_E_bottom;
3821   int adjust_tray_F_left, adjust_tray_F_right, adjust_tray_F_top, adjust_tray_F_bottom;
3822   int adjust_tray_G_left, adjust_tray_G_right, adjust_tray_G_top, adjust_tray_G_bottom;
3823   int adjust_tray_H_left, adjust_tray_H_right, adjust_tray_H_top, adjust_tray_H_bottom;
3824   int adjust_tray_J_left, adjust_tray_J_right, adjust_tray_J_top, adjust_tray_J_bottom;
3825   int adjust_tray_L_left, adjust_tray_L_right, adjust_tray_L_top, adjust_tray_L_bottom;
3826   int paper_width, paper_length;
3827 
3828   /* Canon printer firmware requires paper_width (and paper_length?)
3829      to be exact matches in units of 1/600 inch.
3830      To this end, papersize code is used to find the papersize for the
3831      printjob, and paper_width and paper_length set to exact values,
3832      rather than calculated.
3833   */
3834   unsigned char arg_ESCP_1 = (init->pt) ? canon_size_type(v,init->caps) : 0x03; /* default size A4 */
3835   stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: arg_ESCP_1 = '%x'\n",arg_ESCP_1);
3836 
3837   /* TOFIX: what exactly is to be sent?
3838    * Is it the printable length or the bottom border?
3839    * Is is the printable width or the right border?
3840    */
3841 
3842   int unit = 600;
3843   int printable_width = (init->page_width + 1)*5/6;
3844   int printable_length = (init->page_height + 1)*5/6;
3845 
3846   const char* input_slot = stp_get_string_parameter(v, "InputSlot");
3847   int print_cd = (input_slot && (!strcmp(input_slot, "CD")));
3848 
3849   stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: print_cd = %d\n",print_cd);
3850 
3851   test_cd = 1;
3852   /*
3853     Adjustments for different CD trays:
3854     All based on the following settings:
3855     CANON_CD_X = 176
3856     CANON_CD_Y = 405
3857 
3858     Custom:
3859     printable_width = init->page_width + 24;
3860     printable_length = init->page_height + 132;
3861 
3862     A:
3863     printable_width = init->page_width + 44;
3864     printable_length = init->page_height + 151;
3865 
3866     B/C/D:
3867     printable_width = init->page_width + 10;
3868     printable_length = init->page_height + 84;
3869 
3870     E:
3871     printable_width = init->page_width + 127;
3872     printable_length = init->page_height + 186;
3873 
3874     F:
3875     printable_width = init->page_width + 10;
3876     printable_length = init->page_height + 95;
3877 
3878     G:
3879     printable_width = init->page_width + 10;
3880     printable_length = init->page_height + 127;
3881 
3882     H:
3883     printable_width = init->page_width + 68;
3884     printable_length = init->page_height + 481;
3885 
3886     J:
3887     printable_width = init->page_width + 8;
3888     printable_length = init->page_height + 44;
3889 
3890     L:
3891     printable_width = init->page_width + 10;
3892     printable_length = init->page_height + 263;
3893   */
3894 
3895   /* adjust paper dimensions for CD in points */
3896   adjust_tray_custom_length = 132;
3897   adjust_tray_custom_width = 24;
3898   adjust_tray_A_length = 151;
3899   adjust_tray_A_width = 44;
3900   adjust_tray_BCD_length = 84;
3901   adjust_tray_BCD_width = 10;
3902   adjust_tray_E_length = 186;
3903   adjust_tray_E_width = 127;
3904   adjust_tray_F_length = 95;
3905   adjust_tray_F_width = 10; /* 10 calculated, but empirically 11 */
3906   adjust_tray_G_length = 127;
3907   adjust_tray_G_width = 10; /* 10 calculated, but empirically 11 */
3908   adjust_tray_H_length = 481;
3909   adjust_tray_H_width = 68;
3910   adjust_tray_J_length = 44;
3911   adjust_tray_J_width = 8;
3912   adjust_tray_L_length = 263;
3913   adjust_tray_L_width = 10;
3914 
3915   /* ensure less than or equal to Windows measurements  by border adjustments in points  */
3916   adjust_tray_custom_left = 0;
3917   adjust_tray_custom_right = 0;
3918   adjust_tray_custom_top = 0;
3919   adjust_tray_custom_bottom = 0;
3920   adjust_tray_A_left = 0;
3921   adjust_tray_A_right = 0;
3922   adjust_tray_A_top = 0;
3923   adjust_tray_A_bottom = 0;
3924   adjust_tray_BCD_left = 0;
3925   adjust_tray_BCD_right = 0;
3926   adjust_tray_BCD_top = 0;
3927   adjust_tray_BCD_bottom = 0;
3928   adjust_tray_E_left = 0;
3929   adjust_tray_E_right = 0;
3930   adjust_tray_E_top = 0;
3931   adjust_tray_E_bottom = 0;
3932   adjust_tray_F_left = 0;
3933   adjust_tray_F_right = 0;
3934   adjust_tray_F_top = 0;
3935   adjust_tray_F_bottom = 0;
3936   adjust_tray_G_left = 0;
3937   adjust_tray_G_right = 0;
3938   adjust_tray_G_top = 0;
3939   adjust_tray_G_bottom = 0;
3940   adjust_tray_H_left = 0;
3941   adjust_tray_H_right = 0;
3942   adjust_tray_H_top = 0;
3943   adjust_tray_H_bottom = 0;
3944   adjust_tray_J_left = 0;
3945   adjust_tray_J_right = 0;
3946   adjust_tray_J_top = 0;
3947   adjust_tray_J_bottom = 0;
3948   adjust_tray_L_left = 0;
3949   adjust_tray_L_right = 0;
3950   adjust_tray_L_top = 0;
3951   adjust_tray_L_bottom = 0;
3952 
3953   if ((print_cd) && test_cd) {
3954     /* test all of the parameters for CD */
3955     stp_dprintf(STP_DBG_CANON, v,"==========Start Test Printout=========='\n");
3956 
3957     stp_dprintf(STP_DBG_CANON, v, "Tray Custom original init->page_width (pts): '%d'\n",init->page_width);
3958     stp_dprintf(STP_DBG_CANON, v, "Tray Custom original init->page_height (pts): '%d'\n",init->page_height);
3959     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_custom_width);
3960     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_custom_length);
3961     stp_dprintf(STP_DBG_CANON, v, "Tray Custom printable width (pts): '%d'\n",(init->page_width + adjust_tray_custom_width + 1) * 5 / 6);
3962     stp_dprintf(STP_DBG_CANON, v, "Tray Custom printable length (pts): '%d'\n",(init->page_height + adjust_tray_custom_length + 1) * 5 / 6);
3963     stp_dprintf(STP_DBG_CANON, v, "Tray Custom page_width (1/600): '%d'\n",(init->page_width + adjust_tray_custom_width) * unit / 72);
3964     stp_dprintf(STP_DBG_CANON, v, "Tray Custom page_height (1/600): '%d'\n",(init->page_height + adjust_tray_custom_length) * unit / 72);
3965     stp_dprintf(STP_DBG_CANON, v, "Tray Custom paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_custom_width + 20 + adjust_tray_custom_left + adjust_tray_custom_right) * unit / 72);
3966     stp_dprintf(STP_DBG_CANON, v, "Tray Custom paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_custom_length + 24 + adjust_tray_custom_top + adjust_tray_custom_bottom) * unit / 72);
3967 
3968     stp_dprintf(STP_DBG_CANON, v, "Tray A original init->page_width (pts): '%d'\n",init->page_width);
3969     stp_dprintf(STP_DBG_CANON, v, "Tray A original init->page_height (pts): '%d'\n",init->page_height);
3970     stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_A_width);
3971     stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_A_length);
3972     stp_dprintf(STP_DBG_CANON, v, "Tray A printable width (pts): '%d'\n",(init->page_width + adjust_tray_A_width + 1) * 5 / 6);
3973     stp_dprintf(STP_DBG_CANON, v, "Tray A printable length (pts): '%d'\n",(init->page_height + adjust_tray_A_length + 1) * 5 / 6);
3974     stp_dprintf(STP_DBG_CANON, v, "Tray A page_width (1/600): '%d'\n",(init->page_width + adjust_tray_A_width) * unit / 72);
3975     stp_dprintf(STP_DBG_CANON, v, "Tray A page_height (1/600): '%d'\n",(init->page_height + adjust_tray_A_length) * unit / 72);
3976     stp_dprintf(STP_DBG_CANON, v, "Tray A paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_A_width + 20 + adjust_tray_A_left + adjust_tray_A_right ) * unit / 72);
3977     stp_dprintf(STP_DBG_CANON, v, "Tray A paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_A_length + 24 + adjust_tray_A_top + adjust_tray_A_bottom) * unit / 72);
3978 
3979     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D original init->page_width (pts): '%d'\n",init->page_width);
3980     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D original init->page_height (pts): '%d'\n",init->page_height);
3981     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_BCD_width);
3982     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_BCD_length);
3983     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D printable width (pts): '%d'\n",(init->page_width + adjust_tray_BCD_width + 1) * 5 / 6);
3984     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D printable length (pts): '%d'\n",(init->page_height + adjust_tray_BCD_length + 1) * 5 / 6);
3985     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D page_width (1/600): '%d'\n",(init->page_width + adjust_tray_BCD_width) * unit / 72);
3986     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D page_height (1/600): '%d'\n",(init->page_height + adjust_tray_BCD_length) * unit / 72);
3987     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_BCD_width + 20 + adjust_tray_BCD_left + adjust_tray_BCD_right) * unit / 72);
3988     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_BCD_length + 24 + adjust_tray_BCD_top + adjust_tray_BCD_bottom) * unit / 72);
3989 
3990     stp_dprintf(STP_DBG_CANON, v, "Tray E original init->page_width (pts): '%d'\n",init->page_width);
3991     stp_dprintf(STP_DBG_CANON, v, "Tray E original init->page_height (pts): '%d'\n",init->page_height);
3992     stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_E_width);
3993     stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_E_length);
3994     stp_dprintf(STP_DBG_CANON, v, "Tray E printable width (pts): '%d'\n",(init->page_width + adjust_tray_E_width + 1) * 5 / 6);
3995     stp_dprintf(STP_DBG_CANON, v, "Tray E printable length (pts): '%d'\n",(init->page_height + adjust_tray_E_length + 1) * 5 / 6);
3996     stp_dprintf(STP_DBG_CANON, v, "Tray E page_width (1/600): '%d'\n",(init->page_width + adjust_tray_E_width) * unit / 72);
3997     stp_dprintf(STP_DBG_CANON, v, "Tray E page_height (1/600): '%d'\n",(init->page_height + adjust_tray_E_length) * unit / 72);
3998     stp_dprintf(STP_DBG_CANON, v, "Tray E paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_E_width + 20 + adjust_tray_E_left + adjust_tray_E_right) * unit / 72);
3999     stp_dprintf(STP_DBG_CANON, v, "Tray E paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_E_length + 24 + adjust_tray_E_top + adjust_tray_E_bottom) * unit / 72);
4000 
4001     stp_dprintf(STP_DBG_CANON, v, "Tray F original init->page_width (pts): '%d'\n",init->page_width);
4002     stp_dprintf(STP_DBG_CANON, v, "Tray F original init->page_height (pts): '%d'\n",init->page_height);
4003     stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_F_width);
4004     stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_F_length);
4005     stp_dprintf(STP_DBG_CANON, v, "Tray F printable width (pts): '%d'\n",(init->page_width + adjust_tray_F_width + 1) * 5 / 6);
4006     stp_dprintf(STP_DBG_CANON, v, "Tray F printable length (pts): '%d'\n",(init->page_height + adjust_tray_F_length + 1) * 5 / 6);
4007     stp_dprintf(STP_DBG_CANON, v, "Tray F page_width (1/600): '%d'\n",(init->page_width + adjust_tray_F_width) * unit / 72);
4008     stp_dprintf(STP_DBG_CANON, v, "Tray F page_height (1/600): '%d'\n",(init->page_height + adjust_tray_F_length) * unit / 72);
4009     stp_dprintf(STP_DBG_CANON, v, "Tray F paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_F_width + 20 + adjust_tray_F_left + adjust_tray_F_right) * unit / 72);
4010     stp_dprintf(STP_DBG_CANON, v, "Tray F paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_F_length + 24 + adjust_tray_F_top + adjust_tray_F_bottom) * unit / 72);
4011 
4012     stp_dprintf(STP_DBG_CANON, v, "Tray G original init->page_width (pts): '%d'\n",init->page_width);
4013     stp_dprintf(STP_DBG_CANON, v, "Tray G original init->page_height (pts): '%d'\n",init->page_height);
4014     stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_G_width);
4015     stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_G_length);
4016     stp_dprintf(STP_DBG_CANON, v, "Tray G printable width (pts): '%d'\n",(init->page_width + adjust_tray_G_width + 1) * 5 / 6);
4017     stp_dprintf(STP_DBG_CANON, v, "Tray G printable length (pts): '%d'\n",(init->page_height + adjust_tray_G_length + 1) * 5 / 6);
4018     stp_dprintf(STP_DBG_CANON, v, "Tray G page_width (1/600): '%d'\n",(init->page_width + adjust_tray_G_width) * unit / 72);
4019     stp_dprintf(STP_DBG_CANON, v, "Tray G page_height (1/600): '%d'\n",(init->page_height + adjust_tray_G_length) * unit / 72);
4020     stp_dprintf(STP_DBG_CANON, v, "Tray G paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_G_width + 20 + adjust_tray_G_left + adjust_tray_G_right) * unit / 72);
4021     stp_dprintf(STP_DBG_CANON, v, "Tray G paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_G_length + 24 + adjust_tray_G_top + adjust_tray_G_bottom) * unit / 72);
4022 
4023     stp_dprintf(STP_DBG_CANON, v, "Tray H original init->page_width (pts): '%d'\n",init->page_width);
4024     stp_dprintf(STP_DBG_CANON, v, "Tray H original init->page_height (pts): '%d'\n",init->page_height);
4025     stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_H_width);
4026     stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_H_length);
4027     stp_dprintf(STP_DBG_CANON, v, "Tray H printable width (pts): '%d'\n",(init->page_width + adjust_tray_H_width + 1) * 5 / 6);
4028     stp_dprintf(STP_DBG_CANON, v, "Tray H printable length (pts): '%d'\n",(init->page_height + adjust_tray_H_length + 1) * 5 / 6);
4029     stp_dprintf(STP_DBG_CANON, v, "Tray H page_width (1/600): '%d'\n",(init->page_width + adjust_tray_H_width) * unit / 72);
4030     stp_dprintf(STP_DBG_CANON, v, "Tray H page_height (1/600): '%d'\n",(init->page_height + adjust_tray_H_length) * unit / 72);
4031     stp_dprintf(STP_DBG_CANON, v, "Tray H paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_H_width + 20 + adjust_tray_H_left + adjust_tray_H_right) * unit / 72);
4032     stp_dprintf(STP_DBG_CANON, v, "Tray H paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_H_length + 24 + adjust_tray_H_top + adjust_tray_H_bottom) * unit / 72);
4033 
4034     stp_dprintf(STP_DBG_CANON, v, "Tray J original init->page_width (pts): '%d'\n",init->page_width);
4035     stp_dprintf(STP_DBG_CANON, v, "Tray J original init->page_height (pts): '%d'\n",init->page_height);
4036     stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_J_width);
4037     stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_J_length);
4038     stp_dprintf(STP_DBG_CANON, v, "Tray J printable width (pts): '%d'\n",(init->page_width + adjust_tray_J_width + 1) * 5 / 6);
4039     stp_dprintf(STP_DBG_CANON, v, "Tray J printable length (pts): '%d'\n",(init->page_height + adjust_tray_J_length + 1) * 5 / 6);
4040     stp_dprintf(STP_DBG_CANON, v, "Tray J page_width (1/600): '%d'\n",(init->page_width + adjust_tray_J_width) * unit / 72);
4041     stp_dprintf(STP_DBG_CANON, v, "Tray J page_height (1/600): '%d'\n",(init->page_height + adjust_tray_J_length) * unit / 72);
4042     stp_dprintf(STP_DBG_CANON, v, "Tray J paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_J_width + 20 + adjust_tray_J_left + adjust_tray_J_right) * unit / 72);
4043     stp_dprintf(STP_DBG_CANON, v, "Tray J paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_J_length + 24 + adjust_tray_J_top + adjust_tray_J_bottom) * unit / 72);
4044 
4045     stp_dprintf(STP_DBG_CANON, v, "Tray L original init->page_width (pts): '%d'\n",init->page_width);
4046     stp_dprintf(STP_DBG_CANON, v, "Tray L original init->page_height (pts): '%d'\n",init->page_height);
4047     stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_width (pts): '%d'\n",init->page_width + adjust_tray_L_width);
4048     stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_height (pts): '%d'\n",init->page_height + adjust_tray_L_length);
4049     stp_dprintf(STP_DBG_CANON, v, "Tray L printable width (pts): '%d'\n",(init->page_width + adjust_tray_L_width + 1) * 5 / 6);
4050     stp_dprintf(STP_DBG_CANON, v, "Tray L printable length (pts): '%d'\n",(init->page_height + adjust_tray_L_length + 1) * 5 / 6);
4051     stp_dprintf(STP_DBG_CANON, v, "Tray L page_width (1/600): '%d'\n",(init->page_width + adjust_tray_L_width) * unit / 72);
4052     stp_dprintf(STP_DBG_CANON, v, "Tray L page_height (1/600): '%d'\n",(init->page_height + adjust_tray_L_length) * unit / 72);
4053     stp_dprintf(STP_DBG_CANON, v, "Tray L paper_width (1/600): '%d'\n",(init->page_width + adjust_tray_L_width + 20 + adjust_tray_L_left + adjust_tray_L_right) * unit / 72);
4054     stp_dprintf(STP_DBG_CANON, v, "Tray L paper_height (1/600): '%d'\n",(init->page_height + adjust_tray_L_length + 24 + adjust_tray_L_top + adjust_tray_L_bottom) * unit / 72);
4055 
4056     stp_dprintf(STP_DBG_CANON, v,"==========End Test Printout=========='\n");
4057   }
4058 
4059   /* Tray Custom */
4060   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA MP710")) && (test_cd==1) ) {
4061 
4062     init->page_width +=24;
4063     init->page_height +=132;
4064 
4065     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_width: '%d'\n",init->page_width);
4066     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified init->page_height: '%d'\n",init->page_height);
4067 
4068     printable_width=  (init->page_width+ 1)*5/6;
4069     printable_length= (init->page_height + 1)*5/6;
4070 
4071     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified printable_width: '%d'\n",printable_width);
4072     stp_dprintf(STP_DBG_CANON, v, "Tray Custom modified printable_length: '%d'\n",printable_length);
4073 
4074   }
4075 
4076   /* Tray A */
4077   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP9910")) && (test_cd==1) ) {
4078 
4079     init->page_width +=44;
4080     init->page_height +=151;
4081 
4082     stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_width: '%d'\n",init->page_width);
4083     stp_dprintf(STP_DBG_CANON, v, "Tray A modified init->page_height: '%d'\n",init->page_height);
4084 
4085     printable_width=  (init->page_width+ 1)*5/6;
4086     printable_length= (init->page_height + 1)*5/6;
4087 
4088     stp_dprintf(STP_DBG_CANON, v, "Tray A modified printable_width: '%d'\n",printable_width);
4089     stp_dprintf(STP_DBG_CANON, v, "Tray A modified printable_length: '%d'\n",printable_length);
4090 
4091   }
4092 
4093   /* Tray B,C,D */
4094   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP3000")) && (test_cd==1) ) {
4095 
4096     init->page_width +=10;
4097     init->page_height +=84;
4098 
4099     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified init->page_width: '%d'\n",init->page_width);
4100     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/B modified init->page_height: '%d'\n",init->page_height);
4101 
4102     printable_width=  (init->page_width+ 1)*5/6;
4103     printable_length= (init->page_height + 1)*5/6;
4104 
4105     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified printable_width: '%d'\n",printable_width);
4106     stp_dprintf(STP_DBG_CANON, v, "Tray B/C/D modified printable_length: '%d'\n",printable_length);
4107 
4108   }
4109 
4110   /* Tray E */
4111   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA Pro9000")) && (test_cd==1) ) {
4112 
4113     init->page_width +=127;
4114     init->page_height +=186;
4115 
4116     stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_width: '%d'\n",init->page_width);
4117     stp_dprintf(STP_DBG_CANON, v, "Tray E modified init->page_height: '%d'\n",init->page_height);
4118 
4119     printable_width=  (init->page_width+ 1)*5/6;
4120     printable_length= (init->page_height + 1)*5/6;
4121 
4122     stp_dprintf(STP_DBG_CANON, v, "Tray E modified printable_width: '%d'\n",printable_width);
4123     stp_dprintf(STP_DBG_CANON, v, "Tray E modified printable_length: '%d'\n",printable_length);
4124 
4125   }
4126 
4127   /* Tray F */
4128   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4500")) && (test_cd==1) ) {
4129     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F init->page_width: '%d'\n",init->page_width);
4130     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F init->page_height: '%d'\n",init->page_height);
4131 
4132     stp_dprintf(STP_DBG_CANON, v, "Tray F init->page_width: '%d'\n",init->page_width);
4133     stp_dprintf(STP_DBG_CANON, v, "Tray F init->page_height: '%d'\n",init->page_height);
4134     stp_dprintf(STP_DBG_CANON, v, "Tray F initial printable_width: '%d'\n",printable_width);
4135     stp_dprintf(STP_DBG_CANON, v, "Tray F initial printable_length: '%d'\n",printable_length);
4136 
4137     init->page_width +=10;
4138     init->page_height +=95;
4139 
4140     stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_width: '%d'\n",init->page_width);
4141     stp_dprintf(STP_DBG_CANON, v, "Tray F modified init->page_height: '%d'\n",init->page_height);
4142 
4143     printable_width=  (init->page_width+ 1)*5/6;
4144     printable_length= (init->page_height + 1)*5/6;
4145 
4146     stp_dprintf(STP_DBG_CANON, v, "Tray F modified printable_width: '%d'\n",printable_width);
4147     stp_dprintf(STP_DBG_CANON, v, "Tray F modified printable_length: '%d'\n",printable_length);
4148 
4149     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F modified printable_width: '%d'\n",printable_width);
4150     stp_dprintf(STP_DBG_CANON, v,"DEBUG: Gutenprint: Tray F modified printable_length: '%d'\n",printable_length);
4151   }
4152 
4153   /* Tray G */
4154   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4700")) && (test_cd==1) ) {
4155 
4156     init->page_width +=10;
4157     init->page_height +=127;
4158 
4159     stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_width: '%d'\n",init->page_width);
4160     stp_dprintf(STP_DBG_CANON, v, "Tray G modified init->page_height: '%d'\n",init->page_height);
4161 
4162     printable_width=  (init->page_width+ 1)*5/6;
4163     printable_length= (init->page_height + 1)*5/6;
4164 
4165     stp_dprintf(STP_DBG_CANON, v, "Tray G modified printable_width: '%d'\n",printable_width);
4166     stp_dprintf(STP_DBG_CANON, v, "Tray G modified printable_length: '%d'\n",printable_length);
4167 
4168   }
4169 
4170   /* Tray H */
4171   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA PRO-1")) && (test_cd==1) ) {
4172 
4173     init->page_width +=68;
4174     init->page_height +=481;
4175 
4176     stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_width: '%d'\n",init->page_width);
4177     stp_dprintf(STP_DBG_CANON, v, "Tray H modified init->page_height: '%d'\n",init->page_height);
4178 
4179     printable_width=  (init->page_width+ 1)*5/6;
4180     printable_length= (init->page_height + 1)*5/6;
4181 
4182     stp_dprintf(STP_DBG_CANON, v, "Tray H modified printable_width: '%d'\n",printable_width);
4183     stp_dprintf(STP_DBG_CANON, v, "Tray H modified printable_length: '%d'\n",printable_length);
4184 
4185   }
4186 
4187   /* Tray J */
4188   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP7200")) && (test_cd==1) ) {
4189 
4190     init->page_width +=8;
4191     init->page_height +=44;
4192 
4193     stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_width: '%d'\n",init->page_width);
4194     stp_dprintf(STP_DBG_CANON, v, "Tray J modified init->page_height: '%d'\n",init->page_height);
4195 
4196     printable_width=  (init->page_width+ 1)*5/6;
4197     printable_length= (init->page_height + 1)*5/6;
4198 
4199     stp_dprintf(STP_DBG_CANON, v, "Tray J modified printable_width: '%d'\n",printable_width);
4200     stp_dprintf(STP_DBG_CANON, v, "Tray J modified printable_length: '%d'\n",printable_length);
4201 
4202   }
4203 
4204   /* Tray L */
4205   if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP8700")) && (test_cd==1) ) {
4206 
4207     init->page_width +=10;
4208     init->page_height +=263;
4209 
4210     stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_width: '%d'\n",init->page_width);
4211     stp_dprintf(STP_DBG_CANON, v, "Tray L modified init->page_height: '%d'\n",init->page_height);
4212 
4213     printable_width=  (init->page_width+ 1)*5/6;
4214     printable_length= (init->page_height + 1)*5/6;
4215 
4216     stp_dprintf(STP_DBG_CANON, v, "Tray L modified printable_width: '%d'\n",printable_width);
4217     stp_dprintf(STP_DBG_CANON, v, "Tray L modified printable_length: '%d'\n",printable_length);
4218 
4219   }
4220 
4221   /* Tray M - TODO */
4222   /* to add code here */
4223 
4224   if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4225        !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") )
4226     {
4227       stp_dprintf(STP_DBG_CANON, v,"canon_init_setPageMargins2: for borderless set printable length and width to 0\n");
4228       /* set to 0 for borderless */
4229       printable_width = 0;
4230       printable_length = 0;
4231     }
4232 
4233   /* arguments for short form of Esc (p command  */
4234   arg_70_1= (printable_length >> 8) & 0xff;
4235   arg_70_2= (printable_length) & 0xff;
4236   arg_70_3= (printable_width >> 8) & 0xff;
4237   arg_70_4= (printable_width) & 0xff;
4238 
4239 
4240   if (!(init->caps->features & CANON_CAP_px) && !(init->caps->features & CANON_CAP_p))
4241 	return;
4242 
4243   if ((init->caps->features & CANON_CAP_px) ) {
4244     /* workaround for CD writing that uses CANON_CAP_px --- fix with capabilities */
4245     if ( !( input_slot && !(strcmp(input_slot,"CD")) ) || !(strcmp(init->caps->name,"PIXMA iP4500")) || !(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA MP710")) || !(strcmp(init->caps->name,"PIXMA iP3000")) || !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) )
4246       /* need to check if iP9910, MP710, iP3000, Pro9000 use Esc (p */
4247       {
4248 
4249 	/* original borders */
4250 	border_left=init->caps->border_left;
4251 	border_right=init->caps->border_right;
4252 	border_top=init->caps->border_top;
4253 	border_bottom=init->caps->border_bottom;
4254 
4255 	if (print_cd) {
4256 	  border_top=9;
4257 	  border_bottom=15; /* was 9 originally */
4258 	}
4259 
4260 	/* modified borders */
4261 	border_left2=border_left;
4262 	border_top2=border_top;
4263 	border_right2=border_right;
4264 	border_bottom2=border_bottom;
4265 
4266 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA MP710")) && (test_cd==1) ) {
4267 	  border_left2   = border_left + adjust_tray_custom_left;
4268 	  border_right2  = border_right + adjust_tray_custom_right;
4269 	  border_top2    = border_top + adjust_tray_custom_top;
4270 	  border_bottom2 = border_bottom + adjust_tray_custom_bottom;
4271 	}
4272 
4273 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP9910")) && (test_cd==1) ) {
4274 	  border_left2   = border_left + adjust_tray_A_left;
4275 	  border_right2  = border_right + adjust_tray_A_right;
4276 	  border_top2    = border_top + adjust_tray_A_top;
4277 	  border_bottom2 = border_bottom + adjust_tray_A_bottom;
4278 	}
4279 
4280 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP3000")) && (test_cd==1) ) {
4281 	  border_left2   = border_left + adjust_tray_BCD_left;
4282 	  border_right2  = border_right + adjust_tray_BCD_right;
4283 	  border_top2    = border_top + adjust_tray_BCD_top;
4284 	  border_bottom2 = border_bottom + adjust_tray_BCD_bottom;
4285 	}
4286 
4287 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA Pro9000")) && (test_cd==1) ) {
4288 	  border_left2   = border_left + adjust_tray_E_left;
4289 	  border_right2  = border_right + adjust_tray_E_right;
4290 	  border_top2    = border_top + adjust_tray_E_top;
4291 	  border_bottom2 = border_bottom + adjust_tray_E_bottom;
4292 	}
4293 
4294 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4500")) && (test_cd==1) ) {
4295 	  border_left2   = border_left + adjust_tray_F_left;
4296 	  border_right2  = border_right + adjust_tray_F_right;
4297 	  border_top2    = border_top + adjust_tray_F_top;
4298 	  border_bottom2 = border_bottom + adjust_tray_F_bottom;
4299 	}
4300 
4301 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP4700")) && (test_cd==1) ) {
4302 	  border_left2   = border_left + adjust_tray_G_left;
4303 	  border_right2  = border_right + adjust_tray_G_right;
4304 	  border_top2    = border_top + adjust_tray_G_top;
4305 	  border_bottom2 = border_bottom + adjust_tray_G_bottom;
4306 	}
4307 
4308 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA PRO-1")) && (test_cd==1) ) {
4309 	  border_left2   = border_left + adjust_tray_H_left;
4310 	  border_right2  = border_right + adjust_tray_H_right;
4311 	  border_top2    = border_top + adjust_tray_H_top;
4312 	  border_bottom2 = border_bottom + adjust_tray_H_bottom;
4313 	}
4314 
4315 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP7200")) && (test_cd==1) ) {
4316 	  border_left2   = border_left + adjust_tray_J_left;
4317 	  border_right2  = border_right + adjust_tray_J_right;
4318 	  border_top2    = border_top + adjust_tray_J_top;
4319 	  border_bottom2 = border_bottom + adjust_tray_J_bottom;
4320 	}
4321 
4322 	if ( (print_cd) && !(strcmp(init->caps->name,"PIXMA iP8700")) && (test_cd==1) ) {
4323 	  border_left2   = border_left + adjust_tray_L_left;
4324 	  border_right2  = border_right + adjust_tray_L_right;
4325 	  border_top2    = border_top + adjust_tray_L_top;
4326 	  border_bottom2 = border_bottom + adjust_tray_L_bottom;
4327 	}
4328 
4329 	/* this does not seem to need adjustment, so use original borders */
4330 	area_right = border_left * unit / 72;
4331 	area_top = border_top * unit / 72;
4332 
4333 	if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4334 	     !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4335 	  border_left2=-8; /* -8 mini series -6 */
4336 	  border_right2=-8; /* -8 */
4337 	  border_top2=-6; /* -6 standard */
4338 	  border_bottom2=-15; /* -15 standard */
4339 	  area_right = border_left2 * unit / 72;
4340 	  area_top = border_top2 * unit / 72;
4341 	}
4342 
4343 	stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: init->page_height = %d\n",init->page_height);
4344 	stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: printable_length = %d\n",printable_length);
4345 	stp_dprintf(STP_DBG_CANON, v,"setPageMargins2: paper_height = %d\n",(init->page_height + border_top + border_bottom) * unit / 72);
4346 
4347 
4348 	stp_dprintf(STP_DBG_CANON, v, "final init->page_width: '%d'\n",init->page_width);
4349 	stp_dprintf(STP_DBG_CANON, v, "final init->page_height: '%d'\n",init->page_height);
4350 	stp_dprintf(STP_DBG_CANON, v, "final printable_width: '%d'\n",printable_width);
4351 	stp_dprintf(STP_DBG_CANON, v, "final printable_length: '%d'\n",printable_length);
4352 
4353 	stp_zfwrite(ESC28,2,1,v); /* ESC( */
4354 	stp_putc(0x70,v);         /* p    */
4355 	stp_put16_le(46, v);      /* len  */
4356 	/* 0 for borderless, calculated otherwise */
4357 	stp_put16_be(printable_length,v); /* printable_length */
4358 	stp_put16_be(0,v);
4359 	/* 0 for borderless, calculated otherwise */
4360 	stp_put16_be(printable_width,v); /* printable_width */
4361 	stp_put16_be(0,v);
4362 	stp_put32_be(0,v);
4363 	stp_put16_be(unit,v);
4364 
4365 	/* depends on borderless or not: uses modified borders */
4366 	stp_put32_be(area_right,v); /* area_right : Windows seems to use 9.6, gutenprint uses 10 */
4367 	stp_put32_be(area_top,v);  /* area_top : Windows seems to use 8.4, gutenprint uses 15 */
4368 
4369 	/* calculated depending on borderless or not: uses modified borders */
4370 	if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4371 	     !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4372 	  /* borderless */
4373 	  stp_put32_be((init->page_width - border_left2 - border_right2 ) * unit / 72,v); /* area_width */
4374 	  stp_put32_be((init->page_height - border_top2 - border_bottom2 ) * unit / 72,v); /* area_length */
4375 	}
4376 	else {
4377 	  if ( (print_cd) && (test_cd==1) ) { /* bordered for CD */
4378 	    stp_put32_be(init->page_width * unit / 72,v); /* area_width */
4379 	    stp_put32_be(init->page_height * unit / 72,v); /* area_length */
4380 	  }
4381 	  else { /* bordered non CD media */
4382 	    stp_put32_be((init->page_width) * unit / 72,v); /* area_width */
4383 	    stp_put32_be((init->page_height) * unit / 72,v); /* area_length */
4384 	  }
4385 	}
4386 
4387 	/* 0 under all currently known circumstances */
4388 	stp_put32_be(0,v); /* paper_right : Windows also 0 here for all Trays */
4389 	stp_put32_be(0,v); /* paper_top : Windows also 0 here for all Trays */
4390 
4391 	/* standard paper sizes, unchanged for borderless so use
4392 	   original borders */
4393 
4394 	/* discovered that paper_width needs to be same as Windows
4395 	   dimensions for Canon printer firmware to automatically
4396 	   determine which tray to pull paper from automatically.
4397 	*/
4398 
4399 	if ( (init->caps->features & CANON_CAP_BORDERLESS) &&
4400 	     !(print_cd) && stp_get_boolean_parameter(v, "FullBleed") ) {
4401 	  /* borderless */
4402 	  stp_put32_be((init->page_width) * unit / 72,v); /* paper_width */
4403 	  stp_put32_be((init->page_height) * unit / 72,v); /* paper_length */
4404 	}
4405 	else {
4406 	  if ( (print_cd) && (test_cd==1) ) { /* bordered for CD */
4407 	    paper_width = (init->page_width + border_left2 + border_right2) * unit / 72; /* paper_width */
4408 	    paper_length = (init->page_height + border_top2 + border_bottom2) * unit / 72; /* paper_length */
4409 	    fix_papersize(arg_ESCP_1, &paper_width, &paper_length);
4410 	    stp_put32_be(paper_width,v); /* paper_width */
4411 	    stp_put32_be(paper_length,v); /* paper_length */
4412 	  }
4413 	  else { /* bordered non CD media */
4414             /* set by calculation first, then correct if necessary */
4415 	    paper_width = (init->page_width + border_left + border_right) * unit / 72; /* paper_width */
4416 	    paper_length = (init->page_height + border_top + border_bottom) * unit / 72; /* paper_length */
4417             fix_papersize(arg_ESCP_1, &paper_width, &paper_length);
4418 	    stp_put32_be(paper_width,v); /* paper_width */
4419 	    stp_put32_be(paper_length,v); /* paper_length */
4420 	  }
4421 	}
4422 
4423 	return;
4424       }
4425   }
4426   canon_cmd(v,ESC28,0x70, 8,
4427    	      arg_70_1, arg_70_2, 0x00, 0x00,
4428 	      arg_70_3, arg_70_4, 0x00, 0x00);
4429 }
4430 
4431 /* ESC (P -- 0x50 -- unknown -- :
4432    Seems to set media and page information. Different byte lengths
4433    depending on printer model.
4434    Page rotation option in driver [ESC (v] influences ESC (P command
4435    parameters 5 and 6:
4436        none: 1 0
4437      90 deg: 2 0
4438     180 deg: 1 1
4439     270 deg: 2 1
4440 */
4441 static void
canon_init_setESC_P(const stp_vars_t * v,const canon_privdata_t * init)4442 canon_init_setESC_P(const stp_vars_t *v, const canon_privdata_t *init)
4443 {
4444   unsigned char arg_ESCP_1, arg_ESCP_2, arg_ESCP_5, arg_ESCP_6, arg_ESCP_7, arg_ESCP_9;
4445 
4446   stp_dimension_t width, length;
4447   /*  const char *media_size = stp_get_string_parameter(v, "PageSize");
4448       const stp_papersize_t *pt = NULL; */
4449   const char* orientation_type = stp_get_string_parameter(v, "Orientation");
4450   const char* input_slot = stp_get_string_parameter(v, "InputSlot");
4451   const char* input_tray = stp_get_string_parameter(v, "CassetteTray");
4452   /* const canon_cap_t * caps= canon_get_model_capabilities(v); */
4453   int print_cd = (input_slot && (!strcmp(input_slot, "CD")));
4454   int tray_upper = (input_tray && (!strcmp(input_tray, "Upper")));
4455   int tray_lower = (input_tray && (!strcmp(input_tray, "Lower")));
4456   int tray_user_select;
4457   unsigned char user_ESCP_9;
4458 
4459   if(!(init->caps->features & CANON_CAP_P))
4460     return;
4461 
4462   /*  if (media_size)
4463       pt = stp_describe_papersize(v, media_size); */
4464   stp_default_media_size(v, &width, &length);
4465   if (tray_upper || tray_lower)
4466     tray_user_select=1;
4467   else
4468     tray_user_select=0;
4469   if (tray_upper)
4470     user_ESCP_9=0x01;
4471   else if (tray_lower)
4472     user_ESCP_9=0x02;
4473   else
4474     user_ESCP_9=0x00; /* fall-through setting, but this value is not used */
4475 
4476   arg_ESCP_1 = (init->pt) ? canon_size_type(v,init->caps): 0x03; /* media size: set to A4 size as default */
4477   stp_dprintf(STP_DBG_CANON, v,"canon: ESCP (P code read paper size, resulting arg_ESCP_1: '%x'\n",arg_ESCP_1);
4478   arg_ESCP_2 = (init->pt) ? init->pt->media_code_P: 0x00; /* media type: set to plain as default  */
4479   arg_ESCP_5 = 0x01; /* default for portrait orientation */
4480   arg_ESCP_6 = 0x00; /* default for portrait orientation */
4481 
4482   arg_ESCP_7 = 0x01; /* default - use unknown, with some printers set
4483 			to 0x00 for envelope sizes (and other?)
4484 			regardless of media type */
4485 
4486   if( orientation_type && !strcmp(orientation_type,"Portrait")) { /* none */
4487     arg_ESCP_5 = 0x01;
4488     arg_ESCP_6 = 0x00;
4489   }
4490   else if( orientation_type && !strcmp(orientation_type,"Landscape")) { /* 90 deg */
4491     arg_ESCP_5 = 0x02;
4492     arg_ESCP_6 = 0x00;
4493   }
4494   else if( orientation_type && !strcmp(orientation_type,"UpsideDown")) { /* 180 deg */
4495     arg_ESCP_5 = 0x01;
4496     arg_ESCP_6 = 0x01;
4497   }
4498   else if( orientation_type && !strcmp(orientation_type,"Seascape")) { /* 270 deg */
4499     arg_ESCP_5 = 0x02;
4500     arg_ESCP_6 = 0x01;
4501   }
4502 
4503 
4504   /* Code for last argument in 9-byte ESC (P printers with and upper and lower tray included in the cassette input source
4505      The intention appears to be to allow printing of photos and non-photo paper without needing to change trays.
4506      Note, envelopes are printed from the lower tray.
4507 
4508      Upper tray specification from MG7700 user manual:
4509      Min width:  3.5  inches /  89.0 mm  (L size)
4510      Min height: 5    inches / 127.0 mm  (L size)
4511      Max width:  7.87 inches / 200.0 mm  (marked up to 5 inches)
4512      Max height: 7.28 inches / 184.9 mm
4513 
4514      Lower tray specification:
4515      Min width:  3.54 inches /  90.0 mm (takes business envelopes)
4516      Min height: 7.29 inches / 185.0 mm
4517      Max width:  8.5  inches / 215.9 mm
4518      Max height: 14   inches / 355.6 mm
4519 
4520      Conditions:
4521      Init:  Upper tray
4522      Media:
4523             Hagaki, Photo media --> upper tray
4524 	    Envelopes  (argESCP_2 == 0x08) --> lower tray
4525 	    Other --> lower tray
4526      Size:  Length:
4527             < 7.29 inches (524 pt = 184.85 mm; 525 pt = 185.2 mm ) --> upper tray
4528             >=7.29 inches (524 pt = 184.85 mm; 525 pt = 185.2 mm ) --> lower tray
4529 
4530      Printers with this capability:
4531      Code 0xd for cassette (standard cassette code is 0x8)
4532 
4533      MG5400
4534      MG6300
4535      MG6500
4536      MG6700
4537      MG6900 - same as MG7700
4538      MG7500
4539      MG7700
4540      iP7200
4541      MX720
4542      MX920
4543    */
4544 
4545 
4546   if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX720")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4547     /* default: use upper tray of cassette with two trays, condition check later */
4548     arg_ESCP_9 = 0x01;
4549   }
4550   else if ( !(strcmp(init->caps->name,"PIXMA E400")) || !(strcmp(init->caps->name,"PIXMA E460")) ||  !(strcmp(init->caps->name,"PIXMA E470")) || !(strcmp(init->caps->name,"PIXMA E480")) || !(strcmp(init->caps->name,"PIXMA E560")) || !(strcmp(init->caps->name,"PIXMA E3100")) || !(strcmp(init->caps->name,"PIXMA TS5000")) || !(strcmp(init->caps->name,"PIXMA TS6000")) || !(strcmp(init->caps->name,"PIXMA TS8000")) || !(strcmp(init->caps->name,"PIXMA G1000")) || !(strcmp(init->caps->name,"PIXMA G4000")) || !(strcmp(init->caps->name,"PIXMA MG2900")) || !(strcmp(init->caps->name,"PIXMA MG3500")) || !(strcmp(init->caps->name,"PIXMA MG3600")) || !(strcmp(init->caps->name,"PIXMA MG5500")) || !(strcmp(init->caps->name,"PIXMA MG5600")) || !(strcmp(init->caps->name,"PIXMA iP110")) || !(strcmp(init->caps->name,"PIXMA iP2800")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"MAXIFY iB4000")) || !(strcmp(init->caps->name,"MAXIFY iB4100")) || !(strcmp(init->caps->name,"MAXIFY MB2000")) || !(strcmp(init->caps->name,"MAXIFY MB2100")) || !(strcmp(init->caps->name,"MAXIFY MB2300")) || !(strcmp(init->caps->name,"MAXIFY MB2700")) || !(strcmp(init->caps->name,"PIXMA MX470")) || !(strcmp(init->caps->name,"PIXMA MX490")) ) {
4551     arg_ESCP_9 = 0xff;
4552   }
4553 
4554   else {
4555     arg_ESCP_9 = 0x00;
4556   }
4557 
4558   if ( !(strcmp(init->caps->name,"PIXMA E470")) || !(strcmp(init->caps->name,"PIXMA G4000")) || !(strcmp(init->caps->name,"PIXMA TS5000")) || !(strcmp(init->caps->name,"PIXMA TS6000")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ){
4559     /* all envelope sizes it appears, even if media is not Envelope */
4560     /* currently not sure about custom sizes, thus only specify here the known Canon envelope sizes */
4561       switch(arg_ESCP_2)
4562 	{
4563 	case 0x2e: arg_ESCP_7=0x00; break;; /* US Comm #10 */
4564 	case 0x2f: arg_ESCP_7=0x00; break;; /* Euro DL Env */
4565 	case 0x30: arg_ESCP_7=0x00; break;; /* Western Env #4 (you4) */
4566 	case 0x31: arg_ESCP_7=0x00; break;; /* Western Env #6 (you6) */
4567 	case 0x3a: arg_ESCP_7=0x00; break;; /* Japanese Long Env #3 (chou3) */
4568 	case 0x3b: arg_ESCP_7=0x00; break;; /* Japanese Long Env #4 (chou4) */
4569 	  /* new envelopes for some printers added for completeness */
4570 	case 0x92: arg_ESCP_7=0x00; break;; /* C5 */
4571 	case 0x93: arg_ESCP_7=0x00; break;; /* Monarch */
4572 	}
4573   }
4574 
4575   /* workaround for CD media */
4576 
4577   if ( (arg_ESCP_2 == 0x1f) || ( arg_ESCP_2 == 0x20) ) {
4578     if ( arg_ESCP_1 == 0x53 ) {
4579       /* Tray G as default */
4580       arg_ESCP_1 = 0x53;
4581       /* Custom CD tray */
4582       if ( !(strcmp(init->caps->name,"i865")) || !(strcmp(init->caps->name,"PIXMA MP710")) || !(strcmp(init->caps->name,"PIXMA MP740")) || !(strcmp(init->caps->name,"PIXMA MP900")) ) {
4583 	arg_ESCP_1 = 0x35;
4584       }
4585       /* Tray A */
4586       if ( !(strcmp(init->caps->name,"PIXMA iP9910")) ) {
4587 	arg_ESCP_1 = 0x3f;
4588       }
4589       /* Tray B */
4590       if ( !(strcmp(init->caps->name,"PIXMA MP750")) || !(strcmp(init->caps->name,"PIXMA MP760")) || !(strcmp(init->caps->name,"PIXMA MP770")) || !(strcmp(init->caps->name,"PIXMA MP780")) || !(strcmp(init->caps->name,"PIXMA MP790")) || !(strcmp(init->caps->name,"PIXMA iP3000")) || !(strcmp(init->caps->name,"PIXMA iP3100")) || !(strcmp(init->caps->name,"PIXMA iP4000")) || !(strcmp(init->caps->name,"PIXMA iP4100")) || !(strcmp(init->caps->name,"PIXMA iP5000")) || !(strcmp(init->caps->name,"PIXMA iP6000")) || !(strcmp(init->caps->name,"PIXMA iP6100")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8500")) || !(strcmp(init->caps->name,"PIXMA iP8600")) ) {
4591 	arg_ESCP_1 = 0x40;
4592       }
4593       /* Tray C */
4594       if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA iP4200")) || !(strcmp(init->caps->name,"PIXMA iP5200")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7500")) ) {
4595 	arg_ESCP_1 = 0x4a;
4596       }
4597       /* Tray D */
4598       if ( !(strcmp(init->caps->name,"PIXMA MP500")) || !(strcmp(init->caps->name,"PIXMA MP530")) || !(strcmp(init->caps->name,"PIXMA MP800")) || !(strcmp(init->caps->name,"PIXMA MP830")) ) {
4599 	arg_ESCP_1 = 0x4b;
4600       }
4601       /* Tray E */
4602       if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro95002")) ) {
4603 	arg_ESCP_1 = 0x4c;
4604       }
4605       /* Tray F */
4606       if ( !(strcmp(init->caps->name,"PIXMA MP600")) || !(strcmp(init->caps->name,"PIXMA MP610")) || !(strcmp(init->caps->name,"PIXMA MP810")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MX850")) || !(strcmp(init->caps->name,"PIXMA iP4300")) || !(strcmp(init->caps->name,"PIXMA iP4500")) || !(strcmp(init->caps->name,"PIXMA iP5300")) ) {
4607 	arg_ESCP_1 = 0x51;
4608       }
4609       /* Tray G from iP4600 onwards */
4610       if ( !(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4611 	arg_ESCP_1 = 0x56;
4612       }
4613       /* Tray J from iP7200 onwards */
4614       if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300"))  || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4615 	arg_ESCP_1 = 0x5b;
4616 	arg_ESCP_9 = 0x00;
4617       }
4618       /* Tray L from iP8700 onwards */
4619       if ( !(strcmp(init->caps->name,"PIXMA iP8700"))  ) {
4620 	arg_ESCP_1 = 0x62;
4621       }
4622       /* Tray M from TS8000 onwards */
4623       if ( !(strcmp(init->caps->name,"PIXMA TS8000"))  ) {
4624 	arg_ESCP_1 = 0xbc;
4625       }
4626 
4627     }
4628   }
4629       /*  850i:  CD Tray custom: none --- no ESC (P */
4630       /*  865i:  CD Tray custom: 0x35               */
4631       /* MP500:  CD Tray D     : 0x4b               */
4632       /* MP530:  CD Tray D     : 0x4b               */
4633       /* MP600:  CD Tray F     : 0x51               */
4634       /* MP610:  CD Tray F     : 0x51               */
4635       /* MP630:  CD Tray G     : 0x53               */
4636       /* MP640:  CD Tray G     : 0x53               */
4637       /* MP700:  CD tray custom: none --- no ESC (P */
4638       /* MP710:  CD tray custom: 0x35               */
4639       /* MP730:  CD tray custom: none --- no ESC (P */
4640       /* MP740:  CD tray custom: 0x35               */
4641       /* MP750:  CD Tray B     : 0x40               */
4642       /* MP760:  CD Tray B     : 0x40               */
4643       /* MP770:  CD Tray B     : 0x40               */
4644       /* MP780:  CD Tray B     : 0x40               */
4645       /* MP790:  CD Tray B     : 0x40               */
4646       /* MP800:  CD Tray D     : 0x4b               */
4647       /* MP810:  CD Tray F     : 0x51               */
4648       /* MP830:  CD Tray D     : 0x4b               */
4649       /* MP900:  CD Tray custom: 0x35               */
4650       /* MP950:  CD Tray C     : 0x4a               */
4651       /* MP960:  CD Tray F     : 0x51               */
4652       /* MP970:  CD Tray F     : 0x51               */
4653       /* MP980:  CD Tray G     : 0x53               */
4654       /* MP990:  CD Tray G     : 0x53               */
4655       /* MX850:  CD Tray F     : 0x51               */
4656       /* MX920:  CD Tray J     : 0x5b               */
4657       /* iP3000: CD Tray B     : 0x40               */
4658       /* iP3100: CD Tray B     : 0x40               */
4659       /* iP4000: CD Tray B     : 0x40               */
4660       /* iP4100: CD Tray B     : 0x40               */
4661       /* iP4200: CD Tray C     : 0x4a               */
4662       /* iP4300: CD Tray F     : 0x51               */
4663       /* iP4500: CD Tray F     : 0x51               */
4664       /* iP4600: CD Tray G     : 0x53               */
4665       /* iP4700: CD Tray G     : 0x53               */
4666       /* iP4800: CD Tray G     : 0x56               */
4667       /* iP4900: CD Tray G     : 0x56               */
4668       /* iP5000: CD Tray B     : 0x40               */
4669       /* iP5200: CD Tray C     : 0x4a               */
4670       /* iP5300: CD Tray F     : 0x51               */
4671       /* iP6000D:CD Tray B     : 0x40               */
4672       /* iP6100D:CD Tray B     : 0x40               */
4673       /* iP6700D:CD Tray C     : 0x4a               */
4674       /* iP7100: CD Tray B     : 0x40               */
4675       /* iP7200: CD Tray J     : 0x5b               */
4676       /* iP7500: CD Tray C     : 0x4a               */
4677       /* iP8100: CD Tray B     : 0x40               */
4678       /* iP8500 :CD Tray B     : 0x40               */
4679       /* iP8600: CD Tray B     : 0x40               */
4680       /* iP8700: CD Tray L     : 0x62               */
4681       /* iP9910: CD Tray A     : 0x3f               */
4682       /* MG5200: CD Tray G     : 0x56               */
4683       /* MG5300: CD Tray G     : 0x56               */
4684       /* MG5400: CD Tray J     : 0x5b               */
4685       /* MG6100: CD Tray G     : 0x56               */
4686       /* MG6200: CD Tray G     : 0x56               */
4687       /* MG6300: CD Tray J     : 0x5b               */
4688       /* MG6500: CD Tray J     : 0x5b               */
4689       /* MG6700: CD Tray J     : 0x5b               */
4690       /* MG6900: CD Tray J     : 0x5b               */
4691       /* MG7500: CD Tray J     : 0x5b               */
4692       /* MG7700: CD Tray J     : 0x5b               */
4693       /* MG8100: CD Tray G     : 0x56               */
4694       /* MG8200: CD Tray G     : 0x56               */
4695       /* pro9000:CD Tray E     : 0x4c               */
4696       /* pro9000mk2:CD Tray E  : 0x4c               */
4697       /* pro9500:CD Tray E     : 0x4c               */
4698       /* pro9500mk2:CD Tray E  : 0x4c               */
4699       /* PRO-1:  CD Tray H     : 0x57               */
4700       /* TS8000: CD Tray M     : 0xbc               */
4701 
4702   /* workaround for FineArt media having same size as non-FineArt media */
4703 
4704       /* Fine Art paper codes */
4705       /* iP6700D, iP7100, iP7500, iP8100, iP8600, iP9910 */
4706       /* iX7000 */
4707       /* MG6100, M6200, MG8100, MG8200 */
4708       /* MX7600 */
4709       /* MP950, MP960, MP970, MP980, MP990 */
4710       /* if (!strcmp(name,"A4"))       return 0x42; */ /* FineArt A4 35mm border --- iP7100: gap is 18 */
4711       /* if (!strcmp(name,"A3"))       return 0x43; */ /* FineArt A3 35mm border */
4712       /* if (!strcmp(name,"A3plus"))   return 0x44; */ /* FineArt A3plus 35mm border */
4713       /* if (!strcmp(name,"Letter"))   return 0x45; */ /* FineArt Letter 35mm border */
4714 
4715       /* Fine Art paper codes */
4716       /* Pro series (9000, 9000 Mk.2, 9500, 9500 Mk.2, PRO-1) */
4717       /* if (!strcmp(name,"A4"))       return 0x4d; */ /* FineArt A4 35mm border */
4718       /* if (!strcmp(name,"A3"))       return 0x4e; */ /* FineArt A3 35mm border */
4719       /* if (!strcmp(name,"A3plus"))   return 0x50; */ /* FineArt A3plus 35mm border */
4720       /* if (!strcmp(name,"Letter"))   return 0x4f; */ /* FineArt Letter 35mm border */
4721 
4722       /* Fine Art paper codes */
4723       /* MG6300, MG6500, MG6700, MG7100, MG7500 */
4724       /* if (!strcmp(name,"A4"))       return 0x58; */ /* FineArt A4 35mm border */
4725       /* if (!strcmp(name,"Letter"))   return 0x5a; */ /* FineArt Letter 35mm border */
4726 
4727       /* Fine Art paper codes */
4728       /* iP8700, iX6800 */
4729       /* if (!strcmp(name,"A4"))       return 0x58; */ /* FineArt A4 35mm border */
4730       /* if (!strcmp(name,"A3"))       return 0x59; */ /* FineArt A3 35mm border */
4731       /* if (!strcmp(name,"A3plus"))   return 0x5d; */ /* FineArt A3plus 35mm border */
4732       /* if (!strcmp(name,"Letter"))   return 0x5a; */ /* FineArt Letter 35mm border */
4733 
4734 
4735   /* iP7100 is an exception needing yet another papersize code */
4736   if ( (arg_ESCP_2 == 0x28) || ( arg_ESCP_2 == 0x29) || (arg_ESCP_2 ==  0x2c) || (arg_ESCP_2 == 0x31) ) {
4737     /* A4 FineArt */
4738     if ( arg_ESCP_1 == 0x03 ) {
4739       if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4740 	arg_ESCP_1 = 0x42;
4741       }
4742       else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4743 	arg_ESCP_1 = 0x4d;
4744       }
4745       else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4746 	arg_ESCP_1 = 0x58;
4747       }
4748       else {
4749 	/* default back to non-FineArt */
4750 	arg_ESCP_1 = 0x03;
4751       }
4752     }
4753     /* A3 FineArt */
4754     if ( arg_ESCP_1 == 0x05 ) {
4755       if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4756 	arg_ESCP_1 = 0x43;
4757       }
4758       else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4759 	arg_ESCP_1 = 0x4e;
4760       }
4761 #if 0
4762       /* no known papersize code yet, since these printers do not handle A3 */
4763       else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) ) {
4764         arg_ESCP_1 = 0x59;
4765 	}
4766 #endif
4767       else {
4768 	/* default back to non-FineArt */
4769 	arg_ESCP_1 = 0x05;
4770       }
4771     }
4772     /* Letter FineArt */
4773     if ( arg_ESCP_1 == 0x0d ) {
4774       if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4775 	arg_ESCP_1 = 0x45;
4776       }
4777       else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4778 	arg_ESCP_1 = 0x4f;
4779       }
4780       else if ( !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4781 	arg_ESCP_1 = 0x5a;
4782       }
4783       else {
4784 	/* default back to non-FineArt */
4785 	arg_ESCP_1 = 0x0d;
4786       }
4787     }
4788     /* A3plus FineArt */
4789     if ( arg_ESCP_1 == 0x2c ) {
4790       if ( !(strcmp(init->caps->name,"PIXMA MP950")) || !(strcmp(init->caps->name,"PIXMA MP960")) || !(strcmp(init->caps->name,"PIXMA MP970")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) || !(strcmp(init->caps->name,"PIXMA MX7600")) || !(strcmp(init->caps->name,"PIXMA iP6700")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP7500")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA iX7000")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA MG8100")) || !(strcmp(init->caps->name,"PIXMA MG8200")) ) {
4791 	arg_ESCP_1 = 0x44;
4792       }
4793       else if ( !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
4794 	arg_ESCP_1 = 0x50;
4795       }
4796 #if 0
4797       else if ( !(strcmp(init->caps->name,"PIXMA iP8700")) || !(strcmp(init->caps->name,"PIXMA iX6800")) ) {
4798         arg_ESCP_1 = 0x5d;
4799 	}
4800 #endif
4801       else {
4802 	/* default back to non-FineArt */
4803 	arg_ESCP_1 = 0x2c;
4804       }
4805     }
4806   }
4807 
4808   /* workaround for media type based differences in 9-parameter ESC (P commands */
4809   /* These printers use 0x02 (lower tray) usually and for envelopes, 0x01 (upper tray) with various Hagaki/Photo media, and 0x00 with CD media */
4810   if ( !(strcmp(init->caps->name,"PIXMA iP7200")) || !(strcmp(init->caps->name,"PIXMA MG5400")) || !(strcmp(init->caps->name,"PIXMA MG6300")) || !(strcmp(init->caps->name,"PIXMA MG6500")) || !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500")) || !(strcmp(init->caps->name,"PIXMA MG7700")) || !(strcmp(init->caps->name,"PIXMA MX720")) || !(strcmp(init->caps->name,"PIXMA MX920")) ) {
4811     if (tray_user_select && !print_cd)
4812       arg_ESCP_9=user_ESCP_9;
4813     else {
4814       switch(arg_ESCP_2)
4815 	{
4816 	  /* Hagaki media */
4817 	case 0x07: arg_ESCP_9=0x01; break;;
4818 	case 0x14: arg_ESCP_9=0x01; break;; /* not used with any of these models */
4819 	case 0x1b: arg_ESCP_9=0x01; break;;
4820 	case 0x36: arg_ESCP_9=0x01; break;;
4821 	case 0x38: arg_ESCP_9=0x01; break;;
4822 	case 0x46: arg_ESCP_9=0x01; break;;
4823 	case 0x47: arg_ESCP_9=0x01; break;;
4824 	case 0x48: arg_ESCP_9=0x01; break;;
4825 	  /* Photo media here */
4826 	case 0x32: arg_ESCP_9=0x01; break;;
4827 	case 0x33: arg_ESCP_9=0x01; break;;
4828 	case 0x3f: arg_ESCP_9=0x01; break;;
4829 	case 0x2a: arg_ESCP_9=0x01; break;;
4830 	case 0x16: arg_ESCP_9=0x01; break;;
4831 	case 0x44: arg_ESCP_9=0x01; break;; /* MG6700, MG7500 only, instead of 0x16 */
4832 	case 0x1c: arg_ESCP_9=0x01; break;;
4833 	case 0x24: arg_ESCP_9=0x01; break;;
4834 	  /* Envelope media */
4835 	case 0x08: arg_ESCP_9=0x02; break;;
4836 	  /* CD media */
4837 	case 0x1f: arg_ESCP_9=0x00; break;;
4838 	case 0x20: arg_ESCP_9=0x00; break;;
4839 	  /* other media default to lower tray */
4840 	default:   arg_ESCP_9=0x02; break;;
4841 	}
4842 
4843       /* condition for length to use lower tray: 7.29 in equals 524-525 points */
4844       if ( (arg_ESCP_9 == 0x01) && ( length > 524 ) ) {
4845 	arg_ESCP_9=0x02;
4846       }
4847 
4848       /* even if user does not select correct CD media type, set appropriately */
4849       if (print_cd)
4850 	arg_ESCP_9=0x00;
4851     }
4852   }
4853 
4854   /* MG6700, MG7500, TS8000 uses 0xff with CD media tray */
4855   if (   !(strcmp(init->caps->name,"PIXMA MG6700")) || !(strcmp(init->caps->name,"PIXMA MG7500"))  || !(strcmp(init->caps->name,"PIXMA TS8000")) ) {
4856     if (tray_user_select && !print_cd)
4857       arg_ESCP_9=user_ESCP_9;
4858     else {
4859       switch(arg_ESCP_2)
4860 	{
4861 	  /* CD media */
4862 	case 0x1f: arg_ESCP_9=0xff; break;;
4863 	case 0x20: arg_ESCP_9=0xff; break;;
4864 	}
4865 
4866       /* even if user does not select correct CD media type, set appropriately */
4867       if (print_cd)
4868 	arg_ESCP_9=0x00;
4869     }
4870   }
4871 
4872   if ( init->caps->ESC_P_len == 9 ) /* support for new devices from October 2012. */
4873     {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4874 
4875       if ( !(strcmp(init->caps->name,"PIXMA MG7700")) ) {
4876 	/* output with 3 extra 0s at the end */
4877 	canon_cmd( v,ESC28,0x50,12,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00,arg_ESCP_9,0x00,0x00,0x00 );
4878       }
4879       else {
4880 
4881       /* arg_ESCP_1 = 0x03; */ /* A4 size */
4882       /* arg_ESCP_2 = 0x00; */ /* plain media */
4883       /*                             size                media                                  tray */
4884       canon_cmd( v,ESC28,0x50,9,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00,arg_ESCP_9 );
4885 
4886       }
4887     }
4888   else if ( init->caps->ESC_P_len == 8 ) /* support for new devices from 2012. */
4889     {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4890 
4891       /* arg_ESCP_1 = 0x03; */ /* A4 size */
4892       /* arg_ESCP_2 = 0x00; */ /* plain media */
4893       /*                             size                media             */
4894       canon_cmd( v,ESC28,0x50,8,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6,arg_ESCP_7,0x00 );
4895     }
4896   else if ( init->caps->ESC_P_len == 6 ) /* first devices with XML header and ender */
4897     {/* the 4th of the 6 bytes is the media type. 2nd byte is media size. Both read from canon-media array. */
4898 
4899       /* arg_ESCP_1 = 0x03; */ /* A4 size */
4900       /* arg_ESCP_2 = 0x00; */ /* plain media */
4901       /*                             size                media             */
4902       canon_cmd( v,ESC28,0x50,6,0x00,arg_ESCP_1,0x00,arg_ESCP_2,arg_ESCP_5,arg_ESCP_6 );
4903     }
4904   else if ( init->caps->ESC_P_len == 4 )  {/* 4 bytes */
4905     /*                             size            media       */
4906     canon_cmd( v,ESC28,0x50,4,0x00,arg_ESCP_1,0x00,arg_ESCP_2 );
4907   }
4908   else if ( init->caps->ESC_P_len == 2 )  {
4909     /* 2 bytes only */
4910       canon_cmd( v,ESC28,0x50,2,0x00,arg_ESCP_1 );
4911     }
4912   else /* error in definition */
4913     stp_dprintf(STP_DBG_CANON, v,"SEVERE BUG IN print-canon.c::canon_init_setESC_P() "
4914 		 "ESC_P_len=%d!!\n",init->caps->ESC_P_len);
4915 }
4916 
4917 /* ESC (s -- 0x73 -- :
4918    used in some newer printers for duplex pages except last one.
4919    When capability available, used for non-tumble and tumble (unlike Esc (u which is non-tumble only)
4920    Limitation: outputs on every page */
4921 static void
canon_init_setESC_s(const stp_vars_t * v,const canon_privdata_t * init)4922 canon_init_setESC_s(const stp_vars_t *v, const canon_privdata_t *init)
4923 {
4924   if (!(init->caps->features & CANON_CAP_DUPLEX))
4925     return;
4926   if (!(init->caps->features & CANON_CAP_s))
4927     return;
4928 
4929   canon_cmd(v,ESC28,0x73, 1, 0x00);
4930 }
4931 
4932 /* ESC (S -- 0x53 -- unknown -- :
4933    Required by iP90/iP90v and iP100 printers.
4934  */
4935 static void
canon_init_setESC_S(const stp_vars_t * v,const canon_privdata_t * init)4936 canon_init_setESC_S(const stp_vars_t *v, const canon_privdata_t *init)
4937 {
4938   unsigned char arg_ESCS_01,arg_ESCS_04,arg_ESCS_09,arg_ESCS_11;
4939 
4940   if (!(init->caps->features & CANON_CAP_S))
4941     return;
4942 
4943   if (!(init->mode->flags & MODE_FLAG_S))
4944     return;
4945 
4946   /* iP90 defaults: based on non-photo media */
4947   arg_ESCS_01 = 0x01;
4948   arg_ESCS_04 = 0xff;
4949   arg_ESCS_09 = 0x1a;
4950   arg_ESCS_11 = 0x68;
4951 
4952   /* hard-coded for different media, color and  quality settings */
4953   /* iP90 bytes 1,4,9 and 11 vary */
4954   if ( !(strcmp(init->caps->name,"PIXMA iP90")) ) {
4955     if ( !strcmp(init->mode->name,"600x600dpi_high2") || !strcmp(init->mode->name,"600x600dpi_high4") ) {
4956       /* if inkset is color then set special bytes, else leave default.
4957 	 Note: in this case the mode only has CMYK, mono is a different mode.
4958       */
4959       if (init->used_inks == CANON_INK_CMYK) {
4960 	arg_ESCS_01 = 0xc1;
4961 	arg_ESCS_04 = 0xf1;
4962 	arg_ESCS_09 = 0x50;
4963 	arg_ESCS_11 = 0x28;
4964       }
4965     } else if ( !strcmp(init->mode->name,"300x300dpi_draft") ) {
4966       /* set regardless of inkset */
4967       arg_ESCS_09 = 0x02;
4968       arg_ESCS_11 = 0x08;
4969     } else if ( !strcmp(init->mode->name,"600x600dpi_draft2") ) {
4970       /* if inkset is color then set special bytes, else leave default */
4971       if (init->used_inks == CANON_INK_CMYK) {
4972 	arg_ESCS_09 = 0x0a;
4973 	arg_ESCS_11 = 0x28;
4974       }
4975     } else if ( !strcmp(init->mode->name,"600x600dpi_photohigh") || !strcmp(init->mode->name,"600x600dpi_photo") || !strcmp(init->mode->name,"600x600dpi_photodraft") ) {
4976       /* almost all photo media need (same) changes from defaults */
4977       /* exception: "600x600dpi_photohigh2" no ESC (S command */
4978       /* exception: "600x600dpi_tshirt" no ESC (S command */
4979       arg_ESCS_01 = 0xc1;
4980       arg_ESCS_04 = 0xf0;
4981       arg_ESCS_09 = 0x50;
4982       arg_ESCS_11 = 0x28;
4983     }
4984   }
4985   else if ( !(strcmp(init->caps->name,"PIXMA iP100")) ) {
4986     /* iP100 bytes 9 and 11 vary */
4987     if ( !strcmp(init->mode->name,"300x300dpi_draft") ) {
4988       /* set regardless of inkset */
4989       arg_ESCS_09 = 0x02;
4990       arg_ESCS_11 = 0x08;
4991     } else if  ( !strcmp(init->mode->name,"600x600dpi_photohigh2") || !strcmp(init->mode->name,"600x600dpi_photohigh") || !strcmp(init->mode->name,"600x600dpi_photo2") || !strcmp(init->mode->name,"600x600dpi_photo") || !strcmp(init->mode->name,"600x600dpi_tshirt") ) {
4992       /* all photo media need (same) changes from defaults */
4993       arg_ESCS_09 = 0x0a;
4994       arg_ESCS_11 = 0x28;
4995     }
4996   }
4997 
4998       canon_cmd(v,ESC28,0x53,54,arg_ESCS_01,0x02,0xff,arg_ESCS_04,0x41,0x02,0x00,0x01,arg_ESCS_09,0x00,arg_ESCS_11,0x00,0x01,0x01,0x03,0x02,0x01,0x01,0x01,0x03,0x02,0x00,0x07,0x06,0x02,0x01,0x02,0x04,0x04,0x04,0x05,0x06,0x08,0x08,0x08,0x0a,0x0a,0x09,0x00,0x03,0x02,0x01,0x01,0x01,0x01,0x01,0x06,0x02,0x02,0x02,0x03,0x04,0x05,0x06);
4999 
5000 }
5001 
5002 /* ESC (T -- 0x54 -- setCartridge -- :
5003  */
5004 static void
canon_init_setCartridge(const stp_vars_t * v,const canon_privdata_t * init)5005 canon_init_setCartridge(const stp_vars_t *v, const canon_privdata_t *init)
5006 {
5007   const char *ink_set;
5008 
5009   if (!(init->caps->features & CANON_CAP_T))
5010     return;
5011 
5012   ink_set = stp_get_string_parameter(v, "InkSet");
5013 
5014   if (ink_set && !(strcmp(ink_set,"Both"))) {
5015     if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5016       canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x00); /* default for iP90, iP100, iP110 */
5017     }
5018     else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5019       canon_cmd(v,ESC28,0x54,3,0x03,0x06,0x06); /* default for iP6210D, iP6220D, iP6310D */
5020       /* both:  0x3 0x6 0x6 */
5021       /* color: 0x3 0x1 0x1 */
5022     }
5023     else {
5024       canon_cmd(v,ESC28,0x54,3,0x03,0x04,0x04); /* default: both cartridges */
5025     }
5026   }
5027   else if (ink_set && !(strcmp(ink_set,"Black"))) {
5028     if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5029       canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x00); /* default for iP90, iP100, iP110 */
5030     }
5031     else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5032 	canon_cmd(v,ESC28,0x54,3,0x03,0x06,0x06); /* default for iP6210D, iP6220D, iP6310D */
5033 	/* both:  0x3 0x6 0x6 */
5034 	/* color: 0x3 0x1 0x1 */
5035 	/* workaround since does not have black option */
5036     }
5037     else {
5038       canon_cmd(v,ESC28,0x54,3,0x03,0x02,0x02); /* default: black cartridge */
5039     }
5040   }
5041   else if (ink_set && !(strcmp(ink_set,"Color"))) {
5042     if ( !(strcmp(init->caps->name,"PIXMA iP90")) || !(strcmp(init->caps->name,"PIXMA iP100")) || !(strcmp(init->caps->name,"PIXMA iP110")) ) {
5043       canon_cmd(v,ESC28,0x54,3,0x02,0x00,0x01); /* composite for iP90, iP100, iP110 */
5044       /* black save     : 2 1 0 for selected plain (600dpi std) modes, rest remain 2 0 0 */
5045       /* composite black: 2 0 1 for selected plain (600dpi std & draft) modes, rest remain 2 0 0 */
5046       /* both above set : AND of bytes above */
5047     }
5048     else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5049       canon_cmd(v,ESC28,0x54,3,0x03,0x01,0x01); /* default for iP6210D, iP6220D, iP6310D */
5050       /* both:  0x3 0x6 0x6 */
5051       /* color: 0x3 0x1 0x1 */
5052     }
5053     else {
5054       canon_cmd(v,ESC28,0x54,3,0x03,0x01,0x01); /* default: color cartridges */
5055     }
5056   }
5057   else {
5058     canon_cmd(v,ESC28,0x54,3,0x03,0x04,0x04); /* default: both cartridges */
5059   }
5060 }
5061 
5062 /* ESC (q -- 0x71 -- setPageID -- :
5063  */
5064 static void
canon_init_setPageID(const stp_vars_t * v,const canon_privdata_t * init)5065 canon_init_setPageID(const stp_vars_t *v, const canon_privdata_t *init)
5066 {
5067   if (!(init->caps->features & CANON_CAP_q))
5068     return;
5069 
5070   canon_cmd(v,ESC28,0x71, 1, 0x01);
5071 }
5072 
5073 /* ESC (r -- 0x72 --  -- :
5074  */
5075 static void
canon_init_setX72(const stp_vars_t * v,const canon_privdata_t * init)5076 canon_init_setX72(const stp_vars_t *v, const canon_privdata_t *init)
5077 {
5078   if ( !( (init->caps->features & CANON_CAP_r)
5079          || (init->caps->features & CANON_CAP_rr) ) )
5080     return;
5081 
5082   if ( (init->caps->features & CANON_CAP_r)
5083        || (init->caps->features & CANON_CAP_rr) )
5084     if  (init->caps->ESC_r_arg != 0) /* only output arg if non-zero */
5085       canon_cmd(v,ESC28,0x72, 1, init->caps->ESC_r_arg); /* whatever for - 8200/S200 need it */
5086   if (init->caps->features & CANON_CAP_rr) {
5087     if ( !(strcmp(init->caps->name,"S200")) ) {
5088       canon_cmd(v,ESC28,0x72, 3, 0x63, 1, 0); /* whatever for - S200 needs it */
5089       /* probably to set the print direction of the head */
5090     }
5091     else if ( !(strcmp(init->caps->name,"S820")) || !(strcmp(init->caps->name,"S900")) || !(strcmp(init->caps->name,"S9000")) || !(strcmp(init->caps->name,"i950")) || !(strcmp(init->caps->name,"i960")) || !(strcmp(init->caps->name,"i9100")) || !(strcmp(init->caps->name,"i9900")) || !(strcmp(init->caps->name,"PIXMA iP7100")) || !(strcmp(init->caps->name,"PIXMA iP8100")) || !(strcmp(init->caps->name,"PIXMA iP8500")) || !(strcmp(init->caps->name,"PIXMA iP8600")) || !(strcmp(init->caps->name,"PIXMA iP9910")) || !(strcmp(init->caps->name,"PIXMA MP900")) || !(strcmp(init->caps->name,"PIXMA Pro9000")) || !(strcmp(init->caps->name,"PIXMA Pro9002")) || !(strcmp(init->caps->name,"PIXMA Pro9500")) || !(strcmp(init->caps->name,"PIXMA Pro9502")) ) {
5092       canon_cmd(v,ESC28,0x72, 2, 0x62, 0); /* 2 bytes */
5093     }
5094     /* CD mode only */
5095     else if ( (init->mode->flags & MODE_FLAG_CD) && (!(strcmp(init->caps->name,"PIXMA iP4600")) || !(strcmp(init->caps->name,"PIXMA iP4700")) || !(strcmp(init->caps->name,"PIXMA MP980")) || !(strcmp(init->caps->name,"PIXMA MP990")) ) ) {
5096       canon_cmd(v,ESC28,0x72, 1, 0x65);
5097     }
5098     /* CD mode only */
5099     else if ( (init->mode->flags & MODE_FLAG_CD) && ( !(strcmp(init->caps->name,"PIXMA iP4800")) || !(strcmp(init->caps->name,"PIXMA MG6100")) || !(strcmp(init->caps->name,"PIXMA MG8100")) ) ) {
5100       canon_cmd(v,ESC28,0x72, 1, 0x68);
5101     }
5102     /* CD mode only -- no ESC (r at all otherwise */
5103     else if ( (init->mode->flags & MODE_FLAG_CD) && ( !(strcmp(init->caps->name,"PIXMA iP4900")) || !(strcmp(init->caps->name,"PIXMA MG5200")) || !(strcmp(init->caps->name,"PIXMA MG5300")) || !(strcmp(init->caps->name,"PIXMA MG6200")) || !(strcmp(init->caps->name,"PIXMA MG8200")) || !(strcmp(init->caps->name,"PIXMA TS8000")) ) ) {
5104       canon_cmd(v,ESC28,0x72, 1, 0x68); /* same as above case? */
5105     }
5106     /* other cases here */
5107   }
5108 }
5109 
5110 /* ESC (r -- 0x72 -- ??? set direction ??? -- :
5111    only works if quality = 01  (S200) */
5112 static void
canon_set_X72(const stp_vars_t * v,int x72arg)5113 canon_set_X72(const stp_vars_t *v, int x72arg)
5114 {
5115   canon_cmd(v,ESC28,0x72, 3, 0x63, x72arg, 0);
5116 }
5117 
5118 /* ESC (t -- 0x74 -- cmdSetImage --:
5119  */
5120 static void
canon_init_setImage(const stp_vars_t * v,const canon_privdata_t * init)5121 canon_init_setImage(const stp_vars_t *v, const canon_privdata_t *init)
5122 {
5123   unsigned char
5124     arg_74_1 = 0x01, /* 1 bit per pixel */
5125     arg_74_2 = 0x00, /*  */
5126     arg_74_3 = 0x01; /* 01 <= 360 dpi    09 >= 720 dpi */
5127 
5128   if (!(init->caps->features & CANON_CAP_t))
5129     return;
5130 
5131   if(init->mode->flags & MODE_FLAG_EXTENDED_T)  /*code requires extended mode settings*/
5132   {
5133     int i;
5134     int length = init->mode->num_inks*3 + 3;
5135     unsigned char* buf = stp_zalloc(length);
5136     buf[0]=0x80;
5137     if(init->mode->flags & MODE_FLAG_PRO){
5138         buf[1]=0x90; /* was 0x10, but this should probably be 0x90 */
5139     	buf[2]=0x4;
5140     }else if(init->mode->flags & MODE_FLAG_IP8500){
5141     	buf[1]=0x00;
5142     	buf[2]=0x01;
5143     }else if(init->mode->flags & MODE_FLAG_MP130){
5144     	buf[1]=0x04;
5145     	buf[2]=0x01;
5146     }else if(init->mode->flags & MODE_FLAG_MP360){
5147     	buf[1]=0x84;
5148     	buf[2]=0x01;
5149     }else{
5150     	buf[1]=0x80;
5151     	buf[2]=0x01;
5152     }
5153     for(i=0;i<init->mode->num_inks;i++){
5154         if(init->mode->inks[i].channel != 0){ /* 0 means ink is used in gutenprint for sub-channel setup but not intended for printer */
5155           if(init->mode->inks[i].ink->flags & INK_FLAG_5pixel_in_1byte)
5156             buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5157            /*else if(init->mode->inks[i].ink->flags & INK_FLAG_lowresmode)
5158              {
5159                buf[3+i*3+1]=0x01;
5160                buf[3+i*3+0]=init->mode->inks[i].ink->bits;
5161              }*/
5162 	  else if(init->mode->inks[i].ink->flags & INK_FLAG_3pixel5level_in_1byte)
5163             buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5164 	  else if(init->mode->inks[i].ink->flags & INK_FLAG_3pixel6level_in_1byte)
5165             buf[3+i*3+0]=(1<<5)|init->mode->inks[i].ink->bits; /*info*/
5166           else
5167             buf[3+i*3+0]=init->mode->inks[i].ink->bits;
5168 
5169           /* workaround for now on the 4-4 inkset and others */
5170           /*if (init->mode->inks[i].ink->bits == 4)
5171             buf[3+i*3+2] = 0x04;*/
5172           /*else if (init->mode->inks[i].ink->bits == 2)
5173             buf[3+i*3+2] = 0x04;*/
5174           /*else if (init->mode->inks[i].ink->bits == 1)
5175             buf[3+i*3+2] = 0x02;*/
5176 	  /*else*/ /* normal operation */
5177 	    buf[3+i*3+2]= init->mode->inks[i].ink->numsizes+1;/*level*/
5178           /*else
5179             buf[3+i*3+2] = 0x00;*/
5180           /* this should show that there is an error */
5181        }
5182     }
5183     stp_zfwrite(ESC28,2,1,v);
5184     stp_putc(0x74,v);
5185     stp_put16_le(length,v);
5186     stp_zfwrite((char*)buf,length,1,v);
5187     stp_free(buf);
5188     return;
5189   }
5190 
5191   /* other models mostly hardcoded stuff not really understood ;( */
5192   if (!strcmp(init->caps->name,"S200")) /* 1 bit per pixel (arg 4,7,10,13); */
5193                                /* 2 level per pixel (arg 6,9,12,15) for each color */
5194                                /* though we print only 1bit/pixel - but this is how */
5195                                /* the windows driver works */
5196   {
5197     canon_cmd(v,ESC28,0x74, 30, 0x80, 4, 1, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2,\
5198               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
5199     return;
5200   }
5201 
5202   if (init->mode->xdpi==1440) arg_74_2= 0x04;
5203   if (init->mode->ydpi>=720)  arg_74_3= 0x09;
5204 
5205   if (init->mode->inks[0].ink->bits>1) {
5206     arg_74_1= 0x02;
5207     arg_74_2= 0x80;
5208     arg_74_3= 0x09; /* default for most media */
5209     /* FIXME: (Gernot) below must be corrected I think, since CMY is
5210        not a function of the cartridge but of the driver selection of
5211        which logical inks get sent to the printer. So here the
5212        printers that use this should be enumerated, rather than a
5213        generic condition based on CANON_INK_CMY */
5214     if (init->used_inks == CANON_INK_CMY) arg_74_3= 0x02; /* for BC-06 cartridge!!! */
5215     /* example of better way: for BJC-3000 series */
5216     if  ( !strcmp(init->caps->name,"3000") || !strcmp(init->caps->name,"4300")) {
5217       /* but if photo cartridge selection, set differently again */
5218       if (init->mode->flags & MODE_FLAG_PHOTO)
5219 	arg_74_3= 0x0a;
5220       /* T-Shirt (3), Backprint Film (3) or Transparencies (2) */
5221       else if ((init->pt->media_code_c==2) || (init->pt->media_code_c==3))
5222 	arg_74_3= 0x01;
5223       else
5224 	/* other media */
5225 	arg_74_3= 0x09; /* return to default after broken code above */
5226     }
5227     if  ( (!strcmp(init->caps->name,"2000")) || (!strcmp(init->caps->name,"2100")) ) {
5228       /* but if photo cartridge selection, set differently again */
5229       if (init->mode->flags & MODE_FLAG_PHOTO)
5230 	arg_74_3= 0x0a;
5231       else
5232 	/* other media */
5233 	arg_74_3= 0x09; /* return to default after broken code above */
5234     }
5235 
5236   }
5237 
5238   /* workaround for the bjc8200 in 6color mode - not really understood */
5239   if (!strcmp(init->caps->name,"8200")) {
5240     if (init->used_inks == CANON_INK_CcMmYK) {
5241       arg_74_1= 0xff;
5242       arg_74_2= 0x90;
5243       arg_74_3= 0x04;
5244       if (init->mode->ydpi>600)  arg_74_3= 0x09;
5245     } else {
5246       arg_74_1= 0x01;
5247       arg_74_2= 0x00;
5248       arg_74_3= 0x01;
5249       if (init->mode->ydpi>600)  arg_74_3= 0x09;
5250     }
5251   }
5252 
5253   canon_cmd(v,ESC28,0x74, 3, arg_74_1, arg_74_2, arg_74_3);
5254 }
5255 
5256 /* ESC (I (J (L
5257  */
5258 static void
canon_init_setMultiRaster(const stp_vars_t * v,const canon_privdata_t * init)5259 canon_init_setMultiRaster(const stp_vars_t *v, const canon_privdata_t *init){
5260 
5261   int i; /* introduced for channel counting */
5262   char* raster_channel_order; /* introduced for channel counting */
5263 
5264   if(!(init->caps->features & CANON_CAP_I))
5265 	return;
5266 
5267   canon_cmd(v,ESC28,0x49, 1, 0x1);  /* enable MultiLine Raster? */
5268   /* canon_cmd(v,ESC28,0x4a, 1, init->caps->raster_lines_per_block); */
5269   canon_cmd(v,ESC28,0x4a, 1, init->mode->raster_lines_per_block);    /* set number of lines per raster block */
5270 
5271   /* set the color sequence */
5272   stp_zfwrite("\033(L", 3, 1, v);
5273   stp_put16_le(init->num_channels, v);
5274   /* add an exception here to add 0x60 of cmy channels for those printers/modes that require it */
5275   /* Note: 2017-06-28 this section needs revision, many printers not entered here, thus modes either not supported or incorrectly output */
5276   raster_channel_order=init->channel_order;
5277   if (  !(strcmp(init->caps->name,"PIXMA E3100")) || !(strcmp(init->caps->name,"PIXMA MP140")) || !(strcmp(init->caps->name,"PIXMA MP150")) || !(strcmp(init->caps->name,"PIXMA MP160")) || !(strcmp(init->caps->name,"PIXMA MP170")) || !(strcmp(init->caps->name,"PIXMA MP180")) || !(strcmp(init->caps->name,"PIXMA MP190")) || !(strcmp(init->caps->name,"PIXMA MP210")) || !(strcmp(init->caps->name,"PIXMA MP220")) || !(strcmp(init->caps->name,"PIXMA MP240")) || !(strcmp(init->caps->name,"PIXMA MP250")) || !(strcmp(init->caps->name,"PIXMA MP270")) || !(strcmp(init->caps->name,"PIXMA MP280")) || !(strcmp(init->caps->name,"PIXMA MP450")) || !(strcmp(init->caps->name,"PIXMA MP460")) || !(strcmp(init->caps->name,"PIXMA MP470")) || !(strcmp(init->caps->name,"PIXMA MP480")) || !(strcmp(init->caps->name,"PIXMA MP490")) || !(strcmp(init->caps->name,"PIXMA MP495")) || !(strcmp(init->caps->name,"PIXMA MX300")) || !(strcmp(init->caps->name,"PIXMA MX310")) || !(strcmp(init->caps->name,"PIXMA MX330")) || !(strcmp(init->caps->name,"PIXMA MX340")) || !(strcmp(init->caps->name,"PIXMA MX350")) || !(strcmp(init->caps->name,"PIXMA MX360"))  || !(strcmp(init->caps->name,"PIXMA MX370")) || !(strcmp(init->caps->name,"PIXMA MX410")) || !(strcmp(init->caps->name,"PIXMA MX510")) || !(strcmp(init->caps->name,"PIXMA MX520")) || !(strcmp(init->caps->name,"PIXMA iP2700")) || !(strcmp(init->caps->name,"PIXMA MG2100")) || !(strcmp(init->caps->name,"PIXMA MG2400")) || !(strcmp(init->caps->name,"PIXMA MG2500")) || !(strcmp(init->caps->name,"PIXMA MG3500")) || !(strcmp(init->caps->name,"PIXMA MG3600")) || !(strcmp(init->caps->name,"PIXMA G1000")) || !(strcmp(init->caps->name,"PIXMA G4000")) )
5278     {
5279       /* if cmy there, add 0x60 to each --- all modes using cmy require it */
5280       for(i=0;i<init->num_channels;i++){
5281 	switch(init->channel_order[i]){
5282 	case 'c':raster_channel_order[i]+=0x60; break;;
5283 	case 'm':raster_channel_order[i]+=0x60; break;;
5284 	case 'y':raster_channel_order[i]+=0x60; break;;
5285 	}
5286       }
5287       /* Gernot: debug */
5288       /* if CMY there, add 0x80 to each to change to cmy+0x60 */
5289       /*     for(i=0;i<init->num_channels;i++){
5290 	switch(init->channel_order[i]){
5291 	case 'C':raster_channel_order[i]+=0x80; break;;
5292 	case 'M':raster_channel_order[i]+=0x80; break;;
5293 	case 'Y':raster_channel_order[i]+=0x80; break;;
5294 	}
5295 	}*/
5296       stp_zfwrite((const char *)raster_channel_order,init->num_channels, 1, v);
5297     }
5298   /* note these names are from canon-printers.h, only separate driver strings are required */
5299   else if ( !(strcmp(init->caps->name,"PIXMA iP6210")) ) {
5300     /* if cmy there, add 0x60 to each --- only some modes using cmy require it */
5301     /* case one: all modes with only cmy */
5302     if (init->num_channels==3) {
5303       for(i=0;i<init->num_channels;i++){
5304 	switch(init->channel_order[i]){
5305 	case 'c':raster_channel_order[i]+=0x60; break;;
5306 	case 'm':raster_channel_order[i]+=0x60; break;;
5307 	case 'y':raster_channel_order[i]+=0x60; break;;
5308 	}
5309       }
5310     }
5311     /* case two: CMYcmy modes, but not CMYkcm modes */
5312     else if ( (init->num_channels==6) && (init->used_inks==CANON_INK_CMY) ) {
5313       for(i=0;i<init->num_channels;i++){
5314 	switch(init->channel_order[i]){
5315 	case 'c':raster_channel_order[i]+=0x60; break;;
5316 	case 'm':raster_channel_order[i]+=0x60; break;;
5317 	case 'y':raster_channel_order[i]+=0x60; break;;
5318 	}
5319       }
5320     }
5321     /* case three: CMYkm modes with 0x80 to subtract from all inks with 2 or 8 bits */
5322     else if ( (init->num_channels==6) && (init->used_inks==CANON_INK_CcMmYK) && ((init->mode->inks[0].ink->bits==2) || (init->mode->inks[0].ink->bits==8)) ) {
5323       for(i=0;i<init->num_channels;i++){
5324 	switch(init->channel_order[i]){
5325 	case 'C':raster_channel_order[i]+=0x80; break;;
5326 	case 'M':raster_channel_order[i]+=0x80; break;;
5327 	case 'Y':raster_channel_order[i]+=0x80; break;;
5328 	case 'c':raster_channel_order[i]+=0x80; break;;
5329 	case 'm':raster_channel_order[i]+=0x80; break;;
5330 	case 'k':raster_channel_order[i]+=0x80; break;;
5331 	}
5332       }
5333     }
5334     stp_zfwrite((const char *)raster_channel_order,init->num_channels, 1, v);
5335   }
5336   else
5337     {
5338       stp_zfwrite((const char *)init->channel_order,init->num_channels, 1, v);
5339     }
5340 }
5341 
5342 /* ESC (u -- 0x75 -- even pages duplex for long side only -- */
5343 static void
canon_init_setESC_u(const stp_vars_t * v,const canon_privdata_t * init)5344 canon_init_setESC_u(const stp_vars_t *v, const canon_privdata_t *init)
5345 {
5346   if (!(init->caps->features & CANON_CAP_DUPLEX))
5347     return;
5348 
5349   canon_cmd( v,ESC28,0x75, 1, 0x01 );
5350 }
5351 
5352 /* ESC (v -- 0x76 -- */
5353 /* page rotation in Windows driver settings: */
5354 /*      none: 0x0 */
5355 /*    90 deg: 0x1 */
5356 /*   180 deg: 0x2 */
5357 /*   270 deg: 0x3 */
5358 /* also influences ESC (P command parameters 5 and 6 */
5359 /*      none: 1 0 */
5360 /*    90 deg: 2 0 */
5361 /*   180 deg: 1 1 */
5362 /*   270 deg: 2 1 */
5363 static void
canon_init_setESC_v(const stp_vars_t * v,const canon_privdata_t * init)5364 canon_init_setESC_v(const stp_vars_t *v, const canon_privdata_t *init)
5365 {
5366   const char  *orientation_type =stp_get_string_parameter(v, "Orientation");
5367   unsigned char arg_ESCv_1 = 0x00;
5368 
5369   if (!(init->caps->features & CANON_CAP_v))
5370     return;
5371 
5372   if( orientation_type && !strcmp(orientation_type,"Portrait")) /* none */
5373     arg_ESCv_1 = 0x00;
5374   else if( orientation_type && !strcmp(orientation_type,"Landscape")) /* 90 deg */
5375     arg_ESCv_1 = 0x01;
5376   else if( orientation_type && !strcmp(orientation_type,"UpsideDown")) /* 180 deg */
5377     arg_ESCv_1 = 0x02;
5378   else if( orientation_type && !strcmp(orientation_type,"Seascape")) /* 270 deg */
5379     arg_ESCv_1 = 0x03;
5380 
5381   canon_cmd( v,ESC28,0x76, 1, arg_ESCv_1 );
5382 }
5383 
5384 /* ESC (w -- 0x77 -- :
5385    Unknown.
5386   new September 2015, currently only 1 byte.
5387 */
5388 static void
canon_init_setESC_w(const stp_vars_t * v,const canon_privdata_t * init)5389 canon_init_setESC_w(const stp_vars_t *v, const canon_privdata_t *init)
5390 {
5391   unsigned char arg_ESCw_1;
5392   if (!(init->caps->features & CANON_CAP_w))
5393     return;
5394 
5395   arg_ESCw_1 = (init->pt) ? init->pt->media_code_w: 0x00;
5396   canon_cmd( v,ESC28,0x77, 1, arg_ESCw_1 );
5397 }
5398 
5399 static void
canon_init_printer(const stp_vars_t * v,canon_privdata_t * init)5400 canon_init_printer(const stp_vars_t *v, canon_privdata_t *init)
5401 {
5402   unsigned int mytop;
5403   int          page_number = stp_get_int_parameter(v, "PageNumber");
5404   const char  *duplex_mode = stp_get_string_parameter(v, "Duplex");
5405   /* init printer */
5406   if (init->is_first_page) {
5407     canon_init_resetPrinter(v,init);     /* ESC [K */
5408     canon_init_setESC_M(v,init);         /* ESC (M */
5409     canon_init_setDuplex(v,init);        /* ESC ($ */
5410   }
5411   canon_init_setPageMode(v,init);        /* ESC (a */
5412   canon_init_setDataCompression(v,init); /* ESC (b */
5413   canon_init_setPageID(v,init);          /* ESC (q */
5414   canon_init_setPrintMode(v,init);       /* ESC (m */
5415   canon_init_setResolution(v,init);      /* ESC (d */
5416   canon_init_setImage(v,init);           /* ESC (t */
5417   canon_init_setColor(v,init);           /* ESC (c */
5418   canon_init_setPageMargins(v,init);     /* ESC (g */
5419   canon_init_setPageMargins2(v,init);    /* ESC (p */
5420   canon_init_setESC_P(v,init);           /* ESC (P */
5421   canon_init_setCartridge(v,init);       /* ESC (T */
5422   canon_init_setESC_S(v,init);           /* ESC (S */
5423   canon_init_setTray(v,init);            /* ESC (l */
5424   canon_init_setX72(v,init);             /* ESC (r */
5425   canon_init_setESC_v(v,init);           /* ESC (v */
5426     if (init->is_first_page)
5427       canon_init_setESC_w(v,init);       /* ESC (w */
5428   if((page_number & 1) && duplex_mode && !strcmp(duplex_mode,"DuplexNoTumble"))
5429     canon_init_setESC_u(v,init);         /* ESC (u 0x1 */
5430   if(duplex_mode)
5431     canon_init_setESC_s(v,init);         /* ESC (s 0x0 */
5432   canon_init_setMultiRaster(v,init);     /* ESC (I (J (L */
5433 
5434   /* some linefeeds */
5435 
5436   mytop= (init->top*init->mode->ydpi)/72;
5437 
5438   if(init->caps->features & CANON_CAP_I)
5439     /* mytop /= init->caps->raster_lines_per_block; */
5440     mytop /= init->mode->raster_lines_per_block;
5441 
5442   if(mytop)
5443     canon_cmd(v,ESC28,0x65, 2, (mytop >> 8 ),(mytop & 255));
5444 }
5445 
5446 static void
canon_deinit_printer(const stp_vars_t * v,const canon_privdata_t * init)5447 canon_deinit_printer(const stp_vars_t *v, const canon_privdata_t *init)
5448 {
5449   /* eject page */
5450   stp_putc(0x0c,v);
5451 
5452   /* say goodbye */
5453   canon_cmd(v,ESC28,0x62,1,0);
5454   if (init->caps->features & CANON_CAP_a)
5455     canon_cmd(v,ESC28,0x61, 1, 0);
5456 }
5457 
5458 static int
canon_start_job(const stp_vars_t * v,stp_image_t * image)5459 canon_start_job(const stp_vars_t *v, stp_image_t *image)
5460 {
5461   const canon_cap_t * caps = canon_get_model_capabilities(v);
5462   /* output XML for iP2700 and other devices */
5463   if (caps->features & CANON_CAP_XML) {
5464     int length=strlen(prexml_iP2700); /* 680 */
5465     stp_zfwrite((const char*)prexml_iP2700,length,1,v);
5466   }
5467   return 1;
5468 }
5469 
5470 static int
canon_end_job(const stp_vars_t * v,stp_image_t * image)5471 canon_end_job(const stp_vars_t *v, stp_image_t *image)
5472 {
5473   const canon_cap_t * caps = canon_get_model_capabilities(v);
5474   canon_cmd(v,ESC40,0,0);
5475   /* output XML for iP2700 and other devices */
5476   if (caps->features & CANON_CAP_XML) {
5477     int length=strlen(postxml_iP2700); /* 263 */
5478     stp_zfwrite((const char*)postxml_iP2700,length,1,v);
5479   }
5480   return 1;
5481 }
5482 
5483 /*
5484  * 'advance_buffer()' - Move (num) lines of length (len) down one line
5485  *                      and sets first line to 0s
5486  *                      accepts NULL pointers as buf
5487  *                  !!! buf must contain more than (num) lines !!!
5488  *                      also sets first line to 0s if num<1
5489  */
5490 static void
canon_advance_buffer(unsigned char * buf,int len,int num)5491 canon_advance_buffer(unsigned char *buf, int len, int num)
5492 {
5493   if (!buf || !len) return;
5494   if (num>0) memmove(buf+len,buf,len*num);
5495   memset(buf,0,len);
5496 }
5497 
5498 static void
canon_printfunc(stp_vars_t * v)5499 canon_printfunc(stp_vars_t *v)
5500 {
5501   int i;
5502   canon_privdata_t *pd = (canon_privdata_t *) stp_get_component_data(v, "Driver");
5503   canon_write_line(v);
5504   for (i = 0; i < pd->num_channels ; i++)
5505     canon_advance_buffer(pd->channels[i].buf, pd->length, pd->channels[i].delay);
5506 
5507 }
5508 
5509 static double
get_double_param(stp_vars_t * v,const char * param)5510 get_double_param(stp_vars_t *v, const char *param)
5511 {
5512   if (param && stp_check_float_parameter(v, param, STP_PARAMETER_ACTIVE))
5513     return stp_get_float_parameter(v, param);
5514   else
5515     return 1.0;
5516 }
5517 
5518 
5519 
5520 static void
set_mask(unsigned char * cd_mask,int x_center,int scaled_x_where,int limit,int expansion,int invert)5521 set_mask(unsigned char *cd_mask, int x_center, int scaled_x_where,
5522          int limit, int expansion, int invert)
5523 {
5524   int clear_val = invert ? 255 : 0;
5525   int set_val = invert ? 0 : 255;
5526   int bytesize = 8 / expansion;
5527   int byteextra = bytesize - 1;
5528   int first_x_on = x_center - scaled_x_where;
5529   int first_x_off = x_center + scaled_x_where;
5530   if (first_x_on < 0)
5531     first_x_on = 0;
5532   if (first_x_on > limit)
5533     first_x_on = limit;
5534   if (first_x_off < 0)
5535     first_x_off = 0;
5536   if (first_x_off > limit)
5537     first_x_off = limit;
5538   first_x_on += byteextra;
5539   if (first_x_off > (first_x_on - byteextra))
5540     {
5541       int first_x_on_byte = first_x_on / bytesize;
5542       int first_x_on_mod = expansion * (byteextra - (first_x_on % bytesize));
5543       int first_x_on_extra = ((1 << first_x_on_mod) - 1) ^ clear_val;
5544       int first_x_off_byte = first_x_off / bytesize;
5545       int first_x_off_mod = expansion * (byteextra - (first_x_off % bytesize));
5546       int first_x_off_extra = ((1 << 8) - (1 << first_x_off_mod)) ^ clear_val;
5547       if (first_x_off_byte < first_x_on_byte)
5548         {
5549           /* This can happen, if 6 or fewer points are turned on */
5550           cd_mask[first_x_on_byte] = first_x_on_extra & first_x_off_extra;
5551         }
5552       else
5553         {
5554           if (first_x_on_extra != clear_val)
5555 
5556             cd_mask[first_x_on_byte - 1] = first_x_on_extra;
5557           if (first_x_off_byte > first_x_on_byte)
5558             memset(cd_mask + first_x_on_byte, set_val,
5559                    first_x_off_byte - first_x_on_byte);
5560           if (first_x_off_extra != clear_val)
5561             cd_mask[first_x_off_byte] = first_x_off_extra;
5562         }
5563     }
5564 }
5565 
5566 
5567 /* get delay settings for the specified color and mode */
canon_get_delay(canon_privdata_t * privdata,char color)5568 static int canon_get_delay(canon_privdata_t* privdata,char color){
5569     int i=0;
5570     int delay = 0;
5571     const canon_delay_t* delaylist = privdata->mode->delay;
5572 
5573     while(delaylist && delaylist[i].color){
5574         if(delaylist[i].color == color){
5575            delay = delaylist[i].delay;
5576            break;
5577         }
5578         ++i;
5579     }
5580     if(delay > privdata->delay_max)
5581        privdata->delay_max = delay;
5582     return delay;
5583 }
5584 
5585 
5586 /* add a single channel to the dither engine */
canon_setup_channel(stp_vars_t * v,canon_privdata_t * privdata,int channel,int subchannel,const canon_inkset_t * ink,stp_shade_t ** shades)5587 static int canon_setup_channel(stp_vars_t *v,canon_privdata_t* privdata,int channel,int subchannel,const canon_inkset_t* ink,stp_shade_t** shades){
5588     if(ink->channel && ink->density > 0.0){
5589         int delay = canon_get_delay(privdata,ink->channel);
5590         canon_channel_t* current;
5591 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (start) privdata->num_channels %d\n", privdata->num_channels);
5592 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (start) privdata->channel_order %s\n", privdata->channel_order);
5593 
5594         /* create a new channel */
5595         privdata->channels = stp_realloc(privdata->channels,sizeof(canon_channel_t) * (privdata->num_channels + 1));
5596         privdata->channel_order = stp_realloc(privdata->channel_order,privdata->num_channels + 2);
5597         /* update channel order */
5598         privdata->channel_order[privdata->num_channels]=ink->channel;
5599 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: ink->channel %c\n", ink->channel);
5600         privdata->channel_order[privdata->num_channels+1]='\0';
5601 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: (terminated)privdata->channel_order %s\n", privdata->channel_order);
5602         current = &(privdata->channels[privdata->num_channels]);
5603         ++privdata->num_channels;
5604         /* fill ink properties */
5605         current->name = ink->channel;
5606 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: current->name %c\n", current->name);
5607         current->props = ink->ink;
5608         current->delay = delay;
5609         /* calculate buffer length */
5610         current->buf_length = ((privdata->length * current->props->bits)+1)*(delay + 1);
5611         /* update maximum buffer length */
5612         if(current->buf_length > privdata->buf_length_max)
5613              privdata->buf_length_max = current->buf_length;
5614         /* allocate buffer for the raster data */
5615         current->buf = stp_zalloc(current->buf_length + 1);
5616         /* add channel to the dither engine */
5617         stp_dither_add_channel(v, current->buf , channel , subchannel);
5618 
5619         /* add shades to the shades array */
5620         *shades = stp_realloc(*shades,(subchannel + 1) * sizeof(stp_shade_t));
5621 	/* move previous shades up one position as set_inks_full expects the subchannels first */
5622 	if(subchannel)
5623 		memmove(*shades + 1,*shades,sizeof(stp_shade_t) * subchannel);
5624         (*shades)[0].value = ink->density;
5625 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channel: ink->density %.3f\n", ink->density);
5626         (*shades)[0].numsizes = ink->ink->numsizes;
5627 	/* test for 4-4 inket with 8 levels spaced every 2nd */
5628 	/*if (ink->ink->bits == 4)
5629 	  (*shades)[0].numsizes = 8;*/
5630 
5631         (*shades)[0].dot_sizes = ink->ink->dot_sizes;
5632         return 1;
5633     }
5634     return 0;
5635 }
5636 
5637 
5638 
5639 
5640 
5641 /* setup the dither channels */
canon_setup_channels(stp_vars_t * v,canon_privdata_t * privdata)5642 static void canon_setup_channels(stp_vars_t *v,canon_privdata_t* privdata){
5643     /* (in gutenprint notation) => KCMY,  1230 => CMYK etc. */
5644     const char default_channel_order[STP_NCOLORS] = {0,1,2,3};
5645     /* codes for the primary channels */
5646     const char primary[STP_NCOLORS] = {'K','C','M','Y',};
5647     /* codes for the subchannels */
5648     const char secondary[STP_NCOLORS] = {'k','c','m','y'};
5649     /* names of the density adjustment controls */
5650     const char *primary_density_control[STP_NCOLORS] = {"BlackDensity","CyanDensity","MagentaDensity","YellowDensity"};
5651     const char *secondary_density_control[STP_NCOLORS] = {NULL,"LightCyanTrans","LightMagentaTrans","LightYellowTrans"};
5652     /* ink darkness for every channel */
5653     const double ink_darkness[] = {1.0, 0.31 / .5, 0.61 / .97, 0.08};
5654     const char* channel_order = default_channel_order;
5655 
5656 
5657 
5658     int channel;
5659     int channel_idx;
5660 
5661     if(privdata->caps->channel_order)
5662         channel_order = privdata->caps->channel_order;
5663 
5664 
5665     /* loop through the dither channels */
5666     for(channel_idx = 0; channel_idx < STP_NCOLORS ; channel_idx++){
5667         int i;
5668         unsigned int subchannel = 0;
5669         stp_shade_t* shades = NULL;
5670 	int is_black_channel = 0;
5671         channel = channel_order[channel_idx];
5672 	stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: channel %d\n", channel);
5673         if(channel == STP_ECOLOR_K && privdata->used_inks & CANON_INK_K_MASK){ /* black channel */
5674             /* find K and k inks */
5675             for(i=0;i<privdata->mode->num_inks;i++){
5676                 const canon_inkset_t* ink = &privdata->mode->inks[i];
5677                 if(ink->channel == primary[channel] || ink->channel == secondary[channel]) {
5678                     subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades);
5679 		    /* Gernot: add */
5680 		    stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: got a black channel\n");
5681 		}
5682             }
5683 	    is_black_channel = 1;
5684 	    /* adding cmy channels */
5685 	    /*}else if(channel != STP_ECOLOR_K && privdata->used_inks & (CANON_INK_CMY_MASK | CANON_INK_cmy_MASK)){ */ /* color channels */
5686         }else if(channel != STP_ECOLOR_K && privdata->used_inks & CANON_INK_CMY_MASK){  /* color channels */
5687             for(i=0;i<privdata->mode->num_inks;i++){
5688                 const canon_inkset_t* ink = &privdata->mode->inks[i];
5689 		stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: loop non-K inks %d\n", i);
5690                 /*if(ink->channel == primary[channel] || ((privdata->used_inks & (CANON_INK_CcMmYyKk_MASK | CANON_INK_cmy_MASK)) && (ink->channel == secondary[channel]))) {*/
5691                 if(ink->channel == primary[channel] || ((privdata->used_inks & (CANON_INK_CcMmYyKk_MASK|CANON_INK_CMY_MASK)) && (ink->channel == secondary[channel]))) {
5692 		/* Gernot: see if this works: use the masks that includes secondary channels */
5693                 /* if(ink->channel == primary[channel] || ((privdata->used_inks & CANON_INK_CMYKk_MASK ) && (ink->channel == secondary[channel]))) {*/
5694 		  subchannel += canon_setup_channel(v,privdata,channel,subchannel,ink,&shades);
5695 		  stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: adding subchannel\n");
5696 		}
5697 		else {
5698 		  stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: not creating subchannel\n");
5699 		}
5700             }
5701         }
5702 
5703         /* set inks and density */
5704         if(shades){
5705           stp_dither_set_inks_full(v,channel, subchannel, shades, 1.0, ink_darkness[channel]);
5706           for(i=0;i<subchannel;i++){
5707             double density = get_double_param(v, primary_density_control[channel]) * get_double_param(v, "Density");
5708 	    stp_dprintf(STP_DBG_CANON, v, "canon_setup_channels: loop subchannels for shades %d\n", i);
5709             if(i > 0 && secondary_density_control[channel])
5710               density *= get_double_param(v, secondary_density_control[channel]);
5711             stp_channel_set_density_adjustment(v,channel,subchannel,density);
5712           }
5713 	  if (is_black_channel)
5714 	    stp_channel_set_black_channel(v, channel);
5715           stp_free(shades);
5716         }
5717     }
5718 }
5719 
5720 
5721 
5722 
5723 
5724 
5725 
5726 /* FIXME move this to printercaps, and/or Esc (p command  */
5727 #define CANON_CD_X 176
5728 #define CANON_CD_Y 405
5729 
setup_page(stp_vars_t * v,canon_privdata_t * privdata)5730 static void setup_page(stp_vars_t* v,canon_privdata_t* privdata){
5731   const char *media_source = stp_get_string_parameter(v, "InputSlot");
5732   const char *cd_type = stp_get_string_parameter(v, "PageSize");
5733   int print_cd = (media_source && (!strcmp(media_source, "CD")));
5734   stp_dimension_t page_left,
5735                   page_top,
5736                   page_right,
5737                   page_bottom;
5738   int hub_size = 0;
5739 
5740 #if 0
5741   /* needed in workaround for Oufuku Hagaki */
5742   const stp_papersize_t *pp = stpi_get_papersize_by_size(v,
5743 							stp_get_page_height(v),
5744 							stp_get_page_width(v));
5745 
5746   if (pp)
5747     {
5748       const char *name = pp->name;
5749       if (!strcmp(name,"w420h567")) {
5750 	/* workaround for Oufuku Hagaki: wrong orientation */
5751 	privdata->page_width = stp_get_width(v);
5752 	privdata->page_height = stp_get_height(v);
5753 	stp_set_page_width(v, privdata->page_height);
5754 	stp_set_page_height(v, privdata->page_width);
5755       }
5756     }
5757 #endif
5758 
5759   if (cd_type && (strcmp(cd_type, "CDCustom") == 0 ))
5760     {
5761       int outer_diameter = stp_get_dimension_parameter(v, "CDOuterDiameter");
5762       stp_set_page_width(v, outer_diameter);
5763       stp_set_page_height(v, outer_diameter);
5764       stp_set_width(v, outer_diameter);
5765       stp_set_height(v, outer_diameter);
5766       hub_size = stp_get_dimension_parameter(v, "CDInnerDiameter");
5767     }
5768   else
5769     {
5770       const char *inner_radius_name = stp_get_string_parameter(v, "CDInnerRadius");
5771       hub_size = 43 * 10 * 72 / 254;		/* 43 mm standard CD hub */
5772 
5773       if (inner_radius_name && strcmp(inner_radius_name, "Small") == 0)
5774 	hub_size = 16 * 10 * 72 / 254;		/* 15 mm prints to the hole - play it
5775 						   safe and print 16 mm */
5776     }
5777 
5778   privdata->top = stp_get_top(v);
5779   privdata->left = stp_get_left(v);
5780   privdata->out_width = stp_get_width(v); /* check Epson: page_true_width */
5781   privdata->out_height = stp_get_height(v); /* check Epson: page_true_height */
5782 
5783   stp_dprintf(STP_DBG_CANON, v,"stp_get_width: privdata->out_width is %i\n",privdata->out_width);
5784   stp_dprintf(STP_DBG_CANON, v,"stp_get_height: privdata->out_height is %i\n",privdata->out_height);
5785 
5786   /* Don't use full bleed mode if the paper itself has a margin */
5787   if (privdata->left > 0 || privdata->top > 0)
5788     stp_set_boolean_parameter(v, "FullBleed", 0);
5789 
5790   internal_imageable_area(v, 0, 0, &page_left, &page_right,
5791                           &page_bottom, &page_top);
5792   if (print_cd) {
5793     privdata->cd_inner_radius = hub_size / 2;
5794     privdata->cd_outer_radius = stp_get_width(v) / 2;
5795     privdata->left = CANON_CD_X - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDXAdjustment");;
5796     privdata->top = CANON_CD_Y - privdata->cd_outer_radius + stp_get_dimension_parameter(v, "CDYAdjustment");
5797     privdata->page_width = privdata->left + privdata->out_width;
5798     privdata->page_height = privdata->top + privdata->out_height;
5799   } else {
5800     privdata->left -= page_left;
5801     privdata->top -= page_top; /* checked in Epson: matches */
5802     privdata->page_width = page_right - page_left; /* checked in Epson: matches */
5803     privdata->page_height = page_bottom - page_top; /* checked in Epson: matches */
5804   }
5805 
5806   stp_dprintf(STP_DBG_CANON, v, "setup_page page_top = %f\n",page_top);
5807   stp_dprintf(STP_DBG_CANON, v, "setup_page page_bottom = %f\n",page_bottom);
5808   stp_dprintf(STP_DBG_CANON, v, "setup_page page_left = %f\n",page_left);
5809   stp_dprintf(STP_DBG_CANON, v, "setup_page page_right = %f\n",page_right);
5810   stp_dprintf(STP_DBG_CANON, v, "setup_page top = %i\n",privdata->top);
5811   stp_dprintf(STP_DBG_CANON, v, "setup_page left = %i\n",privdata->left);
5812   stp_dprintf(STP_DBG_CANON, v, "setup_page out_height = %i\n",privdata->out_height);
5813   stp_dprintf(STP_DBG_CANON, v, "setup_page page_height = %i\n",privdata->page_height);
5814   stp_dprintf(STP_DBG_CANON, v, "setup_page page_width = %i\n",privdata->page_width);
5815 
5816 }
5817 
5818 
5819 /* combine all curve parameters in s and apply them */
canon_set_curve_parameter(stp_vars_t * v,const char * type,stp_curve_compose_t comp,const char * s1,const char * s2,const char * s3)5820 static void canon_set_curve_parameter(stp_vars_t *v,const char* type,stp_curve_compose_t comp,const char* s1,const char* s2,const char* s3){
5821   const char * s[3];
5822   size_t count = sizeof(s) / sizeof(s[0]);
5823   stp_curve_t *ret = NULL;
5824   int curve_count = 0;
5825   int i;
5826   const size_t piecewise_point_count = 384;
5827 
5828 
5829   /* ignore settings from the printercaps if the user specified his own parameters */
5830   if(stp_check_curve_parameter(v,type, STP_PARAMETER_ACTIVE))
5831     return;
5832 
5833   /* init parameter list (FIXME pass array directly???)*/
5834   s[0] = s1;
5835   s[1] = s2;
5836   s[2] = s3;
5837 
5838   /* skip empty curves */
5839   for(i=0;i<count;i++){
5840     if(s[i])
5841       s[curve_count++] = s[i];
5842   }
5843 
5844   /* combine curves */
5845   if(curve_count){
5846     for(i=0;i<curve_count;i++){
5847       stp_curve_t* t_tmp = stp_curve_create_from_string(s[i]);
5848       if(t_tmp){
5849         if(stp_curve_is_piecewise(t_tmp)){
5850           stp_curve_resample(t_tmp, piecewise_point_count);
5851         }
5852         if(!ret){
5853           ret = t_tmp;
5854         }else{
5855           stp_curve_t* t_comp = NULL;
5856           stp_curve_compose(&t_comp, ret, t_tmp, comp, -1);
5857           if(t_comp){
5858             stp_curve_destroy(ret);
5859             ret = t_comp;
5860           }
5861           stp_curve_destroy(t_tmp);
5862         }
5863       }
5864     }
5865   }
5866 
5867   /* apply result */
5868   if(ret){
5869     stp_set_curve_parameter(v, type, ret);
5870     stp_curve_destroy(ret);
5871   }
5872 }
5873 
5874 /*
5875  * 'canon_print()' - Print an image to a CANON printer.
5876  */
5877 static int
canon_do_print(stp_vars_t * v,stp_image_t * image)5878 canon_do_print(stp_vars_t *v, stp_image_t *image)
5879 {
5880   int i;
5881   int		status = 1;
5882   const char	*media_source = stp_get_string_parameter(v, "InputSlot");
5883   const char    *ink_type = stp_get_string_parameter(v, "InkType");
5884   const char    *duplex_mode = stp_get_string_parameter(v, "Duplex");
5885   int           page_number = stp_get_int_parameter(v, "PageNumber");
5886   const canon_cap_t * caps = canon_get_model_capabilities(v);
5887   const canon_modeuselist_t* mlist = caps->modeuselist;
5888 #if 0
5889   const canon_modeuse_t* muse;
5890 #endif
5891   /*  int monocheck = 0;
5892       int colcheck = 0; */
5893   int		x,y;		/* Looping vars */
5894   canon_privdata_t privdata;
5895   int		errdiv,		/* Error dividend */
5896 		errmod,		/* Error modulus */
5897 		errval,		/* Current error value */
5898 		errline,	/* Current raster line */
5899                 errlast;	/* Last raster line loaded */
5900 #if 0
5901 		out_channels;	/* Output bytes per pixel */
5902 #endif
5903   unsigned	zero_mask;
5904   int           print_cd = (media_source && (!strcmp(media_source, "CD")));
5905   int           image_height;
5906 #if 0
5907   int           image_width;
5908 #endif
5909   double        k_upper, k_lower;
5910   unsigned char *cd_mask = NULL;
5911   double outer_r_sq = 0;
5912   double inner_r_sq = 0;
5913   unsigned char* weave_cols[4] ; /* TODO clean up weaving code to be more generic */
5914 
5915   stp_dprintf(STP_DBG_CANON, v, "Entering canon_do_print\n");
5916 
5917   if (!stp_verify(v))
5918     {
5919       stp_eprintf(v, "Print options not verified; cannot print.\n");
5920       return 0;
5921     }
5922   /*
5923   * Setup a read-only pixel region for the entire image...
5924   */
5925 
5926   stp_image_init(image);
5927 
5928 
5929   /* rotate even pages for DuplexNoTumble */
5930   if((page_number & 1) && duplex_mode && !strcmp(duplex_mode,"DuplexNoTumble"))
5931   	image = stpi_buffer_image(image,BUFFER_FLAG_FLIP_X | BUFFER_FLAG_FLIP_Y);
5932 
5933   memset(&privdata,0,sizeof(canon_privdata_t));
5934   privdata.caps = caps;
5935 
5936   /* find the wanted media type */
5937   /* - media type has priority
5938      - then we select source
5939      - then inkset (cartridge selection)
5940      - then we select duplex
5941      - after that we compare if mode is compatible with media
5942      - if not, we replace it using closest quality setting
5943      - then we decide on printhead colors based on actual mode to use
5944    */
5945 
5946   privdata.pt = get_media_type(caps,stp_get_string_parameter(v, "MediaType"));
5947   privdata.slot = canon_source_type(media_source,caps);
5948 
5949   /* ---  make adjustment to InkSet based on Media --- */
5950 
5951   /* cartridge selection if any: default is Both---but should change to NULL if CANON_CAP_T is not available */
5952   /* check if InkSet chosen is possible for this Media */
5953   /* - if Black, check if modes for selected media have a black flag */
5954   /*   else, set InkSet to "Both" for now */
5955 
5956   /* scroll through modeuse list to find media */
5957   for(i=0;i<mlist->count;i++){
5958     if(!strcmp(privdata.pt->name,mlist->modeuses[i].name)){
5959 #if 0
5960       muse = &mlist->modeuses[i];
5961 #endif
5962       break;
5963     }
5964   }
5965 
5966   if ( !strcmp(stp_get_string_parameter(v, "InkSet"),"Black")) {
5967     /* check if there is any mode for that media with K-only inktype */
5968     /* if not, change it to "Both" */
5969     /* NOTE: User cannot force monochrome printing here, since that would require changing the Color Model */
5970     if (!(mlist->modeuses[i].use_flags & INKSET_BLACK_SUPPORT)) {
5971       stp_set_string_parameter(v, "InkSet", "Both");
5972     }
5973   }
5974   /* Color-only */
5975   else if ( !strcmp(stp_get_string_parameter(v, "InkSet"),"Color") && (caps->features & CANON_CAP_T) ) {
5976     /* check if there is any mode for that media with no K in the inkset at all */
5977     /* if not, change it to "Both" */
5978     if (!(mlist->modeuses[i].use_flags & INKSET_COLOR_SUPPORT)) {
5979       stp_set_string_parameter(v, "InkSet", "Both");
5980     }
5981   }
5982   /* no restriction for "Both" (non-BJC) or "Color" (BJC) or "Photo" yet */
5983 
5984   /* get InkSet after adjustment */
5985   privdata.ink_set = stp_get_string_parameter(v, "InkSet");
5986 
5987   /* --- no current restrictions for Duplex setting --- */
5988 
5989   /* in particular, we do not constrain duplex printing to certain media */
5990   privdata.duplex_str = duplex_mode;
5991 
5992   /* ---  make adjustment to InkType to comply with InkSet --- */
5993 
5994   /*  although InSet adjustment is pre-supposed, even if InkSet is not
5995       adjusted, the InkType adjustment will be validated against mode
5996       later */
5997   if (!strcmp(privdata.ink_set,"Black")) {
5998     if (strcmp(ink_type,"Gray")) {/* if ink_type is NOT set to Gray yet */
5999       stp_dprintf(STP_DBG_CANON, v, "canon_do_print: InkSet Black, so InkType set to Gray\n");
6000       stp_set_string_parameter(v, "InkType", "Gray");
6001     }
6002   } /* Color-only */
6003   else if ( !strcmp(privdata.ink_set,"Color") && (caps->features & CANON_CAP_T) ) {
6004     if (strcmp(ink_type,"RGB")) {/* if ink_type is NOT set to RGB (CMY) yet */
6005       stp_dprintf(STP_DBG_CANON, v, "canon_do_print: InkSet Color, so InkType changed to RGB (CMY)\n");
6006       stp_set_string_parameter(v, "InkType", "RGB");
6007     }
6008   } /* no restriction for InkSet set to "Both" or "Photo" */
6009 
6010   /* --- make adjustments to mode --- */
6011 
6012   /* find the wanted print mode: NULL if not yet set */
6013   stp_dprintf(STP_DBG_CANON, v, "canon_do_print: calling canon_get_current_mode\n");
6014   privdata.mode = canon_get_current_mode(v);
6015 
6016   if(!privdata.mode) {
6017     privdata.mode = &caps->modelist->modes[caps->modelist->default_mode];
6018   }
6019 
6020   /* then call get_current_mode again to sort out the correct matching of parameters and mode selection */
6021 
6022   stp_dprintf(STP_DBG_CANON, v, "canon_do_print: calling canon_check_current_mode\n");
6023 
6024   privdata.mode = canon_check_current_mode(v);
6025 
6026   /* --- completed all adjustments: options should be consistent --- */
6027 
6028   /* set quality */
6029   privdata.quality = privdata.mode->quality;
6030 
6031 
6032   /* force grayscale if image is grayscale
6033    *                 or single black cartridge installed
6034    */
6035   privdata.used_inks = canon_printhead_colors(v);
6036   if (privdata.used_inks == CANON_INK_K)
6037       stp_set_string_parameter(v, "PrintingMode", "BW");
6038   else
6039     stp_set_string_parameter(v, "PrintingMode", "Color");
6040 
6041   setup_page(v,&privdata);
6042 
6043   image_height = stp_image_height(image);
6044 
6045 #if 0
6046   image_width = stp_image_width(image);
6047 #endif
6048 
6049   privdata.is_first_page = (page_number == 0);
6050 
6051  /*
6052   * Convert image size to printer resolution...
6053   */
6054 #if 0
6055   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: unused image_width is %i pts(?)\n",image_width);
6056 #endif
6057   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_width is %i pts\n",privdata.out_width);
6058   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_height is %i pts\n",privdata.out_height);
6059   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.left is %i pts\n",privdata.left);
6060 
6061   privdata.out_width  = privdata.mode->xdpi * privdata.out_width / 72;
6062   privdata.out_height = privdata.mode->ydpi * privdata.out_height / 72;
6063   privdata.left       = privdata.mode->xdpi * privdata.left / 72;
6064 
6065   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_width is %i dots\n",privdata.out_width);
6066   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.out_height is %i dots\n",privdata.out_height);
6067   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.left is %i dots\n",privdata.left);
6068 
6069   stp_dprintf(STP_DBG_CANON, v,"density is %f\n",
6070                stp_get_float_parameter(v, "Density"));
6071 
6072   /*
6073    * Compute the LUT.  For now, it's 8 bit, but that may eventually
6074    * sometimes change.
6075    */
6076 
6077   if (!stp_check_float_parameter(v, "Density", STP_PARAMETER_DEFAULTED))
6078     {
6079       stp_set_float_parameter_active(v, "Density", STP_PARAMETER_ACTIVE);
6080       stp_set_float_parameter(v, "Density", 1.0);
6081     }
6082 
6083   stp_scale_float_parameter(v, "Density", privdata.pt->base_density);
6084   stp_scale_float_parameter(v, "Density",privdata.mode->density);
6085 
6086   if (stp_get_float_parameter(v, "Density") > 1.0)
6087     stp_set_float_parameter(v, "Density", 1.0);
6088 
6089   if (privdata.used_inks == CANON_INK_K)
6090     stp_scale_float_parameter(v, "Gamma", 1.25);
6091   stp_scale_float_parameter( v, "Gamma", privdata.mode->gamma );
6092 
6093   stp_dprintf(STP_DBG_CANON, v,"density is %f\n",
6094                stp_get_float_parameter(v, "Density"));
6095 
6096   if(privdata.used_inks & CANON_INK_CMYK_MASK)
6097     stp_set_string_parameter(v, "STPIOutputType", "KCMY");
6098   else if(privdata.used_inks & CANON_INK_CMY_MASK)
6099     stp_set_string_parameter(v, "STPIOutputType", "CMY");
6100   /* Gernot: addition */
6101   /*else if(privdata.used_inks & CANON_INK_cmy_MASK)
6102     stp_set_string_parameter(v, "STPIOutputType", "cmy");*/
6103   else
6104     stp_set_string_parameter(v, "STPIOutputType", "Grayscale");
6105 
6106   privdata.length = (privdata.out_width + 7) / 8;
6107 
6108   stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i\n",privdata.length);
6109   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i\n",privdata.num_channels);
6110 
6111   stp_dither_init(v, image, privdata.out_width, privdata.mode->xdpi, privdata.mode->ydpi);
6112 
6113 
6114   stp_dprintf(STP_DBG_CANON, v,"privdata.out_width is %i (after stp_dither_init)\n",privdata.out_width);
6115   stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i (after stp_dither_init)\n",privdata.length);
6116   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i (after stp_dither_init)\n",privdata.num_channels);
6117 
6118   canon_setup_channels(v,&privdata);
6119 
6120   stp_dprintf(STP_DBG_CANON, v,"privdata.out_width is %i (after canon_setup_channels)\n",privdata.out_width);
6121   stp_dprintf(STP_DBG_CANON, v,"privdata.length is %i (after canon_setup_channels)\n",privdata.length);
6122   stp_dprintf(STP_DBG_CANON, v,"canon_do_print: privdata.num_channels is %i (after canon_setup_channels)\n",privdata.num_channels);
6123 
6124   stp_dprintf(STP_DBG_CANON, v,
6125 	       "canon: driver will use colors %s\n",privdata.channel_order);
6126 
6127   /* Allocate compression buffer */
6128   if(caps->features & CANON_CAP_I)
6129     /*privdata.comp_buf = stp_zalloc(privdata.buf_length_max * 2 * caps->raster_lines_per_block * privdata.num_channels); */
6130       privdata.comp_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max * 2 * privdata.mode->raster_lines_per_block * privdata.num_channels)); /* for multiraster we need to buffer 8 lines for every color */
6131   else
6132       privdata.comp_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max * 2));
6133   /* Allocate fold buffer */
6134   privdata.fold_buf = stp_zalloc(stp_compute_tiff_linewidth(v, privdata.buf_length_max));
6135 
6136 
6137 
6138  /*
6139   * Output the page...
6140   */
6141 
6142    /* FIXME this is probably broken, kept for backward compatibility */
6143    if(privdata.num_channels > 4){
6144        k_lower = 0.4 / privdata.channels[4].props->bits + .1;
6145    }else
6146        k_lower = 0.25;
6147 
6148   k_lower *= privdata.pt->k_lower_scale;
6149   k_upper = privdata.pt->k_upper;
6150 
6151   if (!stp_check_float_parameter(v, "GCRLower", STP_PARAMETER_ACTIVE))
6152     stp_set_default_float_parameter(v, "GCRLower", k_lower);
6153   if (!stp_check_float_parameter(v, "GCRUpper", STP_PARAMETER_ACTIVE))
6154     stp_set_default_float_parameter(v, "GCRUpper", k_upper);
6155 
6156 
6157   /* init the printer */
6158   canon_init_printer(v, &privdata);
6159 
6160   /* initialize weaving for S200 for resolutions > 360dpi */
6161   if (privdata.mode->flags & MODE_FLAG_WEAVE)
6162      {
6163        char weave_color_order[] = "KCMY";
6164 
6165        privdata.stepper_ydpi = 720;
6166        privdata.nozzle_ydpi = 360;
6167        if (privdata.mode->xdpi == 2880)
6168          privdata.physical_xdpi = 2880;
6169        else
6170          privdata.physical_xdpi = 720;
6171 
6172        stp_dprintf(STP_DBG_CANON, v,"canon: adjust leftskip: old=%d,\n", privdata.left);
6173        privdata.left = (int)( (float)privdata.left * (float)privdata.physical_xdpi / (float)privdata.mode->xdpi ); /* adjust left margin */
6174        stp_dprintf(STP_DBG_CANON, v,"canon: adjust leftskip: new=%d,\n", privdata.left);
6175 
6176        privdata.ncolors = 4;
6177        privdata.head_offset = stp_zalloc(sizeof(int) * privdata.ncolors);
6178        memset(privdata.head_offset, 0, sizeof(*privdata.head_offset));
6179 
6180        if ( privdata.used_inks == CANON_INK_K )
6181            privdata.nozzles = 64; /* black nozzles */
6182        else
6183            privdata.nozzles = 24; /* color nozzles */
6184        if ( privdata.used_inks == CANON_INK_K )
6185          {
6186            privdata.ncolors = 1;
6187            privdata.head_offset[0] = 0; /* K starts at 0 */
6188            privdata.head_offset[1] = 0 ;/* how far C starts after K */
6189            privdata.head_offset[2] = 0;/* how far M starts after K */
6190            privdata.head_offset[3] = 0;/* how far Y starts after K */
6191            privdata.top += 11;
6192          }
6193        else if ( privdata.used_inks == CANON_INK_CMYK )
6194          {
6195            privdata.head_offset[0] = 0; /* K starts at 0 */
6196            privdata.head_offset[1] = 144 ;/* how far C starts after K */
6197            privdata.head_offset[2] = 144 + 64;/* how far M starts after K */
6198            privdata.head_offset[3] = 144 + 64 + 64;/* how far Y starts after K */
6199            privdata.top += 5;
6200          }
6201        else  /* colormode == CMY */
6202          {
6203            privdata.ncolors = 3;
6204            privdata.head_offset[0] = 0; /* K starts at 0 */
6205            privdata.head_offset[1] = 0 ;/* how far C starts after K */
6206            privdata.head_offset[2] = 64;/* how far M starts after K */
6207            privdata.head_offset[3] = 128;/* how far Y starts after K */
6208            privdata.top += 18;
6209          }
6210 
6211        privdata.nozzle_separation = privdata.stepper_ydpi / privdata.nozzle_ydpi;
6212        privdata.horizontal_passes = privdata.mode->xdpi / privdata.physical_xdpi;
6213        privdata.vertical_passes = 1;
6214        privdata.vertical_oversample = privdata.mode->ydpi / privdata.stepper_ydpi;
6215        privdata.bidirectional = 1; /* 1: bidirectional; 0: unidirectional  printing */
6216        privdata.direction = 1;
6217        stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
6218        stp_dprintf(STP_DBG_CANON, v,"canon: initializing weaving: nozzles=%d, nozzle_separation=%d,\n"
6219                                     "horizontal_passes=%d, vertical_passes=%d,vertical_oversample=%d,\n"
6220                                     "ncolors=%d, out_width=%d, out_height=%d\n"
6221                                     "weave_top=%d, weave_page_height=%d \n"
6222                                     "head_offset=[%d,%d,%d,%d]  \n",
6223                                     privdata.nozzles, privdata.nozzle_separation,
6224                                     privdata.horizontal_passes, privdata.vertical_passes,
6225                                     privdata.vertical_oversample, privdata.ncolors,
6226                                     privdata.out_width, privdata.out_height,
6227                                     privdata.top * privdata.stepper_ydpi / 72, privdata.page_height * privdata.stepper_ydpi / 72,
6228                                     privdata.head_offset[0],privdata.head_offset[1],
6229                                     privdata.head_offset[2],privdata.head_offset[3]);
6230 
6231        stp_initialize_weave(v, privdata.nozzles, privdata.nozzle_separation,
6232                                 privdata.horizontal_passes, privdata.vertical_passes,
6233                                 privdata.vertical_oversample, privdata.ncolors,
6234                                 1,
6235                                 privdata.out_width, privdata.out_height,
6236                                 privdata.top * privdata.stepper_ydpi / 72,
6237                                 privdata.page_height * privdata.stepper_ydpi / 72,
6238                                 privdata.head_offset,
6239                                 STP_WEAVE_ZIGZAG,
6240                                 canon_flush_pass,
6241                                 stp_fill_uncompressed,
6242                                 stp_pack_uncompressed,
6243                                 stp_compute_tiff_linewidth);
6244        privdata.last_pass_offset = 0;
6245 
6246        if (stp_get_debug_level() & STP_DBG_CANON) {
6247 	 for(x=0;x<4;x++){
6248 	   stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: weave_color_order[%d]: %u\n",
6249 		       x, (unsigned int)weave_color_order[x]);
6250 	 }
6251 	 for(x=0;x<privdata.num_channels;x++){
6252 	   stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: channel_order[%d]: %u\n",
6253 		       x, (unsigned int)privdata.channel_order[x]);
6254 	 }
6255        }
6256 
6257        for(i=0;i<4;i++){/* need all 4 channels for weave_cols, but not for privdata.num_channels! */
6258 	   /* see if it helps to initialize to zero */
6259 	   weave_cols[i] = 0;
6260 	   privdata.weave_bits[i] = 0;
6261 
6262            for(x=0;x<privdata.num_channels;x++){
6263 	     if(weave_color_order[i] == privdata.channel_order[x]){
6264 	       weave_cols[i] = privdata.channels[x].buf;
6265 	       privdata.weave_bits[i] = privdata.channels[x].props->bits;
6266 	       stp_dprintf(STP_DBG_CANON, v, "DEBUG print-canon weave: set weave_cols[%d] to privdata.channels[%d].buf\n",
6267 			     i, x);
6268 	     }
6269            }
6270        }
6271   }
6272 
6273 
6274   errdiv  = image_height / privdata.out_height;
6275   errmod  = image_height % privdata.out_height;
6276   errval  = 0;
6277   errlast = -1;
6278   errline  = 0;
6279 
6280   /* set Hue, Lum and Sat Maps */
6281   canon_set_curve_parameter(v,"HueMap",STP_CURVE_COMPOSE_ADD,caps->hue_adjustment,privdata.pt->hue_adjustment,privdata.mode->hue_adjustment);
6282   canon_set_curve_parameter(v,"LumMap",STP_CURVE_COMPOSE_MULTIPLY,caps->lum_adjustment,privdata.pt->lum_adjustment,privdata.mode->lum_adjustment);
6283   canon_set_curve_parameter(v,"SatMap",STP_CURVE_COMPOSE_MULTIPLY,caps->sat_adjustment,privdata.pt->sat_adjustment,privdata.mode->sat_adjustment);
6284 
6285 #if 0
6286   out_channels = stp_color_init(v, image, 65536);
6287 #endif
6288   (void) stp_color_init(v, image, 65536);
6289   stp_allocate_component_data(v, "Driver", NULL, NULL, &privdata);
6290 
6291   privdata.emptylines = 0;
6292   if (print_cd) {
6293     cd_mask = stp_malloc(1 + (privdata.out_width + 7) / 8);
6294     outer_r_sq = (double)privdata.cd_outer_radius * (double)privdata.cd_outer_radius;
6295     inner_r_sq = (double)privdata.cd_inner_radius * (double)privdata.cd_inner_radius;
6296   }
6297   for (y = 0; y < privdata.out_height; y ++)
6298   {
6299     int duplicate_line = 1;
6300 
6301     if (errline != errlast)
6302     {
6303       errlast = errline;
6304       duplicate_line = 0;
6305       if (stp_color_get_row(v, image, errline, &zero_mask))
6306 	{
6307 	  status = 2;
6308 	  break;
6309 	}
6310     }
6311     if (print_cd)
6312       {
6313 	int x_center = privdata.cd_outer_radius * privdata.mode->xdpi / 72;
6314 	int y_distance_from_center =
6315 	  privdata.cd_outer_radius - (y * 72 / privdata.mode->ydpi);
6316 	if (y_distance_from_center < 0)
6317 	  y_distance_from_center = -y_distance_from_center;
6318 	memset(cd_mask, 0, (privdata.out_width + 7) / 8);
6319 	if (y_distance_from_center < privdata.cd_outer_radius)
6320 	  {
6321 	    double y_sq = (double) y_distance_from_center *
6322 	      (double) y_distance_from_center;
6323 	    int x_where = sqrt(outer_r_sq - y_sq) + .5;
6324 	    int scaled_x_where = x_where * privdata.mode->xdpi / 72;
6325 	    set_mask(cd_mask, x_center, scaled_x_where,
6326 		     privdata.out_width, 1, 0);
6327 	    if (y_distance_from_center < privdata.cd_inner_radius)
6328 	      {
6329 		x_where = sqrt(inner_r_sq - y_sq) + .5;
6330 		scaled_x_where = x_where * privdata.mode->ydpi / 72;
6331 		set_mask(cd_mask, x_center, scaled_x_where,
6332 			 privdata.out_width, 1, 1);
6333 	      }
6334 	  }
6335       }
6336     stp_dither(v, y, duplicate_line, zero_mask, cd_mask);
6337     if ( privdata.mode->flags & MODE_FLAG_WEAVE )
6338         stp_write_weave(v, weave_cols);
6339     else if ( caps->features & CANON_CAP_I)
6340         canon_write_multiraster(v,&privdata,y);
6341     else
6342         canon_printfunc(v);
6343     errval += errmod;
6344     errline += errdiv;
6345     if (errval >= privdata.out_height)
6346     {
6347       errval -= privdata.out_height;
6348       errline ++;
6349     }
6350   }
6351 
6352   if ( privdata.mode->flags & MODE_FLAG_WEAVE )
6353   {
6354       stp_flush_all(v);
6355       canon_advance_paper(v, 5);
6356   }
6357   else
6358   {
6359 
6360   /*
6361    * Flush delayed buffers...
6362    */
6363 
6364   if (privdata.delay_max) {
6365     stp_dprintf(STP_DBG_CANON, v,"\ncanon: flushing %d possibly delayed buffers\n",
6366 		 privdata.delay_max);
6367     for (y= 0; y<privdata.delay_max; y++) {
6368 
6369       canon_write_line(v);
6370       for (i = 0; i < privdata.num_channels; i++)
6371 	canon_advance_buffer(privdata.channels[i].buf, privdata.length,
6372 			     privdata.channels[i].delay);
6373     }
6374   }
6375   }
6376   stp_image_conclude(image);
6377 
6378  /*
6379   * Cleanup...
6380   */
6381 
6382   stp_free(privdata.fold_buf);
6383   stp_free(privdata.comp_buf);
6384 
6385   if(cd_mask)
6386       stp_free(cd_mask);
6387 
6388 
6389   canon_deinit_printer(v, &privdata);
6390   /* canon_end_job does not get called for jobmode automatically */
6391   if(!stp_get_string_parameter(v, "JobMode") ||
6392     strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0){
6393     canon_end_job(v,image);
6394   }
6395 
6396   for(i=0;i< privdata.num_channels;i++)
6397       if(privdata.channels[i].buf)
6398           stp_free(privdata.channels[i].buf);
6399   if(privdata.channels)
6400       stp_free(privdata.channels);
6401 
6402   stp_free(privdata.channel_order);
6403   if (privdata.head_offset)
6404     stp_free(privdata.head_offset);
6405 
6406 
6407   return status;
6408 }
6409 
6410 static int
canon_print(const stp_vars_t * v,stp_image_t * image)6411 canon_print(const stp_vars_t *v, stp_image_t *image)
6412 {
6413   int status;
6414   stp_vars_t *nv = stp_vars_create_copy(v);
6415   status = canon_do_print(nv, image);
6416   stp_vars_destroy(nv);
6417   return status;
6418 }
6419 
6420 static const stp_printfuncs_t print_canon_printfuncs =
6421 {
6422   canon_list_parameters,
6423   canon_parameters,
6424   stp_default_media_size,
6425   canon_imageable_area,
6426   canon_maximum_imageable_area,
6427   canon_limit,
6428   canon_print,
6429   canon_describe_resolution,
6430   canon_describe_output,
6431   stp_verify_printer_params,
6432   canon_start_job,
6433   canon_end_job,
6434   NULL,
6435   stpi_standard_describe_papersize
6436 };
6437 
6438 static void
canon_shift_buffer(unsigned char * line,int length,int bits)6439 canon_shift_buffer(unsigned char *line,int length,int bits)
6440 {
6441   int i,j;
6442   for (j=0; j<bits; j++) {
6443     for (i=length-1; i>0; i--) {
6444       line[i]= (line[i] >> 1) | (line[i-1] << 7);
6445     }
6446     line[0] = line[0] >> 1;
6447   }
6448 }
6449 
6450 
6451 /* fold, apply the necessary compression, pack tiff and return the compressed length */
canon_compress(stp_vars_t * v,canon_privdata_t * pd,unsigned char * line,int length,int offset,unsigned char * comp_buf,int bits,int ink_flags)6452 static int canon_compress(stp_vars_t *v, canon_privdata_t *pd, unsigned char* line,int length,int offset,unsigned char* comp_buf,int bits, int ink_flags)
6453 {
6454   unsigned char
6455     *in_ptr= line,
6456     *comp_ptr, *comp_data;
6457   int offset2,bitoffset;
6458 
6459   /* Don't send blank lines... */
6460 
6461   if (line[0] == 0 && memcmp(line, line + 1, (length * bits)  - 1) == 0)
6462     return 0;
6463 
6464   /* if no modulation: 1 bit per pixel */
6465 
6466   offset2 = offset / 8;
6467   bitoffset = offset % 8;
6468 
6469   /* fold lsb/msb pairs if drop modulation is active */
6470 
6471   if (bits==2) {
6472     int pixels_per_byte = 4;
6473     if(ink_flags & INK_FLAG_5pixel_in_1byte)
6474       pixels_per_byte = 5;
6475 
6476     stp_fold(line,length,pd->fold_buf);
6477     in_ptr    = pd->fold_buf;
6478     length    = (length*8/4); /* 4 pixels in 8bit */
6479     /* calculate the number of compressed bytes that can be sent directly */
6480     offset2   = offset / pixels_per_byte;
6481     /* calculate the number of (uncompressed) bits that have to be added to the raster data */
6482     bitoffset = (offset % pixels_per_byte) * 2;
6483   }
6484   else if (bits==3) {
6485     stp_fold_3bit_323(line,length,pd->fold_buf);
6486     in_ptr  = pd->fold_buf;
6487     length  = (length*8)/3;
6488     offset2 = offset/3;
6489 #if 0
6490     switch(offset%3){
6491     case 0: offset= (offset/3)*8;   break;
6492     case 1: offset= (offset/3)*8/*+3 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
6493     case 2: offset= (offset/3)*8/*+5 CAREFUL! CANNOT SHIFT _AFTER_ RECODING!!*/; break;
6494     }
6495 #endif
6496     bitoffset= 0;
6497   }
6498   else if (bits==4) {
6499     int pixels_per_byte = 2;
6500     if(ink_flags & INK_FLAG_3pixel5level_in_1byte)
6501       pixels_per_byte = 3;
6502     else if(ink_flags & INK_FLAG_3pixel6level_in_1byte)
6503       pixels_per_byte = 3;
6504 
6505     stp_fold_4bit(line,length,pd->fold_buf);
6506     in_ptr    = pd->fold_buf;
6507     length    = (length*8)/2; /* 2 pixels in 8 bits */
6508     /* calculate the number of compressed bytes that can be sent directly */
6509     offset2   = offset / pixels_per_byte;
6510     /* calculate the number of (uncompressed) bits that have to be added to the raster data */
6511     bitoffset = (offset % pixels_per_byte) * 2; /* not sure what this value means */
6512   }
6513   else if (bits==8) {
6514     stp_fold_8bit(line,length,pd->fold_buf);
6515     in_ptr= pd->fold_buf;
6516     length    = length*8; /* 1 pixel per 8 bits */
6517     offset2   = offset;
6518     bitoffset = 0;
6519   }
6520 
6521   /* pack left border rounded to multiples of 8 dots */
6522 
6523   comp_data= comp_buf;
6524 
6525   while (offset2>0) {
6526     unsigned char toffset = offset2 > 127 ? 127 : offset2;
6527     comp_data[0] = 1 - toffset;
6528     comp_data[1] = 0;
6529     comp_data += 2;
6530     offset2-= toffset;
6531   }
6532   if (bitoffset) {
6533     if (bitoffset<8)
6534       {
6535 	in_ptr[ length++ ] = 0;
6536 	canon_shift_buffer(in_ptr,length,bitoffset);
6537       }
6538     else if (bitoffset == 8)
6539       {
6540 	memmove(in_ptr + 1,in_ptr,length++);
6541 	in_ptr[0] = 0;
6542       }
6543     else
6544       stp_dprintf(STP_DBG_CANON, v,"SEVERE BUG IN print-canon.c::canon_write() "
6545 		   "bitoffset=%d!!\n",bitoffset);
6546   }
6547 
6548   if(ink_flags & INK_FLAG_5pixel_in_1byte)
6549     length = pack_pixels(in_ptr,length);
6550   else if(ink_flags & INK_FLAG_3pixel5level_in_1byte)
6551     length = pack_pixels3_5(in_ptr,length);
6552   else if(ink_flags & INK_FLAG_3pixel6level_in_1byte)
6553     length = pack_pixels3_6(in_ptr,length);
6554 
6555 
6556   stp_pack_tiff(v, in_ptr, length, comp_data, &comp_ptr, NULL, NULL);
6557 
6558   return comp_ptr - comp_buf;
6559 }
6560 
6561 /*
6562  * 'canon_write()' - Send graphics using TIFF packbits compression.
6563  */
6564 
6565 static int
canon_write(stp_vars_t * v,canon_privdata_t * pd,const canon_cap_t * caps,unsigned char * line,int length,int coloridx,int * empty,int width,int offset,int bits,int ink_flags)6566 canon_write(stp_vars_t *v,		/* I - Print file or command */
6567             canon_privdata_t *pd,       /* privdata */
6568 	    const canon_cap_t *   caps,	        /* I - Printer model */
6569 	    unsigned char *line,	/* I - Output bitmap data */
6570 	    int           length,	/* I - Length of bitmap data */
6571 	    int           coloridx,	/* I - Which color */
6572 	    int           *empty,       /* IO- Preceding empty lines */
6573 	    int           width,	/* I - Printed width */
6574 	    int           offset, 	/* I - Offset from left side */
6575 	    int           bits,
6576             int           ink_flags)
6577 {
6578 
6579   unsigned char color;
6580   int newlength = canon_compress(v,pd,line,length,offset,pd->comp_buf,bits,ink_flags);
6581   if(!newlength)
6582       return 0;
6583   /* send packed empty lines if any */
6584 
6585   if (*empty) {
6586     stp_zfwrite("\033\050\145\002\000", 5, 1, v);
6587     stp_put16_be(*empty, v);
6588     *empty= 0;
6589   }
6590 
6591  /* Send a line of raster graphics... */
6592 
6593   stp_zfwrite("\033\050\101", 3, 1, v);
6594   stp_put16_le(newlength + 1, v);
6595   color= "CMYKcmyk"[coloridx];
6596   if (!color) color= 'K';
6597   stp_putc(color,v);
6598   stp_zfwrite((const char *)pd->comp_buf, newlength, 1, v);
6599   stp_putc('\015', v);
6600   return 1;
6601 }
6602 
6603 
6604 static void
canon_write_line(stp_vars_t * v)6605 canon_write_line(stp_vars_t *v)
6606 {
6607   canon_privdata_t *pd =
6608     (canon_privdata_t *) stp_get_component_data(v, "Driver");
6609   char write_sequence[] = "KYMCymck";
6610   static const int write_number[] = { 3, 2, 1, 0, 6, 5, 4, 7 };   /* KYMCymc */
6611   int i;
6612   int written= 0;
6613   for (i = 0; i < strlen(write_sequence) ; i++)
6614     {
6615       int x;
6616       const canon_channel_t* channel=NULL;
6617       int num = write_number[i];
6618 
6619       /* TODO optimize => move reorder code to do_print */
6620       for(x=0;x < pd->num_channels; x++){
6621 	if(pd->channels[x].name == write_sequence[i]){
6622               channel = &(pd->channels[x]);
6623               break;
6624           }
6625       }
6626       if(channel){
6627         written += canon_write(v, pd, pd->caps,
6628                                channel->buf + channel->delay * pd->length /*buf_length[i]*/,
6629                                pd->length, num,
6630                                &(pd->emptylines), pd->out_width,
6631                                pd->left, channel->props->bits, channel->props->flags);
6632       }
6633     }
6634   if (written)
6635     stp_zfwrite("\033\050\145\002\000\000\001", 7, 1, v);
6636   else
6637     pd->emptylines += 1;
6638 }
6639 
6640 
6641 /* write one multiraster block */
canon_write_block(stp_vars_t * v,canon_privdata_t * pd,unsigned char * start,unsigned char * end)6642 static void canon_write_block(stp_vars_t* v,canon_privdata_t* pd,unsigned char* start, unsigned char* end){
6643     unsigned int length = end - start;
6644     if(!length)
6645         return;
6646     stp_zfwrite("\033(F", 3, 1, v);
6647     stp_put16_le(length, v);
6648     stp_zfwrite((const char *)start, length, 1, v);
6649 }
6650 
6651 
canon_write_multiraster(stp_vars_t * v,canon_privdata_t * pd,int y)6652 static void canon_write_multiraster(stp_vars_t *v,canon_privdata_t* pd,int y){
6653     int i;
6654     /*int raster_lines_per_block = pd->caps->raster_lines_per_block;*/
6655     int raster_lines_per_block = pd->mode->raster_lines_per_block;
6656     unsigned int max_length = 2*pd->buf_length_max * raster_lines_per_block;
6657     /* a new raster block begins */
6658     if(!(y % raster_lines_per_block)){
6659         if(y != 0){
6660             /* write finished blocks */
6661             for(i=0;i<pd->num_channels;i++)
6662                 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset);
6663         }
6664         /* reset start offsets */
6665         for(i=0;i<pd->num_channels;i++)
6666             pd->channels[i].comp_buf_offset = pd->comp_buf + i * max_length;
6667     }
6668     /* compress lines and add them to the buffer */
6669     for(i=0;i<pd->num_channels;i++){
6670        pd->channels[i].comp_buf_offset += canon_compress(v,pd, pd->channels[i].buf,pd->length,pd->left,pd->channels[i].comp_buf_offset,pd->channels[i].props->bits, pd->channels[i].props->flags);
6671        *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */
6672         ++pd->channels[i].comp_buf_offset;
6673     }
6674     if(y == pd->out_height - 1){
6675         /* we just compressed our last line */
6676         if(pd->out_height % raster_lines_per_block){
6677             /* but our raster block is not finished yet */
6678             int missing = raster_lines_per_block - (pd->out_height % raster_lines_per_block); /* calculate missing lines */
6679             for(i=0;i<pd->num_channels;i++){
6680                 /* add missing empty lines and write blocks */
6681                 int x;
6682                 for(x=0;x < missing ; x++){
6683                   *(pd->channels[i].comp_buf_offset) = 0x80; /* terminate the line */
6684                   ++pd->channels[i].comp_buf_offset;
6685                 }
6686                 canon_write_block(v,pd,pd->comp_buf + i * max_length,pd->channels[i].comp_buf_offset);
6687             }
6688         }
6689     }
6690 }
6691 
6692 
6693 static void
canon_advance_paper(stp_vars_t * v,int advance)6694 canon_advance_paper(stp_vars_t *v, int advance)
6695 {
6696   if ( advance > 0 )
6697     {
6698       int a0, a1, a2, a3;
6699       stp_dprintf(STP_DBG_CANON, v,"                      --advance paper %d\n", advance);
6700       a0 = advance         & 0xff;
6701       a1 = (advance >> 8)  & 0xff;
6702       a2 = (advance >> 16) & 0xff;
6703       a3 = (advance >> 24) & 0xff;
6704       stp_zprintf(v, "\033(e%c%c%c%c%c%c", 4, 0, a3, a2, a1, a0);
6705     }
6706 }
6707 
6708 static void
canon_flush_pass(stp_vars_t * v,int passno,int vertical_subpass)6709 canon_flush_pass(stp_vars_t *v, int passno, int vertical_subpass)
6710 {
6711   stp_lineoff_t        *lineoffs   = stp_get_lineoffsets_by_pass(v, passno);
6712   stp_lineactive_t     *lineactive = stp_get_lineactive_by_pass(v, passno);
6713   const stp_linebufs_t *bufs       = stp_get_linebases_by_pass(v, passno);
6714   stp_pass_t           *pass       = stp_get_pass_by_pass(v, passno);
6715   stp_linecount_t      *linecount  = stp_get_linecount_by_pass(v, passno);
6716   canon_privdata_t      *pd         = (canon_privdata_t *) stp_get_component_data(v, "Driver");
6717   int                    papershift = (pass->logicalpassstart - pd->last_pass_offset);
6718 
6719   int color, line, written = 0, linelength = 0, lines = 0;
6720   int idx[4]={3, 0, 1, 2}; /* color numbering is different between canon_write and weaving */
6721 
6722   stp_dprintf(STP_DBG_CANON, v,"canon_flush_pass: ----pass=%d,---- \n", passno);
6723   (pd->emptylines) = 0;
6724 
6725   for ( color = 0; color < pd->ncolors; color++ ) /* find max. linecount */
6726     {
6727       if ( linecount[0].v[color] > lines )
6728         lines = linecount[0].v[color];
6729     }
6730 
6731   for ( line = 0; line < lines; line++ )  /* go through each nozzle f that pass */
6732     {
6733       stp_dprintf(STP_DBG_CANON, v,"                      --line=%d\n", line);
6734 
6735       if ( written > 0 )
6736         canon_cmd(v,ESC28,0x65, 2, 0, 1); /* go to next nozzle*/
6737                                            /* if there was printed some data */
6738 
6739       written = 0;
6740       for ( color = 0; color < pd->ncolors; color++ )
6741         {
6742           if ( line < linecount[0].v[color] )  /* try only existing lines */
6743             {
6744               if ( lineactive[0].v[color] > 0 )
6745                 {
6746                   linelength = lineoffs[0].v[color] / linecount[0].v[color];
6747 /*                stp_dprintf(STP_DBG_CANON, v,"canon_flush_pass: linelength=%d, bufs[0].v[color]=%p,"
6748                   "bufs[0].v[color]+line * linelength=%p, empty=%d \n", linelength, bufs[0].v[color],
6749                    bufs[0].v[color] + line * linelength, (pd->emptylines));
6750 */
6751                   if ( pass->logicalpassstart - pd->last_pass_offset > 0 )
6752                     {
6753                       canon_advance_paper(v, papershift);
6754                       pd->last_pass_offset = pass->logicalpassstart;
6755                       if (pd->bidirectional)
6756                         {
6757                          pd->direction = (pd->direction +1) & 1;
6758                          canon_set_X72(v, pd->direction);
6759                          stp_dprintf(STP_DBG_CANON, v,"                      --set direction %d\n", pd->direction);
6760                         }
6761                     }
6762 
6763                   written += canon_write(v, pd, pd->caps,
6764                                (unsigned char *)(bufs[0].v[color] + line * linelength),
6765                                linelength, idx[color],
6766                                &(pd->emptylines), pd->out_width,
6767                                pd->left, pd->weave_bits[color],0);
6768                   if (written) stp_dprintf(STP_DBG_CANON, v,"                        --written color %d,\n", color);
6769 
6770                 }
6771             }
6772         }
6773 
6774       if ( written == 0 ) /* count unused nozzles */
6775         (pd->emptylines) += 1;
6776     }
6777 
6778   for ( color = 0; color < pd->ncolors; color++ )
6779     {
6780       lineoffs[0].v[color] = 0;
6781       linecount[0].v[color] = 0;
6782     }
6783   stp_dprintf(STP_DBG_CANON, v,"                  --ended-- with empty=%d \n", (pd->emptylines));
6784 }
6785 
6786 static stp_family_t print_canon_module_data =
6787   {
6788     &print_canon_printfuncs,
6789     NULL
6790   };
6791 
6792 
6793 static int
print_canon_module_init(void)6794 print_canon_module_init(void)
6795 {
6796   return stpi_family_register(print_canon_module_data.printer_list);
6797 }
6798 
6799 
6800 static int
print_canon_module_exit(void)6801 print_canon_module_exit(void)
6802 {
6803   return stpi_family_unregister(print_canon_module_data.printer_list);
6804 }
6805 
6806 
6807 /* Module header */
6808 #define stp_module_version print_canon_LTX_stp_module_version
6809 #define stp_module_data print_canon_LTX_stp_module_data
6810 
6811 stp_module_version_t stp_module_version = {0, 0};
6812 
6813 stp_module_t stp_module_data =
6814   {
6815     "canon",
6816     VERSION,
6817     "Canon family driver",
6818     STP_MODULE_CLASS_FAMILY,
6819     NULL,
6820     print_canon_module_init,
6821     print_canon_module_exit,
6822     (void *) &print_canon_module_data
6823   };
6824