libgimpprint API Reference: src/main/printers.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/printers.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: printers_8c-source.html,v 1.1.1.2 2004/12/22 23:49:11 jlovell Exp $"
    00003  *
    00004  *   Print plug-in driver utility functions for the GIMP.
    00005  *
    00006  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
    00007  *      Robert Krawitz (rlk@alum.mit.edu)
    00008  *
    00009  *   This program is free software; you can redistribute it and/or modify it
    00010  *   under the terms of the GNU General Public License as published by the Free
    00011  *   Software Foundation; either version 2 of the License, or (at your option)
    00012  *   any later version.
    00013  *
    00014  *   This program is distributed in the hope that it will be useful, but
    00015  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00016  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00017  *   for more details.
    00018  *
    00019  *   You should have received a copy of the GNU General Public License
    00020  *   along with this program; if not, write to the Free Software
    00021  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00022  */
    00023
    00024 /*
    00025  * This file must include only standard C header files.  The core code must
    00026  * compile on generic platforms that don't support glib, gimp, gtk, etc.
    00027  */
    00028
    00029 #ifdef HAVE_CONFIG_H
    00030 #include <config.h>
    00031 #endif
    00032 #include <gimp-print/gimp-print.h>
    00033 #include "gimp-print-internal.h"
    00034 #include <gimp-print/gimp-print-intl-internal.h>
    00035 #include <math.h>
    00036 #ifdef HAVE_LIMITS_H
    00037 #include <limits.h>
    00038 #endif
    00039 #include <string.h>
    00040 #include <stdlib.h>
    00041
    00042 #define FMIN(a, b) ((a) < (b) ? (a) : (b))
    00043
    00044
    00045 static void stpi_printer_freefunc(void *item);
    00046 static const char* stpi_printer_namefunc(const void *item);
    00047 static const char* stpi_printer_long_namefunc(const void *item);
    00048
    00049 static stp_list_t *printer_list = NULL;
    00050
    00051 struct stp_printer
    00052 {
    00053   const char *driver;
    00054   char       *long_name;        /* Long name for UI */
    00055   char       *family;           /* Printer family */
    00056   char       *manufacturer;     /* Printer manufacturer */
    00057   int        model;             /* Model number */
    00058   const stp_printfuncs_t *printfuncs;
    00059   stp_vars_t *printvars;
    00060 };
    00061
    00062 static int
    00063 stpi_init_printer_list(void)
    00064 {
    00065   if(printer_list)
    00066     stp_list_destroy(printer_list);
    00067   printer_list = stp_list_create();
    00068   stp_list_set_freefunc(printer_list, stpi_printer_freefunc);
    00069   stp_list_set_namefunc(printer_list, stpi_printer_namefunc);
    00070   stp_list_set_long_namefunc(printer_list, stpi_printer_long_namefunc);
    00071   /* stp_list_set_sortfunc(printer_list, stpi_printer_sortfunc); */
    00072
    00073   return 0;
    00074 }
    00075
    00076 int
    00077 stp_printer_model_count(void)
    00078 {
    00079   if (printer_list == NULL)
    00080     {
    00081       stp_erprintf("No printer drivers found: "
    00082                    "are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
    00083       stpi_init_printer_list();
    00084     }
    00085   return stp_list_get_length(printer_list);
    00086 }
    00087
    00088 static void
    00089 null_printer(void)
    00090 {
    00091   stp_erprintf("Null stp_printer_t! Please report this bug.\n");
    00092   stp_abort();
    00093 }
    00094
    00095 static inline void
    00096 check_printer(const stp_printer_t *p)
    00097 {
    00098   if (p == NULL)
    00099     null_printer();
    00100 }
    00101
    00102 const stp_printer_t *
    00103 stp_get_printer_by_index(int idx)
    00104 {
    00105   stp_list_item_t *printer;
    00106   if (printer_list == NULL)
    00107     {
    00108       stp_erprintf("No printer drivers found: "
    00109                    "are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
    00110       stpi_init_printer_list();
    00111     }
    00112   printer = stp_list_get_item_by_index(printer_list, idx);
    00113   if (printer == NULL)
    00114     return NULL;
    00115   return (const stp_printer_t *) stp_list_item_get_data(printer);
    00116 }
    00117
    00118 static void
    00119 stpi_printer_freefunc(void *item)
    00120 {
    00121   stp_printer_t *printer = (stp_printer_t *) item;
    00122   stp_free(printer->long_name);
    00123   stp_free(printer->family);
    00124   stp_free(printer);
    00125 }
    00126
    00127 const char *
    00128 stp_printer_get_driver(const stp_printer_t *printer)
    00129 {
    00130   return printer->driver;
    00131 }
    00132
    00133 static const char *
    00134 stpi_printer_namefunc(const void *item)
    00135 {
    00136   const stp_printer_t *printer = (const stp_printer_t *) item;
    00137   return printer->driver;
    00138 }
    00139
    00140 const char *
    00141 stp_printer_get_long_name(const stp_printer_t *printer)
    00142 {
    00143   return printer->long_name;
    00144 }
    00145
    00146 static const char *
    00147 stpi_printer_long_namefunc(const void *item)
    00148 {
    00149   const stp_printer_t *printer = (const stp_printer_t *) item;
    00150   return printer->long_name;
    00151 }
    00152
    00153 const char *
    00154 stp_printer_get_family(const stp_printer_t *printer)
    00155 {
    00156   return printer->family;
    00157 }
    00158
    00159 const char *
    00160 stp_printer_get_manufacturer(const stp_printer_t *printer)
    00161 {
    00162   return printer->manufacturer;
    00163 }
    00164
    00165 int
    00166 stp_printer_get_model(const stp_printer_t *printer)
    00167 {
    00168   return printer->model;
    00169 }
    00170
    00171 static inline const stp_printfuncs_t *
    00172 stpi_get_printfuncs(const stp_printer_t *printer)
    00173 {
    00174   return printer->printfuncs;
    00175 }
    00176
    00177 const stp_vars_t *
    00178 stp_printer_get_defaults(const stp_printer_t *printer)
    00179 {
    00180   return printer->printvars;
    00181 }
    00182
    00183
    00184 const stp_printer_t *
    00185 stp_get_printer_by_long_name(const char *long_name)
    00186 {
    00187   stp_list_item_t *printer_item;
    00188   if (printer_list == NULL)
    00189     {
    00190       stp_erprintf("No printer drivers found: "
    00191                    "are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
    00192       stpi_init_printer_list();
    00193     }
    00194   printer_item = stp_list_get_item_by_long_name(printer_list, long_name);
    00195   if (!printer_item)
    00196     return NULL;
    00197   return (const stp_printer_t *) stp_list_item_get_data(printer_item);
    00198 }
    00199
    00200 const stp_printer_t *
    00201 stp_get_printer_by_driver(const char *driver)
    00202 {
    00203   stp_list_item_t *printer_item;
    00204   if (printer_list == NULL)
    00205     {
    00206       stp_erprintf("No printer drivers found: "
    00207                    "are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
    00208       stpi_init_printer_list();
    00209     }
    00210   printer_item = stp_list_get_item_by_name(printer_list, driver);
    00211   if (!printer_item)
    00212     return NULL;
    00213   return (const stp_printer_t *) stp_list_item_get_data(printer_item);
    00214 }
    00215
    00216 int
    00217 stp_get_printer_index_by_driver(const char *driver)
    00218 {
    00219   /* There should be no need to ever know the index! */
    00220   int idx = 0;
    00221   for (idx = 0; idx < stp_printer_model_count(); idx++)
    00222     {
    00223       const stp_printer_t *printer = stp_get_printer_by_index(idx);
    00224       if (!strcmp(stp_printer_get_driver(printer), driver))
    00225         return idx;
    00226     }
    00227   return -1;
    00228 }
    00229
    00230 const stp_printer_t *
    00231 stp_get_printer(const stp_vars_t *v)
    00232 {
    00233   return stp_get_printer_by_driver(stp_get_driver(v));
    00234 }
    00235
    00236 int
    00237 stp_get_model_id(const stp_vars_t *v)
    00238 {
    00239   const stp_printer_t *printer = stp_get_printer_by_driver(stp_get_driver(v));
    00240   return printer->model;
    00241 }
    00242
    00243 stp_parameter_list_t
    00244 stp_printer_list_parameters(const stp_vars_t *v)
    00245 {
    00246   const stp_printfuncs_t *printfuncs =
    00247     stpi_get_printfuncs(stp_get_printer(v));
    00248   return (printfuncs->list_parameters)(v);
    00249 }
    00250
    00251 void
    00252 stp_printer_describe_parameter(const stp_vars_t *v, const char *name,
    00253                                stp_parameter_t *description)
    00254 {
    00255   const stp_printfuncs_t *printfuncs =
    00256     stpi_get_printfuncs(stp_get_printer(v));
    00257   (printfuncs->parameters)(v, name, description);
    00258 }
    00259
    00260 static void
    00261 set_printer_defaults(stp_vars_t *v, int core_only)
    00262 {
    00263   stp_parameter_list_t *params;
    00264   int count;
    00265   int i;
    00266   stp_parameter_t desc;
    00267   params = stp_get_parameter_list(v);
    00268   count = stp_parameter_list_count(params);
    00269   for (i = 0; i < count; i++)
    00270     {
    00271       const stp_parameter_t *p = stp_parameter_list_param(params, i);
    00272       if (p->is_mandatory &&
    00273           (!core_only || p->p_class == STP_PARAMETER_CLASS_CORE))
    00274         {
    00275           stp_describe_parameter(v, p->name, &desc);
    00276           switch (p->p_type)
    00277             {
    00278             case STP_PARAMETER_TYPE_STRING_LIST:
    00279               stp_set_string_parameter(v, p->name, desc.deflt.str);
    00280               stp_set_string_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00281               break;
    00282             case STP_PARAMETER_TYPE_DOUBLE:
    00283               stp_set_float_parameter(v, p->name, desc.deflt.dbl);
    00284               stp_set_float_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00285               break;
    00286             case STP_PARAMETER_TYPE_INT:
    00287               stp_set_int_parameter(v, p->name, desc.deflt.integer);
    00288               stp_set_int_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00289               break;
    00290             case STP_PARAMETER_TYPE_DIMENSION:
    00291               stp_set_dimension_parameter(v, p->name, desc.deflt.dimension);
    00292               stp_set_dimension_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00293               break;
    00294             case STP_PARAMETER_TYPE_BOOLEAN:
    00295               stp_set_boolean_parameter(v, p->name, desc.deflt.boolean);
    00296               stp_set_boolean_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00297               break;
    00298             case STP_PARAMETER_TYPE_CURVE:
    00299               stp_set_curve_parameter(v, p->name, desc.deflt.curve);
    00300               stp_set_curve_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00301               break;
    00302             case STP_PARAMETER_TYPE_ARRAY:
    00303               stp_set_array_parameter(v, p->name, desc.deflt.array);
    00304               stp_set_array_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
    00305               break;
    00306             default:
    00307               break;
    00308             }
    00309           stp_parameter_description_destroy(&desc);
    00310         }
    00311     }
    00312   stp_parameter_list_destroy(params);
    00313 }
    00314
    00315 void
    00316 stp_set_printer_defaults(stp_vars_t *v, const stp_printer_t *printer)
    00317 {
    00318   stp_set_driver(v, stp_printer_get_driver(printer));
    00319   set_printer_defaults(v, 0);
    00320 }
    00321
    00322 void
    00323 stp_initialize_printer_defaults(void)
    00324 {
    00325   stp_list_item_t *printer_item;
    00326   if (printer_list == NULL)
    00327     {
    00328       stpi_init_printer_list();
    00329       stp_deprintf
    00330         (STP_DBG_PRINTERS,
    00331          "stpi_family_register(): initialising printer_list...\n");
    00332     }
    00333   printer_item = stp_list_get_start(printer_list);
    00334   while (printer_item)
    00335     {
    00336       set_printer_defaults
    00337         (((stp_printer_t *)(stp_list_item_get_data(printer_item)))->printvars, 1);
    00338       printer_item = stp_list_item_next(printer_item);
    00339     }
    00340 }
    00341
    00342 void
    00343 stp_get_media_size(const stp_vars_t *v, int *width, int *height)
    00344 {
    00345   const stp_printfuncs_t *printfuncs =
    00346     stpi_get_printfuncs(stp_get_printer(v));
    00347   (printfuncs->media_size)(v, width, height);
    00348 }
    00349
    00350 void
    00351 stp_get_imageable_area(const stp_vars_t *v,
    00352                        int *left, int *right, int *bottom, int *top)
    00353 {
    00354   const stp_printfuncs_t *printfuncs =
    00355     stpi_get_printfuncs(stp_get_printer(v));
    00356   (printfuncs->imageable_area)(v, left, right, bottom, top);
    00357 }
    00358
    00359 void
    00360 stp_get_size_limit(const stp_vars_t *v, int *max_width, int *max_height,
    00361                    int *min_width, int *min_height)
    00362 {
    00363   const stp_printfuncs_t *printfuncs =
    00364     stpi_get_printfuncs(stp_get_printer(v));
    00365   (printfuncs->limit)(v, max_width, max_height, min_width,min_height);
    00366 }
    00367
    00368 void
    00369 stp_describe_resolution(const stp_vars_t *v, int *x, int *y)
    00370 {
    00371   const stp_printfuncs_t *printfuncs =
    00372     stpi_get_printfuncs(stp_get_printer(v));
    00373   (printfuncs->describe_resolution)(v, x, y);
    00374 }
    00375
    00376 const char *
    00377 stp_describe_output(const stp_vars_t *v)
    00378 {
    00379   const stp_printfuncs_t *printfuncs =
    00380     stpi_get_printfuncs(stp_get_printer(v));
    00381   return (printfuncs->describe_output)(v);
    00382 }
    00383
    00384 int
    00385 stp_verify(stp_vars_t *v)
    00386 {
    00387   const stp_printfuncs_t *printfuncs =
    00388     stpi_get_printfuncs(stp_get_printer(v));
    00389   stp_vars_t *nv = stp_vars_create_copy(v);
    00390   int status;
    00391   stp_prune_inactive_options(nv);
    00392   status = (printfuncs->verify)(nv);
    00393   stp_set_verified(v, stp_get_verified(nv));
    00394   stp_vars_destroy(nv);
    00395   return status;
    00396 }
    00397
    00398 int
    00399 stp_print(const stp_vars_t *v, stp_image_t *image)
    00400 {
    00401   const stp_printfuncs_t *printfuncs =
    00402     stpi_get_printfuncs(stp_get_printer(v));
    00403   return (printfuncs->print)(v, image);
    00404 }
    00405
    00406 int
    00407 stp_start_job(const stp_vars_t *v, stp_image_t *image)
    00408 {
    00409   const stp_printfuncs_t *printfuncs =
    00410     stpi_get_printfuncs(stp_get_printer(v));
    00411   if (!stp_get_string_parameter(v, "JobMode") ||
    00412       strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
    00413     return 1;
    00414   if (printfuncs->start_job)
    00415     return (printfuncs->start_job)(v, image);
    00416   else
    00417     return 1;
    00418 }
    00419
    00420 int
    00421 stp_end_job(const stp_vars_t *v, stp_image_t *image)
    00422 {
    00423   const stp_printfuncs_t *printfuncs =
    00424     stpi_get_printfuncs(stp_get_printer(v));
    00425   if (!stp_get_string_parameter(v, "JobMode") ||
    00426       strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
    00427     return 1;
    00428   if (printfuncs->end_job)
    00429     return (printfuncs->end_job)(v, image);
    00430   else
    00431     return 1;
    00432 }
    00433
    00434 static int
    00435 verify_string_param(const stp_vars_t *v, const char *parameter,
    00436                     stp_parameter_t *desc, int quiet)
    00437 {
    00438   stp_parameter_verify_t answer = PARAMETER_OK;
    00439   stp_dprintf(STP_DBG_VARS, v, "    Verifying string %s\n", parameter);
    00440   if (desc->is_mandatory ||
    00441       stp_check_string_parameter(v, parameter, STP_PARAMETER_ACTIVE))
    00442     {
    00443       const char *checkval = stp_get_string_parameter(v, parameter);
    00444       stp_string_list_t *vptr = desc->bounds.str;
    00445       size_t count = 0;
    00446       int i;
    00447       stp_dprintf(STP_DBG_VARS, v, "     value %s\n",
    00448                   checkval ? checkval : "(null)");
    00449       if (vptr)
    00450         count = stp_string_list_count(vptr);
    00451       answer = PARAMETER_BAD;
    00452       if (checkval == NULL)
    00453         {
    00454           if (count == 0)
    00455             answer = PARAMETER_OK;
    00456           else
    00457             {
    00458               if (!quiet)
    00459                 stp_eprintf(v, _("Value must be set for %s\n"), parameter);
    00460               answer = PARAMETER_BAD;
    00461             }
    00462         }
    00463       else if (count > 0)
    00464         {
    00465           for (i = 0; i < count; i++)
    00466             if (!strcmp(checkval, stp_string_list_param(vptr, i)->name))
    00467               {
    00468                 answer = PARAMETER_OK;
    00469                 break;
    00470               }
    00471           if (!answer && !quiet)
    00472             stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter);
    00473         }
    00474       else if (strlen(checkval) == 0)
    00475         answer = PARAMETER_OK;
    00476       else if (!quiet)
    00477         stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter);
    00478     }
    00479   stp_parameter_description_destroy(desc);
    00480   return answer;
    00481 }
    00482
    00483 static int
    00484 verify_double_param(const stp_vars_t *v, const char *parameter,
    00485                     stp_parameter_t *desc, int quiet)
    00486 {
    00487   stp_dprintf(STP_DBG_VARS, v, "    Verifying double %s\n", parameter);
    00488   if (desc->is_mandatory ||
    00489       stp_check_float_parameter(v, parameter, STP_PARAMETER_ACTIVE))
    00490     {
    00491       double checkval = stp_get_float_parameter(v, parameter);
    00492       if (checkval < desc->bounds.dbl.lower ||
    00493           checkval > desc->bounds.dbl.upper)
    00494         {
    00495           if (!quiet)
    00496             stp_eprintf(v, _("%s must be between %f and %f (is %f)\n"),
    00497                         parameter, desc->bounds.dbl.lower,
    00498                         desc->bounds.dbl.upper, checkval);
    00499           return PARAMETER_BAD;
    00500         }
    00501     }
    00502   return PARAMETER_OK;
    00503 }
    00504
    00505 static int
    00506 verify_int_param(const stp_vars_t *v, const char *parameter,
    00507                  stp_parameter_t *desc, int quiet)
    00508 {
    00509   stp_dprintf(STP_DBG_VARS, v, "    Verifying int %s\n", parameter);
    00510   if (desc->is_mandatory ||
    00511       stp_check_int_parameter(v, parameter, STP_PARAMETER_ACTIVE))
    00512     {
    00513       int checkval = stp_get_int_parameter(v, parameter);
    00514       if (checkval < desc->bounds.integer.lower ||
    00515           checkval > desc->bounds.integer.upper)
    00516         {
    00517           if (!quiet)
    00518             stp_eprintf(v, _("%s must be between %d and %d (is %d)\n"),
    00519                         parameter, desc->bounds.integer.lower,
    00520                         desc->bounds.integer.upper, checkval);
    00521           stp_parameter_description_destroy(desc);
    00522           return PARAMETER_BAD;
    00523         }
    00524     }
    00525   stp_parameter_description_destroy(desc);
    00526   return PARAMETER_OK;
    00527 }
    00528
    00529 static int
    00530 verify_dimension_param(const stp_vars_t *v, const char *parameter,
    00531                  stp_parameter_t *desc, int quiet)
    00532 {
    00533   stp_dprintf(STP_DBG_VARS, v, "    Verifying dimension %s\n", parameter);
    00534   if (desc->is_mandatory ||
    00535       stp_check_dimension_parameter(v, parameter, STP_PARAMETER_ACTIVE))
    00536     {
    00537       int checkval = stp_get_dimension_parameter(v, parameter);
    00538       if (checkval < desc->bounds.dimension.lower ||
    00539           checkval > desc->bounds.dimension.upper)
    00540         {
    00541           if (!quiet)
    00542             stp_eprintf(v, _("%s must be between %d and %d (is %d)\n"),
    00543                         parameter, desc->bounds.dimension.lower,
    00544                         desc->bounds.dimension.upper, checkval);
    00545           stp_parameter_description_destroy(desc);
    00546           return PARAMETER_BAD;
    00547         }
    00548     }
    00549   stp_parameter_description_destroy(desc);
    00550   return PARAMETER_OK;
    00551 }
    00552
    00553 static int
    00554 verify_curve_param(const stp_vars_t *v, const char *parameter,
    00555                    stp_parameter_t *desc, int quiet)
    00556 {
    00557   stp_parameter_verify_t answer = 1;
    00558   stp_dprintf(STP_DBG_VARS, v, "    Verifying curve %s\n", parameter);
    00559   if (desc->bounds.curve &&
    00560       (desc->is_mandatory ||
    00561        stp_check_curve_parameter(v, parameter, STP_PARAMETER_ACTIVE)))
    00562     {
    00563       const stp_curve_t *checkval = stp_get_curve_parameter(v, parameter);
    00564       if (checkval)
    00565         {
    00566           double u0, l0;
    00567           double u1, l1;
    00568           stp_curve_get_bounds(checkval, &l0, &u0);
    00569           stp_curve_get_bounds(desc->bounds.curve, &l1, &u1);
    00570           if (u0 > u1 || l0 < l1)
    00571             {
    00572               if (!quiet)
    00573                 stp_eprintf(v, _("%s bounds must be between %f and %f\n"),
    00574                             parameter, l1, u1);
    00575               answer = PARAMETER_BAD;
    00576             }
    00577           if (stp_curve_get_wrap(checkval) !=
    00578               stp_curve_get_wrap(desc->bounds.curve))
    00579             {
    00580               if (!quiet)
    00581                 stp_eprintf(v, _("%s wrap mode must be %s\n"),
    00582                             parameter,
    00583                             (stp_curve_get_wrap(desc->bounds.curve) ==
    00584                              STP_CURVE_WRAP_NONE) ?
    00585                             _("no wrap") : _("wrap around"));
    00586               answer = PARAMETER_BAD;
    00587             }
    00588         }
    00589     }
    00590   stp_parameter_description_destroy(desc);
    00591   return answer;
    00592 }
    00593
    00594 stp_parameter_verify_t
    00595 stp_verify_parameter(const stp_vars_t *v, const char *parameter,
    00596                      int quiet)
    00597 {
    00598   stp_parameter_t desc;
    00599   quiet = 0;
    00600   stp_describe_parameter(v, parameter, &desc);
    00601   stp_dprintf(STP_DBG_VARS, v, "  Verifying %s %d %d\n", parameter,
    00602               desc.is_active, desc.read_only);
    00603   if (!desc.is_active || desc.read_only)
    00604     {
    00605       stp_parameter_description_destroy(&desc);
    00606       return PARAMETER_INACTIVE;
    00607     }
    00608   switch (desc.p_type)
    00609     {
    00610     case STP_PARAMETER_TYPE_STRING_LIST:
    00611       return verify_string_param(v, parameter, &desc, quiet);
    00612     case STP_PARAMETER_TYPE_DOUBLE:
    00613       return verify_double_param(v, parameter, &desc, quiet);
    00614     case STP_PARAMETER_TYPE_INT:
    00615       return verify_int_param(v, parameter, &desc, quiet);
    00616     case STP_PARAMETER_TYPE_DIMENSION:
    00617       return verify_dimension_param(v, parameter, &desc, quiet);
    00618     case STP_PARAMETER_TYPE_CURVE:
    00619       return verify_curve_param(v, parameter, &desc, quiet);
    00620     case STP_PARAMETER_TYPE_RAW:
    00621     case STP_PARAMETER_TYPE_FILE:
    00622       stp_parameter_description_destroy(&desc);
    00623       return PARAMETER_OK;              /* No way to verify this here */
    00624     case STP_PARAMETER_TYPE_BOOLEAN:
    00625       stp_parameter_description_destroy(&desc);
    00626       return PARAMETER_OK;              /* Booleans always OK */
    00627     default:
    00628       if (!quiet)
    00629         stp_eprintf(v, _("Unknown type parameter %s (%d)\n"),
    00630                     parameter, desc.p_type);
    00631       stp_parameter_description_destroy(&desc);
    00632       return 0;
    00633     }
    00634 }
    00635
    00636 #define CHECK_INT_RANGE(v, component, min, max)                             \
    00637 do                                                                          \
    00638 {                                                                           \
    00639   if (stp_get_##component((v)) < (min) || stp_get_##component((v)) > (max)) \
    00640     {                                                                       \
    00641       answer = 0;                                                           \
    00642       stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"),     \
    00643                   #component, stp_get_##component(v), min, max);            \
    00644     }                                                                       \
    00645 } while (0)
    00646
    00647 #define CHECK_INT_RANGE_INTERNAL(v, component, min, max)                      \
    00648 do                                                                            \
    00649 {                                                                             \
    00650   if (stpi_get_##component((v)) < (min) || stpi_get_##component((v)) > (max)) \
    00651     {                                                                         \
    00652       answer = 0;                                                             \
    00653       stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"),       \
    00654                   #component, stpi_get_##component(v), min, max);             \
    00655     }                                                                         \
    00656 } while (0)
    00657
    00658 typedef struct
    00659 {
    00660   char *data;
    00661   size_t bytes;
    00662 } errbuf_t;
    00663
    00664 static void
    00665 fill_buffer_writefunc(void *priv, const char *buffer, size_t bytes)
    00666 {
    00667   errbuf_t *errbuf = (errbuf_t *) priv;
    00668   if (errbuf->bytes == 0)
    00669     errbuf->data = stp_malloc(bytes + 1);
    00670   else
    00671     errbuf->data = stp_realloc(errbuf->data, errbuf->bytes + bytes + 1);
    00672   memcpy(errbuf->data + errbuf->bytes, buffer, bytes);
    00673   errbuf->bytes += bytes;
    00674   errbuf->data[errbuf->bytes] = '\0';
    00675 }
    00676
    00677 int
    00678 stp_verify_printer_params(stp_vars_t *v)
    00679 {
    00680   errbuf_t errbuf;
    00681   stp_outfunc_t ofunc = stp_get_errfunc(v);
    00682   void *odata = stp_get_errdata(v);
    00683
    00684   stp_parameter_list_t params;
    00685   int nparams;
    00686   int i;
    00687   int answer = 1;
    00688   int left, top, bottom, right;
    00689   const char *pagesize = stp_get_string_parameter(v, "PageSize");
    00690
    00691   stp_set_errfunc((stp_vars_t *) v, fill_buffer_writefunc);
    00692   stp_set_errdata((stp_vars_t *) v, &errbuf);
    00693
    00694   errbuf.data = NULL;
    00695   errbuf.bytes = 0;
    00696
    00697   if (pagesize && strlen(pagesize) > 0)
    00698     {
    00699       if (stp_verify_parameter(v, "PageSize", 0) == 0)
    00700         answer = 0;
    00701     }
    00702   else
    00703     {
    00704       int width, height, min_height, min_width;
    00705       stp_get_size_limit(v, &width, &height, &min_width, &min_height);
    00706       if (stp_get_page_height(v) <= min_height ||
    00707           stp_get_page_height(v) > height ||
    00708           stp_get_page_width(v) <= min_width || stp_get_page_width(v) > width)
    00709         {
    00710           answer = 0;
    00711           stp_eprintf(v, _("Page size is not valid\n"));
    00712         }
    00713       stp_dprintf(STP_DBG_PAPER, v,
    00714                   "page size max %d %d min %d %d actual %d %d\n",
    00715                   width, height, min_width, min_height,
    00716                   stp_get_page_width(v), stp_get_page_height(v));
    00717     }
    00718
    00719   stp_get_imageable_area(v, &left, &right, &bottom, &top);
    00720
    00721   stp_dprintf(STP_DBG_PAPER, v,
    00722               "page      left %d top %d right %d bottom %d\n",
    00723               left, top, right, bottom);
    00724   stp_dprintf(STP_DBG_PAPER, v,
    00725               "requested left %d top %d width %d height %d\n",
    00726               stp_get_left(v), stp_get_top(v),
    00727               stp_get_width(v), stp_get_height(v));
    00728
    00729   if (stp_get_top(v) < top)
    00730     {
    00731       answer = 0;
    00732       stp_eprintf(v, _("Top margin must not be less than %d\n"), top);
    00733     }
    00734
    00735   if (stp_get_left(v) < left)
    00736     {
    00737       answer = 0;
    00738       stp_eprintf(v, _("Left margin must not be less than %d\n"), left);
    00739     }
    00740
    00741   if (stp_get_height(v) <= 0)
    00742     {
    00743       answer = 0;
    00744       stp_eprintf(v, _("Height must be greater than zero\n"));
    00745     }
    00746
    00747   if (stp_get_width(v) <= 0)
    00748     {
    00749       answer = 0;
    00750       stp_eprintf(v, _("Width must be greater than zero\n"));
    00751     }
    00752
    00753   if (stp_get_left(v) + stp_get_width(v) > right)
    00754     {
    00755       answer = 0;
    00756       stp_eprintf(v, _("Image is too wide for the page: left margin is %d, width %d, right edge is %d\n"),
    00757                   stp_get_left(v), stp_get_width(v), right);
    00758     }
    00759
    00760   if (stp_get_top(v) + stp_get_height(v) > bottom)
    00761     {
    00762       answer = 0;
    00763       stp_eprintf(v, _("Image is too long for the page: top margin is %d, height %d, bottom edge is %d\n"),
    00764                   stp_get_left(v), stp_get_width(v), right);
    00765     }
    00766
    00767   params = stp_get_parameter_list(v);
    00768   nparams = stp_parameter_list_count(params);
    00769   for (i = 0; i < nparams; i++)
    00770     {
    00771       const stp_parameter_t *param = stp_parameter_list_param(params, i);
    00772       stp_dprintf(STP_DBG_VARS, v, "Checking %s %d %d\n", param->name,
    00773                   param->is_active, param->verify_this_parameter);
    00774
    00775       if (strcmp(param->name, "PageSize") != 0 &&
    00776           param->is_active && param->verify_this_parameter &&
    00777           stp_verify_parameter(v, param->name, 0) == 0)
    00778         answer = 0;
    00779     }
    00780   stp_parameter_list_destroy(params);
    00781   stp_set_errfunc((stp_vars_t *) v, ofunc);
    00782   stp_set_errdata((stp_vars_t *) v, odata);
    00783   stp_set_verified((stp_vars_t *) v, answer);
    00784   if (errbuf.bytes > 0)
    00785     {
    00786       stp_eprintf(v, "%s", errbuf.data);
    00787       stp_free(errbuf.data);
    00788     }
    00789   return answer;
    00790 }
    00791
    00792 int
    00793 stp_family_register(stp_list_t *family)
    00794 {
    00795   stp_list_item_t *printer_item;
    00796   const stp_printer_t *printer;
    00797
    00798   if (printer_list == NULL)
    00799     {
    00800       stpi_init_printer_list();
    00801       stp_deprintf
    00802         (STP_DBG_PRINTERS,
    00803          "stpi_family_register(): initialising printer_list...\n");
    00804     }
    00805
    00806   if (family)
    00807     {
    00808       printer_item = stp_list_get_start(family);
    00809
    00810       while(printer_item)
    00811         {
    00812           printer = (const stp_printer_t *) stp_list_item_get_data(printer_item);
    00813           if (!stp_list_get_item_by_name(printer_list,
    00814                                           stp_get_driver(printer->printvars)))
    00815             stp_list_item_create(printer_list, NULL, printer);
    00816           printer_item = stp_list_item_next(printer_item);
    00817         }
    00818     }
    00819
    00820   return 0;
    00821 }
    00822
    00823 int
    00824 stp_family_unregister(stp_list_t *family)
    00825 {
    00826   stp_list_item_t *printer_item;
    00827   stp_list_item_t *old_printer_item;
    00828   const stp_printer_t *printer;
    00829
    00830   if (printer_list == NULL)
    00831     {
    00832       stpi_init_printer_list();
    00833       stp_deprintf
    00834         (STP_DBG_PRINTERS,
    00835          "stpi_family_unregister(): initialising printer_list...\n");
    00836     }
    00837
    00838   if (family)
    00839     {
    00840       printer_item = stp_list_get_start(family);
    00841
    00842       while(printer_item)
    00843         {
    00844           printer = (const stp_printer_t *) stp_list_item_get_data(printer_item);
    00845           old_printer_item =
    00846             stp_list_get_item_by_name(printer_list,
    00847                                       stp_get_driver(printer->printvars));
    00848
    00849           if (old_printer_item)
    00850             stp_list_item_destroy(printer_list, old_printer_item);
    00851           printer_item = stp_list_item_next(printer_item);
    00852         }
    00853     }
    00854   return 0;
    00855 }
    00856
    00857 /*
    00858  * Parse the printer node, and return the generated printer.  Returns
    00859  * NULL on failure.
    00860  */
    00861 static stp_printer_t*
    00862 stp_printer_create_from_xmltree(stp_mxml_node_t *printer, /* The printer node */
    00863                                 const char *family,       /* Family name */
    00864                                 const stp_printfuncs_t *printfuncs)
    00865                                                        /* Family printfuncs */
    00866 {
    00867   stp_mxml_node_t *prop;                                  /* Temporary node pointer */
    00868   const char *stmp;                                    /* Temporary string */
    00869   stp_printer_t *outprinter;                 /* Generated printer */
    00870   int
    00871     driver = 0,                                       /* Check driver */
    00872     long_name = 0;
    00873
    00874   outprinter = stp_zalloc(sizeof(stp_printer_t));
    00875   if (!outprinter)
    00876     return NULL;
    00877   outprinter->printvars = stp_vars_create();
    00878   if (outprinter->printvars == NULL)
    00879     {
    00880       stp_free(outprinter);
    00881       return NULL;
    00882     }
    00883
    00884   stmp = stp_mxmlElementGetAttr(printer, "driver");
    00885   stp_set_driver(outprinter->printvars, (const char *) stmp);
    00886
    00887   outprinter->long_name = stp_strdup(stp_mxmlElementGetAttr(printer, "name"));
    00888   outprinter->manufacturer = stp_strdup(stp_mxmlElementGetAttr(printer, "manufacturer"));
    00889   outprinter->model = stp_xmlstrtol(stp_mxmlElementGetAttr(printer, "model"));
    00890   outprinter->family = stp_strdup((const char *) family);
    00891
    00892   if (stp_get_driver(outprinter->printvars))
    00893     driver = 1;
    00894   if (outprinter->long_name)
    00895     long_name = 1;
    00896
    00897   outprinter->printfuncs = printfuncs;
    00898
    00899   prop = printer->child;
    00900   while (prop)
    00901     {
    00902       if (prop->type == STP_MXML_ELEMENT)
    00903         {
    00904           const char *prop_name = prop->value.element.name;
    00905           if (!strcmp(prop_name, "parameter"))
    00906             {
    00907               const char *p_type = stp_mxmlElementGetAttr(prop, "type");
    00908               const char *p_name = stp_mxmlElementGetAttr(prop, "name");
    00909               stp_mxml_node_t *child = prop->child;
    00910               if (!p_type || !p_name)
    00911                 stp_erprintf("Bad property on driver %s\n", outprinter->driver);
    00912               else if (strcmp(p_type, "float") == 0)
    00913                 {
    00914                   if (child->type == STP_MXML_TEXT)
    00915                     stp_set_float_parameter
    00916                       (outprinter->printvars, p_name,
    00917                        stp_xmlstrtod(child->value.text.string));
    00918                 }
    00919               else if (strcmp(p_type, "integer") == 0)
    00920                 {
    00921                   if (child->type == STP_MXML_TEXT)
    00922                     stp_set_int_parameter
    00923                       (outprinter->printvars, p_name,
    00924                        (int) stp_xmlstrtol(child->value.text.string));
    00925                 }
    00926               else if (strcmp(p_type, "boolean") == 0)
    00927                 {
    00928                   if (child->type == STP_MXML_TEXT)
    00929                     stp_set_boolean_parameter
    00930                       (outprinter->printvars, p_name,
    00931                        (int) stp_xmlstrtol(child->value.text.string));
    00932                 }
    00933               else if (strcmp(p_type, "string") == 0)
    00934                 {
    00935                   if (child->type == STP_MXML_TEXT)
    00936                     stp_set_string_parameter
    00937                       (outprinter->printvars, p_name, child->value.text.string);
    00938                 }
    00939               else if (strcmp(p_type, "curve") == 0)
    00940                 {
    00941                   stp_curve_t *curve = stp_curve_create_from_xmltree(child);
    00942                   if (curve)
    00943                     {
    00944                       stp_set_curve_parameter(outprinter->printvars,
    00945                                               p_name, curve);
    00946                       stp_curve_destroy(curve);
    00947                     }
    00948                 }
    00949               else if (strcmp(p_type, "array") == 0)
    00950                 {
    00951                   stp_array_t *array = stp_array_create_from_xmltree(child);
    00952                   if (array)
    00953                     {
    00954                       stp_set_array_parameter(outprinter->printvars,
    00955                                               p_name, array);
    00956                       stp_array_destroy(array);
    00957                     }
    00958                 }
    00959               else
    00960                 {
    00961                   stp_erprintf("Bad property %s type %s on driver %s\n",
    00962                                p_name, p_type, outprinter->driver);
    00963                   continue;
    00964                 }
    00965             }
    00966         }
    00967       prop = prop->next;
    00968     }
    00969   if (driver && long_name && printfuncs)
    00970     {
    00971       if (stp_get_debug_level() & STP_DBG_XML)
    00972         {
    00973           stmp = stp_mxmlElementGetAttr(printer, "driver");
    00974           stp_erprintf("stp_printer_create_from_xmltree: printer: %s\n", stmp);
    00975         }
    00976       outprinter->driver = stp_get_driver(outprinter->printvars);
    00977       return outprinter;
    00978     }
    00979   stp_free(outprinter);
    00980   return NULL;
    00981 }
    00982
    00983 /*
    00984  * Parse the <family> node.
    00985  */
    00986 static void
    00987 stpi_xml_process_family(stp_mxml_node_t *family)     /* The family node */
    00988 {
    00989   stp_list_t *family_module_list = NULL;      /* List of valid families */
    00990   stp_list_item_t *family_module_item;        /* Current family */
    00991   const char *family_name;                       /* Name of family */
    00992   stp_mxml_node_t *printer;                         /* printer child node */
    00993   stp_module_t *family_module_data;           /* Family module data */
    00994   stp_family_t *family_data = NULL;  /* Family data */
    00995   int family_valid = 0;                       /* Is family valid? */
    00996   stp_printer_t *outprinter;         /* Generated printer */
    00997
    00998   family_module_list = stp_module_get_class(STP_MODULE_CLASS_FAMILY);
    00999   if (!family_module_list)
    01000     return;
    01001
    01002   family_name = stp_mxmlElementGetAttr(family, "name");
    01003   family_module_item = stp_list_get_start(family_module_list);
    01004   while (family_module_item)
    01005     {
    01006       family_module_data = (stp_module_t *)
    01007         stp_list_item_get_data(family_module_item);
    01008       if (!strcmp(family_name, family_module_data->name))
    01009         {
    01010           stp_deprintf(STP_DBG_XML,
    01011                        "stpi_xml_process_family: family module: %s\n",
    01012                        family_module_data->name);
    01013           family_data = family_module_data->syms;
    01014           if (family_data->printer_list == NULL)
    01015             family_data->printer_list = stp_list_create();
    01016           family_valid = 1;
    01017         }
    01018       family_module_item = stp_list_item_next(family_module_item);
    01019     }
    01020
    01021   printer = family->child;
    01022   while (family_valid && printer)
    01023     {
    01024       if (printer->type == STP_MXML_ELEMENT)
    01025         {
    01026           const char *printer_name = printer->value.element.name;
    01027           if (!strcmp(printer_name, "printer"))
    01028             {
    01029               outprinter =
    01030                 stp_printer_create_from_xmltree(printer, family_name,
    01031                                                 family_data->printfuncs);
    01032               if (outprinter)
    01033                 stp_list_item_create(family_data->printer_list, NULL,
    01034                                       outprinter);
    01035             }
    01036         }
    01037       printer = printer->next;
    01038     }
    01039
    01040   stp_list_destroy(family_module_list);
    01041   return;
    01042 }
    01043
    01044 /*
    01045  * Parse the <printdef> node.
    01046  */
    01047 static int
    01048 stpi_xml_process_printdef(stp_mxml_node_t *printdef, const char *file) /* The printdef node */
    01049 {
    01050   stp_mxml_node_t *family;                          /* Family child node */
    01051
    01052   family = printdef->child;
    01053   while (family)
    01054     {
    01055       if (family->type == STP_MXML_ELEMENT)
    01056         {
    01057           const char *family_name = family->value.element.name;
    01058           if (!strcmp(family_name, "family"))
    01059             {
    01060               stpi_xml_process_family(family);
    01061             }
    01062         }
    01063       family = family->next;
    01064     }
    01065   return 1;
    01066 }
    01067
    01068 void
    01069 stpi_init_printer(void)
    01070 {
    01071   stp_register_xml_parser("printdef", stpi_xml_process_printdef);
    01072   stp_register_xml_preload("printers.xml");
    01073 }