1 /*
2 * gprintersettings.cpp - Bridges GutenPrint's stp_vars_t and the configuration file.
3 * A subclass of ConfigSectionHandler.
4 *
5 * Copyright (c) 2004, 2008 by Alastair M. Robinson
6 * Distributed under the terms of the GNU General Public License -
7 * see the file named "COPYING" for more details.
8 *
9 * TODO: Add support for multi-line parameters (heredoc syntax?)
10 */
11
12 #include <iostream>
13
14 #include <string.h>
15 #include <glib.h>
16 #include <glib/gprintf.h>
17
18 #include "stp_support/stputil.h"
19 #include "gprintersettings.h"
20
21 #include "../support/debug.h"
22 #include "../support/util.h"
23
24 #include "../miscwidgets/generaldialogs.h"
25
26 #include "../config.h"
27 #include "../gettext.h"
28
29 #define _(x) gettext(x)
30 #define N_(x) gettext_noop(x)
31
32
33 #define DEFAULT_PPD_STRING "<Default Queue PPD>"
34
35 using namespace std;
36
37
dumpstrings(const stp_parameter_t * desc)38 static void dumpstrings(const stp_parameter_t *desc)
39 {
40 int j,strcount;
41 stp_string_list_t *strlist=desc->bounds.str;
42 if(strlist)
43 {
44 strcount=stp_string_list_count(strlist);
45 for(j=0;j<strcount;++j)
46 {
47 stp_param_string_t *p=stp_string_list_param(strlist,j);
48 fprintf(stderr," %s (%s)\n",p->text,p->name);
49 }
50 }
51 else
52 fprintf(stderr," No string list!\n");
53 }
54
55
dumpvars(stp_vars_t * v)56 static void dumpvars(stp_vars_t *v)
57 {
58 stp_parameter_list_t params = stp_get_parameter_list(v);
59
60 int count = stp_parameter_list_count(params);
61
62 for (int i = 0; i < count; i++)
63 {
64 const stp_parameter_t *p = stp_parameter_list_param(params, i);
65 // if((p->p_level<=STP_PARAMETER_LEVEL_ADVANCED4)
66 // && ((p->p_class==STP_PARAMETER_CLASS_FEATURE) || (p->p_class==STP_PARAMETER_CLASS_OUTPUT)))
67 {
68 stp_parameter_t desc;
69 stp_describe_parameter(v,p->name,&desc);
70 const char *str;
71 int ival;
72 double fval;
73
74 fprintf(stderr,"%s, %d, %d, %d, %d ",desc.name,desc.p_type,p->p_type,desc.p_class,desc.p_level);
75
76 if(desc.is_active)
77 {
78 fprintf(stderr,", Active");
79 }
80 else
81 {
82 fprintf(stderr,", Inactive");
83 }
84 switch(desc.p_type)
85 {
86 case STP_PARAMETER_TYPE_STRING_LIST:
87 str=stp_get_string_parameter(v,desc.name);
88 fprintf(stderr,", StringList\n");
89 dumpstrings(&desc);
90 if(str)
91 fprintf(stderr," Currently set to: %s\n",str);
92 break;
93
94 case STP_PARAMETER_TYPE_INT:
95 ival=stp_get_int_parameter(v,desc.name);
96 fprintf(stderr,", Int\n");
97 fprintf(stderr," Currently set to: %d\n",ival);
98 break;
99
100 case STP_PARAMETER_TYPE_BOOLEAN:
101 ival=stp_get_boolean_parameter(v,desc.name);
102 fprintf(stderr,", Boolean\n");
103 fprintf(stderr," Currently set to: %d\n",ival);
104 break;
105
106 case STP_PARAMETER_TYPE_DOUBLE:
107 fval=stp_get_float_parameter(v,desc.name);
108 fprintf(stderr,", Double\n");
109 fprintf(stderr," Currently set to: %f\n",fval);
110 break;
111
112 default:
113 fprintf(stderr,", Other\n");
114 break;
115 }
116 }
117 }
118 stp_parameter_list_destroy(params);
119 }
120
121
Dump()122 void GPrinterSettings::Dump()
123 {
124 dumpvars(stpvars);
125 }
126
127
GPrinterSettings(PrintOutput & output,ConfigFile * inf,const char * section)128 GPrinterSettings::GPrinterSettings(PrintOutput &output,ConfigFile *inf,const char *section)
129 : ConfigSectionHandler(inf,section), PageExtent(), stpvars(NULL), output(output),
130 initialised(false), ppdsizes_workaround_done(false)
131 {
132 stpvars=stp_vars_create();
133
134 // Set the driver to that of the default queue in case no preset is loaded
135 const char *driver=output.FindString("Driver");
136 if(!SetDriver(driver))
137 output.SetString("Driver",DEFAULT_PRINTER_DRIVER);
138 }
139
140
~GPrinterSettings()141 GPrinterSettings::~GPrinterSettings()
142 {
143 if(stpvars)
144 stp_vars_destroy(stpvars);
145 }
146
147
SelectSection()148 void GPrinterSettings::SelectSection()
149 {
150 /* Slight hack here: The printer driver is stored in the [Output] section
151 which is prior to the [Print] section. Clearing this forces the driver
152 to be set before the printer options are set */
153
154 initialised=false;
155 }
156
157
ParseString(const char * string)158 void GPrinterSettings::ParseString(const char *string)
159 {
160 if(!initialised)
161 {
162 const char *driver=output.FindString("Driver");
163 if(!SetDriver(driver))
164 output.SetString("Driver",DEFAULT_PRINTER_DRIVER);
165 initialised=true;
166 }
167
168 while(*string==' ')
169 ++string;
170
171 char *value;
172 char *token;
173 value=token=strdup(string);
174 int l=strlen(token)-1;
175 while((l>0) && ((token[l]=='\n') || (token[l]=='\r')))
176 --l;
177 token[l+1]=0;
178
179 while(1)
180 {
181 switch (*value)
182 {
183 case '\0':
184 free(token);
185 return;
186 break;
187 case '=':
188 *value='\0';
189 ++value;
190 if(*value)
191 {
192 if(strcmp("CustomWidth",token)==0)
193 {
194 Debug[TRACE] << "Setting custom width to: " << value << endl;
195 stp_set_page_width(stpvars,pagewidth=atoi(value));
196 }
197 else if(strcmp("CustomHeight",token)==0)
198 {
199 Debug[TRACE] << "Setting custom height to: " << value << endl;
200 stp_set_page_height(stpvars,pageheight=atoi(value));
201 }
202 else
203 {
204 stp_parameter_t param;
205 stp_describe_parameter(stpvars,token,¶m);
206 switch(param.p_type)
207 {
208 case STP_PARAMETER_TYPE_STRING_LIST:
209 if(strcmp("PageSize",token)==0)
210 Debug[TRACE] << "Setting PageSize to: " << value << endl;
211 stp_set_string_parameter(stpvars,token,value);
212 break;
213
214 case STP_PARAMETER_TYPE_FILE:
215 // Because the queue PPD filenames returned by CUPS
216 // aren't persistent between sessions, we have to
217 // save an escape string, and substitute the current
218 // filename at preset loading time.
219 if(strcmp(value,DEFAULT_PPD_STRING)==0)
220 {
221 Debug[TRACE] << "*** Fetching default PPD filename" << endl;
222 char *defppd=output.GetPPD();
223 if(defppd)
224 {
225 Debug[TRACE] << "Got default PPD filename: " << defppd << endl;
226 stp_set_file_parameter(stpvars,token,defppd);
227 free(defppd);
228
229 stp_parameter_t desc2;
230 stp_describe_parameter(stpvars,"PageSize",&desc2);
231 Debug[TRACE] << "After setting PPD Default page size is now: " << desc2.deflt.str << endl;
232 stp_set_string_parameter(stpvars,"PageSize",desc2.deflt.str);
233 stp_parameter_description_destroy(&desc2);
234 ppdsizes_workaround_done=true;
235 }
236 else
237 Debug[TRACE] << "Couldn't get default PPD." << endl;
238 }
239 else
240 stp_set_file_parameter(stpvars,token,value);
241 break;
242
243 case STP_PARAMETER_TYPE_INT:
244 // Debug[TRACE] << "Setting " << token << " to " << value << endl;
245 stp_set_int_parameter(stpvars,token,atoi(value));
246 break;
247
248 case STP_PARAMETER_TYPE_BOOLEAN:
249 // Debug[TRACE] << "Setting " << token << " to " << value << endl;
250 stp_set_boolean_parameter(stpvars,token,atoi(value));
251 break;
252
253 case STP_PARAMETER_TYPE_DOUBLE:
254 // Debug[TRACE] << "Setting " << token << " to " << value << endl;
255 stp_set_float_parameter(stpvars,token,atof(value));
256 break;
257
258 default:
259 break;
260 }
261 stp_parameter_description_destroy(¶m);
262 }
263 }
264 free(token);
265 return;
266 break;
267 }
268 ++value;
269 }
270 }
271
272
SaveSection(FILE * file)273 void GPrinterSettings::SaveSection(FILE *file)
274 {
275 stp_parameter_list_t params = stp_get_parameter_list(stpvars);
276 stp_parameter_t desc;
277 desc.is_active=false;
278
279 int count = stp_parameter_list_count(params);
280
281 // PPDFile parameter must be saved first, because it must be restored
282 // before other parameters upon loading.
283 // Because CUPS returns a local temporary filename for a queue's PPD
284 // which is not persistent between sessions, we must save an escape
285 // string to indicate that the queue's default should be used.
286
287 stp_describe_parameter(stpvars,"PPDFile",&desc);
288 if(desc.is_active)
289 {
290 Debug[TRACE] << "Saving PPDFile parameter..." << endl;
291 const char *ppd=stp_get_file_parameter(stpvars,"PPDFile");
292 char *defppd=output.GetPPD();
293 if(ppd)
294 Debug[TRACE] << "Current PPD: " << ppd << endl;
295 if(defppd)
296 Debug[TRACE] << "Default PPD: " << defppd << endl;
297 if(defppd && ppd && CompareFiles(defppd,ppd))
298 ppd=DEFAULT_PPD_STRING;
299 if(!ppd)
300 ppd=DEFAULT_PPD_STRING;
301 if(defppd)
302 free(defppd);
303 fprintf(file,"PPDFile=%s\n",ppd);
304 }
305
306 for (int i = 0; i < count; i++)
307 {
308 const stp_parameter_t *p = stp_parameter_list_param(params, i);
309 if((p->p_level<=STP_PARAMETER_LEVEL_ADVANCED4))
310 {
311 stp_parameter_t desc;
312 stp_describe_parameter(stpvars,p->name,&desc);
313 if(desc.is_active)
314 {
315 switch(desc.p_type)
316 {
317 case STP_PARAMETER_TYPE_STRING_LIST:
318 {
319 if(stp_check_string_parameter(stpvars,desc.name,STP_PARAMETER_DEFAULTED))
320 {
321 const char *str=stp_get_string_parameter(stpvars,desc.name);
322 // if(!desc.is_mandatory || strcmp(str,desc.deflt.str)!=0)
323 fprintf(file,"%s=%s\n",desc.name,str);
324 }
325 }
326 break;
327
328 case STP_PARAMETER_TYPE_INT:
329 {
330 if(stp_check_int_parameter(stpvars,desc.name,STP_PARAMETER_DEFAULTED))
331 {
332 int val=stp_get_int_parameter(stpvars,desc.name);
333 // if(!desc.is_mandatory || val!=desc.deflt.integer)
334 fprintf(file,"%s=%d\n",desc.name,val);
335 }
336 }
337 break;
338
339 case STP_PARAMETER_TYPE_BOOLEAN:
340 {
341 if(stp_check_boolean_parameter(stpvars,desc.name,STP_PARAMETER_DEFAULTED))
342 {
343 int val=stp_get_boolean_parameter(stpvars,desc.name);
344 // if(!desc.is_mandatory || val!=desc.deflt.boolean)
345 fprintf(file,"%s=%d\n",desc.name,val);
346 }
347 }
348 break;
349
350 case STP_PARAMETER_TYPE_DOUBLE:
351 {
352 if(stp_check_float_parameter(stpvars,desc.name,STP_PARAMETER_DEFAULTED))
353 {
354 double val=stp_get_float_parameter(stpvars,desc.name);
355 // if(!desc.is_mandatory || val!=desc.deflt.dbl)
356 fprintf(file,"%s=%f\n",desc.name,val);
357 }
358 }
359 break;
360
361 default:
362 break;
363 }
364 }
365 stp_parameter_description_destroy(&desc);
366 }
367 }
368
369 fprintf(file,"CustomWidth=%d\n",pagewidth);
370 fprintf(file,"CustomHeight=%d\n",pageheight);
371
372 stp_parameter_list_destroy(params);
373 }
374
375
376 // SetDriver
377 // Returns false if the driver isn't recognised, true otherwise.
378
SetDriver(const char * driver)379 bool GPrinterSettings::SetDriver(const char *driver)
380 {
381 bool result=true;
382 bool driverchanged=false;
383
384 // FIXME - Not pretty. We need to strdup() the result of this because it's
385 // not valid after the driver has changed.
386 const char *_oldpagesize=stp_get_string_parameter(stpvars,"PageSize");
387 char *oldpagesize=NULL;
388 if(_oldpagesize)
389 {
390 oldpagesize=strdup(_oldpagesize);
391 Debug[TRACE] << "Old page size is: " << oldpagesize << endl;
392 }
393
394 Debug[TRACE] << "Checking stpvars" << endl;
395 if(stpvars)
396 {
397 // We avoid messing with this stuff as much as possible if the driver didn't change -
398 // that way you can change from a printer's queue to "Save to file" without
399 // messing up the print settings.
400 const char *olddriver=stp_get_driver(stpvars);
401 Debug[TRACE] << "Checking olddriver" << endl;
402 if(!olddriver)
403 olddriver="None";
404 Debug[TRACE] << "Checking driver" << endl;
405 if(!driver)
406 driver=DEFAULT_PRINTER_DRIVER;
407 Debug[TRACE] << "Comparing drivers:" << olddriver << " against " << driver << endl;
408 if(strcmp(driver,olddriver)==0) // If the driver hasn't changed...
409 {
410 // We ensure we can get the printer. If we can't, chances are the Gutenprint
411 // data files weren't loaded correctly.
412 if(!stp_get_printer(stpvars))
413 throw _("Can't obtain printer from Gutenprint\nCheck STP_DATA_PATH and Gutenprint version!");
414 }
415 else
416 {
417 driverchanged=true;
418 Debug[TRACE] << "SetDriver(): Setting driver to " << driver << endl;
419
420 // Work around the non-defaulting of inactive settings...
421 const stp_vars_t *defaults=stp_default_settings();
422 stp_vars_copy(stpvars,defaults);
423
424 stp_set_driver(stpvars,driver);
425 output.SetString("Driver",driver);
426
427 const stp_printer_t *printer=stp_get_printer(stpvars);
428 Debug[TRACE] << "Checking printer" << endl;
429 if(printer)
430 {
431 Debug[TRACE] << "Setting defaults" << endl;
432 stp_set_printer_defaults(stpvars,printer);
433 }
434 else
435 {
436 Debug[TRACE] << "Unable to get printer - reverting to default driver" << endl;
437 output.SetString("Driver",DEFAULT_PRINTER_DRIVER);
438 stp_set_driver(stpvars,DEFAULT_PRINTER_DRIVER);
439 Debug[TRACE] << "Checking printer again" << endl;
440 if((printer=stp_get_printer(stpvars)))
441 stp_set_printer_defaults(stpvars,printer);
442 else
443 Debug[TRACE] << "Still can't get printer!" << endl;
444 result=false;
445 }
446 }
447 stp_set_page_width(stpvars,pagewidth);
448 stp_set_page_height(stpvars,pageheight);
449
450
451 stp_parameter_t desc;
452 desc.is_active=false;
453 stp_describe_parameter(stpvars,"PPDFile",&desc);
454 if(desc.is_active)
455 {
456 driverchanged=true;
457 Debug[TRACE] << "Getting default PPD..." << endl;
458 char *defppd=output.GetPPD();
459 Debug[TRACE] << "Checking defppd" << endl;
460 if(defppd)
461 {
462 Debug[TRACE] << "Setting PPDFile to " << defppd << endl;
463 stp_set_file_parameter(stpvars,"PPDFile",defppd);
464 free(defppd);
465
466 Debug[TRACE] << "Checking ppdsizes_workaround_done" << endl;
467 if(!ppdsizes_workaround_done)
468 {
469 stp_parameter_t desc2;
470 stp_describe_parameter(stpvars,"PageSize",&desc2);
471 Debug[TRACE] << "After setting PPD Default page size is now: " << desc2.deflt.str << endl;
472 stp_set_string_parameter(stpvars,"PageSize",desc2.deflt.str);
473 stp_parameter_description_destroy(&desc2);
474 ppdsizes_workaround_done=true;
475 }
476 }
477 }
478 stp_parameter_description_destroy(&desc);
479
480 if(driverchanged)
481 {
482 // We attempt to set the previously used pagesize if possible.
483 // We do this by looping through the known papersizes for the
484 // new driver and comparing against the old papersize.
485 if(oldpagesize)
486 {
487 Debug[TRACE] << "Old page size is: " << oldpagesize << endl;
488 stp_describe_parameter(stpvars,"PageSize",&desc);
489 stp_string_list_t *strlist=desc.bounds.str;
490 if(strlist)
491 {
492 int strcount=stp_string_list_count(strlist);
493 for(int j=0;j<strcount;++j)
494 {
495 stp_param_string_t *p=stp_string_list_param(strlist,j);
496 Debug[TRACE] << "Comparing against " << p->text << endl;
497 if(strcmp(p->text,oldpagesize)==0)
498 {
499 stp_set_string_parameter(stpvars,"PageSize",oldpagesize);
500 j=strcount;
501 }
502 }
503 }
504 stp_parameter_description_destroy(&desc);
505 free(oldpagesize);
506 }
507
508 Validate();
509 }
510 }
511 else
512 Debug[TRACE] << "No stp vars!" << endl;
513 return(result);
514 }
515
516
Validate()517 void GPrinterSettings::Validate()
518 {
519 stputil_validate_parameters(stpvars);
520 }
521
522
Reset()523 void GPrinterSettings::Reset()
524 {
525 stp_vars_destroy(stpvars);
526 stpvars=stp_vars_create();
527 // FIXME - a bit of a hack this - set the driver so we can compare against it.
528 // (We set the queue's own driver here in case the app doesn't over-ride it
529 // Make sure this doesn't break anything...)
530 const char *driver=output.FindString("Driver");
531 if(!SetDriver(driver))
532 output.SetString("Driver",DEFAULT_PRINTER_DRIVER);
533 // stp_set_driver(stpvars,"ps");
534
535 Debug[TRACE] << "Created fresh stp_vars" << endl;
536 initialised=false;
537 }
538