1/* 2 * "$Id: printers.c,v 1.89 2010/08/07 02:30:38 rlk Exp $" 3 * 4 * Print plug-in driver utility functions for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com) and 7 * Robert Krawitz (rlk@alum.mit.edu) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 */ 23 24/* 25 * This file must include only standard C header files. The core code must 26 * compile on generic platforms that don't support glib, gimp, gtk, etc. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <gutenprint/gutenprint.h> 33#include "gutenprint-internal.h" 34#include <gutenprint/gutenprint-intl-internal.h> 35#include <math.h> 36#ifdef HAVE_LIMITS_H 37#include <limits.h> 38#endif 39#include <string.h> 40#include <stdlib.h> 41 42#define FMIN(a, b) ((a) < (b) ? (a) : (b)) 43 44 45static void stpi_printvars_freefunc(void *item); 46static const char* stpi_printvars_namefunc(const void *item); 47 48static stp_list_t *printvars_list = NULL; 49 50typedef struct stp_printvars 51{ 52 const char *name; 53 stp_vars_t *printvars; 54} stp_printvars_t; 55 56static void stpi_printer_freefunc(void *item); 57static const char* stpi_printer_namefunc(const void *item); 58static const char* stpi_printer_long_namefunc(const void *item); 59 60static stp_list_t *printer_list = NULL; 61 62struct stp_printer 63{ 64 const char *driver; 65 char *long_name; /* Long name for UI */ 66 char *family; /* Printer family */ 67 char *manufacturer; /* Printer manufacturer */ 68 char *device_id; /* IEEE 1284 device ID */ 69 char *foomatic_id; /* Foomatic printer ID */ 70 int model; /* Model number */ 71 int vars_initialized; 72 const stp_printfuncs_t *printfuncs; 73 stp_vars_t *printvars; 74}; 75 76static void 77stpi_init_printvars_list(void) 78{ 79 if (!printvars_list) 80 { 81 printvars_list = stp_list_create(); 82 stp_list_set_freefunc(printvars_list, stpi_printvars_freefunc); 83 stp_list_set_namefunc(printvars_list, stpi_printvars_namefunc); 84 stp_list_set_long_namefunc(printvars_list, stpi_printvars_namefunc); 85 } 86} 87 88static int 89stpi_init_printer_list(void) 90{ 91 if(printer_list) 92 stp_list_destroy(printer_list); 93 printer_list = stp_list_create(); 94 stp_list_set_freefunc(printer_list, stpi_printer_freefunc); 95 stp_list_set_namefunc(printer_list, stpi_printer_namefunc); 96 stp_list_set_long_namefunc(printer_list, stpi_printer_long_namefunc); 97 /* stp_list_set_sortfunc(printer_list, stpi_printer_sortfunc); */ 98 return 0; 99} 100 101int 102stp_printer_model_count(void) 103{ 104 if (printer_list == NULL) 105 { 106 stp_erprintf("No printer drivers found: " 107 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 108 stpi_init_printer_list(); 109 } 110 return stp_list_get_length(printer_list); 111} 112 113const stp_printer_t * 114stp_get_printer_by_index(int idx) 115{ 116 stp_list_item_t *printer; 117 if (printer_list == NULL) 118 { 119 stp_erprintf("No printer drivers found: " 120 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 121 stpi_init_printer_list(); 122 } 123 printer = stp_list_get_item_by_index(printer_list, idx); 124 if (printer == NULL) 125 return NULL; 126 return (const stp_printer_t *) stp_list_item_get_data(printer); 127} 128 129static void 130stpi_printer_freefunc(void *item) 131{ 132 stp_printer_t *printer = (stp_printer_t *) item; 133 stp_free(printer->long_name); 134 stp_free(printer->family); 135 stp_free(printer); 136} 137 138/* ARGSUSED */ 139static void 140stpi_printvars_freefunc(void *item) 141{ 142} 143 144static const char * 145stpi_printvars_namefunc(const void *item) 146{ 147 const stp_printvars_t *printvars = (const stp_printvars_t *) item; 148 return printvars->name; 149} 150 151const char * 152stp_printer_get_driver(const stp_printer_t *printer) 153{ 154 return printer->driver; 155} 156 157static const char * 158stpi_printer_namefunc(const void *item) 159{ 160 const stp_printer_t *printer = (const stp_printer_t *) item; 161 return printer->driver; 162} 163 164const char * 165stp_printer_get_long_name(const stp_printer_t *printer) 166{ 167 return printer->long_name; 168} 169 170static const char * 171stpi_printer_long_namefunc(const void *item) 172{ 173 const stp_printer_t *printer = (const stp_printer_t *) item; 174 return printer->long_name; 175} 176 177const char * 178stp_printer_get_device_id(const stp_printer_t *printer) 179{ 180 return printer->device_id; 181} 182 183const char * 184stp_printer_get_family(const stp_printer_t *printer) 185{ 186 return printer->family; 187} 188 189const char * 190stp_printer_get_manufacturer(const stp_printer_t *printer) 191{ 192 return printer->manufacturer; 193} 194 195const char * 196stp_printer_get_foomatic_id(const stp_printer_t *printer) 197{ 198 return printer->foomatic_id; 199} 200 201int 202stp_printer_get_model(const stp_printer_t *printer) 203{ 204 return printer->model; 205} 206 207static inline const stp_printfuncs_t * 208stpi_get_printfuncs(const stp_printer_t *printer) 209{ 210 return printer->printfuncs; 211} 212 213 214const stp_printer_t * 215stp_get_printer_by_long_name(const char *long_name) 216{ 217 stp_list_item_t *printer_item; 218 if (printer_list == NULL) 219 { 220 stp_erprintf("No printer drivers found: " 221 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 222 stpi_init_printer_list(); 223 } 224 printer_item = stp_list_get_item_by_long_name(printer_list, long_name); 225 if (!printer_item) 226 return NULL; 227 return (const stp_printer_t *) stp_list_item_get_data(printer_item); 228} 229 230const stp_printer_t * 231stp_get_printer_by_driver(const char *driver) 232{ 233 stp_list_item_t *printer_item; 234 if (printer_list == NULL) 235 { 236 stp_erprintf("No printer drivers found: " 237 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 238 stpi_init_printer_list(); 239 } 240 printer_item = stp_list_get_item_by_name(printer_list, driver); 241 if (!printer_item) 242 return NULL; 243 return (const stp_printer_t *) stp_list_item_get_data(printer_item); 244} 245 246const stp_printer_t * 247stp_get_printer_by_device_id(const char *device_id) 248{ 249 stp_list_item_t *printer_item; 250 if (printer_list == NULL) 251 { 252 stp_erprintf("No printer drivers found: " 253 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 254 stpi_init_printer_list(); 255 } 256 if (! device_id || strcmp(device_id, "") == 0) 257 return NULL; 258 259 printer_item = stp_list_get_start(printer_list); 260 while (printer_item) 261 { 262 if (strcmp(((const stp_printer_t *) stp_list_item_get_data(printer_item))->device_id, 263 device_id) == 0) 264 return ((const stp_printer_t *) stp_list_item_get_data(printer_item)); 265 printer_item = stp_list_item_next(printer_item); 266 } 267 return NULL; 268} 269 270const stp_printer_t * 271stp_get_printer_by_foomatic_id(const char *foomatic_id) 272{ 273 stp_list_item_t *printer_item; 274 if (printer_list == NULL) 275 { 276 stp_erprintf("No printer drivers found: " 277 "are STP_DATA_PATH and STP_MODULE_PATH correct?\n"); 278 stpi_init_printer_list(); 279 } 280 if (! foomatic_id || strcmp(foomatic_id, "") == 0) 281 return NULL; 282 283 printer_item = stp_list_get_start(printer_list); 284 while (printer_item) 285 { 286 if (strcmp(((const stp_printer_t *) stp_list_item_get_data(printer_item))->foomatic_id, 287 foomatic_id) == 0) 288 return ((const stp_printer_t *) stp_list_item_get_data(printer_item)); 289 printer_item = stp_list_item_next(printer_item); 290 } 291 return NULL; 292} 293 294int 295stp_get_printer_index_by_driver(const char *driver) 296{ 297 /* There should be no need to ever know the index! */ 298 int idx = 0; 299 for (idx = 0; idx < stp_printer_model_count(); idx++) 300 { 301 const stp_printer_t *printer = stp_get_printer_by_index(idx); 302 if (!strcmp(stp_printer_get_driver(printer), driver)) 303 return idx; 304 } 305 return -1; 306} 307 308const stp_printer_t * 309stp_get_printer(const stp_vars_t *v) 310{ 311 return stp_get_printer_by_driver(stp_get_driver(v)); 312} 313 314int 315stp_get_model_id(const stp_vars_t *v) 316{ 317 const stp_printer_t *printer = stp_get_printer_by_driver(stp_get_driver(v)); 318 return printer->model; 319} 320 321stp_parameter_list_t 322stp_printer_list_parameters(const stp_vars_t *v) 323{ 324 const stp_printfuncs_t *printfuncs = 325 stpi_get_printfuncs(stp_get_printer(v)); 326 return (printfuncs->list_parameters)(v); 327} 328 329void 330stp_printer_describe_parameter(const stp_vars_t *v, const char *name, 331 stp_parameter_t *description) 332{ 333 const stp_printfuncs_t *printfuncs = 334 stpi_get_printfuncs(stp_get_printer(v)); 335 (printfuncs->parameters)(v, name, description); 336} 337 338static void 339set_printer_defaults(stp_vars_t *v, int core_only, int soft) 340{ 341 stp_parameter_list_t *params; 342 int count; 343 int i; 344 stp_parameter_t desc; 345 params = stp_get_parameter_list(v); 346 count = stp_parameter_list_count(params); 347 for (i = 0; i < count; i++) 348 { 349 const stp_parameter_t *p = stp_parameter_list_param(params, i); 350 if (p->is_mandatory && 351 (!core_only || p->p_class == STP_PARAMETER_CLASS_CORE)) 352 { 353 stp_describe_parameter(v, p->name, &desc); 354 switch (p->p_type) 355 { 356 case STP_PARAMETER_TYPE_STRING_LIST: 357 if (!soft || 358 !stp_check_string_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 359 { 360 stp_set_string_parameter(v, p->name, desc.deflt.str); 361 stp_set_string_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 362 } 363 break; 364 case STP_PARAMETER_TYPE_DOUBLE: 365 if (!soft || 366 !stp_check_float_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 367 { 368 stp_set_float_parameter(v, p->name, desc.deflt.dbl); 369 stp_set_float_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 370 } 371 break; 372 case STP_PARAMETER_TYPE_INT: 373 if (!soft || 374 !stp_check_int_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 375 { 376 stp_set_int_parameter(v, p->name, desc.deflt.integer); 377 stp_set_int_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 378 } 379 break; 380 case STP_PARAMETER_TYPE_DIMENSION: 381 if (!soft || 382 !stp_check_dimension_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 383 { 384 stp_set_dimension_parameter(v, p->name, desc.deflt.dimension); 385 stp_set_dimension_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 386 } 387 break; 388 case STP_PARAMETER_TYPE_BOOLEAN: 389 if (!soft || 390 !stp_check_boolean_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 391 { 392 stp_set_boolean_parameter(v, p->name, desc.deflt.boolean); 393 stp_set_boolean_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 394 } 395 break; 396 case STP_PARAMETER_TYPE_CURVE: 397 if (!soft || 398 !stp_check_curve_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 399 { 400 stp_set_curve_parameter(v, p->name, desc.deflt.curve); 401 stp_set_curve_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 402 } 403 break; 404 case STP_PARAMETER_TYPE_ARRAY: 405 if (!soft || 406 !stp_check_array_parameter(v, p->name, STP_PARAMETER_DEFAULTED)) 407 { 408 stp_set_array_parameter(v, p->name, desc.deflt.array); 409 stp_set_array_parameter_active(v, p->name, STP_PARAMETER_ACTIVE); 410 } 411 break; 412 default: 413 break; 414 } 415 stp_parameter_description_destroy(&desc); 416 } 417 } 418 stp_parameter_list_destroy(params); 419} 420 421void 422stp_set_printer_defaults(stp_vars_t *v, const stp_printer_t *printer) 423{ 424 stp_set_driver(v, stp_printer_get_driver(printer)); 425 set_printer_defaults(v, 0, 0); 426} 427 428void 429stp_set_printer_defaults_soft(stp_vars_t *v, const stp_printer_t *printer) 430{ 431 stp_set_driver(v, stp_printer_get_driver(printer)); 432 set_printer_defaults(v, 0, 1); 433} 434 435void 436stp_initialize_printer_defaults(void) 437{ 438 if (printer_list == NULL) 439 { 440 stpi_init_printer_list(); 441 stp_deprintf 442 (STP_DBG_PRINTERS, 443 "stpi_family_register(): initialising printer_list...\n"); 444 } 445} 446 447const stp_vars_t * 448stp_printer_get_defaults(const stp_printer_t *printer) 449{ 450 if (! printer->vars_initialized) 451 { 452 stp_printer_t *nc_printer = (stp_printer_t *) printer; 453 stp_deprintf(STP_DBG_PRINTERS, " ==>init %s\n", printer->driver); 454 set_printer_defaults (nc_printer->printvars, 1, 0); 455 nc_printer->vars_initialized = 1; 456 } 457 return printer->printvars; 458} 459 460void 461stp_get_media_size(const stp_vars_t *v, int *width, int *height) 462{ 463 const stp_printfuncs_t *printfuncs = 464 stpi_get_printfuncs(stp_get_printer(v)); 465 (printfuncs->media_size)(v, width, height); 466} 467 468void 469stp_get_imageable_area(const stp_vars_t *v, 470 int *left, int *right, int *bottom, int *top) 471{ 472 const stp_printfuncs_t *printfuncs = 473 stpi_get_printfuncs(stp_get_printer(v)); 474 (printfuncs->imageable_area)(v, left, right, bottom, top); 475} 476 477void 478stp_get_maximum_imageable_area(const stp_vars_t *v, 479 int *left, int *right, int *bottom, int *top) 480{ 481 const stp_printfuncs_t *printfuncs = 482 stpi_get_printfuncs(stp_get_printer(v)); 483 (printfuncs->maximum_imageable_area)(v, left, right, bottom, top); 484} 485 486void 487stp_get_size_limit(const stp_vars_t *v, int *max_width, int *max_height, 488 int *min_width, int *min_height) 489{ 490 const stp_printfuncs_t *printfuncs = 491 stpi_get_printfuncs(stp_get_printer(v)); 492 (printfuncs->limit)(v, max_width, max_height, min_width,min_height); 493} 494 495void 496stp_describe_resolution(const stp_vars_t *v, int *x, int *y) 497{ 498 const stp_printfuncs_t *printfuncs = 499 stpi_get_printfuncs(stp_get_printer(v)); 500 (printfuncs->describe_resolution)(v, x, y); 501} 502 503const char * 504stp_describe_output(const stp_vars_t *v) 505{ 506 const stp_printfuncs_t *printfuncs = 507 stpi_get_printfuncs(stp_get_printer(v)); 508 return (printfuncs->describe_output)(v); 509} 510 511int 512stp_verify(stp_vars_t *v) 513{ 514 const stp_printfuncs_t *printfuncs = 515 stpi_get_printfuncs(stp_get_printer(v)); 516 stp_vars_t *nv = stp_vars_create_copy(v); 517 int status; 518 stp_prune_inactive_options(nv); 519 status = (printfuncs->verify)(nv); 520 stp_set_verified(v, stp_get_verified(nv)); 521 stp_vars_destroy(nv); 522 return status; 523} 524 525int 526stp_print(const stp_vars_t *v, stp_image_t *image) 527{ 528 const stp_printfuncs_t *printfuncs = 529 stpi_get_printfuncs(stp_get_printer(v)); 530 return (printfuncs->print)(v, image); 531} 532 533int 534stp_start_job(const stp_vars_t *v, stp_image_t *image) 535{ 536 const stp_printfuncs_t *printfuncs = 537 stpi_get_printfuncs(stp_get_printer(v)); 538 if (!stp_get_string_parameter(v, "JobMode") || 539 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0) 540 return 1; 541 if (printfuncs->start_job) 542 return (printfuncs->start_job)(v, image); 543 else 544 return 1; 545} 546 547int 548stp_end_job(const stp_vars_t *v, stp_image_t *image) 549{ 550 const stp_printfuncs_t *printfuncs = 551 stpi_get_printfuncs(stp_get_printer(v)); 552 if (!stp_get_string_parameter(v, "JobMode") || 553 strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0) 554 return 1; 555 if (printfuncs->end_job) 556 return (printfuncs->end_job)(v, image); 557 else 558 return 1; 559} 560 561stp_string_list_t * 562stp_get_external_options(const stp_vars_t *v) 563{ 564 const stp_printfuncs_t *printfuncs = 565 stpi_get_printfuncs(stp_get_printer(v)); 566 if (printfuncs->get_external_options) 567 return (printfuncs->get_external_options)(v); 568 else 569 return NULL; 570} 571 572static int 573verify_string_param(const stp_vars_t *v, const char *parameter, 574 stp_parameter_t *desc, int quiet) 575{ 576 stp_parameter_verify_t answer = PARAMETER_OK; 577 stp_dprintf(STP_DBG_VARS, v, " Verifying string %s\n", parameter); 578 if (desc->is_mandatory || 579 stp_check_string_parameter(v, parameter, STP_PARAMETER_ACTIVE)) 580 { 581 const char *checkval = stp_get_string_parameter(v, parameter); 582 stp_string_list_t *vptr = desc->bounds.str; 583 size_t count = 0; 584 int i; 585 stp_dprintf(STP_DBG_VARS, v, " value %s\n", 586 checkval ? checkval : "(null)"); 587 if (vptr) 588 count = stp_string_list_count(vptr); 589 answer = PARAMETER_BAD; 590 if (checkval == NULL) 591 { 592 if (count == 0) 593 answer = PARAMETER_OK; 594 else 595 { 596 if (!quiet) 597 stp_eprintf(v, _("Value must be set for %s\n"), parameter); 598 answer = PARAMETER_BAD; 599 } 600 } 601 else if (count > 0) 602 { 603 for (i = 0; i < count; i++) 604 if (!strcmp(checkval, stp_string_list_param(vptr, i)->name)) 605 { 606 answer = PARAMETER_OK; 607 break; 608 } 609 if (!answer && !quiet) 610 stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter); 611 } 612 else if (strlen(checkval) == 0) 613 answer = PARAMETER_OK; 614 else if (!quiet) 615 stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter); 616 } 617 stp_parameter_description_destroy(desc); 618 return answer; 619} 620 621static int 622verify_double_param(const stp_vars_t *v, const char *parameter, 623 stp_parameter_t *desc, int quiet) 624{ 625 stp_dprintf(STP_DBG_VARS, v, " Verifying double %s\n", parameter); 626 if (desc->is_mandatory || 627 stp_check_float_parameter(v, parameter, STP_PARAMETER_ACTIVE)) 628 { 629 double checkval = stp_get_float_parameter(v, parameter); 630 if (checkval < desc->bounds.dbl.lower || 631 checkval > desc->bounds.dbl.upper) 632 { 633 if (!quiet) 634 stp_eprintf(v, _("%s must be between %f and %f (is %f)\n"), 635 parameter, desc->bounds.dbl.lower, 636 desc->bounds.dbl.upper, checkval); 637 return PARAMETER_BAD; 638 } 639 } 640 return PARAMETER_OK; 641} 642 643static int 644verify_int_param(const stp_vars_t *v, const char *parameter, 645 stp_parameter_t *desc, int quiet) 646{ 647 stp_dprintf(STP_DBG_VARS, v, " Verifying int %s\n", parameter); 648 if (desc->is_mandatory || 649 stp_check_int_parameter(v, parameter, STP_PARAMETER_ACTIVE)) 650 { 651 int checkval = stp_get_int_parameter(v, parameter); 652 if (checkval < desc->bounds.integer.lower || 653 checkval > desc->bounds.integer.upper) 654 { 655 if (!quiet) 656 stp_eprintf(v, _("%s must be between %d and %d (is %d)\n"), 657 parameter, desc->bounds.integer.lower, 658 desc->bounds.integer.upper, checkval); 659 stp_parameter_description_destroy(desc); 660 return PARAMETER_BAD; 661 } 662 } 663 stp_parameter_description_destroy(desc); 664 return PARAMETER_OK; 665} 666 667static int 668verify_dimension_param(const stp_vars_t *v, const char *parameter, 669 stp_parameter_t *desc, int quiet) 670{ 671 stp_dprintf(STP_DBG_VARS, v, " Verifying dimension %s\n", parameter); 672 if (desc->is_mandatory || 673 stp_check_dimension_parameter(v, parameter, STP_PARAMETER_ACTIVE)) 674 { 675 int checkval = stp_get_dimension_parameter(v, parameter); 676 if (checkval < desc->bounds.dimension.lower || 677 checkval > desc->bounds.dimension.upper) 678 { 679 if (!quiet) 680 stp_eprintf(v, _("%s must be between %d and %d (is %d)\n"), 681 parameter, desc->bounds.dimension.lower, 682 desc->bounds.dimension.upper, checkval); 683 stp_parameter_description_destroy(desc); 684 return PARAMETER_BAD; 685 } 686 } 687 stp_parameter_description_destroy(desc); 688 return PARAMETER_OK; 689} 690 691static int 692verify_curve_param(const stp_vars_t *v, const char *parameter, 693 stp_parameter_t *desc, int quiet) 694{ 695 stp_parameter_verify_t answer = 1; 696 stp_dprintf(STP_DBG_VARS, v, " Verifying curve %s\n", parameter); 697 if (desc->bounds.curve && 698 (desc->is_mandatory || 699 stp_check_curve_parameter(v, parameter, STP_PARAMETER_ACTIVE))) 700 { 701 const stp_curve_t *checkval = stp_get_curve_parameter(v, parameter); 702 if (checkval) 703 { 704 double u0, l0; 705 double u1, l1; 706 stp_curve_get_bounds(checkval, &l0, &u0); 707 stp_curve_get_bounds(desc->bounds.curve, &l1, &u1); 708 if (u0 > u1 || l0 < l1) 709 { 710 if (!quiet) 711 stp_eprintf(v, _("%s bounds must be between %f and %f\n"), 712 parameter, l1, u1); 713 answer = PARAMETER_BAD; 714 } 715 if (stp_curve_get_wrap(checkval) != 716 stp_curve_get_wrap(desc->bounds.curve)) 717 { 718 if (!quiet) 719 stp_eprintf(v, _("%s wrap mode must be %s\n"), 720 parameter, 721 (stp_curve_get_wrap(desc->bounds.curve) == 722 STP_CURVE_WRAP_NONE) ? 723 _("no wrap") : _("wrap around")); 724 answer = PARAMETER_BAD; 725 } 726 } 727 } 728 stp_parameter_description_destroy(desc); 729 return answer; 730} 731 732stp_parameter_verify_t 733stp_verify_parameter(const stp_vars_t *v, const char *parameter, 734 int quiet) 735{ 736 stp_parameter_t desc; 737 quiet = 0; 738 stp_describe_parameter(v, parameter, &desc); 739 stp_dprintf(STP_DBG_VARS, v, " Verifying %s %d %d\n", parameter, 740 desc.is_active, desc.read_only); 741 if (!desc.is_active || desc.read_only) 742 { 743 stp_parameter_description_destroy(&desc); 744 return PARAMETER_INACTIVE; 745 } 746 switch (desc.p_type) 747 { 748 case STP_PARAMETER_TYPE_STRING_LIST: 749 return verify_string_param(v, parameter, &desc, quiet); 750 case STP_PARAMETER_TYPE_DOUBLE: 751 return verify_double_param(v, parameter, &desc, quiet); 752 case STP_PARAMETER_TYPE_INT: 753 return verify_int_param(v, parameter, &desc, quiet); 754 case STP_PARAMETER_TYPE_DIMENSION: 755 return verify_dimension_param(v, parameter, &desc, quiet); 756 case STP_PARAMETER_TYPE_CURVE: 757 return verify_curve_param(v, parameter, &desc, quiet); 758 case STP_PARAMETER_TYPE_RAW: 759 case STP_PARAMETER_TYPE_FILE: 760 stp_parameter_description_destroy(&desc); 761 return PARAMETER_OK; /* No way to verify this here */ 762 case STP_PARAMETER_TYPE_BOOLEAN: 763 stp_parameter_description_destroy(&desc); 764 return PARAMETER_OK; /* Booleans always OK */ 765 default: 766 if (!quiet) 767 stp_eprintf(v, _("Unknown type parameter %s (%d)\n"), 768 parameter, desc.p_type); 769 stp_parameter_description_destroy(&desc); 770 return 0; 771 } 772} 773 774#define CHECK_INT_RANGE(v, component, min, max) \ 775do \ 776{ \ 777 if (stp_get_##component((v)) < (min) || stp_get_##component((v)) > (max)) \ 778 { \ 779 answer = 0; \ 780 stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"), \ 781 #component, stp_get_##component(v), min, max); \ 782 } \ 783} while (0) 784 785#define CHECK_INT_RANGE_INTERNAL(v, component, min, max) \ 786do \ 787{ \ 788 if (stpi_get_##component((v)) < (min) || stpi_get_##component((v)) > (max)) \ 789 { \ 790 answer = 0; \ 791 stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"), \ 792 #component, stpi_get_##component(v), min, max); \ 793 } \ 794} while (0) 795 796typedef struct 797{ 798 char *data; 799 size_t bytes; 800} errbuf_t; 801 802static void 803fill_buffer_writefunc(void *priv, const char *buffer, size_t bytes) 804{ 805 errbuf_t *errbuf = (errbuf_t *) priv; 806 if (errbuf->bytes == 0) 807 errbuf->data = stp_malloc(bytes + 1); 808 else 809 errbuf->data = stp_realloc(errbuf->data, errbuf->bytes + bytes + 1); 810 memcpy(errbuf->data + errbuf->bytes, buffer, bytes); 811 errbuf->bytes += bytes; 812 errbuf->data[errbuf->bytes] = '\0'; 813} 814 815int 816stp_verify_printer_params(stp_vars_t *v) 817{ 818 errbuf_t errbuf; 819 stp_outfunc_t ofunc = stp_get_errfunc(v); 820 void *odata = stp_get_errdata(v); 821 stp_parameter_list_t params; 822 int nparams; 823 int i; 824 int answer = 1; 825 int left, top, bottom, right; 826 const char *pagesize = stp_get_string_parameter(v, "PageSize"); 827 828 stp_dprintf(STP_DBG_VARS, v, "** Entering stp_verify_printer_params(0x%p)\n", 829 (void *) v); 830 831 stp_set_errfunc((stp_vars_t *) v, fill_buffer_writefunc); 832 stp_set_errdata((stp_vars_t *) v, &errbuf); 833 834 errbuf.data = NULL; 835 errbuf.bytes = 0; 836 837 if (pagesize && strlen(pagesize) > 0) 838 { 839 if (stp_verify_parameter(v, "PageSize", 0) == 0) 840 answer = 0; 841 } 842 else 843 { 844 int width, height, min_height, min_width; 845 stp_get_size_limit(v, &width, &height, &min_width, &min_height); 846 if (stp_get_page_height(v) <= min_height || 847 stp_get_page_height(v) > height || 848 stp_get_page_width(v) <= min_width || stp_get_page_width(v) > width) 849 { 850 answer = 0; 851 stp_eprintf(v, _("Page size is not valid\n")); 852 } 853 stp_dprintf(STP_DBG_PAPER, v, 854 "page size max %d %d min %d %d actual %d %d\n", 855 width, height, min_width, min_height, 856 stp_get_page_width(v), stp_get_page_height(v)); 857 } 858 859 stp_get_imageable_area(v, &left, &right, &bottom, &top); 860 861 stp_dprintf(STP_DBG_PAPER, v, 862 "page left %d top %d right %d bottom %d\n", 863 left, top, right, bottom); 864 stp_dprintf(STP_DBG_PAPER, v, 865 "requested left %d top %d width %d height %d\n", 866 stp_get_left(v), stp_get_top(v), 867 stp_get_width(v), stp_get_height(v)); 868 869 if (stp_get_top(v) < top) 870 { 871 answer = 0; 872 stp_eprintf(v, _("Top margin must not be less than %d\n"), top); 873 } 874 875 if (stp_get_left(v) < left) 876 { 877 answer = 0; 878 stp_eprintf(v, _("Left margin must not be less than %d\n"), left); 879 } 880 881 if (stp_get_height(v) <= 0) 882 { 883 answer = 0; 884 stp_eprintf(v, _("Height must be greater than zero\n")); 885 } 886 887 if (stp_get_width(v) <= 0) 888 { 889 answer = 0; 890 stp_eprintf(v, _("Width must be greater than zero\n")); 891 } 892 893 if (stp_get_left(v) + stp_get_width(v) > right) 894 { 895 answer = 0; 896 stp_eprintf(v, _("Image is too wide for the page: left margin is %d, width %d, right edge is %d\n"), 897 stp_get_left(v), stp_get_width(v), right); 898 } 899 900 if (stp_get_top(v) + stp_get_height(v) > bottom) 901 { 902 answer = 0; 903 stp_eprintf(v, _("Image is too long for the page: top margin is %d, height %d, bottom edge is %d\n"), 904 stp_get_top(v), stp_get_height(v), bottom); 905 } 906 907 params = stp_get_parameter_list(v); 908 nparams = stp_parameter_list_count(params); 909 for (i = 0; i < nparams; i++) 910 { 911 const stp_parameter_t *param = stp_parameter_list_param(params, i); 912 stp_dprintf(STP_DBG_VARS, v, "Checking %s %d %d\n", param->name, 913 param->is_active, param->verify_this_parameter); 914 915 if (strcmp(param->name, "PageSize") != 0 && 916 param->is_active && param->verify_this_parameter && 917 stp_verify_parameter(v, param->name, 0) == 0) 918 answer = 0; 919 } 920 stp_parameter_list_destroy(params); 921 stp_set_errfunc((stp_vars_t *) v, ofunc); 922 stp_set_errdata((stp_vars_t *) v, odata); 923 stp_set_verified((stp_vars_t *) v, answer); 924 if (errbuf.bytes > 0) 925 { 926 stp_eprintf(v, "%s", errbuf.data); 927 stp_free(errbuf.data); 928 } 929 stp_dprintf(STP_DBG_VARS, v, "** Exiting stp_verify_printer_params(0x%p) => %d\n", 930 (void *) v, answer); 931 return answer; 932} 933 934static const stp_vars_t * 935stp_find_params(const char *name, const char *family) 936{ 937 if (printvars_list) 938 { 939 char *stmp = 940 stp_malloc(strlen(family) + strlen("::") + strlen(name) + 1); 941 stp_list_item_t *item; 942 strcpy(stmp, family); 943 strcat(stmp, "::"); 944 strcat(stmp, name); 945 item = stp_list_get_item_by_name(printvars_list, stmp); 946 if (item) 947 { 948 stp_free(stmp); 949 return ((const stp_printvars_t *) 950 stp_list_item_get_data(item))->printvars; 951 } 952 strcpy(stmp, name); 953 item = stp_list_get_item_by_name(printvars_list, stmp); 954 stp_free(stmp); 955 if (item) 956 return ((const stp_printvars_t *) 957 stp_list_item_get_data(item))->printvars; 958 } 959 return NULL; 960} 961 962int 963stp_family_register(stp_list_t *family) 964{ 965 stp_list_item_t *printer_item; 966 const stp_printer_t *printer; 967 968 if (printer_list == NULL) 969 { 970 stpi_init_printer_list(); 971 stp_deprintf 972 (STP_DBG_PRINTERS, 973 "stpi_family_register(): initialising printer_list...\n"); 974 } 975 976 if (family) 977 { 978 printer_item = stp_list_get_start(family); 979 980 while(printer_item) 981 { 982 printer = (const stp_printer_t *) stp_list_item_get_data(printer_item); 983 if (!stp_list_get_item_by_name(printer_list, printer->driver)) 984 stp_list_item_create(printer_list, NULL, printer); 985 printer_item = stp_list_item_next(printer_item); 986 } 987 } 988 989 return 0; 990} 991 992int 993stp_family_unregister(stp_list_t *family) 994{ 995 stp_list_item_t *printer_item; 996 stp_list_item_t *old_printer_item; 997 const stp_printer_t *printer; 998 999 if (printer_list == NULL) 1000 { 1001 stpi_init_printer_list(); 1002 stp_deprintf 1003 (STP_DBG_PRINTERS, 1004 "stpi_family_unregister(): initialising printer_list...\n"); 1005 } 1006 1007 if (family) 1008 { 1009 printer_item = stp_list_get_start(family); 1010 1011 while(printer_item) 1012 { 1013 printer = (const stp_printer_t *) stp_list_item_get_data(printer_item); 1014 old_printer_item = 1015 stp_list_get_item_by_name(printer_list, printer->driver); 1016 1017 if (old_printer_item) 1018 stp_list_item_destroy(printer_list, old_printer_item); 1019 printer_item = stp_list_item_next(printer_item); 1020 } 1021 } 1022 return 0; 1023} 1024 1025static stp_printvars_t * 1026stp_printvars_create_from_xmltree(stp_mxml_node_t *printer, 1027 const char *family) 1028{ 1029 stp_mxml_node_t *prop; /* Temporary node pointer */ 1030 const char *stmp; /* Temporary string */ 1031 char *sbuf; 1032 stp_printvars_t *outprintvars; 1033 outprintvars = stp_zalloc(sizeof(stp_printvars_t)); 1034 if (!outprintvars) 1035 return NULL; 1036 outprintvars->printvars = stp_vars_create(); 1037 if (outprintvars->printvars == NULL) 1038 { 1039 stp_free(outprintvars); 1040 return NULL; 1041 } 1042 stmp = stp_mxmlElementGetAttr(printer, "name"); 1043 if (!stmp) 1044 { 1045 stp_vars_destroy(outprintvars->printvars); 1046 stp_free(outprintvars); 1047 return NULL; 1048 } 1049 sbuf = stp_malloc(strlen(family) + strlen("::") + strlen(stmp) + 1); 1050 strcpy(sbuf, family); 1051 strcat(sbuf, "::"); 1052 strcat(sbuf, stmp); 1053 outprintvars->name = sbuf; 1054 prop = printer->child; 1055 stp_deprintf(STP_DBG_XML, ">>stp_printvars_create_from_xmltree: %p, %s\n", 1056 (void *) (outprintvars->printvars), outprintvars->name); 1057 stp_vars_fill_from_xmltree(prop, outprintvars->printvars); 1058 stp_deprintf(STP_DBG_XML, "<<stp_printvars_create_from_xmltree: %p, %s\n", 1059 (void *) (outprintvars->printvars), outprintvars->name); 1060 return outprintvars; 1061} 1062 1063 1064/* 1065 * Parse the printer node, and return the generated printer. Returns 1066 * NULL on failure. 1067 */ 1068static stp_printer_t* 1069stp_printer_create_from_xmltree(stp_mxml_node_t *printer, /* The printer node */ 1070 const char *family, /* Family name */ 1071 const stp_printfuncs_t *printfuncs) 1072 /* Family printfuncs */ 1073{ 1074 stp_mxml_node_t *prop; /* Temporary node pointer */ 1075 const char *stmp; /* Temporary string */ 1076 stp_printer_t *outprinter; /* Generated printer */ 1077 int 1078 driver = 0, /* Check driver */ 1079 long_name = 0; 1080 1081 outprinter = stp_zalloc(sizeof(stp_printer_t)); 1082 if (!outprinter) 1083 return NULL; 1084 stmp = stp_mxmlElementGetAttr(printer, "parameters"); 1085 if (stmp && !stp_find_params(stmp, family)) 1086 stp_erprintf("stp_printer_create_from_xmltree: cannot find parameters %s::%s\n", 1087 family, stmp); 1088 if (stmp && stp_find_params(stmp, family)) 1089 outprinter->printvars = stp_vars_create_copy(stp_find_params(stmp, family)); 1090 else 1091 outprinter->printvars = stp_vars_create(); 1092 if (outprinter->printvars == NULL) 1093 { 1094 stp_free(outprinter); 1095 return NULL; 1096 } 1097 1098 stmp = stp_mxmlElementGetAttr(printer, "driver"); 1099 stp_set_driver(outprinter->printvars, (const char *) stmp); 1100 1101 outprinter->long_name = stp_strdup(stp_mxmlElementGetAttr(printer, "name")); 1102 outprinter->manufacturer = stp_strdup(stp_mxmlElementGetAttr(printer, "manufacturer")); 1103 outprinter->model = stp_xmlstrtol(stp_mxmlElementGetAttr(printer, "model")); 1104 outprinter->family = stp_strdup((const char *) family); 1105 stmp = stp_mxmlElementGetAttr(printer, "deviceid"); 1106 if (stmp) 1107 outprinter->device_id = stp_strdup(stmp); 1108 stmp = stp_mxmlElementGetAttr(printer, "foomaticid"); 1109 if (stmp) 1110 outprinter->foomatic_id = stp_strdup(stmp); 1111 1112 if (stp_get_driver(outprinter->printvars)) 1113 driver = 1; 1114 if (outprinter->long_name) 1115 long_name = 1; 1116 1117 outprinter->printfuncs = printfuncs; 1118 1119 prop = printer->child; 1120 stp_vars_fill_from_xmltree(prop, outprinter->printvars); 1121 if (driver && long_name && printfuncs) 1122 { 1123 if (stp_get_debug_level() & STP_DBG_XML) 1124 { 1125 stmp = stp_mxmlElementGetAttr(printer, "driver"); 1126 stp_erprintf("stp_printer_create_from_xmltree: printer: %s\n", stmp); 1127 } 1128 outprinter->driver = stp_get_driver(outprinter->printvars); 1129 return outprinter; 1130 } 1131 stp_free(outprinter); 1132 return NULL; 1133} 1134 1135/* 1136 * Parse the <family> node. 1137 */ 1138static void 1139stpi_xml_process_family(stp_mxml_node_t *family) /* The family node */ 1140{ 1141 stp_list_t *family_module_list = NULL; /* List of valid families */ 1142 stp_list_item_t *family_module_item; /* Current family */ 1143 const char *family_name; /* Name of family */ 1144 stp_mxml_node_t *printer; /* printer child node */ 1145 stp_module_t *family_module_data; /* Family module data */ 1146 stp_family_t *family_data = NULL; /* Family data */ 1147 int family_valid = 0; /* Is family valid? */ 1148 1149 family_module_list = stp_module_get_class(STP_MODULE_CLASS_FAMILY); 1150 if (!family_module_list) 1151 return; 1152 1153 family_name = stp_mxmlElementGetAttr(family, "name"); 1154 family_module_item = stp_list_get_start(family_module_list); 1155 while (family_module_item) 1156 { 1157 family_module_data = (stp_module_t *) 1158 stp_list_item_get_data(family_module_item); 1159 if (!strcmp(family_name, family_module_data->name)) 1160 { 1161 stp_deprintf(STP_DBG_XML, 1162 "stpi_xml_process_family: family module: %s\n", 1163 family_module_data->name); 1164 family_data = family_module_data->syms; 1165 if (family_data->printer_list == NULL) 1166 family_data->printer_list = stp_list_create(); 1167 family_valid = 1; 1168 } 1169 family_module_item = stp_list_item_next(family_module_item); 1170 } 1171 1172 printer = family->child; 1173 while (family_valid && printer) 1174 { 1175 if (printer->type == STP_MXML_ELEMENT) 1176 { 1177 const char *printer_name = printer->value.element.name; 1178 if (!strcmp(printer_name, "printer")) 1179 { 1180 stp_printer_t *outprinter = 1181 stp_printer_create_from_xmltree(printer, family_name, 1182 family_data->printfuncs); 1183 if (outprinter) 1184 stp_list_item_create(family_data->printer_list, NULL, 1185 outprinter); 1186 } 1187 else if (!strcmp(printer_name, "parameters")) 1188 { 1189 stp_printvars_t *printvars = 1190 stp_printvars_create_from_xmltree(printer, family_name); 1191 if (printvars) 1192 { 1193 stpi_init_printvars_list(); 1194 stp_list_item_create(printvars_list, NULL, printvars); 1195 } 1196 } 1197 } 1198 printer = printer->next; 1199 } 1200 1201 stp_list_destroy(family_module_list); 1202 return; 1203} 1204 1205/* 1206 * Parse the <printdef> node. 1207 */ 1208static int 1209stpi_xml_process_printdef(stp_mxml_node_t *printdef, const char *file) /* The printdef node */ 1210{ 1211 stp_mxml_node_t *family; /* Family child node */ 1212 1213 family = printdef->child; 1214 while (family) 1215 { 1216 if (family->type == STP_MXML_ELEMENT) 1217 { 1218 const char *family_name = family->value.element.name; 1219 if (!strcmp(family_name, "family")) 1220 { 1221 stpi_xml_process_family(family); 1222 } 1223 } 1224 family = family->next; 1225 } 1226 return 1; 1227} 1228 1229void 1230stpi_init_printer(void) 1231{ 1232 stp_register_xml_parser("printdef", stpi_xml_process_printdef); 1233 stp_register_xml_preload("printers.xml"); 1234} 1235