X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Foutput.c;h=368b37b050703fabd9c47281d721548e14b506e4;hb=10add4c7fbb4076b69e27c524e24081067c39f40;hp=0ea8ea49ad3230d091cbc0df06c4426a5e08db6c;hpb=8444d8d47de5e5f8d076b6f43f73c2c29494031e;p=pspp-builds.git diff --git a/src/output/output.c b/src/output/output.c index 0ea8ea49..368b37b0 100644 --- a/src/output/output.c +++ b/src/output/output.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -19,19 +18,18 @@ #include #include "output.h" -#include #include #include #include #include #include -#include -#include +#include #include "htmlP.h" #include "intprops.h" #include #include #include +#include "error.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -71,12 +69,12 @@ static struct outp_names *outp_configure_vec; /* A list of driver classes. */ struct outp_driver_class_list { - struct outp_class *class; + const struct outp_class *class; struct outp_driver_class_list *next; }; -struct outp_driver_class_list *outp_class_list; -struct outp_driver *outp_driver_list; +static struct outp_driver_class_list *outp_class_list; +static struct outp_driver *outp_driver_list; char *outp_title; char *outp_subtitle; @@ -86,13 +84,13 @@ char *outp_subtitle; static int disabled_devices; static void destroy_driver (struct outp_driver *); -static void configure_driver_line (struct string *); -static void configure_driver (const struct string *, const struct string *, - const struct string *, const struct string *); +static void configure_driver_line (struct substring); +static void configure_driver (const struct substring, const struct substring, + const struct substring, const struct substring); /* Add a class to the class list. */ static void -add_class (struct outp_class *class) +add_class (const struct outp_class *class) { struct outp_driver_class_list *new_list = xmalloc (sizeof *new_list); @@ -163,9 +161,10 @@ check_configure_vec (void) for (n = outp_configure_vec; n; n = n->next) if (n->source == OUTP_S_COMMAND_LINE) - msg (ME, _("Unknown output driver `%s'."), n->name); + error (0, 0, _("unknown output driver `%s'"), n->name); else - msg (IE, _("Output driver `%s' referenced but never defined."), n->name); + error (0, 0, _("output driver `%s' referenced but never defined"), + n->name); outp_configure_clear (); } @@ -206,7 +205,7 @@ find_defn_value (const char *key) for (d = outp_macros; d; d = d->next) if (!strcmp (key, d->key)) - return ds_c_str(&d->value); + return ds_cstr (&d->value); if (!strcmp (key, "viewwidth")) { sprintf (buf, "%d", get_viewwidth ()); @@ -227,7 +226,6 @@ outp_init (void) { extern struct outp_class ascii_class; extern struct outp_class postscript_class; - extern struct outp_class html_class; char def[] = "default"; @@ -256,15 +254,11 @@ delete_macros (void) static void init_default_drivers (void) { - struct string s; - - msg (MM, _("Using default output driver configuration.")); - - ds_create (&s, - "list:ascii:listing:" - "length=66 width=79 output-file=\"pspp.list\""); - configure_driver_line (&s); - ds_destroy (&s); + error (0, 0, _("using default output driver configuration")); + configure_driver (ss_cstr ("list"), + ss_cstr ("ascii"), + ss_cstr ("listing"), + ss_cstr ("length=66 width=79 output-file=\"pspp.list\"")); } /* Reads the initialization file; initializes @@ -278,44 +272,41 @@ outp_read_devices (void) FILE *f = NULL; struct string line; - struct file_locator where; + int line_number; init_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_INIT_FILE", "devices"), fn_getenv_default ("STAT_OUTPUT_INIT_PATH", - config_path), - NULL); - where.filename = init_fn; - where.line_number = 0; - err_push_file_locator (&where); - - ds_init (&line, 128); + config_path)); + + ds_init_empty (&line); if (init_fn == NULL) { - msg (IE, _("Cannot find output initialization file. " - "Use `-vvvvv' to view search path.")); + error (0, 0, _("cannot find output initialization file " + "(use `-vv' to view search path)")); goto exit; } f = fopen (init_fn, "r"); if (f == NULL) { - msg (IE, _("Opening %s: %s."), init_fn, strerror (errno)); + error (0, errno, _("cannot open \"%s\""), init_fn); goto exit; } + line_number = 0; for (;;) { char *cp; - if (!ds_get_config_line (f, &line, &where.line_number)) + if (!ds_read_config_line (&line, &line_number, f)) { if (ferror (f)) - msg (ME, _("Reading %s: %s."), init_fn, strerror (errno)); + error (0, errno, _("reading \"%s\""), init_fn); break; } - for (cp = ds_c_str (&line); isspace ((unsigned char) *cp); cp++); + for (cp = ds_cstr (&line); isspace ((unsigned char) *cp); cp++); if (!strncmp ("define", cp, 6) && isspace ((unsigned char) cp[6])) outp_configure_macro (&cp[7]); else if (*cp) @@ -329,12 +320,12 @@ outp_read_devices (void) struct outp_names *n = search_names (cp, ep); if (n) { - configure_driver_line (&line); + configure_driver_line (ds_ss (&line)); delete_name (n); } } else - msg (IS, _("Syntax error.")); + error_at_line (0, 0, init_fn, line_number, _("syntax error")); } } result = 1; @@ -342,9 +333,8 @@ outp_read_devices (void) check_configure_vec (); exit: - err_pop_file_locator (&where); if (f && -1 == fclose (f)) - msg (MW, _("Closing %s: %s."), init_fn, strerror (errno)); + error (0, errno, _("error closing \"%s\""), init_fn); free (init_fn); ds_destroy (&line); delete_macros (); @@ -352,10 +342,10 @@ exit: if (result) { if (outp_driver_list == NULL) - msg (MW, _("No output drivers are active.")); + error (0, 0, _("no active output drivers")); } else - msg (VM (1), _("Error reading device definition file.")); + error (0, 0, _("error reading device definition file")); if (!result || outp_driver_list == NULL) init_default_drivers (); @@ -418,8 +408,8 @@ outp_configure_macro (char *bp) while (isspace ((unsigned char) *ep)) ep++; - ds_create(&d->value, ep); - fn_interp_vars(&d->value, find_defn_value); + ds_init_cstr (&d->value, ep); + fn_interp_vars (ds_ss (&d->value), find_defn_value, &d->value); d->next = outp_macros; d->prev = NULL; if (outp_macros) @@ -488,177 +478,172 @@ outp_list_classes (void) putc('\n', stdout); } -static int op_token; /* `=', 'a', 0. */ -static struct string op_tokstr; -static const char *prog; +/* Obtains a token from S and advances its position. Errors are + reported against the given DRIVER_NAME. + The token is stored in TOKEN. Returns true if successful, + false on syntax error. -/* Parses a token from prog into op_token, op_tokstr. Sets op_token - to '=' on an equals sign, to 'a' on a string or identifier token, - or to 0 at end of line. Returns the new op_token. */ -static int -tokener (void) + Caller is responsible for skipping leading spaces. */ +static bool +get_option_token (struct substring *s, const char *driver_name, + struct string *token) { - if (op_token == 0) + int c; + + ds_clear (token); + c = ss_get_char (s); + if (c == EOF) { - msg (IS, _("Syntax error.")); - return 0; + error (0, 0, _("syntax error parsing options for \"%s\" driver"), + driver_name); + return false; } - - while (isspace ((unsigned char) *prog)) - prog++; - if (!*prog) + else if (c == '\'' || c == '"') { - op_token = 0; - return 0; - } + int quote = c; - if (*prog == '=') - op_token = *prog++; - else + for (;;) + { + c = ss_get_char (s); + if (c == quote) + break; + else if (c == EOF) + { + error (0, 0, + _("reached end of options inside quoted string " + "parsing options for \"%s\" driver"), + driver_name); + return false; + } + else if (c != '\\') + ds_put_char (token, c); + else + { + int out; + + c = ss_get_char (s); + switch (c) + { + case '\'': + out = '\''; + break; + case '"': + out = '"'; + break; + case '\\': + out = '\\'; + break; + case 'a': + out = '\a'; + break; + case 'b': + out = '\b'; + break; + case 'f': + out = '\f'; + break; + case 'n': + out = '\n'; + break; + case 'r': + out = '\r'; + break; + case 't': + out = '\t'; + break; + case 'v': + out = '\v'; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + out = c - '0'; + while (ss_first (*s) >= '0' && ss_first (*s) <= '7') + out = c * 8 + (ss_get_char (s) - '0'); + break; + case 'x': + case 'X': + out = 0; + while (isxdigit (ss_first (*s))) + { + c = ss_get_char (s); + out *= 16; + if (isdigit (c)) + out += c - '0'; + else + out += tolower (c) - 'a' + 10; + } + break; + default: + error (0, 0, _("syntax error in string constant " + "parsing options for \"%s\" driver"), + driver_name); + return false; + } + ds_put_char (token, out); + } + } + } + else { - ds_clear (&op_tokstr); - - if (*prog == '\'' || *prog == '"') - { - int quote = *prog++; + for (;;) + { + ds_put_char (token, c); - while (*prog && *prog != quote) - { - if (*prog != '\\') - ds_putc (&op_tokstr, *prog++); - else - { - int c; - - prog++; - assert ((int) *prog); /* How could a line end in `\'? */ - switch (*prog++) - { - case '\'': - c = '\''; - break; - case '"': - c = '"'; - break; - case '?': - c = '?'; - break; - case '\\': - c = '\\'; - break; - case '}': - c = '}'; - break; - case 'a': - c = '\a'; - break; - case 'b': - c = '\b'; - break; - case 'f': - c = '\f'; - break; - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'v': - c = '\v'; - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - c = prog[-1] - '0'; - while (*prog >= '0' && *prog <= '7') - c = c * 8 + *prog++ - '0'; - } - break; - case 'x': - case 'X': - { - c = 0; - while (isxdigit ((unsigned char) *prog)) - { - c *= 16; - if (isdigit ((unsigned char) *prog)) - c += *prog - '0'; - else - c += (tolower ((unsigned char) (*prog)) - - 'a' + 10); - prog++; - } - } - break; - default: - msg (IS, _("Syntax error in string constant.")); - continue; - } - ds_putc (&op_tokstr, (unsigned char) c); - } - } - prog++; - } - else - while (*prog && !isspace ((unsigned char) *prog) && *prog != '=') - ds_putc (&op_tokstr, *prog++); - op_token = 'a'; + c = ss_first (*s); + if (c == EOF || c == '=' || isspace (c)) + break; + ss_advance (s, 1); + } } - + return 1; } bool -outp_parse_options (const char *options, +outp_parse_options (struct substring options, bool (*callback) (struct outp_driver *, const char *key, const struct string *value), struct outp_driver *driver) { + struct string key = DS_EMPTY_INITIALIZER; + struct string value = DS_EMPTY_INITIALIZER; + struct substring left = options; bool ok = true; - prog = options; - op_token = -1; - - ds_init (&op_tokstr, 64); - while (ok && tokener ()) + do { - char key[65]; - - if (op_token != 'a') + ss_ltrim (&left, ss_cstr (CC_SPACES)); + if (ss_is_empty (left)) + break; + + if (!get_option_token (&left, driver->name, &key)) + break; + + ss_ltrim (&left, ss_cstr (CC_SPACES)); + if (!ss_match_char (&left, '=')) { - msg (IS, _("Syntax error in options.")); + error (0, 0, _("syntax error expecting `=' " + "parsing options for driver \"%s\""), + driver->name); break; } - ds_truncate (&op_tokstr, 64); - strcpy (key, ds_c_str (&op_tokstr)); + ss_ltrim (&left, ss_cstr (CC_SPACES)); + if (!get_option_token (&left, driver->name, &value)) + break; - tokener (); - if (op_token != '=') - { - msg (IS, _("Syntax error in options (`=' expected).")); - break; - } - - tokener (); - if (op_token != 'a') - { - msg (IS, _("Syntax error in options (value expected after `=').")); - break; - } - ok = callback (driver, key, &op_tokstr); + ok = callback (driver, ds_cstr (&key), &value); } - ds_destroy (&op_tokstr); + while (ok); + + ds_destroy (&key); + ds_destroy (&value); return ok; } @@ -675,57 +660,48 @@ find_driver (char *name) return NULL; } -/* String S is in format: - DRIVERNAME:CLASSNAME:DEVICETYPE:OPTIONS - Adds a driver to outp_driver_list pursuant to the specification - provided. */ +/* Adds a driver to outp_driver_list pursuant to the + specification provided. */ static void -configure_driver (const struct string *driver_name, - const struct string *class_name, - const struct string *device_type, - const struct string *options) +configure_driver (struct substring driver_name, struct substring class_name, + struct substring device_type, struct substring options) { struct outp_driver *d, *iter; struct outp_driver_class_list *c; + + struct substring token; + size_t save_idx = 0; int device; /* Find class. */ for (c = outp_class_list; c; c = c->next) - if (!strcmp (c->class->name, ds_c_str (class_name))) + if (!ss_compare (ss_cstr (c->class->name), class_name)) break; if (c == NULL) { - msg (IS, _("Unknown output driver class `%s'."), ds_c_str (class_name)); + error (0, 0, _("unknown output driver class `%.*s'"), + (int) ss_length (class_name), ss_data (class_name)); return; } /* Parse device type. */ device = 0; - if (device_type != NULL) - { - struct string token = DS_INITIALIZER; - size_t save_idx = 0; - - while (ds_tokenize (device_type, &token, " \t\r\v", &save_idx)) - { - const char *type = ds_c_str (&token); - if (!strcmp (type, "listing")) - device |= OUTP_DEV_LISTING; - else if (!strcmp (type, "screen")) - device |= OUTP_DEV_SCREEN; - else if (!strcmp (type, "printer")) - device |= OUTP_DEV_PRINTER; - else - msg (IS, _("Unknown device type `%s'."), type); - } - ds_destroy (&token); - } + while (ss_tokenize (device_type, ss_cstr (CC_SPACES), &save_idx, &token)) + if (!ss_compare (token, ss_cstr ("listing"))) + device |= OUTP_DEV_LISTING; + else if (!ss_compare (token, ss_cstr ("screen"))) + device |= OUTP_DEV_SCREEN; + else if (!ss_compare (token, ss_cstr ("printer"))) + device |= OUTP_DEV_PRINTER; + else + error (0, 0, _("unknown device type `%.*s'"), + (int) ss_length (token), ss_data (token)); /* Open the device. */ d = xmalloc (sizeof *d); d->next = d->prev = NULL; d->class = c->class; - d->name = xstrdup (ds_c_str (driver_name)); + d->name = ss_xstrdup (driver_name); d->page_open = false; d->device = OUTP_DEV_NONE; d->cp_x = d->cp_y = 0; @@ -733,10 +709,10 @@ configure_driver (const struct string *driver_name, d->prc = NULL; /* Open driver. */ - if (!d->class->open_driver (d, ds_c_str (options))) + if (!d->class->open_driver (d, options)) { - msg (IS, _("Can't initialize output driver `%s' of class `%s'."), - d->name, d->class->name); + error (0, 0, _("cannot initialize output driver `%s' of class `%s'"), + d->name, d->class->name); free (d->name); free (d); return; @@ -760,30 +736,30 @@ configure_driver (const struct string *driver_name, Adds a driver to outp_driver_list pursuant to the specification provided. */ static void -configure_driver_line (struct string *line) +configure_driver_line (struct substring line_) { - struct string tokens[4]; + struct string line = DS_EMPTY_INITIALIZER; + struct substring tokens[4]; size_t save_idx; size_t i; - fn_interp_vars (line, find_defn_value); + fn_interp_vars (line_, find_defn_value, &line); save_idx = 0; for (i = 0; i < 4; i++) { - struct string *token = &tokens[i]; - ds_init (token, 0); - ds_separate (line, token, i < 3 ? ":" : "", &save_idx); - ds_trim_spaces (token); + struct substring *token = &tokens[i]; + ds_separate (&line, ss_cstr (i < 3 ? ":" : ""), &save_idx, token); + ss_trim (token, ss_cstr (CC_SPACES)); } - if (!ds_is_empty (&tokens[0]) && !ds_is_empty (&tokens[1])) - configure_driver (&tokens[0], &tokens[1], &tokens[2], &tokens[3]); + if (!ss_is_empty (tokens[0]) && !ss_is_empty (tokens[1])) + configure_driver (tokens[0], tokens[1], tokens[2], tokens[3]); else - msg (IS, _("Driver definition line missing driver name or class name")); + error (0, 0, + _("driver definition line missing driver name or class name")); - for (i = 0; i < 4; i++) - ds_destroy (&tokens[i]); + ds_destroy (&line); } /* Destroys output driver D. */ @@ -818,7 +794,7 @@ destroy_driver (struct outp_driver *d) code and stores subcategory in *SUBCAT on success. Returns -1 on failure. */ int -outp_match_keyword (const char *s, struct outp_option *tab, int *subcat) +outp_match_keyword (const char *s, const struct outp_option *tab, int *subcat) { for (; tab->keyword != NULL; tab++) if (!strcmp (s, tab->keyword)) @@ -926,7 +902,8 @@ outp_evaluate_dimension (char *dimen, char **tail) factor = 72000 / 72.27 / 65536.0; break; default: - msg (SE, _("Unit \"%s\" is unknown in dimension \"%s\"."), s, dimen); + error (0, 0, + _("unit \"%s\" is unknown in dimension \"%s\""), s, dimen); *tail = NULL; return 0; } @@ -941,15 +918,15 @@ outp_evaluate_dimension (char *dimen, char **tail) lossage: *tail = NULL; - msg (SE, _("Bad dimension \"%s\"."), dimen); + error (0, 0, _("bad dimension \"%s\""), dimen); return 0; } /* Stores the dimensions in 1/72000" units of paper identified by SIZE, which is of form `HORZ x VERT' or `HORZ by VERT' where each - of HORZ and VERT are dimensions, into *H and *V. Return nonzero on + of HORZ and VERT are dimensions, into *H and *V. Return true on success. */ -static int +static bool internal_get_paper_size (char *size, int *h, int *v) { char *tail; @@ -958,7 +935,7 @@ internal_get_paper_size (char *size, int *h, int *v) size++; *h = outp_evaluate_dimension (size, &tail); if (tail == NULL) - return 0; + return false; while (isspace ((unsigned char) *tail)) tail++; if (*tail == 'x') @@ -967,8 +944,8 @@ internal_get_paper_size (char *size, int *h, int *v) tail += 2; else { - msg (SE, _("`x' expected in paper size `%s'."), size); - return 0; + error (0, 0, _("`x' expected in paper size `%s'"), size); + return false; } *v = outp_evaluate_dimension (tail, &tail); if (tail == NULL) @@ -977,20 +954,20 @@ internal_get_paper_size (char *size, int *h, int *v) tail++; if (*tail) { - msg (SE, _("Trailing garbage `%s' on paper size `%s'."), tail, size); - return 0; + error (0, 0, _("trailing garbage `%s' on paper size `%s'"), tail, size); + return false; } - return 1; + return true; } /* Stores the dimensions, in 1/72000" units, of paper identified by SIZE into *H and *V. SIZE may be a pair of dimensions of form `H x V', or it may be a case-insensitive paper identifier, which is - looked up in the `papersize' configuration file. Returns nonzero + looked up in the `papersize' configuration file. Returns true on success. May modify SIZE. */ /* Don't read further unless you've got a strong stomach. */ -int +bool outp_get_paper_size (char *size, int *h, int *v) { struct paper_size @@ -1000,20 +977,15 @@ outp_get_paper_size (char *size, int *h, int *v) int h, v; }; - static struct paper_size cache[4]; - static int use; - FILE *f; char *pprsz_fn; struct string line; - struct file_locator where; + int line_number = 0; - int free_it = 0; - int result = 0; - int min_value, min_index; + bool free_it = false; + bool result = false; char *ep; - int i; while (isspace ((unsigned char) *size)) size++; @@ -1026,7 +998,7 @@ outp_get_paper_size (char *size, int *h, int *v) ep--; if (ep == size) { - msg (SE, _("Paper size name must not be empty.")); + error (0, 0, _("paper size name cannot be empty")); return 0; } @@ -1034,104 +1006,72 @@ outp_get_paper_size (char *size, int *h, int *v) if (*ep) *ep = 0; - use++; - for (i = 0; i < 4; i++) - if (cache[i].name != NULL && !strcasecmp (cache[i].name, size)) - { - *h = cache[i].h; - *v = cache[i].v; - cache[i].use = use; - return 1; - } - pprsz_fn = fn_search_path (fn_getenv_default ("STAT_OUTPUT_PAPERSIZE_FILE", "papersize"), fn_getenv_default ("STAT_OUTPUT_INIT_PATH", - config_path), - NULL); - - where.filename = pprsz_fn; - where.line_number = 0; - err_push_file_locator (&where); - ds_init (&line, 128); + config_path)); + + ds_init_empty (&line); if (pprsz_fn == NULL) { - msg (IE, _("Cannot find `papersize' configuration file.")); + error (0, 0, _("cannot find `papersize' configuration file")); goto exit; } f = fopen (pprsz_fn, "r"); if (!f) { - msg (IE, _("Opening %s: %s."), pprsz_fn, strerror (errno)); + error (0, errno, _("error opening \"%s\""), pprsz_fn); goto exit; } for (;;) { - char *cp, *bp, *ep; + struct substring p, name; - if (!ds_get_config_line (f, &line, &where.line_number)) + if (!ds_read_config_line (&line, &line_number, f)) { if (ferror (f)) - msg (ME, _("Reading %s: %s."), pprsz_fn, strerror (errno)); + error (0, errno, _("error reading \"%s\""), pprsz_fn); break; } - for (cp = ds_c_str (&line); isspace ((unsigned char) *cp); cp++); - if (*cp == 0) - continue; - if (*cp != '"') - goto lex_error; - for (bp = ep = cp + 1; *ep && *ep != '"'; ep++); - if (!*ep) + + p = ds_ss (&line); + ss_ltrim (&p, ss_cstr (CC_SPACES)); + if (!ss_match_char (&p, '"') || !ss_get_until (&p, '"', &name)) goto lex_error; - *ep = 0; - if (0 != strcasecmp (bp, size)) + if (ss_compare (name, ss_cstr (size))) continue; - for (cp = ep + 1; isspace ((unsigned char) *cp); cp++); - if (*cp == '=') + ss_ltrim (&p, ss_cstr (CC_SPACES)); + if (ss_match_char (&p, '=')) { - size = xmalloc (ep - bp + 1); - strcpy (size, bp); - free_it = 1; + if (free_it) + free (size); + ss_trim (&p, ss_cstr (CC_SPACES)); + size = ss_xstrdup (p); + free_it = true; continue; } - size = &ep[1]; + size = ss_data (p); break; lex_error: - msg (IE, _("Syntax error in paper size definition.")); + error_at_line (0, 0, pprsz_fn, line_number, + _("syntax error in paper size definition")); } /* We found the one we want! */ result = internal_get_paper_size (size, h, v); - if (result) - { - min_value = cache[0].use; - min_index = 0; - for (i = 1; i < 4; i++) - if (cache[0].use < min_value) - { - min_value = cache[i].use; - min_index = i; - } - free (cache[min_index].name); - cache[min_index].name = xstrdup (size); - cache[min_index].use = use; - cache[min_index].h = *h; - cache[min_index].v = *v; - } exit: - err_pop_file_locator (&where); ds_destroy (&line); if (free_it) free (size); if (!result) - msg (VM (1), _("Error reading paper size definition file.")); + error (0, 0, _("error reading paper size definition file")); return result; } @@ -1143,10 +1083,6 @@ exit: struct outp_driver * outp_drivers (struct outp_driver *d) { -#if DEBUGGING - struct outp_driver *orig_d = d; -#endif - for (;;) { if (d == NULL) @@ -1199,16 +1135,14 @@ outp_close_page (struct outp_driver *d) } } -/* Ejects the paper on device D, if a page is open and is not - blank. */ +/* Ejects the page on device D, if a page is open and non-blank, + and opens a new page. */ void outp_eject_page (struct outp_driver *d) { if (d->page_open && d->cp_y != 0) - { - outp_close_page (d); - outp_open_page (d); - } + outp_close_page (d); + outp_open_page (d); } /* Returns the width of string S, in device units, when output on @@ -1221,7 +1155,7 @@ outp_string_width (struct outp_driver *d, const char *s, enum outp_font font) text.font = font; text.justification = OUTP_LEFT; - ls_init (&text.string, (char *) s, strlen (s)); + text.string = ss_cstr (s); text.h = text.v = INT_MAX; d->class->text_metrics (d, &text, &width, NULL);