1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
28 #include <data/file-name.h>
29 #include <data/settings.h>
30 #include <libpspp/misc.h>
31 #include <libpspp/str.h>
32 #include <output/htmlP.h>
33 #include <output/output.h>
40 #define _(msgid) gettext (msgid)
42 /* Where the output driver name came from. */
45 OUTP_S_COMMAND_LINE, /* Specified by the user. */
46 OUTP_S_INIT_FILE /* `default' or the init file. */
49 /* Names the output drivers to be used. */
52 char *name; /* Name of the output driver. */
53 int source; /* OUTP_S_* */
54 struct outp_names *next, *prev;
57 /* Defines an init file macro. */
62 struct outp_defn *next, *prev;
65 static struct outp_defn *outp_macros;
66 static struct outp_names *outp_configure_vec;
68 /* A list of driver classes. */
69 struct outp_driver_class_list
71 const struct outp_class *class;
72 struct outp_driver_class_list *next;
75 static struct outp_driver_class_list *outp_class_list;
76 static struct ll_list outp_driver_list = LL_INITIALIZER (outp_driver_list);
81 /* A set of OUTP_DEV_* bits indicating the devices that are
83 static int disabled_devices;
85 static void destroy_driver (struct outp_driver *);
86 static void configure_driver (const struct substring, const struct substring,
87 const struct substring, const struct substring);
89 /* Add a class to the class list. */
91 add_class (const struct outp_class *class)
93 struct outp_driver_class_list *new_list = xmalloc (sizeof *new_list);
95 new_list->class = class;
99 outp_class_list = new_list;
100 new_list->next = NULL;
104 new_list->next = outp_class_list;
105 outp_class_list = new_list;
109 /* Finds the outp_names in outp_configure_vec with name between BP and
111 static struct outp_names *
112 search_names (char *bp, char *ep)
114 struct outp_names *n;
116 for (n = outp_configure_vec; n; n = n->next)
117 if ((int) strlen (n->name) == ep - bp && !memcmp (n->name, bp, ep - bp))
122 /* Deletes outp_names NAME from outp_configure_vec. */
124 delete_name (struct outp_names * n)
128 n->prev->next = n->next;
130 n->next->prev = n->prev;
131 if (n == outp_configure_vec)
132 outp_configure_vec = n->next;
136 /* Adds the name between BP and EP exclusive to list
137 outp_configure_vec with source SOURCE. */
139 add_name (char *bp, char *ep, int source)
141 struct outp_names *n = xmalloc (sizeof *n);
142 n->name = xmalloc (ep - bp + 1);
143 memcpy (n->name, bp, ep - bp);
144 n->name[ep - bp] = 0;
146 n->next = outp_configure_vec;
148 if (outp_configure_vec)
149 outp_configure_vec->prev = n;
150 outp_configure_vec = n;
153 /* Checks that outp_configure_vec is empty, complains and clears
156 check_configure_vec (void)
158 struct outp_names *n;
160 for (n = outp_configure_vec; n; n = n->next)
161 if (n->source == OUTP_S_COMMAND_LINE)
162 error (0, 0, _("unknown output driver `%s'"), n->name);
164 error (0, 0, _("output driver `%s' referenced but never defined"),
166 outp_configure_clear ();
169 /* Searches outp_configure_vec for the name between BP and EP
170 exclusive. If found, it is deleted, then replaced by the names
171 given in EP+1, if any. */
173 expand_name (char *bp, char *ep)
175 struct outp_names *n = search_names (bp, ep);
183 while (isspace ((unsigned char) *bp))
186 while (*ep && !isspace ((unsigned char) *ep))
190 if (!search_names (bp, ep))
191 add_name (bp, ep, OUTP_S_INIT_FILE);
196 /* Looks for a macro with key KEY, and returns the corresponding value
197 if found, or NULL if not. */
199 find_defn_value (const char *key)
201 static char buf[INT_STRLEN_BOUND (int) + 1];
204 for (d = outp_macros; d; d = d->next)
205 if (!strcmp (key, d->key))
206 return ds_cstr (&d->value);
207 if (!strcmp (key, "viewwidth"))
209 sprintf (buf, "%d", settings_get_viewwidth ());
212 else if (!strcmp (key, "viewlength"))
214 sprintf (buf, "%d", settings_get_viewlength ());
222 insert_defn_value (const char *var, struct string *dst, void *aux UNUSED)
224 const char *value = find_defn_value (var);
226 ds_put_cstr (dst, value);
229 /* Initializes global variables. */
233 char def[] = "default";
235 add_class (&html_class);
236 add_class (&ascii_class);
238 add_class (&cairo_class);
240 add_class (&odt_class);
242 add_name (def, &def[strlen (def)], OUTP_S_INIT_FILE);
245 /* Deletes all the output macros. */
249 struct outp_defn *d, *next;
251 for (d = outp_macros; d; d = next)
255 ds_destroy (&d->value);
261 init_default_drivers (void)
263 error (0, 0, _("using default output driver configuration"));
264 configure_driver (ss_cstr ("list"),
267 ss_cstr ("length=66 width=79 output-file=\"pspp.list\""));
270 /* Reads the initialization file; initializes
273 outp_read_devices (void)
283 init_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_INIT_FILE",
285 fn_getenv_default ("STAT_OUTPUT_INIT_PATH",
288 ds_init_empty (&line);
292 error (0, 0, _("cannot find output initialization file "
293 "(use `-vv' to view search path)"));
297 f = fopen (init_fn, "r");
300 error (0, errno, _("cannot open \"%s\""), init_fn);
309 if (!ds_read_config_line (&line, &line_number, f))
312 error (0, errno, _("reading \"%s\""), init_fn);
315 for (cp = ds_cstr (&line); isspace ((unsigned char) *cp); cp++);
316 if (!strncmp ("define", cp, 6) && isspace ((unsigned char) cp[6]))
317 outp_configure_macro (&cp[7]);
321 for (ep = cp; *ep && *ep != ':' && *ep != '='; ep++);
323 expand_name (cp, ep);
326 struct outp_names *n = search_names (cp, ep);
329 outp_configure_driver_line (ds_ss (&line));
334 error_at_line (0, 0, init_fn, line_number, _("syntax error"));
339 check_configure_vec ();
342 if (f && -1 == fclose (f))
343 error (0, errno, _("error closing \"%s\""), init_fn);
350 if (ll_is_empty (&outp_driver_list))
351 error (0, 0, _("no active output drivers"));
354 error (0, 0, _("error reading device definition file"));
356 if (!result || ll_is_empty (&outp_driver_list))
357 init_default_drivers ();
360 /* Clear the list of drivers to configure. */
362 outp_configure_clear (void)
364 struct outp_names *n, *next;
366 for (n = outp_configure_vec; n; n = next)
372 outp_configure_vec = NULL;
375 /* Adds the name BP to the list of drivers to configure into
378 outp_configure_add (char *bp)
380 char *ep = &bp[strlen (bp)];
381 if (!search_names (bp, ep))
382 add_name (bp, ep, OUTP_S_COMMAND_LINE);
385 /* Defines one configuration macro based on the text in BP, which
386 should be of the form `KEY=VALUE'. */
388 outp_configure_macro (char *bp)
393 while (isspace ((unsigned char) *bp))
396 while (*ep && !isspace ((unsigned char) *ep) && *ep != '=')
399 d = xmalloc (sizeof *d);
400 d->key = xmalloc (ep - bp + 1);
401 memcpy (d->key, bp, ep - bp);
404 /* Earlier definitions for a particular KEY override later ones. */
405 if (find_defn_value (d->key))
414 while (isspace ((unsigned char) *ep))
417 ds_init_cstr (&d->value, ep);
418 fn_interp_vars (ds_ss (&d->value), insert_defn_value, NULL, &d->value);
419 d->next = outp_macros;
422 outp_macros->prev = d;
426 /* Closes all the output drivers. */
430 struct outp_driver_class_list *n = outp_class_list ;
431 outp_configure_clear ();
432 while (!ll_is_empty (&outp_driver_list))
434 struct outp_driver *d = ll_data (ll_head (&outp_driver_list),
435 struct outp_driver, node);
441 struct outp_driver_class_list *next = n->next;
445 outp_class_list = NULL;
450 free (outp_subtitle);
451 outp_subtitle = NULL;
454 /* Display on stdout a list of all registered driver classes. */
456 outp_list_classes (void)
458 int width = settings_get_viewwidth ();
459 struct outp_driver_class_list *c;
461 printf (_("Driver classes:\n\t"));
463 for (c = outp_class_list; c; c = c->next)
465 if ((int) strlen (c->class->name) + 1 > width)
468 width = settings_get_viewwidth () - 8;
472 fputs (c->class->name, stdout);
477 /* Obtains a token from S and advances its position. Errors are
478 reported against the given DRIVER_NAME.
479 The token is stored in TOKEN. Returns true if successful,
480 false on syntax error.
482 Caller is responsible for skipping leading spaces. */
484 get_option_token (struct substring *s, const char *driver_name,
485 struct string *token)
493 error (0, 0, _("syntax error parsing options for \"%s\" driver"),
497 else if (c == '\'' || c == '"')
509 _("reached end of options inside quoted string "
510 "parsing options for \"%s\" driver"),
515 ds_put_char (token, c);
562 while (ss_first (*s) >= '0' && ss_first (*s) <= '7')
563 out = out * 8 + (ss_get_char (s) - '0');
568 while (isxdigit (ss_first (*s)))
575 out += tolower (c) - 'a' + 10;
579 error (0, 0, _("syntax error in string constant "
580 "parsing options for \"%s\" driver"),
584 ds_put_char (token, out);
592 ds_put_char (token, c);
595 if (c == EOF || c == '=' || isspace (c))
605 outp_parse_options (const char *driver_name, struct substring options,
606 bool (*callback) (void *aux, const char *key,
607 const struct string *value), void *aux)
609 struct string key = DS_EMPTY_INITIALIZER;
610 struct string value = DS_EMPTY_INITIALIZER;
611 struct substring left = options;
616 ss_ltrim (&left, ss_cstr (CC_SPACES));
617 if (ss_is_empty (left))
620 if (!get_option_token (&left, driver_name, &key))
623 ss_ltrim (&left, ss_cstr (CC_SPACES));
624 if (!ss_match_char (&left, '='))
626 error (0, 0, _("syntax error expecting `=' "
627 "parsing options for driver \"%s\""),
632 ss_ltrim (&left, ss_cstr (CC_SPACES));
633 if (!get_option_token (&left, driver_name, &value))
636 ok = callback (aux, ds_cstr (&key), &value);
646 /* Find the driver in outp_driver_list with name NAME. */
647 static struct outp_driver *
648 find_driver (char *name)
650 struct outp_driver *d;
651 ll_for_each (d, struct outp_driver, node, &outp_driver_list)
652 if (!strcmp (d->name, name))
657 /* Adds a driver to outp_driver_list pursuant to the
658 specification provided. */
660 configure_driver (struct substring driver_name, struct substring class_name,
661 struct substring device_type, struct substring options)
663 struct outp_driver_class_list *c;
664 struct substring token;
670 for (c = outp_class_list; c; c = c->next)
671 if (!ss_compare (ss_cstr (c->class->name), class_name))
675 error (0, 0, _("unknown output driver class `%.*s'"),
676 (int) ss_length (class_name), ss_data (class_name));
680 /* Parse device type. */
682 while (ss_tokenize (device_type, ss_cstr (CC_SPACES), &save_idx, &token))
683 if (!ss_compare (token, ss_cstr ("listing")))
684 device |= OUTP_DEV_LISTING;
685 else if (!ss_compare (token, ss_cstr ("screen")))
686 device |= OUTP_DEV_SCREEN;
687 else if (!ss_compare (token, ss_cstr ("printer")))
688 device |= OUTP_DEV_PRINTER;
690 error (0, 0, _("unknown device type `%.*s'"),
691 (int) ss_length (token), ss_data (token));
694 name = ss_xstrdup (driver_name);
695 if (!c->class->open_driver (name, device, options))
696 error (0, 0, _("cannot initialize output driver `%s' of class `%s'"),
697 name, c->class->name);
701 /* Allocates and returns a new outp_driver for a device with the
702 given NAME and CLASS and the OUTP_DEV_* type(s) in TYPES
704 This function is intended to be used by output drivers, not
707 outp_allocate_driver (const struct outp_class *class,
708 const char *name, int types)
710 struct outp_driver *d = xmalloc (sizeof *d);
712 d->name = xstrdup (name);
713 d->page_open = false;
715 d->cp_x = d->cp_y = 0;
720 /* Frees driver D and the data that it owns directly. The
721 driver's class must already have unregistered D (if it was
722 registered) and freed data private to its class.
724 This function is intended to be used by output drivers, not
727 outp_free_driver (struct outp_driver *d)
733 /* Adds D to the list of drivers that will be used for output. */
735 outp_register_driver (struct outp_driver *d)
737 struct outp_driver *victim;
739 /* Find like-named driver and delete. */
740 victim = find_driver (d->name);
742 destroy_driver (victim);
745 ll_push_tail (&outp_driver_list, &d->node);
748 /* Remove driver D from the list of drivers that will be used for
751 outp_unregister_driver (struct outp_driver *d)
753 ll_remove (&d->node);
756 /* String LINE is in format:
757 DRIVERNAME:CLASSNAME:DEVICETYPE:OPTIONS
758 Adds a driver to outp_driver_list pursuant to the specification
761 outp_configure_driver_line (struct substring line_)
763 struct string line = DS_EMPTY_INITIALIZER;
764 struct substring tokens[4];
768 fn_interp_vars (line_, insert_defn_value, NULL, &line);
771 for (i = 0; i < 4; i++)
773 struct substring *token = &tokens[i];
774 ds_separate (&line, ss_cstr (i < 3 ? ":" : ""), &save_idx, token);
775 ss_trim (token, ss_cstr (CC_SPACES));
778 if (!ss_is_empty (tokens[0]) && !ss_is_empty (tokens[1]))
779 configure_driver (tokens[0], tokens[1], tokens[2], tokens[3]);
782 _("driver definition line missing driver name or class name"));
787 /* Destroys output driver D. */
789 destroy_driver (struct outp_driver *d)
792 if (d->class && d->class->close_driver)
793 d->class->close_driver (d);
794 outp_unregister_driver (d);
795 outp_free_driver (d);
798 /* Tries to match S as one of the keywords in TAB, with
799 corresponding information structure INFO. Returns category
800 code and stores subcategory in *SUBCAT on success. Returns -1
803 outp_match_keyword (const char *s, const struct outp_option *tab, int *subcat)
805 for (; tab->keyword != NULL; tab++)
806 if (!strcmp (s, tab->keyword))
808 *subcat = tab->subcat;
814 /* Parses UNIT as a dimensional unit. Returns the multiplicative
815 factor needed to change a quantity measured in that unit into
816 1/72000" units. If UNIT is empty, it is treated as
817 millimeters. If the unit is unrecognized, returns 0. */
819 parse_unit (const char *unit)
827 static const struct unit units[] =
830 {"pc", 72000 / 72 * 12.0},
832 {"cm", 72000 / 2.54},
833 {"mm", 72000 / 25.4},
837 const struct unit *p;
839 unit += strspn (unit, CC_SPACES);
840 for (p = units; p < units + sizeof units / sizeof *units; p++)
841 if (!strcasecmp (unit, p->name))
846 /* Determines the size of a dimensional measurement and returns
847 the size in units of 1/72000". Units are assumed to be
848 millimeters unless otherwise specified. Returns 0 on
851 outp_evaluate_dimension (const char *dimen)
857 raw = strtod (dimen, &tail);
862 factor = parse_unit (tail);
869 error (0, 0, _("`%s' is not a valid length."), dimen);
873 /* Stores the dimensions in 1/72000" units of paper identified by
874 SIZE, which is of form `HORZ x VERT [UNIT]' where HORZ and
875 VERT are numbers and UNIT is an optional unit of measurement,
876 into *H and *V. Return true on success. */
878 parse_paper_size (const char *size, int *h, int *v)
880 double raw_h, raw_v, factor;
884 raw_h = strtod (size, &tail);
889 tail += strspn (tail, CC_SPACES "x,");
892 raw_v = strtod (tail, &tail);
897 factor = parse_unit (tail);
901 *h = raw_h * factor + .5;
902 *v = raw_v * factor + .5;
907 get_standard_paper_size (struct substring name, int *h, int *v)
909 static const char *sizes[][2] =
911 {"a0", "841 x 1189 mm"},
912 {"a1", "594 x 841 mm"},
913 {"a2", "420 x 594 mm"},
914 {"a3", "297 x 420 mm"},
915 {"a4", "210 x 297 mm"},
916 {"a5", "148 x 210 mm"},
917 {"b5", "176 x 250 mm"},
918 {"a6", "105 x 148 mm"},
919 {"a7", "74 x 105 mm"},
920 {"a8", "52 x 74 mm"},
921 {"a9", "37 x 52 mm"},
922 {"a10", "26 x 37 mm"},
923 {"b0", "1000 x 1414 mm"},
924 {"b1", "707 x 1000 mm"},
925 {"b2", "500 x 707 mm"},
926 {"b3", "353 x 500 mm"},
927 {"b4", "250 x 353 mm"},
928 {"letter", "612 x 792 pt"},
929 {"legal", "612 x 1008 pt"},
930 {"executive", "522 x 756 pt"},
931 {"note", "612 x 792 pt"},
932 {"11x17", "792 x 1224 pt"},
933 {"tabloid", "792 x 1224 pt"},
934 {"statement", "396 x 612 pt"},
935 {"halfletter", "396 x 612 pt"},
936 {"halfexecutive", "378 x 522 pt"},
937 {"folio", "612 x 936 pt"},
938 {"quarto", "610 x 780 pt"},
939 {"ledger", "1224 x 792 pt"},
940 {"archA", "648 x 864 pt"},
941 {"archB", "864 x 1296 pt"},
942 {"archC", "1296 x 1728 pt"},
943 {"archD", "1728 x 2592 pt"},
944 {"archE", "2592 x 3456 pt"},
945 {"flsa", "612 x 936 pt"},
946 {"flse", "612 x 936 pt"},
947 {"csheet", "1224 x 1584 pt"},
948 {"dsheet", "1584 x 2448 pt"},
949 {"esheet", "2448 x 3168 pt"},
954 for (i = 0; i < sizeof sizes / sizeof *sizes; i++)
955 if (ss_equals_case (ss_cstr (sizes[i][0]), name))
957 bool ok = parse_paper_size (sizes[i][1], h, v);
961 error (0, 0, _("unknown paper type `%.*s'"),
962 (int) ss_length (name), ss_data (name));
966 /* Reads file FILE_NAME to find a paper size. Stores the
967 dimensions, in 1/72000" units, into *H and *V. Returns true
968 on success, false on failure. */
970 read_paper_conf (const char *file_name, int *h, int *v)
972 struct string line = DS_EMPTY_INITIALIZER;
976 file = fopen (file_name, "r");
979 error (0, errno, _("error opening \"%s\""), file_name);
985 struct substring name;
987 if (!ds_read_config_line (&line, &line_number, file))
990 error (0, errno, _("error reading \"%s\""), file_name);
994 name = ds_ss (&line);
995 ss_trim (&name, ss_cstr (CC_SPACES));
996 if (!ss_is_empty (name))
998 bool ok = get_standard_paper_size (name, h, v);
1007 error (0, 0, _("paper size file \"%s\" does not state a paper size"),
1012 /* The user didn't specify a paper size, so let's choose a
1013 default based on his environment. Stores the
1014 dimensions, in 1/72000" units, into *H and *V. Returns true
1015 on success, false on failure. */
1017 get_default_paper_size (int *h, int *v)
1019 /* libpaper in Debian (and other distributions?) allows the
1020 paper size to be specified in $PAPERSIZE or in a file
1021 specified in $PAPERCONF. */
1022 if (getenv ("PAPERSIZE") != NULL)
1023 return get_standard_paper_size (ss_cstr (getenv ("PAPERSIZE")), h, v);
1024 if (getenv ("PAPERCONF") != NULL)
1025 return read_paper_conf (getenv ("PAPERCONF"), h, v);
1028 /* LC_PAPER is a non-standard glibc extension. */
1029 *h = (int) nl_langinfo(_NL_PAPER_WIDTH) * (72000 / 25.4);
1030 *v = (int) nl_langinfo(_NL_PAPER_HEIGHT) * (72000 / 25.4);
1031 if (*h > 0 && *v > 0)
1035 /* libpaper defaults to /etc/papersize. */
1036 if (fn_exists ("/etc/papersize"))
1037 return read_paper_conf ("/etc/papersize", h, v);
1039 /* Can't find a default. */
1043 /* Stores the dimensions, in 1/72000" units, of paper identified
1044 by SIZE into *H and *V. SIZE can be the name of a kind of
1045 paper ("a4", "letter", ...) or a pair of dimensions
1046 ("210x297", "8.5x11in", ...). Returns true on success, false
1047 on failure. On failure, *H and *V are set for A4 paper. */
1049 outp_get_paper_size (const char *size, int *h, int *v)
1055 ss_trim (&s, ss_cstr (CC_SPACES));
1057 if (ss_is_empty (s))
1059 /* Treat empty string as default paper size. */
1060 ok = get_default_paper_size (h, v);
1062 else if (isdigit (ss_first (s)))
1064 /* Treat string that starts with digit as explicit size. */
1065 ok = parse_paper_size (size, h, v);
1067 error (0, 0, _("syntax error in paper size `%s'"), size);
1071 /* Check against standard paper sizes. */
1072 ok = get_standard_paper_size (s, h, v);
1075 /* Default to A4 on error. */
1078 *h = 210 * (72000 / 25.4);
1079 *v = 297 * (72000 / 25.4);
1084 /* If D is NULL, returns the first enabled driver if any, NULL if
1085 none. Otherwise D must be the last driver returned by this
1086 function, in which case the next enabled driver is returned or NULL
1087 if that was the last. */
1088 struct outp_driver *
1089 outp_drivers (struct outp_driver *d)
1095 next = d == NULL ? ll_head (&outp_driver_list) : ll_next (&d->node);
1096 if (next == ll_null (&outp_driver_list))
1099 d = ll_data (next, struct outp_driver, node);
1101 while (d->device != 0 && (d->device & disabled_devices) == d->device);
1106 /* Enables (if ENABLE is true) or disables (if ENABLE is false) the
1107 device(s) given in mask DEVICE. */
1109 outp_enable_device (bool enable, int device)
1112 disabled_devices &= ~device;
1114 disabled_devices |= device;
1117 /* Opens a page on driver D (if one is not open). */
1119 outp_open_page (struct outp_driver *d)
1123 d->cp_x = d->cp_y = 0;
1125 d->page_open = true;
1126 if (d->class->open_page != NULL)
1127 d->class->open_page (d);
1131 /* Closes the page on driver D (if one is open). */
1133 outp_close_page (struct outp_driver *d)
1137 if (d->class->close_page != NULL)
1138 d->class->close_page (d);
1139 d->page_open = false;
1143 /* Ejects the page on device D, if a page is open and non-blank,
1144 and opens a new page. */
1146 outp_eject_page (struct outp_driver *d)
1148 if (d->page_open && d->cp_y != 0)
1149 outp_close_page (d);
1153 /* Flushes output to screen devices, so that the user can see
1154 output that doesn't fill up an entire page. */
1156 outp_flush (struct outp_driver *d)
1158 if (d->device & OUTP_DEV_SCREEN && d->class->flush != NULL)
1160 outp_close_page (d);
1161 d->class->flush (d);
1165 /* Returns the width of string S, in device units, when output on
1168 outp_string_width (struct outp_driver *d, const char *s, enum outp_font font)
1170 struct outp_text text;
1174 text.justification = OUTP_LEFT;
1175 text.string = ss_cstr (s);
1176 text.h = text.v = INT_MAX;
1177 d->class->text_metrics (d, &text, &width, NULL);