1/*
2 * "$Id: print-util.c,v 1.117 2010/06/26 20:02:02 rlk Exp $"
3 *
4 *   Print plug-in driver utility functions for the GIMP.
5 *
6 *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
7 *	Robert Krawitz (rlk@alum.mit.edu)
8 *
9 *   This program is free software; you can redistribute it and/or modify it
10 *   under the terms of the GNU General Public License as published by the Free
11 *   Software Foundation; either version 2 of the License, or (at your option)
12 *   any later version.
13 *
14 *   This program is distributed in the hope that it will be useful, but
15 *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 *   for more details.
18 *
19 *   You should have received a copy of the GNU General Public License
20 *   along with this program; if not, write to the Free Software
21 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/*
25 * This file must include only standard C header files.  The core code must
26 * compile on generic platforms that don't support glib, gimp, gtk, etc.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <gutenprint/gutenprint.h>
33#include "gutenprint-internal.h"
34#include <gutenprint/gutenprint-intl-internal.h>
35#include <math.h>
36#include <limits.h>
37#if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
38#include <varargs.h>
39#else
40#include <stdarg.h>
41#endif
42#include <string.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <unistd.h>
48#include "generic-options.h"
49
50#define FMIN(a, b) ((a) < (b) ? (a) : (b))
51
52typedef struct
53{
54  stp_outfunc_t ofunc;
55  void *odata;
56  char *data;
57  size_t bytes;
58} debug_msgbuf_t;
59
60/*
61 * We cannot avoid use of the (non-ANSI) vsnprintf here; ANSI does
62 * not provide a safe, length-limited sprintf function.
63 */
64
65#define STPI_VASPRINTF(result, bytes, format)				\
66{									\
67  int current_allocation = 64;						\
68  result = stp_malloc(current_allocation);				\
69  while (1)								\
70    {									\
71      va_list args;							\
72      va_start(args, format);						\
73      bytes = vsnprintf(result, current_allocation, format, args);	\
74      va_end(args);							\
75      if (bytes >= 0 && bytes < current_allocation)			\
76	break;								\
77      else								\
78	{								\
79	  stp_free (result);						\
80	  if (bytes < 0)						\
81	    current_allocation *= 2;					\
82	  else								\
83	    current_allocation = bytes + 1;				\
84	  result = stp_malloc(current_allocation);			\
85	}								\
86    }									\
87}
88
89void
90stp_zprintf(const stp_vars_t *v, const char *format, ...)
91{
92  char *result;
93  int bytes;
94  STPI_VASPRINTF(result, bytes, format);
95  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), result, bytes);
96  stp_free(result);
97}
98
99void
100stp_asprintf(char **strp, const char *format, ...)
101{
102  char *result;
103  int bytes;
104  STPI_VASPRINTF(result, bytes, format);
105  *strp = result;
106}
107
108void
109stp_catprintf(char **strp, const char *format, ...)
110{
111  char *result1;
112  char *result2;
113  int bytes;
114  STPI_VASPRINTF(result1, bytes, format);
115  stp_asprintf(&result2, "%s%s", *strp, result1);
116  stp_free(result1);
117  *strp = result2;
118}
119
120
121void
122stp_zfwrite(const char *buf, size_t bytes, size_t nitems, const stp_vars_t *v)
123{
124  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), buf, bytes * nitems);
125}
126
127void
128stp_write_raw(const stp_raw_t *raw, const stp_vars_t *v)
129{
130  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), raw->data, raw->bytes);
131}
132
133void
134stp_putc(int ch, const stp_vars_t *v)
135{
136  unsigned char a = (unsigned char) ch;
137  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), (char *) &a, 1);
138}
139
140#define BYTE(expr, byteno) (((expr) >> (8 * byteno)) & 0xff)
141
142void
143stp_put16_le(unsigned short sh, const stp_vars_t *v)
144{
145  stp_putc(BYTE(sh, 0), v);
146  stp_putc(BYTE(sh, 1), v);
147}
148
149void
150stp_put16_be(unsigned short sh, const stp_vars_t *v)
151{
152  stp_putc(BYTE(sh, 1), v);
153  stp_putc(BYTE(sh, 0), v);
154}
155
156void
157stp_put32_le(unsigned int in, const stp_vars_t *v)
158{
159  stp_putc(BYTE(in, 0), v);
160  stp_putc(BYTE(in, 1), v);
161  stp_putc(BYTE(in, 2), v);
162  stp_putc(BYTE(in, 3), v);
163}
164
165void
166stp_put32_be(unsigned int in, const stp_vars_t *v)
167{
168  stp_putc(BYTE(in, 3), v);
169  stp_putc(BYTE(in, 2), v);
170  stp_putc(BYTE(in, 1), v);
171  stp_putc(BYTE(in, 0), v);
172}
173
174void
175stp_puts(const char *s, const stp_vars_t *v)
176{
177  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), s, strlen(s));
178}
179
180void
181stp_putraw(const stp_raw_t *r, const stp_vars_t *v)
182{
183  (stp_get_outfunc(v))((void *)(stp_get_outdata(v)), r->data, r->bytes);
184}
185
186void
187stp_send_command(const stp_vars_t *v, const char *command,
188		 const char *format, ...)
189{
190  int i = 0;
191  char fchar;
192  const char *out_str;
193  const stp_raw_t *out_raw;
194  unsigned short byte_count = 0;
195  va_list args;
196
197  if (strlen(format) > 0)
198    {
199      va_start(args, format);
200      for (i = 0; i < strlen(format); i++)
201	{
202	  switch (format[i])
203	    {
204	    case 'a':
205	    case 'b':
206	    case 'B':
207	    case 'd':
208	    case 'D':
209	      break;
210	    case 'c':
211	      (void) va_arg(args, unsigned int);
212	      byte_count += 1;
213	      break;
214	    case 'h':
215	    case 'H':
216	      (void) va_arg(args, unsigned int);
217	      byte_count += 2;
218	      break;
219	    case 'l':
220	    case 'L':
221	      (void) va_arg(args, unsigned int);
222	      byte_count += 4;
223	      break;
224	    case 'r':
225	      out_raw = va_arg(args, const stp_raw_t *);
226	      byte_count += out_raw->bytes;
227	      break;
228	    case 's':
229	      out_str = va_arg(args, const char *);
230	      byte_count += strlen(out_str);
231	      break;
232	    }
233	}
234      va_end(args);
235    }
236
237  stp_puts(command, v);
238
239  va_start(args, format);
240  while ((fchar = format[0]) != '\0')
241    {
242      switch (fchar)
243	{
244	case 'a':
245	  stp_putc(byte_count, v);
246	  break;
247	case 'b':
248	  stp_put16_le(byte_count, v);
249	  break;
250	case 'B':
251	  stp_put16_be(byte_count, v);
252	  break;
253	case 'd':
254	  stp_put32_le(byte_count, v);
255	  break;
256	case 'D':
257	  stp_put32_be(byte_count, v);
258	  break;
259	case 'c':
260	  stp_putc(va_arg(args, unsigned int), v);
261	  break;
262	case 'h':
263	  stp_put16_le(va_arg(args, unsigned int), v);
264	  break;
265	case 'H':
266	  stp_put16_be(va_arg(args, unsigned int), v);
267	  break;
268	case 'l':
269	  stp_put32_le(va_arg(args, unsigned int), v);
270	  break;
271	case 'L':
272	  stp_put32_be(va_arg(args, unsigned int), v);
273	  break;
274	case 's':
275	  stp_puts(va_arg(args, const char *), v);
276	  break;
277	case 'r':
278	  stp_putraw(va_arg(args, const stp_raw_t *), v);
279	  break;
280	}
281      format++;
282    }
283  va_end(args);
284}
285
286void
287stp_eprintf(const stp_vars_t *v, const char *format, ...)
288{
289  int bytes;
290  if (stp_get_errfunc(v))
291    {
292      char *result;
293      STPI_VASPRINTF(result, bytes, format);
294      (stp_get_errfunc(v))((void *)(stp_get_errdata(v)), result, bytes);
295      stp_free(result);
296    }
297  else
298    {
299      va_list args;
300      va_start(args, format);
301      vfprintf(stderr, format, args);
302      va_end(args);
303    }
304}
305
306void
307stp_erputc(int ch)
308{
309  putc(ch, stderr);
310}
311
312void
313stp_erprintf(const char *format, ...)
314{
315  va_list args;
316  va_start(args, format);
317  vfprintf(stderr, format, args);
318  va_end(args);
319}
320
321static unsigned long stpi_debug_level = 0;
322
323static void
324stpi_init_debug(void)
325{
326  static int debug_initialized = 0;
327  if (!debug_initialized)
328    {
329      const char *dval = getenv("STP_DEBUG");
330      debug_initialized = 1;
331      if (dval)
332	{
333	  stpi_debug_level = strtoul(dval, 0, 0);
334	  stp_erprintf("Gutenprint %s %s\n", VERSION, RELEASE_DATE);
335	}
336    }
337}
338
339unsigned long
340stp_get_debug_level(void)
341{
342  stpi_init_debug();
343  return stpi_debug_level;
344}
345
346void
347stp_dprintf(unsigned long level, const stp_vars_t *v, const char *format, ...)
348{
349  int bytes;
350  stpi_init_debug();
351  if (level & stpi_debug_level)
352    {
353      if (stp_get_errfunc(v))
354	{
355	  char *result;
356	  STPI_VASPRINTF(result, bytes, format);
357	  (stp_get_errfunc(v))((void *)(stp_get_errdata(v)), result, bytes);
358	  stp_free(result);
359	} else {
360	  va_list args;
361	  va_start(args, format);
362	  vfprintf(stderr, format, args);
363	  va_end(args);
364	}
365    }
366}
367
368void
369stp_deprintf(unsigned long level, const char *format, ...)
370{
371  va_list args;
372  va_start(args, format);
373  stpi_init_debug();
374  if (level & stpi_debug_level)
375    vfprintf(stderr, format, args);
376  va_end(args);
377}
378
379static void
380fill_buffer_writefunc(void *priv, const char *buffer, size_t bytes)
381{
382  debug_msgbuf_t *msgbuf = (debug_msgbuf_t *) priv;
383  if (msgbuf->bytes == 0)
384    msgbuf->data = stp_malloc(bytes + 1);
385  else
386    msgbuf->data = stp_realloc(msgbuf->data, msgbuf->bytes + bytes + 1);
387  memcpy(msgbuf->data + msgbuf->bytes, buffer, bytes);
388  msgbuf->bytes += bytes;
389  msgbuf->data[msgbuf->bytes] = '\0';
390}
391
392void
393stp_init_debug_messages(stp_vars_t *v)
394{
395  int verified_flag = stp_get_verified(v);
396  debug_msgbuf_t *msgbuf = stp_malloc(sizeof(debug_msgbuf_t));
397  msgbuf->ofunc = stp_get_errfunc(v);
398  msgbuf->odata = stp_get_errdata(v);
399  msgbuf->data = NULL;
400  msgbuf->bytes = 0;
401  stp_set_errfunc((stp_vars_t *) v, fill_buffer_writefunc);
402  stp_set_errdata((stp_vars_t *) v, msgbuf);
403  stp_set_verified((stp_vars_t *) v, verified_flag);
404}
405
406void
407stp_flush_debug_messages(stp_vars_t *v)
408{
409  int verified_flag = stp_get_verified(v);
410  debug_msgbuf_t *msgbuf = (debug_msgbuf_t *)stp_get_errdata(v);
411  stp_set_errfunc((stp_vars_t *) v, msgbuf->ofunc);
412  stp_set_errdata((stp_vars_t *) v, msgbuf->odata);
413  stp_set_verified((stp_vars_t *) v, verified_flag);
414  if (msgbuf->bytes > 0)
415    {
416      stp_eprintf(v, "%s", msgbuf->data);
417      stp_free(msgbuf->data);
418    }
419  stp_free(msgbuf);
420}
421
422/* pointers to the allocation functions to use, which may be set by
423   client applications */
424void *(*stp_malloc_func)(size_t size) = malloc;
425void *(*stpi_realloc_func)(void *ptr, size_t size) = realloc;
426void (*stpi_free_func)(void *ptr) = free;
427
428void *
429stp_malloc (size_t size)
430{
431  register void *memptr = NULL;
432
433  if ((memptr = stp_malloc_func (size)) == NULL)
434    {
435      fputs("Virtual memory exhausted.\n", stderr);
436      stp_abort();
437    }
438  return (memptr);
439}
440
441void *
442stp_zalloc (size_t size)
443{
444  register void *memptr = stp_malloc(size);
445  (void) memset(memptr, 0, size);
446  return (memptr);
447}
448
449void *
450stp_realloc (void *ptr, size_t size)
451{
452  register void *memptr = NULL;
453
454  if (size > 0 && ((memptr = stpi_realloc_func (ptr, size)) == NULL))
455    {
456      fputs("Virtual memory exhausted.\n", stderr);
457      stp_abort();
458    }
459  return (memptr);
460}
461
462void
463stp_free(void *ptr)
464{
465  stpi_free_func(ptr);
466}
467
468int
469stp_init(void)
470{
471  static int stpi_is_initialised = 0;
472  if (!stpi_is_initialised)
473    {
474      /* Things that are only initialised once */
475      /* Set up gettext */
476#ifdef HAVE_LOCALE_H
477      char *locale = stp_strdup(setlocale (LC_ALL, ""));
478#endif
479#ifdef ENABLE_NLS
480      bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
481#endif
482#ifdef HAVE_LOCALE_H
483      setlocale(LC_ALL, locale);
484      stp_free(locale);
485#endif
486      stpi_init_debug();
487      stp_xml_preinit();
488      stpi_init_printer();
489      stpi_init_paper();
490      stpi_init_dither();
491      /* Load modules */
492      if (stp_module_load())
493	return 1;
494      /* Load XML data */
495      if (stp_xml_init_defaults())
496	return 1;
497      /* Initialise modules */
498      if (stp_module_init())
499	return 1;
500      /* Set up defaults for core parameters */
501      stp_initialize_printer_defaults();
502    }
503
504  stpi_is_initialised = 1;
505  return 0;
506}
507
508size_t
509stp_strlen(const char *s)
510{
511  return strlen(s);
512}
513
514char *
515stp_strndup(const char *s, int n)
516{
517  char *ret;
518  if (!s || n < 0)
519    {
520      ret = stp_malloc(1);
521      ret[0] = 0;
522      return ret;
523    }
524  else
525    {
526      ret = stp_malloc(n + 1);
527      memcpy(ret, s, n);
528      ret[n] = 0;
529      return ret;
530    }
531}
532
533char *
534stp_strdup(const char *s)
535{
536  char *ret;
537  if (!s)
538    {
539      ret = stp_malloc(1);
540      ret[0] = '\0';
541      return ret;
542    }
543  else
544    return stp_strndup(s, stp_strlen(s));
545}
546
547const char *
548stp_set_output_codeset(const char *codeset)
549{
550#if defined(ENABLE_NLS) && !defined(__APPLE__)
551  return (const char *)(bind_textdomain_codeset(PACKAGE, codeset));
552#else
553  return "US-ASCII";
554#endif
555}
556
557stp_curve_t *
558stp_read_and_compose_curves(const char *s1, const char *s2,
559			    stp_curve_compose_t comp,
560			    size_t piecewise_point_count)
561{
562  stp_curve_t *ret = NULL;
563  stp_curve_t *t1 = NULL;
564  stp_curve_t *t2 = NULL;
565  if (s1)
566    t1 = stp_curve_create_from_string(s1);
567  if (s2)
568    t2 = stp_curve_create_from_string(s2);
569  if (t1 && t2)
570    {
571      if (stp_curve_is_piecewise(t1) && stp_curve_is_piecewise(t2))
572	{
573	  stp_curve_resample(t1, piecewise_point_count);
574	  stp_curve_resample(t2, piecewise_point_count);
575	}
576      stp_curve_compose(&ret, t1, t2, comp, -1);
577    }
578  if (ret)
579    {
580      stp_curve_destroy(t1);
581      stp_curve_destroy(t2);
582      return ret;
583    }
584  else if (t1)
585    {
586      if(t2)
587        stp_curve_destroy(t2);
588      return t1;
589    }
590  else
591    return t2;
592}
593
594void
595stp_merge_printvars(stp_vars_t *user, const stp_vars_t *print)
596{
597  int i;
598  stp_parameter_list_t params = stp_get_parameter_list(print);
599  int count = stp_parameter_list_count(params);
600  stp_deprintf(STP_DBG_VARS, "Merging printvars from %s\n",
601	       stp_get_driver(print));
602  for (i = 0; i < count; i++)
603    {
604      const stp_parameter_t *p = stp_parameter_list_param(params, i);
605      if (p->p_type == STP_PARAMETER_TYPE_DOUBLE &&
606	  p->p_class == STP_PARAMETER_CLASS_OUTPUT &&
607	  stp_check_float_parameter(print, p->name, STP_PARAMETER_DEFAULTED))
608	{
609	  stp_parameter_t desc;
610	  double prnval = stp_get_float_parameter(print, p->name);
611	  double usrval;
612	  stp_describe_parameter(print, p->name, &desc);
613	  if (stp_check_float_parameter(user, p->name, STP_PARAMETER_ACTIVE))
614	    usrval = stp_get_float_parameter(user, p->name);
615	  else
616	    usrval = desc.deflt.dbl;
617	  if (strcmp(p->name, "Gamma") == 0)
618	    usrval /= prnval;
619	  else
620	    usrval *= prnval;
621	  if (usrval < desc.bounds.dbl.lower)
622	    usrval = desc.bounds.dbl.lower;
623	  else if (usrval > desc.bounds.dbl.upper)
624	    usrval = desc.bounds.dbl.upper;
625	  if (!stp_check_float_parameter(user, p->name, STP_PARAMETER_ACTIVE))
626	    {
627	      stp_clear_float_parameter(user, p->name);
628	      stp_set_default_float_parameter(user, p->name, usrval);
629	    }
630	  else
631	    stp_set_float_parameter(user, p->name, usrval);
632	  stp_parameter_description_destroy(&desc);
633	}
634    }
635  stp_deprintf(STP_DBG_VARS, "Exiting merge printvars\n");
636  stp_parameter_list_destroy(params);
637}
638
639stp_parameter_list_t
640stp_get_parameter_list(const stp_vars_t *v)
641{
642  stp_parameter_list_t ret = stp_parameter_list_create();
643  stp_parameter_list_t tmp_list;
644
645  tmp_list = stp_printer_list_parameters(v);
646  stp_parameter_list_append(ret, tmp_list);
647  stp_parameter_list_destroy(tmp_list);
648
649  tmp_list = stp_color_list_parameters(v);
650  stp_parameter_list_append(ret, tmp_list);
651  stp_parameter_list_destroy(tmp_list);
652
653  tmp_list = stp_dither_list_parameters(v);
654  stp_parameter_list_append(ret, tmp_list);
655  stp_parameter_list_destroy(tmp_list);
656
657  tmp_list = stp_list_generic_parameters(v);
658  stp_parameter_list_append(ret, tmp_list);
659  stp_parameter_list_destroy(tmp_list);
660
661  return ret;
662}
663
664void
665stp_abort(void)
666{
667  abort();
668}
669