1/* 2 * "$Id: escp2-papers.c,v 1.119 2010/08/04 00:33:56 rlk Exp $" 3 * 4 * Print plug-in EPSON ESC/P2 driver 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 eral 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#ifdef HAVE_CONFIG_H 25#include <config.h> 26#endif 27#include <gutenprint/gutenprint.h> 28#include "gutenprint-internal.h" 29#include <gutenprint/gutenprint-intl-internal.h> 30#include "print-escp2.h" 31 32static stp_mxml_node_t * 33get_media_size_xml(const stp_vars_t *v) 34{ 35 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 36 return printdef->media_sizes; 37} 38 39int 40stp_escp2_load_media_sizes(const stp_vars_t *v, const char *name) 41{ 42 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 43 stp_list_t *dirlist = stpi_data_path(); 44 stp_list_item_t *item; 45 int found = 0; 46 item = stp_list_get_start(dirlist); 47 while (item) 48 { 49 const char *dn = (const char *) stp_list_item_get_data(item); 50 char *ffn = stpi_path_merge(dn, name); 51 stp_mxml_node_t *sizes = 52 stp_mxmlLoadFromFile(NULL, ffn, STP_MXML_NO_CALLBACK); 53 stp_free(ffn); 54 if (sizes) 55 { 56 stp_mxml_node_t **xnode = 57 (stp_mxml_node_t **) &(printdef->media_sizes); 58 *xnode = sizes; 59 found = 1; 60 break; 61 } 62 item = stp_list_item_next(item); 63 } 64 stp_list_destroy(dirlist); 65 STPI_ASSERT(found, v); 66 return found; 67} 68 69void 70stp_escp2_set_media_size(stp_vars_t *v, const stp_vars_t *src) 71{ 72 const char *name = stp_get_string_parameter(src, "PageSize"); 73 if (name) 74 { 75 stp_mxml_node_t *node = get_media_size_xml(src); 76 stp_mxml_node_t *xnode = stp_mxmlFindElement(node, node, "MediaSize", 77 "name", name, STP_MXML_DESCEND); 78 if (xnode) 79 { 80 stp_vars_fill_from_xmltree_ref(xnode->child, node, v); 81 return; 82 } 83 xnode = stp_mxmlFindElement(node, node, "MediaSize", "type", "default", 84 STP_MXML_DESCEND); 85 if (xnode) 86 { 87 stp_vars_fill_from_xmltree_ref(xnode->child, node, v); 88 return; 89 } 90 } 91} 92 93static const char * 94paper_namefunc(const void *item) 95{ 96 const paper_t *p = (const paper_t *) (item); 97 return p->cname; 98} 99 100int 101stp_escp2_load_media(const stp_vars_t *v, const char *name) 102{ 103 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 104 stp_list_t *dirlist = stpi_data_path(); 105 stp_list_item_t *item; 106 int found = 0; 107 item = stp_list_get_start(dirlist); 108 while (item) 109 { 110 const char *dn = (const char *) stp_list_item_get_data(item); 111 char *ffn = stpi_path_merge(dn, name); 112 stp_mxml_node_t *media = 113 stp_mxmlLoadFromFile(NULL, ffn, STP_MXML_NO_CALLBACK); 114 stp_free(ffn); 115 if (media) 116 { 117 stp_mxml_node_t **xnode = 118 (stp_mxml_node_t **) &(printdef->media); 119 stp_list_t **xlist = 120 (stp_list_t **) &(printdef->media_cache); 121 stp_string_list_t **xpapers = 122 (stp_string_list_t **) &(printdef->papers); 123 stp_mxml_node_t *node = stp_mxmlFindElement(media, media, 124 "escp2:papers", NULL, 125 NULL, STP_MXML_DESCEND); 126 *xnode = media; 127 *xlist = stp_list_create(); 128 stp_list_set_namefunc(*xlist, paper_namefunc); 129 *xpapers = stp_string_list_create(); 130 if (node) 131 { 132 node = node->child; 133 while (node) 134 { 135 if (node->type == STP_MXML_ELEMENT && 136 strcmp(node->value.element.name, "paper") == 0) 137 stp_string_list_add_string(*xpapers, 138 stp_mxmlElementGetAttr(node, "name"), 139 stp_mxmlElementGetAttr(node, "text")); 140 node = node->next; 141 } 142 } 143 found = 1; 144 break; 145 } 146 item = stp_list_item_next(item); 147 } 148 stp_list_destroy(dirlist); 149 STPI_ASSERT(found, v); 150 return found; 151} 152 153static stp_mxml_node_t * 154get_media_xml(const stp_vars_t *v) 155{ 156 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 157 return printdef->media; 158} 159 160static stp_list_t * 161get_media_cache(const stp_vars_t *v) 162{ 163 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 164 return printdef->media_cache; 165} 166 167int 168stp_escp2_has_media_feature(const stp_vars_t *v, const char *name) 169{ 170 stp_mxml_node_t *doc = get_media_xml(v); 171 if (doc) 172 return (stp_mxmlFindElement(doc, doc, "feature", "name", name, 173 STP_MXML_DESCEND) != NULL); 174 else 175 return 0; 176} 177 178 179static paper_t * 180build_media_type(const stp_vars_t *v, const char *name, const inklist_t *ink, 181 const res_t *res) 182{ 183 stp_mxml_node_t *node; 184 stp_mxml_node_t *doc = get_media_xml(v); 185 const char *pclass; 186 paper_t *answer; 187 stp_vars_t *vv = stp_vars_create(); 188 if (!doc) 189 return NULL; 190 node = stp_mxmlFindElement(doc, doc, "paper", "name", name, STP_MXML_DESCEND); 191 if (!node) 192 return NULL; 193 answer = stp_zalloc(sizeof(paper_t)); 194 answer->name = stp_mxmlElementGetAttr(node, "name"); 195 answer->text = gettext(stp_mxmlElementGetAttr(node, "text")); 196 pclass = stp_mxmlElementGetAttr(node, "class"); 197 answer->v = vv; 198 if (! pclass || strcasecmp(pclass, "plain") == 0) 199 answer->paper_class = PAPER_PLAIN; 200 else if (strcasecmp(pclass, "good") == 0) 201 answer->paper_class = PAPER_GOOD; 202 else if (strcasecmp(pclass, "photo") == 0) 203 answer->paper_class = PAPER_PHOTO; 204 else if (strcasecmp(pclass, "premium") == 0) 205 answer->paper_class = PAPER_PREMIUM_PHOTO; 206 else if (strcasecmp(pclass, "transparency") == 0) 207 answer->paper_class = PAPER_TRANSPARENCY; 208 else 209 answer->paper_class = PAPER_PLAIN; 210 answer->preferred_ink_type = stp_mxmlElementGetAttr(node, "PreferredInktype"); 211 answer->preferred_ink_set = stp_mxmlElementGetAttr(node, "PreferredInkset"); 212 stp_vars_fill_from_xmltree_ref(node->child, doc, vv); 213 if (ink && ink->name) 214 { 215 stp_mxml_node_t *inknode = stp_mxmlFindElement(node, node, "ink", 216 "name", ink->name, 217 STP_MXML_DESCEND); 218 STPI_ASSERT(inknode, v); 219 stp_vars_fill_from_xmltree_ref(inknode->child, doc, vv); 220 } 221 if (res && res->name) 222 { 223 stp_mxml_node_t *resnode = stp_mxmlFindElement(node, node, "resolution", 224 "name", res->name, 225 STP_MXML_DESCEND); 226 if (resnode) 227 stp_vars_fill_from_xmltree_ref(resnode->child, doc, vv); 228 } 229 return answer; 230} 231 232static char * 233build_media_id(const char *name, const inklist_t *ink, const res_t *res) 234{ 235 char *answer; 236 stp_asprintf(&answer, "%s %s %s", 237 name, 238 ink ? ink->name : "", 239 res ? res->name : ""); 240 return answer; 241} 242 243static const paper_t * 244get_media_type_named(const stp_vars_t *v, const char *name, 245 int ignore_res) 246{ 247 paper_t *answer = NULL; 248 int i; 249 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 250 const stp_string_list_t *p = printdef->papers; 251 const res_t *res = ignore_res ? NULL : stp_escp2_find_resolution(v); 252 const inklist_t *inklist = stp_escp2_inklist(v); 253 char *media_id = build_media_id(name, inklist, res); 254 stp_list_t *cache = get_media_cache(v); 255 stp_list_item_t *li = stp_list_get_item_by_name(cache, media_id); 256 if (li) 257 { 258 stp_free(media_id); 259 answer = (paper_t *) stp_list_item_get_data(li); 260 } 261 else 262 { 263 int paper_type_count = stp_string_list_count(p); 264 for (i = 0; i < paper_type_count; i++) 265 { 266 if (!strcmp(name, stp_string_list_param(p, i)->name)) 267 { 268#ifdef HAVE_LOCALE_H 269 char *locale = stp_strdup(setlocale(LC_ALL, NULL)); 270 setlocale(LC_ALL, "C"); 271#endif 272 answer = build_media_type(v, name, inklist, res); 273#ifdef HAVE_LOCALE_H 274 setlocale(LC_ALL, locale); 275 stp_free(locale); 276#endif 277 break; 278 } 279 } 280 if (answer) 281 { 282 answer->cname = media_id; 283 stp_list_item_create(cache, NULL, answer); 284 } 285 } 286 return answer; 287} 288 289const paper_t * 290stp_escp2_get_media_type(const stp_vars_t *v, int ignore_res) 291{ 292 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 293 const stp_string_list_t *p = printdef->papers; 294 if (p) 295 { 296 const char *name = stp_get_string_parameter(v, "MediaType"); 297 if (name) 298 return get_media_type_named(v, name, ignore_res); 299 } 300 return NULL; 301} 302 303const paper_t * 304stp_escp2_get_default_media_type(const stp_vars_t *v) 305{ 306 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 307 const stp_string_list_t *p = printdef->papers; 308 if (p) 309 { 310 int paper_type_count = stp_string_list_count(p); 311 if (paper_type_count >= 0) 312 return get_media_type_named(v, stp_string_list_param(p, 0)->name, 1); 313 } 314 return NULL; 315} 316 317 318static const char * 319slots_namefunc(const void *item) 320{ 321 const input_slot_t *p = (const input_slot_t *) (item); 322 return p->name; 323} 324 325int 326stp_escp2_load_input_slots(const stp_vars_t *v, const char *name) 327{ 328 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 329 stp_list_t *dirlist = stpi_data_path(); 330 stp_list_item_t *item; 331 int found = 0; 332 item = stp_list_get_start(dirlist); 333 while (item) 334 { 335 const char *dn = (const char *) stp_list_item_get_data(item); 336 char *ffn = stpi_path_merge(dn, name); 337 stp_mxml_node_t *slots = 338 stp_mxmlLoadFromFile(NULL, ffn, STP_MXML_NO_CALLBACK); 339 stp_free(ffn); 340 if (slots) 341 { 342 stp_mxml_node_t **xnode = 343 (stp_mxml_node_t **) &(printdef->slots); 344 stp_list_t **xlist = 345 (stp_list_t **) &(printdef->slots_cache); 346 stp_string_list_t **xslots = 347 (stp_string_list_t **) &(printdef->input_slots); 348 stp_mxml_node_t *node = stp_mxmlFindElement(slots, slots, 349 "escp2:InputSlots", NULL, 350 NULL, STP_MXML_DESCEND); 351 *xnode = slots; 352 *xlist = stp_list_create(); 353 stp_list_set_namefunc(*xlist, slots_namefunc); 354 *xslots = stp_string_list_create(); 355 if (node) 356 { 357 node = node->child; 358 while (node) 359 { 360 if (node->type == STP_MXML_ELEMENT && 361 strcmp(node->value.element.name, "slot") == 0) 362 stp_string_list_add_string(*xslots, 363 stp_mxmlElementGetAttr(node, "name"), 364 stp_mxmlElementGetAttr(node, "text")); 365 node = node->next; 366 } 367 } 368 found = 1; 369 break; 370 } 371 item = stp_list_item_next(item); 372 } 373 stp_list_destroy(dirlist); 374 STPI_ASSERT(found, v); 375 return found; 376} 377 378static stp_mxml_node_t * 379get_slots_xml(const stp_vars_t *v) 380{ 381 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 382 return printdef->slots; 383} 384 385static stp_list_t * 386get_slots_cache(const stp_vars_t *v) 387{ 388 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 389 return printdef->slots_cache; 390} 391 392static input_slot_t * 393build_input_slot(const stp_vars_t *v, const char *name) 394{ 395 stp_mxml_node_t *node, *n1; 396 stp_mxml_node_t *doc = get_slots_xml(v); 397 input_slot_t *answer; 398 if (!doc) 399 return NULL; 400 node = stp_mxmlFindElement(doc, doc, "slot", "name", name, STP_MXML_DESCEND); 401 if (!node) 402 return NULL; 403 answer = stp_zalloc(sizeof(input_slot_t)); 404 answer->name = stp_mxmlElementGetAttr(node, "name"); 405 answer->text = gettext(stp_mxmlElementGetAttr(node, "text")); 406 n1 = stp_mxmlFindElement(node, node, "CD", NULL, NULL, STP_MXML_DESCEND); 407 if (n1) 408 answer->is_cd = 1; 409 n1 = stp_mxmlFindElement(node, node, "RollFeed", NULL, NULL, STP_MXML_DESCEND); 410 if (n1) 411 { 412 answer->is_roll_feed = 1; 413 if (stp_mxmlFindElement(n1, n1, "CutAll", NULL, NULL, STP_MXML_DESCEND)) 414 answer->roll_feed_cut_flags |= ROLL_FEED_CUT_ALL; 415 if (stp_mxmlFindElement(n1, n1, "CutLast", NULL, NULL, STP_MXML_DESCEND)) 416 answer->roll_feed_cut_flags |= ROLL_FEED_CUT_LAST; 417 if (stp_mxmlFindElement(n1, n1, "DontEject", NULL, NULL, STP_MXML_DESCEND)) 418 answer->roll_feed_cut_flags |= ROLL_FEED_DONT_EJECT; 419 } 420 n1 = stp_mxmlFindElement(node, node, "Duplex", NULL, NULL, STP_MXML_DESCEND); 421 if (n1) 422 { 423 if (stp_mxmlFindElement(n1, n1, "Tumble", NULL, NULL, STP_MXML_DESCEND)) 424 answer->duplex |= DUPLEX_TUMBLE; 425 if (stp_mxmlFindElement(n1, n1, "NoTumble", NULL, NULL, STP_MXML_DESCEND)) 426 answer->duplex |= DUPLEX_NO_TUMBLE; 427 } 428 n1 = stp_mxmlFindElement(node, node, "InitSequence", NULL, NULL, STP_MXML_DESCEND); 429 if (n1 && n1->child && n1->child->type == STP_MXML_TEXT) 430 answer->init_sequence = stp_xmlstrtoraw(n1->child->value.text.string); 431 n1 = stp_mxmlFindElement(node, node, "DeinitSequence", NULL, NULL, STP_MXML_DESCEND); 432 if (n1 && n1->child && n1->child->type == STP_MXML_TEXT) 433 answer->deinit_sequence = stp_xmlstrtoraw(n1->child->value.text.string); 434 n1 = stp_mxmlFindElement(node, node, "ExtraHeight", NULL, NULL, STP_MXML_DESCEND); 435 if (n1 && n1->child && n1->child->type == STP_MXML_TEXT) 436 answer->extra_height = stp_xmlstrtoul(n1->child->value.text.string); 437 return answer; 438} 439 440int 441stp_escp2_printer_supports_rollfeed(const stp_vars_t *v) 442{ 443 stp_mxml_node_t *node = get_slots_xml(v); 444 if (stp_mxmlFindElement(node, node, "RollFeed", NULL, NULL, STP_MXML_DESCEND)) 445 return 1; 446 else 447 return 0; 448} 449 450int 451stp_escp2_printer_supports_print_to_cd(const stp_vars_t *v) 452{ 453 stp_mxml_node_t *node = get_slots_xml(v); 454 if (stp_mxmlFindElement(node, node, "CD", NULL, NULL, STP_MXML_DESCEND)) 455 return 1; 456 else 457 return 0; 458} 459 460int 461stp_escp2_printer_supports_duplex(const stp_vars_t *v) 462{ 463 stp_mxml_node_t *node = get_slots_xml(v); 464 if (stp_mxmlFindElement(node, node, "Duplex", NULL, NULL, STP_MXML_DESCEND)) 465 return 1; 466 else 467 return 0; 468} 469 470static const input_slot_t * 471get_input_slot_named(const stp_vars_t *v, const char *name) 472{ 473 input_slot_t *answer = NULL; 474 int i; 475 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 476 const stp_string_list_t *p = printdef->input_slots; 477 stp_list_t *cache = get_slots_cache(v); 478 stp_list_item_t *li = stp_list_get_item_by_name(cache, name); 479 if (li) 480 answer = (input_slot_t *) stp_list_item_get_data(li); 481 else 482 { 483 int slot_count = stp_string_list_count(p); 484 for (i = 0; i < slot_count; i++) 485 { 486 if (!strcmp(name, stp_string_list_param(p, i)->name)) 487 { 488#ifdef HAVE_LOCALE_H 489 char *locale = stp_strdup(setlocale(LC_ALL, NULL)); 490 setlocale(LC_ALL, "C"); 491#endif 492 answer = build_input_slot(v, name); 493#ifdef HAVE_LOCALE_H 494 setlocale(LC_ALL, locale); 495 stp_free(locale); 496#endif 497 break; 498 } 499 } 500 if (answer) 501 stp_list_item_create(cache, NULL, answer); 502 } 503 return answer; 504} 505 506const input_slot_t * 507stp_escp2_get_input_slot(const stp_vars_t *v) 508{ 509 stpi_escp2_printer_t *printdef = stp_escp2_get_printer(v); 510 const stp_string_list_t *p = printdef->input_slots; 511 if (p) 512 { 513 const char *name = stp_get_string_parameter(v, "InputSlot"); 514 if (name) 515 return get_input_slot_named(v, name); 516 } 517 return NULL; 518} 519