/*
*
* Print plug-in driver utility functions for the GIMP.
*
* Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
* Robert Krawitz (rlk@alum.mit.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* This file must include only standard C header files. The core code must
* compile on generic platforms that don't support glib, gimp, gtk, etc.
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include "gutenprint-internal.h"
#include
#include
#include
#ifdef HAVE_LIMITS_H
#include
#endif
#include
#include
#define FMIN(a, b) ((a) < (b) ? (a) : (b))
static void stpi_printvars_freefunc(void *item);
static const char* stpi_printvars_namefunc(const void *item);
static stp_list_t *printvars_list = NULL;
typedef struct stp_printvars
{
const char *name;
stp_vars_t *printvars;
} stp_printvars_t;
static void stpi_printer_freefunc(void *item);
static const char* stpi_printer_namefunc(const void *item);
static const char* stpi_printer_long_namefunc(const void *item);
static stp_list_t *printer_list = NULL;
struct stp_printer
{
const char *driver;
char *long_name; /* Long name for UI */
char *family; /* Printer family */
char *manufacturer; /* Printer manufacturer */
char *device_id; /* IEEE 1284 device ID */
char *comment; /* Comment string, if any */
int model; /* Model number */
int vars_initialized;
const stp_printfuncs_t *printfuncs;
stp_vars_t *printvars;
};
static void
stpi_init_printvars_list(void)
{
if (!printvars_list)
{
printvars_list = stp_list_create();
stp_list_set_freefunc(printvars_list, stpi_printvars_freefunc);
stp_list_set_namefunc(printvars_list, stpi_printvars_namefunc);
stp_list_set_long_namefunc(printvars_list, stpi_printvars_namefunc);
}
}
static int
stpi_init_printer_list(void)
{
if(printer_list)
stp_list_destroy(printer_list);
printer_list = stp_list_create();
stp_list_set_freefunc(printer_list, stpi_printer_freefunc);
stp_list_set_namefunc(printer_list, stpi_printer_namefunc);
stp_list_set_long_namefunc(printer_list, stpi_printer_long_namefunc);
/* stp_list_set_sortfunc(printer_list, stpi_printer_sortfunc); */
return 0;
}
int
stp_printer_model_count(void)
{
if (printer_list == NULL)
{
stp_erprintf("No printer drivers found: "
"are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
stpi_init_printer_list();
}
return stp_list_get_length(printer_list);
}
const stp_printer_t *
stp_get_printer_by_index(int idx)
{
stp_list_item_t *printer;
if (printer_list == NULL)
{
stp_erprintf("No printer drivers found: "
"are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
stpi_init_printer_list();
}
printer = stp_list_get_item_by_index(printer_list, idx);
if (printer == NULL)
return NULL;
return (const stp_printer_t *) stp_list_item_get_data(printer);
}
static void
stpi_printer_freefunc(void *item)
{
stp_printer_t *printer = (stp_printer_t *) item;
if (printer->comment)
{
stp_free(printer->comment);
printer->comment = NULL;
}
stp_free(printer->long_name);
stp_free(printer->family);
stp_free(printer);
}
/* ARGSUSED */
static void
stpi_printvars_freefunc(void *item)
{
}
static const char *
stpi_printvars_namefunc(const void *item)
{
const stp_printvars_t *printvars = (const stp_printvars_t *) item;
return printvars->name;
}
const char *
stp_printer_get_driver(const stp_printer_t *printer)
{
return printer->driver;
}
static const char *
stpi_printer_namefunc(const void *item)
{
const stp_printer_t *printer = (const stp_printer_t *) item;
return printer->driver;
}
const char *
stp_printer_get_long_name(const stp_printer_t *printer)
{
return printer->long_name;
}
static const char *
stpi_printer_long_namefunc(const void *item)
{
const stp_printer_t *printer = (const stp_printer_t *) item;
return printer->long_name;
}
const char *
stp_printer_get_device_id(const stp_printer_t *printer)
{
return printer->device_id;
}
const char *
stp_printer_get_family(const stp_printer_t *printer)
{
return printer->family;
}
const char *
stp_printer_get_manufacturer(const stp_printer_t *printer)
{
return printer->manufacturer;
}
const char *
stp_printer_get_comment(const stp_printer_t *printer)
{
return printer->comment;
}
int
stp_printer_get_model(const stp_printer_t *printer)
{
return printer->model;
}
static inline const stp_printfuncs_t *
stpi_get_printfuncs(const stp_printer_t *printer)
{
return printer->printfuncs;
}
const stp_printer_t *
stp_get_printer_by_long_name(const char *long_name)
{
stp_list_item_t *printer_item;
if (printer_list == NULL)
{
stp_erprintf("No printer drivers found: "
"are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
stpi_init_printer_list();
}
printer_item = stp_list_get_item_by_long_name(printer_list, long_name);
if (!printer_item)
return NULL;
return (const stp_printer_t *) stp_list_item_get_data(printer_item);
}
const stp_printer_t *
stp_get_printer_by_driver(const char *driver)
{
stp_list_item_t *printer_item;
if (printer_list == NULL)
{
stp_erprintf("No printer drivers found: "
"are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
stpi_init_printer_list();
}
printer_item = stp_list_get_item_by_name(printer_list, driver);
if (!printer_item)
return NULL;
return (const stp_printer_t *) stp_list_item_get_data(printer_item);
}
const stp_printer_t *
stp_get_printer_by_device_id(const char *device_id)
{
stp_list_item_t *printer_item;
if (printer_list == NULL)
{
stp_erprintf("No printer drivers found: "
"are STP_DATA_PATH and STP_MODULE_PATH correct?\n");
stpi_init_printer_list();
}
if (! device_id || strcmp(device_id, "") == 0)
return NULL;
printer_item = stp_list_get_start(printer_list);
while (printer_item)
{
if (strcmp(((const stp_printer_t *) stp_list_item_get_data(printer_item))->device_id,
device_id) == 0)
return ((const stp_printer_t *) stp_list_item_get_data(printer_item));
printer_item = stp_list_item_next(printer_item);
}
return NULL;
}
int
stp_get_printer_index_by_driver(const char *driver)
{
/* There should be no need to ever know the index! */
int idx = 0;
for (idx = 0; idx < stp_printer_model_count(); idx++)
{
const stp_printer_t *printer = stp_get_printer_by_index(idx);
if (!strcmp(stp_printer_get_driver(printer), driver))
return idx;
}
return -1;
}
const stp_printer_t *
stp_get_printer(const stp_vars_t *v)
{
return stp_get_printer_by_driver(stp_get_driver(v));
}
int
stp_get_model_id(const stp_vars_t *v)
{
const stp_printer_t *printer = stp_get_printer_by_driver(stp_get_driver(v));
return printer->model;
}
stp_parameter_list_t
stp_printer_list_parameters(const stp_vars_t *v)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
return (printfuncs->list_parameters)(v);
}
void
stp_printer_describe_parameter(const stp_vars_t *v, const char *name,
stp_parameter_t *description)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->parameters)(v, name, description);
}
static void
set_printer_defaults(stp_vars_t *v, int core_only, int soft)
{
stp_parameter_list_t *params;
int count;
int i;
stp_parameter_t desc;
params = stp_get_parameter_list(v);
count = stp_parameter_list_count(params);
for (i = 0; i < count; i++)
{
const stp_parameter_t *p = stp_parameter_list_param(params, i);
if (p->is_mandatory &&
(!core_only || p->p_class == STP_PARAMETER_CLASS_CORE))
{
stp_describe_parameter(v, p->name, &desc);
switch (p->p_type)
{
case STP_PARAMETER_TYPE_STRING_LIST:
if (!soft ||
!stp_check_string_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_string_parameter(v, p->name, desc.deflt.str);
stp_set_string_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_DOUBLE:
if (!soft ||
!stp_check_float_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_float_parameter(v, p->name, desc.deflt.dbl);
stp_set_float_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_INT:
if (!soft ||
!stp_check_int_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_int_parameter(v, p->name, desc.deflt.integer);
stp_set_int_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_DIMENSION:
if (!soft ||
!stp_check_dimension_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_dimension_parameter(v, p->name, desc.deflt.dimension);
stp_set_dimension_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_BOOLEAN:
if (!soft ||
!stp_check_boolean_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_boolean_parameter(v, p->name, desc.deflt.boolean);
stp_set_boolean_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_CURVE:
if (!soft ||
!stp_check_curve_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_curve_parameter(v, p->name, desc.deflt.curve);
stp_set_curve_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
case STP_PARAMETER_TYPE_ARRAY:
if (!soft ||
!stp_check_array_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
stp_set_array_parameter(v, p->name, desc.deflt.array);
stp_set_array_parameter_active(v, p->name, STP_PARAMETER_ACTIVE);
}
break;
default:
break;
}
stp_parameter_description_destroy(&desc);
}
}
stp_parameter_list_destroy(params);
}
void
stp_set_printer_defaults(stp_vars_t *v, const stp_printer_t *printer)
{
stp_set_driver(v, stp_printer_get_driver(printer));
set_printer_defaults(v, 0, 0);
}
void
stp_set_printer_defaults_soft(stp_vars_t *v, const stp_printer_t *printer)
{
stp_set_driver(v, stp_printer_get_driver(printer));
set_printer_defaults(v, 0, 1);
}
void
stp_initialize_printer_defaults(void)
{
if (printer_list == NULL)
{
stpi_init_printer_list();
stp_deprintf
(STP_DBG_PRINTERS,
"stpi_family_register(): initialising printer_list...\n");
}
}
const stp_vars_t *
stp_printer_get_defaults(const stp_printer_t *printer)
{
if (! printer->vars_initialized)
{
stp_printer_t *nc_printer = (stp_printer_t *) stpi_cast_safe(printer);
stp_deprintf(STP_DBG_PRINTERS, " ==>init %s\n", printer->driver);
set_printer_defaults (nc_printer->printvars, 1, 0);
nc_printer->vars_initialized = 1;
}
return printer->printvars;
}
void
stp_get_media_size(const stp_vars_t *v, stp_dimension_t *width, stp_dimension_t *height)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->media_size)(v, width, height);
}
void
stp_get_imageable_area(const stp_vars_t *v,
stp_dimension_t *left, stp_dimension_t *right,
stp_dimension_t *bottom, stp_dimension_t *top)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->imageable_area)(v, left, right, bottom, top);
}
void
stp_get_maximum_imageable_area(const stp_vars_t *v,
stp_dimension_t *left, stp_dimension_t *right,
stp_dimension_t *bottom, stp_dimension_t *top)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->maximum_imageable_area)(v, left, right, bottom, top);
}
void
stp_get_size_limit(const stp_vars_t *v,
stp_dimension_t *max_width, stp_dimension_t *max_height,
stp_dimension_t *min_width, stp_dimension_t *min_height)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->limit)(v, max_width, max_height, min_width,min_height);
}
void
stp_describe_resolution(const stp_vars_t *v, stp_resolution_t *x, stp_resolution_t *y)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
(printfuncs->describe_resolution)(v, x, y);
}
const char *
stp_describe_output(const stp_vars_t *v)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
return (printfuncs->describe_output)(v);
}
int
stp_verify(stp_vars_t *v)
{
if (stp_get_verified(v))
return 1;
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
stp_vars_t *nv = stp_vars_create_copy(v);
int status;
stp_prune_inactive_options(nv);
status = (printfuncs->verify)(nv);
stp_set_verified(v, stp_get_verified(nv));
stp_vars_destroy(nv);
return status;
}
int
stp_print(const stp_vars_t *v, stp_image_t *image)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
return (printfuncs->print)(v, image);
}
int
stp_start_job(const stp_vars_t *v, stp_image_t *image)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
if (!stp_get_string_parameter(v, "JobMode") ||
strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
return 1;
if (printfuncs->start_job)
return (printfuncs->start_job)(v, image);
else
return 1;
}
int
stp_end_job(const stp_vars_t *v, stp_image_t *image)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
if (!stp_get_string_parameter(v, "JobMode") ||
strcmp(stp_get_string_parameter(v, "JobMode"), "Page") == 0)
return 1;
if (printfuncs->end_job)
return (printfuncs->end_job)(v, image);
else
return 1;
}
stp_string_list_t *
stp_get_external_options(const stp_vars_t *v)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
if (printfuncs->get_external_options)
return (printfuncs->get_external_options)(v);
else
return NULL;
}
const stp_papersize_t *
stpi_printer_describe_papersize(const stp_vars_t *v, const char *name)
{
const stp_printfuncs_t *printfuncs =
stpi_get_printfuncs(stp_get_printer(v));
return (printfuncs->describe_papersize)(v, name);
}
static int
verify_string_param(const stp_vars_t *v, const char *parameter,
stp_parameter_t *desc, int quiet)
{
stp_parameter_verify_t answer = PARAMETER_OK;
stp_dprintf(STP_DBG_VARS, v, " Verifying string %s\n", parameter);
if (desc->is_mandatory ||
stp_check_string_parameter(v, parameter, STP_PARAMETER_ACTIVE))
{
const char *checkval = stp_get_string_parameter(v, parameter);
stp_string_list_t *vptr = desc->bounds.str;
size_t count = 0;
stp_dprintf(STP_DBG_VARS, v, " value %s\n",
checkval ? checkval : "(null)");
if (vptr)
count = stp_string_list_count(vptr);
answer = PARAMETER_BAD;
if (checkval == NULL)
{
if (count == 0)
answer = PARAMETER_OK;
else
{
if (!quiet)
stp_eprintf(v, _("Value must be set for %s\n"), parameter);
answer = PARAMETER_BAD;
}
}
else if (count > 0)
{
if (stp_string_list_is_present(vptr, checkval))
answer = PARAMETER_OK;
if (!answer && !quiet)
stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter);
}
else if (strlen(checkval) == 0)
answer = PARAMETER_OK;
else if (!quiet)
stp_eprintf(v, _("`%s' is not a valid %s\n"), checkval, parameter);
}
stp_parameter_description_destroy(desc);
return answer;
}
static int
verify_double_param(const stp_vars_t *v, const char *parameter,
stp_parameter_t *desc, int quiet)
{
stp_dprintf(STP_DBG_VARS, v, " Verifying double %s\n", parameter);
if (desc->is_mandatory ||
stp_check_float_parameter(v, parameter, STP_PARAMETER_ACTIVE))
{
double checkval = stp_get_float_parameter(v, parameter);
if (checkval < desc->bounds.dbl.lower ||
checkval > desc->bounds.dbl.upper)
{
if (!quiet)
stp_eprintf(v, _("%s must be between %f and %f (is %f)\n"),
parameter, desc->bounds.dbl.lower,
desc->bounds.dbl.upper, checkval);
return PARAMETER_BAD;
}
}
return PARAMETER_OK;
}
static int
verify_int_param(const stp_vars_t *v, const char *parameter,
stp_parameter_t *desc, int quiet)
{
stp_dprintf(STP_DBG_VARS, v, " Verifying int %s\n", parameter);
if (desc->is_mandatory ||
stp_check_int_parameter(v, parameter, STP_PARAMETER_ACTIVE))
{
int checkval = stp_get_int_parameter(v, parameter);
if (checkval < desc->bounds.integer.lower ||
checkval > desc->bounds.integer.upper)
{
if (!quiet)
stp_eprintf(v, _("%s must be between %d and %d (is %d)\n"),
parameter, desc->bounds.integer.lower,
desc->bounds.integer.upper, checkval);
stp_parameter_description_destroy(desc);
return PARAMETER_BAD;
}
}
stp_parameter_description_destroy(desc);
return PARAMETER_OK;
}
static int
verify_dimension_param(const stp_vars_t *v, const char *parameter,
stp_parameter_t *desc, int quiet)
{
stp_dprintf(STP_DBG_VARS, v, " Verifying dimension %s\n", parameter);
if (desc->is_mandatory ||
stp_check_dimension_parameter(v, parameter, STP_PARAMETER_ACTIVE))
{
stp_dimension_t checkval = stp_get_dimension_parameter(v, parameter);
if (checkval < desc->bounds.dimension.lower ||
checkval > desc->bounds.dimension.upper)
{
if (!quiet)
stp_eprintf(v, _("%s must be between %f and %f (is %f)\n"),
parameter, desc->bounds.dimension.lower,
desc->bounds.dimension.upper, checkval);
stp_parameter_description_destroy(desc);
return PARAMETER_BAD;
}
}
stp_parameter_description_destroy(desc);
return PARAMETER_OK;
}
static int
verify_curve_param(const stp_vars_t *v, const char *parameter,
stp_parameter_t *desc, int quiet)
{
stp_parameter_verify_t answer = 1;
stp_dprintf(STP_DBG_VARS, v, " Verifying curve %s\n", parameter);
if (desc->bounds.curve &&
(desc->is_mandatory ||
stp_check_curve_parameter(v, parameter, STP_PARAMETER_ACTIVE)))
{
const stp_curve_t *checkval = stp_get_curve_parameter(v, parameter);
if (checkval)
{
double u0, l0;
double u1, l1;
stp_curve_get_bounds(checkval, &l0, &u0);
stp_curve_get_bounds(desc->bounds.curve, &l1, &u1);
if (u0 > u1 || l0 < l1)
{
if (!quiet)
stp_eprintf(v, _("%s bounds must be between %f and %f\n"),
parameter, l1, u1);
answer = PARAMETER_BAD;
}
if (stp_curve_get_wrap(checkval) !=
stp_curve_get_wrap(desc->bounds.curve))
{
if (!quiet)
stp_eprintf(v, _("%s wrap mode must be %s\n"),
parameter,
(stp_curve_get_wrap(desc->bounds.curve) ==
STP_CURVE_WRAP_NONE) ?
_("no wrap") : _("wrap around"));
answer = PARAMETER_BAD;
}
}
}
stp_parameter_description_destroy(desc);
return answer;
}
stp_parameter_verify_t
stp_verify_parameter(const stp_vars_t *v, const char *parameter,
int quiet)
{
stp_parameter_t desc;
quiet = 0;
stp_describe_parameter(v, parameter, &desc);
stp_dprintf(STP_DBG_VARS, v, " Verifying %s %d %d\n", parameter,
desc.is_active, desc.read_only);
if (!desc.is_active || desc.read_only)
{
stp_parameter_description_destroy(&desc);
return PARAMETER_INACTIVE;
}
switch (desc.p_type)
{
case STP_PARAMETER_TYPE_STRING_LIST:
return verify_string_param(v, parameter, &desc, quiet);
case STP_PARAMETER_TYPE_DOUBLE:
return verify_double_param(v, parameter, &desc, quiet);
case STP_PARAMETER_TYPE_INT:
return verify_int_param(v, parameter, &desc, quiet);
case STP_PARAMETER_TYPE_DIMENSION:
return verify_dimension_param(v, parameter, &desc, quiet);
case STP_PARAMETER_TYPE_CURVE:
return verify_curve_param(v, parameter, &desc, quiet);
case STP_PARAMETER_TYPE_RAW:
case STP_PARAMETER_TYPE_FILE:
stp_parameter_description_destroy(&desc);
return PARAMETER_OK; /* No way to verify this here */
case STP_PARAMETER_TYPE_BOOLEAN:
stp_parameter_description_destroy(&desc);
return PARAMETER_OK; /* Booleans always OK */
default:
if (!quiet)
stp_eprintf(v, _("Unknown type parameter %s (%d)\n"),
parameter, desc.p_type);
stp_parameter_description_destroy(&desc);
return 0;
}
}
#define CHECK_INT_RANGE(v, component, min, max) \
do \
{ \
if (stp_get_##component((v)) < (min) || stp_get_##component((v)) > (max)) \
{ \
answer = 0; \
stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"), \
#component, stp_get_##component(v), min, max); \
} \
} while (0)
#define CHECK_INT_RANGE_INTERNAL(v, component, min, max) \
do \
{ \
if (stpi_get_##component((v)) < (min) || stpi_get_##component((v)) > (max)) \
{ \
answer = 0; \
stp_eprintf(v, _("%s out of range (value %d, min %d, max %d)\n"), \
#component, stpi_get_##component(v), min, max); \
} \
} while (0)
typedef struct
{
char *data;
size_t bytes;
} errbuf_t;
static void
fill_buffer_writefunc(void *priv, const char *buffer, size_t bytes)
{
errbuf_t *errbuf = (errbuf_t *) priv;
if (errbuf->bytes == 0)
errbuf->data = stp_malloc(bytes + 1);
else
errbuf->data = stp_realloc(errbuf->data, errbuf->bytes + bytes + 1);
memcpy(errbuf->data + errbuf->bytes, buffer, bytes);
errbuf->bytes += bytes;
errbuf->data[errbuf->bytes] = '\0';
}
int
stp_verify_printer_params(stp_vars_t *v)
{
errbuf_t errbuf;
stp_outfunc_t ofunc = stp_get_errfunc(v);
void *odata = stp_get_errdata(v);
stp_parameter_list_t params;
int nparams;
int i;
int answer = 1;
stp_dimension_t left, top, bottom, right;
const char *pagesize = stp_get_string_parameter(v, "PageSize");
stp_dprintf(STP_DBG_VARS, v, "** Entering stp_verify_printer_params(0x%p)\n",
(void *) v);
stp_set_errfunc((stp_vars_t *) v, fill_buffer_writefunc);
stp_set_errdata((stp_vars_t *) v, &errbuf);
errbuf.data = NULL;
errbuf.bytes = 0;
if (pagesize && strlen(pagesize) > 0)
{
if (stp_verify_parameter(v, "PageSize", 0) == 0)
answer = 0;
}
else
{
stp_dimension_t width, height, min_height, min_width;
stp_get_size_limit(v, &width, &height, &min_width, &min_height);
if (stp_get_page_height(v) <= min_height ||
stp_get_page_height(v) > height ||
stp_get_page_width(v) <= min_width || stp_get_page_width(v) > width)
{
answer = 0;
stp_eprintf(v, _("Page size is not valid\n"));
}
stp_dprintf(STP_DBG_PAPER, v,
"page size max %f %f min %f %f actual %f %f\n",
width, height, min_width, min_height,
stp_get_page_width(v), stp_get_page_height(v));
}
stp_get_imageable_area(v, &left, &right, &bottom, &top);
stp_dprintf(STP_DBG_PAPER, v,
"page left %f top %f right %f bottom %f\n",
left, top, right, bottom);
stp_dprintf(STP_DBG_PAPER, v,
"requested left %f top %f width %f height %f\n",
stp_get_left(v), stp_get_top(v),
stp_get_width(v), stp_get_height(v));
if (stp_get_top(v) < top)
{
answer = 0;
stp_eprintf(v, _("Top margin must not be less than %f\n"), top);
}
if (stp_get_left(v) < left)
{
answer = 0;
stp_eprintf(v, _("Left margin must not be less than %f\n"), left);
}
if (stp_get_height(v) <= 0)
{
answer = 0;
stp_eprintf(v, _("Height must be greater than zero\n"));
}
if (stp_get_width(v) <= 0)
{
answer = 0;
stp_eprintf(v, _("Width must be greater than zero\n"));
}
if (stp_get_left(v) + stp_get_width(v) > right)
{
answer = 0;
stp_eprintf(v, _("Image is too wide for the page: left margin is %f, width %f, right edge is %f\n"),
stp_get_left(v), stp_get_width(v), right);
}
if (stp_get_top(v) + stp_get_height(v) > bottom)
{
answer = 0;
stp_eprintf(v, _("Image is too long for the page: top margin is %f, height %f, bottom edge is %f\n"),
stp_get_top(v), stp_get_height(v), bottom);
}
params = stp_get_parameter_list(v);
nparams = stp_parameter_list_count(params);
for (i = 0; i < nparams; i++)
{
const stp_parameter_t *param = stp_parameter_list_param(params, i);
stp_dprintf(STP_DBG_VARS, v, "Checking %s %d %d\n", param->name,
param->is_active, param->verify_this_parameter);
if (strcmp(param->name, "PageSize") != 0 &&
param->is_active && param->verify_this_parameter &&
stp_verify_parameter(v, param->name, 0) == 0)
answer = 0;
}
stp_parameter_list_destroy(params);
stp_set_errfunc((stp_vars_t *) v, ofunc);
stp_set_errdata((stp_vars_t *) v, odata);
stp_set_verified((stp_vars_t *) v, answer);
if (errbuf.bytes > 0)
{
stp_eprintf(v, "%s", errbuf.data);
stp_free(errbuf.data);
}
stp_dprintf(STP_DBG_VARS, v, "** Exiting stp_verify_printer_params(0x%p) => %d\n",
(void *) v, answer);
return answer;
}
static const stp_vars_t *
stp_find_params(const char *name, const char *family)
{
if (printvars_list)
{
char *stmp =
stp_malloc(strlen(family) + strlen("::") + strlen(name) + 1);
stp_list_item_t *item;
strcpy(stmp, family);
strcat(stmp, "::");
strcat(stmp, name);
item = stp_list_get_item_by_name(printvars_list, stmp);
if (item)
{
stp_free(stmp);
return ((const stp_printvars_t *)
stp_list_item_get_data(item))->printvars;
}
strcpy(stmp, name);
item = stp_list_get_item_by_name(printvars_list, stmp);
stp_free(stmp);
if (item)
return ((const stp_printvars_t *)
stp_list_item_get_data(item))->printvars;
}
return NULL;
}
/* Why couldn't strcmp be a valid comparison function... */
static int
compare_names(const void *n1, const void *n2)
{
return strcmp((const char *) n2, (const char *) n2);
}
void
stpi_find_duplicate_printers(void)
{
size_t nelts = stp_list_get_length(printer_list);
const char **str_data = stp_zalloc(sizeof(const char *) * nelts);
stp_list_item_t *printer_item = stp_list_get_start(printer_list);
size_t i = 0;
int found_dups = 0;
const stp_printer_t *printer;
while (printer_item)
{
printer = stp_list_item_get_data(printer_item);
STPI_ASSERT(i < nelts, NULL);
str_data[i] = printer->driver;
printer_item = stp_list_item_next(printer_item);
i++;
}
qsort(str_data, nelts, sizeof(const char *), compare_names);
for (i = 0; i < nelts - 1; i++)
{
if (!strcmp(str_data[i], str_data[i+1]))
{
printer_item =
stp_list_get_item_by_name(printer_list, str_data[i]);
printer = stp_list_item_get_data(printer_item);
stp_erprintf("Duplicate printer entry '%s' (%s)\n",
printer->driver, printer->long_name);
found_dups++;
}
}
printer_item = stp_list_get_start(printer_list);
i = 0;
while (printer_item)
{
printer = stp_list_item_get_data(printer_item);
STPI_ASSERT(i < nelts, NULL);
str_data[i] = printer->long_name;
printer_item = stp_list_item_next(printer_item);
i++;
}
qsort(str_data, nelts, sizeof(const char *), compare_names);
for (i = 0; i < nelts - 1; i++)
{
if (!strcmp(str_data[i], str_data[i+1]))
{
printer_item =
stp_list_get_item_by_long_name(printer_list, str_data[i]);
printer = stp_list_item_get_data(printer_item);
stp_erprintf("Duplicate printer entry '%s' (%s)\n",
printer->driver, printer->long_name);
found_dups++;
}
}
stp_free(str_data);
if (found_dups > 0)
{
stp_erprintf("FATAL Duplicate printers in printer list. Aborting!\n");
stp_abort();
}
}
int
stpi_family_register(stp_list_t *family)
{
stp_list_item_t *printer_item;
const stp_printer_t *printer;
if (printer_list == NULL)
{
stpi_init_printer_list();
stp_deprintf
(STP_DBG_PRINTERS,
"stpi_family_register(): initialising printer_list...\n");
}
if (family)
{
/* Check for duplicates after loading printers */
printer_item = stp_list_get_start(family);
while(printer_item)
{
printer = (const stp_printer_t *) stp_list_item_get_data(printer_item);
stp_list_item_create(printer_list, NULL, printer);
printer_item = stp_list_item_next(printer_item);
}
}
return 0;
}
int
stpi_family_unregister(stp_list_t *family)
{
stp_list_item_t *printer_item;
stp_list_item_t *old_printer_item;
const stp_printer_t *printer;
if (printer_list == NULL)
{
stpi_init_printer_list();
stp_deprintf
(STP_DBG_PRINTERS,
"stpi_family_unregister(): initialising printer_list...\n");
}
if (family)
{
printer_item = stp_list_get_start(family);
while(printer_item)
{
printer = (const stp_printer_t *) stp_list_item_get_data(printer_item);
old_printer_item =
stp_list_get_item_by_name(printer_list, printer->driver);
if (old_printer_item)
stp_list_item_destroy(printer_list, old_printer_item);
printer_item = stp_list_item_next(printer_item);
}
}
return 0;
}
static stp_printvars_t *
stp_printvars_create_from_xmltree(stp_mxml_node_t *printer,
const char *family)
{
stp_mxml_node_t *prop; /* Temporary node pointer */
const char *stmp; /* Temporary string */
char *sbuf;
stp_printvars_t *outprintvars;
outprintvars = stp_zalloc(sizeof(stp_printvars_t));
if (!outprintvars)
return NULL;
outprintvars->printvars = stp_vars_create();
if (outprintvars->printvars == NULL)
{
stp_free(outprintvars);
return NULL;
}
stmp = stp_mxmlElementGetAttr(printer, "name");
if (!stmp)
{
stp_vars_destroy(outprintvars->printvars);
stp_free(outprintvars);
return NULL;
}
sbuf = stp_malloc(strlen(family) + strlen("::") + strlen(stmp) + 1);
strcpy(sbuf, family);
strcat(sbuf, "::");
strcat(sbuf, stmp);
outprintvars->name = sbuf;
prop = printer->child;
stp_deprintf(STP_DBG_XML, ">>stp_printvars_create_from_xmltree: %p, %s\n",
(void *) (outprintvars->printvars), outprintvars->name);
stp_vars_fill_from_xmltree(prop, outprintvars->printvars);
stp_deprintf(STP_DBG_XML, "<printvars), outprintvars->name);
return outprintvars;
}
/*
* Parse the printer node, and return the generated printer. Returns
* NULL on failure.
*/
static stp_printer_t*
stp_printer_create_from_xmltree(stp_mxml_node_t *printer, /* The printer node */
const char *family, /* Family name */
const stp_printfuncs_t *printfuncs)
/* Family printfuncs */
{
stp_mxml_node_t *prop; /* Temporary node pointer */
stp_mxml_node_t *child;
const char *stmp; /* Temporary string */
stp_printer_t *outprinter; /* Generated printer */
size_t slen = 0;
int
driver = 0, /* Check driver */
long_name = 0;
outprinter = stp_zalloc(sizeof(stp_printer_t));
if (!outprinter)
return NULL;
stmp = stp_mxmlElementGetAttr(printer, "parameters");
if (stmp && !stp_find_params(stmp, family))
stp_erprintf("stp_printer_create_from_xmltree: cannot find parameters %s::%s\n",
family, stmp);
if (stmp && stp_find_params(stmp, family))
outprinter->printvars = stp_vars_create_copy(stp_find_params(stmp, family));
else
outprinter->printvars = stp_vars_create();
if (outprinter->printvars == NULL)
{
stp_free(outprinter);
return NULL;
}
stmp = stp_mxmlElementGetAttr(printer, "driver");
stp_set_driver(outprinter->printvars, (const char *) stmp);
outprinter->long_name = stp_strdup(stp_mxmlElementGetAttr(printer, "name"));
outprinter->manufacturer = stp_strdup(stp_mxmlElementGetAttr(printer, "manufacturer"));
outprinter->model = stp_xmlstrtol(stp_mxmlElementGetAttr(printer, "model"));
outprinter->family = stp_strdup((const char *) family);
stmp = stp_mxmlElementGetAttr(printer, "deviceid");
if (stmp)
outprinter->device_id = stp_strdup(stmp);
child = printer->child;
while (child)
{
if (child->type == STP_MXML_TEXT)
{
if (outprinter->comment)
{
size_t oslen = slen;
slen += strlen(child->value.text.string);
if (child->value.text.whitespace)
slen += 1;
outprinter->comment = stp_realloc(outprinter->comment, slen + 1);
(void) memset(outprinter->comment + oslen, 0, slen - oslen);
if (child->value.text.whitespace)
outprinter->comment[oslen++] = ' ';
strncat(outprinter->comment + oslen,
child->value.text.string, slen - oslen);
}
else
{
outprinter->comment = stp_strdup(child->value.text.string);
slen = strlen(outprinter->comment);
}
}
child = child->next;
}
if (stp_get_driver(outprinter->printvars))
driver = 1;
if (outprinter->long_name)
long_name = 1;
outprinter->printfuncs = printfuncs;
prop = printer->child;
stp_vars_fill_from_xmltree(prop, outprinter->printvars);
if (driver && long_name && printfuncs)
{
if (stp_get_debug_level() & STP_DBG_XML)
{
stmp = stp_mxmlElementGetAttr(printer, "driver");
stp_erprintf("stp_printer_create_from_xmltree: printer: %s\n", stmp);
}
outprinter->driver = stp_get_driver(outprinter->printvars);
return outprinter;
}
stp_free(outprinter);
return NULL;
}
/*
* Parse the node.
*/
static void
stpi_xml_process_family(stp_mxml_node_t *family) /* The family node */
{
stp_list_t *family_module_list = NULL; /* List of valid families */
stp_list_item_t *family_module_item; /* Current family */
const char *family_name; /* Name of family */
stp_mxml_node_t *printer; /* printer child node */
stp_module_t *family_module_data; /* Family module data */
stp_family_t *family_data = NULL; /* Family data */
int family_valid = 0; /* Is family valid? */
family_module_list = stp_module_get_class(STP_MODULE_CLASS_FAMILY);
if (!family_module_list)
return;
family_name = stp_mxmlElementGetAttr(family, "name");
family_module_item = stp_list_get_start(family_module_list);
while (family_module_item)
{
family_module_data = (stp_module_t *)
stp_list_item_get_data(family_module_item);
if (!strcmp(family_name, family_module_data->name))
{
stp_deprintf(STP_DBG_XML,
"stpi_xml_process_family: family module: %s\n",
family_module_data->name);
family_data = family_module_data->syms;
if (family_data->printer_list == NULL)
family_data->printer_list = stp_list_create();
family_valid = 1;
}
family_module_item = stp_list_item_next(family_module_item);
}
printer = family->child;
while (family_valid && printer)
{
if (printer->type == STP_MXML_ELEMENT)
{
const char *printer_name = printer->value.element.name;
if (!strcmp(printer_name, "printer"))
{
stp_printer_t *outprinter =
stp_printer_create_from_xmltree(printer, family_name,
family_data->printfuncs);
if (outprinter)
stp_list_item_create(family_data->printer_list, NULL,
outprinter);
}
else if (!strcmp(printer_name, "parameters"))
{
stp_printvars_t *printvars =
stp_printvars_create_from_xmltree(printer, family_name);
if (printvars)
{
stpi_init_printvars_list();
stp_list_item_create(printvars_list, NULL, printvars);
}
}
}
printer = printer->next;
}
stp_list_destroy(family_module_list);
return;
}
/*
* Parse the node.
*/
static int
stpi_xml_process_printdef(stp_mxml_node_t *printdef, const char *file) /* The printdef node */
{
stp_mxml_node_t *family; /* Family child node */
family = printdef->child;
while (family)
{
if (family->type == STP_MXML_ELEMENT)
{
const char *family_name = family->value.element.name;
if (!strcmp(family_name, "family"))
{
stpi_xml_process_family(family);
}
}
family = family->next;
}
return 1;
}
void
stpi_init_printer(void)
{
stp_register_xml_parser("printdef", stpi_xml_process_printdef);
}