/* * * 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 #ifdef HAVE_LIMITS_H #include #endif #include #include #include typedef struct { char *name; stp_papersize_list_t *list; } papersize_list_impl_t; static stp_list_t *list_of_papersize_lists = NULL; static void papersize_list_impl_freefunc(void *item) { papersize_list_impl_t *papersize_list = (papersize_list_impl_t *) item; stp_list_destroy(papersize_list->list); STP_SAFE_FREE(papersize_list->name); STP_SAFE_FREE(papersize_list); } static const char * papersize_list_impl_namefunc(const void *item) { return ((const papersize_list_impl_t *) item)->name; } static const char * papersize_list_impl_long_namefunc(const void *item) { return ((const papersize_list_impl_t *) item)->name; } static void check_list_of_papersize_lists(void) { if (! list_of_papersize_lists) { stp_deprintf(STP_DBG_PAPER, "Initializing...\n"); list_of_papersize_lists = stp_list_create(); stp_list_set_freefunc(list_of_papersize_lists, papersize_list_impl_freefunc); stp_list_set_namefunc(list_of_papersize_lists, papersize_list_impl_namefunc); stp_list_set_long_namefunc(list_of_papersize_lists, papersize_list_impl_long_namefunc); } } static void stpi_papersize_freefunc(void *item) { stp_papersize_t *paper = (stp_papersize_t *) (item); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" STP_SAFE_FREE(paper->name); STP_SAFE_FREE(paper->text); STP_SAFE_FREE(paper->comment); #pragma GCC diagnostic pop STP_SAFE_FREE(paper); } static const char * stpi_papersize_namefunc(const void *item) { const stp_papersize_t *paper = (const stp_papersize_t *) (item); return paper->name; } static const char * stpi_papersize_long_namefunc(const void *item) { const stp_papersize_t *paper = (const stp_papersize_t *) (item); return paper->text; } stp_papersize_list_t * stpi_create_papersize_list(void) { stp_list_t *papersize_list = stp_list_create(); stp_list_set_freefunc(papersize_list, stpi_papersize_freefunc); stp_list_set_namefunc(papersize_list, stpi_papersize_namefunc); stp_list_set_long_namefunc(papersize_list, stpi_papersize_long_namefunc); return (stp_papersize_list_t *) papersize_list; } int stpi_papersize_create(stp_papersize_list_t *list, stp_papersize_t *p) { stp_list_item_t *papersize_item; /* * Check the paper does not already exist * Not the most efficient way of doing it, but the number of papers * is not large enough to be a significant bottleneck. */ papersize_item = stp_list_get_start(list); while (papersize_item) { const stp_papersize_t *ep = (const stp_papersize_t *) stp_list_item_get_data(papersize_item); if (ep && !strcmp(p->name, ep->name)) { stp_erprintf("Duplicate paper size `%s'\n", p->name); stpi_papersize_freefunc(p); return 1; } papersize_item = stp_list_item_next(papersize_item); } /* Add paper to list */ stp_list_item_create(list, NULL, (void *) p); return 0; } int stpi_papersize_count(const stp_papersize_list_t *paper_size_list) { return stp_list_get_length(paper_size_list); } const stp_papersize_t * stpi_get_papersize_by_name(const stp_papersize_list_t *list, const char *name) { stp_list_item_t *paper; paper = stp_list_get_item_by_name(list, name); if (!paper) return NULL; else return (const stp_papersize_t *) stp_list_item_get_data(paper); } const stp_papersize_t * stpi_get_listed_papersize(const char *name, const char *papersize_list) { const stp_papersize_list_t *list = stpi_get_papersize_list_named(papersize_list, ""); if (list) return stpi_get_papersize_by_name(list, name); else return NULL; } const stp_papersize_t * stpi_standard_describe_papersize(const stp_vars_t *v, const char *name) { STPI_ASSERT(v, NULL); return stpi_get_listed_papersize(name, "standard"); } const stp_papersize_t * stp_describe_papersize(const stp_vars_t *v, const char *name) { return stpi_printer_describe_papersize(v, name); } static int papersize_size_mismatch(stp_dimension_t l, stp_dimension_t w, const stp_papersize_t *val) { stp_dimension_t hdiff = STP_DABS(l - (stp_dimension_t) val->height); stp_dimension_t vdiff = STP_DABS(w - (stp_dimension_t) val->width); return hdiff > vdiff ? hdiff : vdiff; } static const stp_papersize_t * get_papersize_by_size_internal(const stp_papersize_list_t *list, stp_dimension_t l, stp_dimension_t w, int exact) { int score = INT_MAX; const stp_papersize_t *ref = NULL; const stp_papersize_t *val = NULL; const stp_papersize_list_item_t *ptli = stpi_papersize_list_get_start(list); STPI_ASSERT(list, NULL); while (ptli) { val = stpi_paperlist_item_get_data(ptli); if (val->width == w && val->height == l) { if (val->top == 0 && val->left == 0 && val->bottom == 0 && val->right == 0) return val; else ref = val; } else if (!exact) { int myscore = papersize_size_mismatch(l, w, val); if (myscore < score && myscore < 5) { ref = val; score = myscore; } } ptli = stpi_paperlist_item_next(ptli); } return ref; } const stp_papersize_t * stpi_get_papersize_by_size(const stp_papersize_list_t *list, stp_dimension_t l, stp_dimension_t w) { return get_papersize_by_size_internal(list, l, w, 0); } const stp_papersize_t * stpi_get_papersize_by_size_exact(const stp_papersize_list_t *list, stp_dimension_t l, stp_dimension_t w) { return get_papersize_by_size_internal(list, l, w, 1); } void stp_default_media_size(const stp_vars_t *v, /* I */ stp_dimension_t *width, /* O - Width in points */ stp_dimension_t *height) /* O - Height in points */ { if (stp_get_page_width(v) > 0 && stp_get_page_height(v) > 0) { *width = stp_get_page_width(v); *height = stp_get_page_height(v); } else { const char *page_size = stp_get_string_parameter(v, "PageSize"); const stp_papersize_t *papersize = NULL; if (page_size) papersize = stp_describe_papersize(v, page_size); if (!papersize) { *width = 1; *height = 1; } else { *width = papersize->width; *height = papersize->height; } if (*width == 0) *width = 612; if (*height == 0) *height = 792; } } /* * Process the node. */ static stp_papersize_t * stp_xml_process_paper(stp_mxml_node_t *paper) /* The paper node */ { stp_mxml_node_t *prop; /* Temporary node pointer */ const char *stmp; /* Temporary string */ /* props[] (unused) is the correct tag sequence */ /* const char *props[] = { "name", "description", "width", "height", "left", "right", "bottom", "top", "unit", "type", NULL };*/ stp_papersize_t *outpaper; /* Generated paper */ int id = 0, /* Check id is present */ name = 0, /* Check name is present */ height = 0, /* Check height is present */ width = 0, /* Check width is present */ unit = 0; /* Check unit is present */ if (stp_get_debug_level() & STP_DBG_XML) { stmp = stp_mxmlElementGetAttr(paper, (const char*) "name"); stp_erprintf("stp_xml_process_paper: name: %s\n", stmp); } outpaper = stp_zalloc(sizeof(stp_papersize_t)); if (!outpaper) return NULL; outpaper->name = stp_strdup(stp_mxmlElementGetAttr(paper, "name")); outpaper->top = 0; outpaper->left = 0; outpaper->bottom = 0; outpaper->right = 0; outpaper->paper_size_type = PAPERSIZE_TYPE_STANDARD; if (outpaper->name) id = 1; prop = paper->child; while(prop) { if (prop->type == STP_MXML_ELEMENT) { const char *prop_name = prop->value.element.name; if (!strcmp(prop_name, "description")) { outpaper->text = stp_strdup(stp_mxmlElementGetAttr(prop, "value")); name = 1; } if (!strcmp(prop_name, "comment")) outpaper->comment = stp_strdup(stp_mxmlElementGetAttr(prop, "value")); if (!strcmp(prop_name, "width")) { stmp = stp_mxmlElementGetAttr(prop, "value"); if (stmp) { outpaper->width = stp_xmlstrtodim(stmp); width = 1; } } if (!strcmp(prop_name, "height")) { stmp = stp_mxmlElementGetAttr(prop, "value"); if (stmp) { outpaper->height = stp_xmlstrtodim(stmp); height = 1; } } if (!strcmp(prop_name, "left")) { stmp = stp_mxmlElementGetAttr(prop, "value"); outpaper->left = stp_xmlstrtodim(stmp); } if (!strcmp(prop_name, "right")) { stmp = stp_mxmlElementGetAttr(prop, "value"); outpaper->right = stp_xmlstrtodim(stmp); } if (!strcmp(prop_name, "bottom")) { stmp = stp_mxmlElementGetAttr(prop, "value"); outpaper->bottom = stp_xmlstrtodim(stmp); } if (!strcmp(prop_name, "top")) { stmp = stp_mxmlElementGetAttr(prop, "value"); outpaper->top = stp_xmlstrtodim(stmp); } if (!strcmp(prop_name, "unit")) { stmp = stp_mxmlElementGetAttr(prop, "value"); if (stmp) { if (!strcmp(stmp, "english")) outpaper->paper_unit = PAPERSIZE_ENGLISH_STANDARD; else if (!strcmp(stmp, "english-extended")) outpaper->paper_unit = PAPERSIZE_ENGLISH_EXTENDED; else if (!strcmp(stmp, "metric")) outpaper->paper_unit = PAPERSIZE_METRIC_STANDARD; else if (!strcmp(stmp, "metric-extended")) outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED; /* Default unit */ else outpaper->paper_unit = PAPERSIZE_METRIC_EXTENDED; unit = 1; } } if (!strcmp(prop_name, "type")) { stmp = stp_mxmlElementGetAttr(prop, "value"); if (stmp) { if (!strcmp(stmp, "envelope")) outpaper->paper_size_type = PAPERSIZE_TYPE_ENVELOPE; else outpaper->paper_size_type = PAPERSIZE_TYPE_STANDARD; } } } prop = prop->next; } if (id && name && width && height && unit) /* Margins and type are optional */ return outpaper; stp_free(outpaper); outpaper = NULL; return NULL; } /* * Parse the node. */ static int stp_xml_process_papersize_def(stp_mxml_node_t *paperdef, const char *file, stp_papersize_list_t *papersize_list) { stp_mxml_node_t *paper; /* paper node pointer */ stp_papersize_t *outpaper; /* Generated paper */ paper = paperdef->child; while (paper) { if (paper->type == STP_MXML_ELEMENT) { const char *papersize_name = paper->value.element.name; if (!strcmp(papersize_name, "paper")) { outpaper = stp_xml_process_paper(paper); if (outpaper) stpi_papersize_create(papersize_list, outpaper); } } paper = paper->next; } return 1; } const stp_papersize_list_t * stpi_get_papersize_list_named(const char *name, const char *file) { stp_list_item_t *item; papersize_list_impl_t *impl; check_list_of_papersize_lists(); item = stp_list_get_item_by_name(list_of_papersize_lists, name); if (item) { impl = (papersize_list_impl_t *) stp_list_item_get_data(item); } else { char buf[MAXPATHLEN+1]; stp_deprintf(STP_DBG_PAPER, "Loading paper list %s from %s\n", name, file ? file : "(null)"); if (! file) return NULL; else if (!strcmp(file, "")) (void) snprintf(buf, MAXPATHLEN, "papers/%s.xml", name); else strncpy(buf, file, MAXPATHLEN); stp_mxml_node_t *node = stp_xml_parse_file_from_path_safe(buf, "paperdef", NULL); const char *stmp = stp_mxmlElementGetAttr(node, "name"); STPI_ASSERT(stmp && !strcmp(name, stmp), NULL); impl = stp_malloc(sizeof(papersize_list_impl_t)); impl->name = stp_strdup(name); impl->list = stpi_create_papersize_list(); stp_deprintf(STP_DBG_PAPER, " Loading %s\n", stmp); stp_list_item_create(list_of_papersize_lists, NULL, impl); stp_xml_process_papersize_def(node, buf, impl->list); } return impl->list; } stp_papersize_list_t * stpi_find_papersize_list_named(const char *name) { stp_list_item_t *item; check_list_of_papersize_lists(); item = stp_list_get_item_by_name(list_of_papersize_lists, name); if (item) { papersize_list_impl_t *impl = (papersize_list_impl_t *) stp_list_item_get_data(item); if (impl) return impl->list; } return NULL; } stp_papersize_list_t * stpi_new_papersize_list(const char *name) { stp_list_item_t *item; papersize_list_impl_t *impl; check_list_of_papersize_lists(); item = stp_list_get_item_by_name(list_of_papersize_lists, name); if (item) return NULL; impl = stp_malloc(sizeof(papersize_list_impl_t)); impl->name = stp_strdup(name); impl->list = stpi_create_papersize_list(); stp_list_item_create(list_of_papersize_lists, NULL, impl); return impl->list; } const stp_papersize_list_t * stpi_get_standard_papersize_list(void) { return stpi_get_papersize_list_named("standard", ""); }