From d1fff00503280cb951cb8d3f592776ddf3c8595a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 2 Jan 2004 07:28:39 +0000 Subject: [PATCH] Thu Jan 1 23:16:41 2004 Ben Pfaff * html.c: (change_attributes) Dead code, removed. (escape_string) Eliminate code to call change_attributes() that never actually called it. (output_tab_table) Get rid of dependence on tab_hit and struct tab_joined_cell's hit member, which are abominations. * tab.c: (tab_output_text) Don't call d->class->text_set_font_by_name if it's a null pointer. (macro UNROLL_LOOP) Eliminate. (macro UNROLL_3_LOOPS) Eliminate (tabi_render) Rewrite not to use the above macros. Thu Jan 1 23:09:07 2004 Ben Pfaff Start working on a new output driver system, one that doesn't suck so much, by adding a "device-independent" output driver. The idea is to write out only a single output stream, then use separate processes to translate them into whatever formats we want. This is similar to how "groff" works with its various output drivers (grops, grotty, grodvi, ...). * Makefile.am: (pspp_SOURCES) Add devind.c, devind.h. * list.q: (write_all_headers) Stub out devind class. (clean_up) Ditto. (determine_layout) Ditto. (list_cases) Ditto. * output.c: (outp_init) Add devind class. * devind.c: New file. * devind.h: New file. Thu Jan 1 23:08:14 2004 Ben Pfaff * frequencies.q: (hash_value_alpha) Fixed up the previous change to use the proper string length. --- src/ChangeLog | 41 ++++ src/Makefile.am | 32 ++-- src/devind.c | 477 ++++++++++++++++++++++++++++++++++++++++++++++ src/devind.h | 27 +++ src/frequencies.q | 7 +- src/html.c | 48 ++--- src/list.q | 20 ++ src/output.c | 6 +- src/tab.c | 79 ++++---- 9 files changed, 644 insertions(+), 93 deletions(-) create mode 100644 src/devind.c create mode 100644 src/devind.h diff --git a/src/ChangeLog b/src/ChangeLog index 4eb438ae0f..e656ecd0b5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,44 @@ +Thu Jan 1 23:16:41 2004 Ben Pfaff + + * html.c: (change_attributes) Dead code, removed. + (escape_string) Eliminate code to call change_attributes() that + never actually called it. + (output_tab_table) Get rid of dependence on tab_hit + and struct tab_joined_cell's hit member, which are abominations. + + * tab.c: (tab_output_text) Don't call + d->class->text_set_font_by_name if it's a null pointer. + (macro UNROLL_LOOP) Eliminate. + (macro UNROLL_3_LOOPS) Eliminate + (tabi_render) Rewrite not to use the above macros. + +Thu Jan 1 23:09:07 2004 Ben Pfaff + + Start working on a new output driver system, one that doesn't suck + so much, by adding a "device-independent" output driver. The idea + is to write out only a single output stream, then use separate + processes to translate them into whatever formats we want. This + is similar to how "groff" works with its various output drivers + (grops, grotty, grodvi, ...). + + * Makefile.am: (pspp_SOURCES) Add devind.c, devind.h. + + * list.q: (write_all_headers) Stub out devind class. + (clean_up) Ditto. + (determine_layout) Ditto. + (list_cases) Ditto. + + * output.c: (outp_init) Add devind class. + + * devind.c: New file. + + * devind.h: New file. + +Thu Jan 1 23:08:14 2004 Ben Pfaff + + * frequencies.q: (hash_value_alpha) Fixed up the previous change + to use the proper string length. + Wed Dec 31 16:27:33 WAST 2003 John Darrington * Fixed bug where FREQ would crash on alpha values diff --git a/src/Makefile.am b/src/Makefile.am index 329711e2a5..2442ca990c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,22 +36,22 @@ pspp_SOURCES = aggregate.c algorithm.c algorithm.h alloc.c alloc.h \ apply-dict.c approx.h ascii.c autorecode.c bitvector.h cases.c cases.h \ cmdline.c cmdline.h command.c command.def command.h compute.c \ correlations.c count.c crosstabs.c data-in.c data-in.h data-list.c \ -data-out.c debug-print.h descript.c dfm.c dfm.h dictionary.c do-if.c \ -do-ifP.h error.c error.h expr-evl.c expr-opt.c expr-prs.c expr.h \ -exprP.h file-handle.c file-handle.h file-type.c filename.c filename.h \ -flip.c font.h format.c format.def format.h formats.c frequencies.c \ -get.c getline.c getline.h glob.c glob.h groff-font.c hash.c hash.h \ -heap.c heap.h html.c htmlP.h include.c inpt-pgm.c lexer.c lexer.h \ -list.c log.h loop.c magic.c magic.h main.c main.h matrix-data.c \ -matrix.c matrix.h means.c mis-val.c misc.c misc.h modify-vars.c \ -numeric.c output.c output.h pfm-read.c pfm-write.c pfm.h pool.c pool.h \ -postscript.c print.c random.c random.h recode.c rename-vars.c repeat.c \ -repeat.h sample.c sel-if.c set.c settings.h sfm-read.c sfm-write.c \ -sfm.h sfmP.h som.c som.h sort.c sort.h split-file.c stat.h stats.c \ -stats.h str.c str.h sysfile-info.c tab.c tab.h temporary.c title.c \ -t-test.c val-labs.c value-labels.c value-labels.h var-labs.c var.h \ -vars-atr.c vars-prs.c vector.c version.c version.h vfm.c vfm.h vfmP.h \ -weight.c +data-out.c debug-print.h descript.c devind.c devind.h dfm.c dfm.h \ +dictionary.c do-if.c do-ifP.h error.c error.h expr-evl.c expr-opt.c \ +expr-prs.c expr.h exprP.h file-handle.c file-handle.h file-type.c \ +filename.c filename.h flip.c font.h format.c format.def format.h \ +formats.c frequencies.c get.c getline.c getline.h glob.c glob.h \ +groff-font.c hash.c hash.h heap.c heap.h html.c htmlP.h include.c \ +inpt-pgm.c lexer.c lexer.h list.c log.h loop.c magic.c magic.h main.c \ +main.h matrix-data.c matrix.c matrix.h means.c mis-val.c misc.c misc.h \ +modify-vars.c numeric.c output.c output.h pfm-read.c pfm-write.c pfm.h \ +pool.c pool.h postscript.c print.c random.c random.h recode.c \ +rename-vars.c repeat.c repeat.h sample.c sel-if.c set.c settings.h \ +sfm-read.c sfm-write.c sfm.h sfmP.h som.c som.h sort.c sort.h \ +split-file.c stat.h stats.c stats.h str.c str.h sysfile-info.c tab.c \ +tab.h temporary.c title.c t-test.c val-labs.c value-labels.c \ +value-labels.h var-labs.c var.h vars-atr.c vars-prs.c vector.c \ +version.c version.h vfm.c vfm.h vfmP.h weight.c pspp_LDADD = ../lib/julcal/libjulcal.a \ ../lib/misc/libmisc.a \ diff --git a/src/devind.c b/src/devind.c new file mode 100644 index 0000000000..8432ea8e4d --- /dev/null +++ b/src/devind.c @@ -0,0 +1,477 @@ +/* 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 + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +/* Device-independent output format. Eventually I intend for all + PSPP output to work this way, but adding it as an available + format is a first step. + + Each line in the output is a command. The first character on + the line is the command name, and the rest of the line is the + command arguments. The commands are described below as Perl + regular expressions: + + #.* comment + + s starts a new table + S[rc]\d+ table size in rows or columns (optional) + H[lrtb]\d+ number of left/right/top/bottom header rows/columns + B(\d+)-(\d+)/(\d+) + allow column breaks every \3 rows from \1 to \2 exclusive + T.* table title + C.* table caption (not yet supported) + t(\d+)(-\d+)?,(\d+)(-\d+)?[wn][hb][lcr][tmb]:.* + text for cells in rows (\1-\2) inclusive and + columns (\3-\4) inclusive, + wrappable/nonwrappable, header/body, + left/center/right justified, top/middle/bottom + justified + l[hv][sdtn](\d+),(\d+)-(\d+) + horiz/vert line in single/double/thick/none + style, running across columns/rows \2 to \3 + inclusive at offset \1 from top/left side of + table + b[sdtno]{4}(\d+)-(\d+),(\d+)-(\d+) + box across columns \1 to \2 inclusive and rows \3 + to \4 inclusive with + single/double/thick/none/omit style for horiz & + vert frame and horiz & vert interior lines + f(\d+),(\d+):.* + add footnote for cell \1, \2 + e end table + + v(\d(.\d+)+) insert \1 lines of blank space + + p:.* plain text + m[ewmlu]:(.*),(\d+),((\d+)(-\d+)?)?:(.*) + error/warning/message/listing/user class message + for file \1, line \2, columns \4 to \5, actual + message \6 + + q end of file + + Text tokens are free-form, except that they are terminated by + commas and new-lines. The following escapes are allowed: + + \\n line break + \\c comma + \\s non-breaking space + \\[0-7]{3} octal escape + \\B toggle subscript + \\P toggle superscript + \\e toggle emphasis + \\E toggle strong emphasis + \\v toggle variable name font + \\F toggle file name font + \\p toggle fixed-pitch text font (default: proportional) + \\n\((\d+)?(\.\d+)?(-?\d+(\.\d+)?+(e-?\d+))?\) + number \3 (sysmis if not provided) in \1.\2 format + \\f\(([A-Z]*(\d+)?(\.\d+)?)(-?\d+(\.\d+)?+(e-?\d+))?\) + number \1 in \4 format + +*/ + +#include +#include "devind.h" +#include +#include +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#include "alloc.h" +#include "error.h" +#include "filename.h" +#include "getline.h" +#include "output.h" +#include "som.h" +#include "tab.h" +#include "version.h" + +/* Device-independent output driver extension record. */ +struct devind_driver_ext + { + /* Internal state. */ + struct file_ext file; /* Output file. */ + int sequence_no; /* Sequence number. */ + }; + +static int +devind_open_global (struct outp_class *this unused) +{ + return 1; +} + +static int +devind_close_global (struct outp_class *this unused) +{ + return 1; +} + +static int +devind_preopen_driver (struct outp_driver *this) +{ + struct devind_driver_ext *x; + + assert (this->driver_open == 0); + msg (VM (1), _("DEVIND driver initializing as `%s'..."), this->name); + + this->ext = x = xmalloc (sizeof *x); + this->res = 0; + this->horiz = this->vert = 0; + this->width = this->length = 0; + + this->cp_x = this->cp_y = 0; + + x->file.filename = NULL; + x->file.mode = "w"; + x->file.file = NULL; + x->file.sequence_no = &x->sequence_no; + x->file.param = this; + x->file.postopen = NULL; + x->file.preclose = NULL; + + x->sequence_no = 0; + + return 1; +} + +static int +devind_postopen_driver (struct outp_driver *this) +{ + struct devind_driver_ext *x = this->ext; + + assert (this->driver_open == 0); + if (NULL == x->file.filename) + x->file.filename = xstrdup ("pspp.devind"); + + msg (VM (2), _("%s: Initialization complete."), this->name); + this->driver_open = 1; + + return 1; +} + +static int +devind_close_driver (struct outp_driver *this) +{ + struct devind_driver_ext *x = this->ext; + + assert (this->driver_open); + msg (VM (2), _("%s: Beginning closing..."), this->name); + fputs ("q\n", x->file.file); + fn_close_ext (&x->file); + free (x->file.filename); + free (x); + msg (VM (3), _("%s: Finished closing."), this->name); + this->driver_open = 0; + + return 1; +} + +/* Generic option types. */ +enum +{ + boolean_arg = -10, + string_arg, + nonneg_int_arg +}; + +/* All the options that the DEVIND driver supports. */ +static struct outp_option option_tab[] = +{ + /* *INDENT-OFF* */ + {"output-file", 1, 0}, + {"", 0, 0}, + /* *INDENT-ON* */ +}; +static struct outp_option_info option_info; + +static void +devind_option (struct outp_driver *this, const char *key, const struct string *val) +{ + struct devind_driver_ext *x = this->ext; + int cat, subcat; + + cat = outp_match_keyword (key, option_tab, &option_info, &subcat); + switch (cat) + { + case 0: + msg (SE, _("Unknown configuration parameter `%s' for DEVIND device " + "driver."), key); + break; + case 1: + free (x->file.filename); + x->file.filename = xstrdup (ds_value (val)); + break; + default: + assert (0); + } +} + +static int +devind_open_page (struct outp_driver *this) +{ + struct devind_driver_ext *x = this->ext; + + assert (this->driver_open && this->page_open == 0); + x->sequence_no++; + if (!fn_open_ext (&x->file)) + { + if (errno) + msg (ME, _("DEVIND output driver: %s: %s"), x->file.filename, + strerror (errno)); + return 0; + } + + if (!ferror (x->file.file)) + this->page_open = 1; + return !ferror (x->file.file); +} + +static int +devind_close_page (struct outp_driver *this) +{ + struct devind_driver_ext *x = this->ext; + + assert (this->driver_open && this->page_open); + this->page_open = 0; + return !ferror (x->file.file); +} + +static void output_tab_table (struct outp_driver *, struct tab_table *); + +static void +devind_submit (struct outp_driver *this, struct som_table *s) +{ + extern struct som_table_class tab_table_class; + struct devind_driver_ext *x = this->ext; + + assert (this->driver_open && this->page_open); + if (x->sequence_no == 0 && !devind_open_page (this)) + { + msg (ME, _("Cannot open first page on DEVIND device %s."), this->name); + return; + } + + if (s->class == &tab_table_class) + output_tab_table (this, s->ext); + else + assert (0); +} + +/* Write string S of length LEN to file F, escaping characters as + necessary for DEVIND. */ +static void +escape_string (FILE *f, char *s, int len) +{ + char *ep = &s[len]; + char *bp, *cp; + + putc (':', f); + + for (bp = cp = s; bp < ep; bp = cp) + { + while (cp < ep && *cp != ',' && *cp != '\n' && *cp) + cp++; + if (cp > bp) + fwrite (bp, 1, cp - bp, f); + if (cp < ep) + switch (*cp++) + { + case ',': + fputs ("\\c", f); + break; + case '\n': + fputs ("\\n", f); + break; + case 0: + break; + default: + assert (0); + } + } +} + +/* Write table T to THIS output driver. */ +static void +output_tab_table (struct outp_driver *this, struct tab_table *t) +{ + struct devind_driver_ext *x = this->ext; + + if (t->nr == 1 && t->nc == 1) + { + fputs ("p:", x->file.file); + escape_string (x->file.file, ls_value (t->cc), ls_length (t->cc)); + putc ('\n', x->file.file); + + return; + } + + /* Start table. */ + fprintf (x->file.file, "s\n"); + + /* Table size. */ + fprintf (x->file.file, "Sr%d\n", t->nr); + fprintf (x->file.file, "Sc%d\n", t->nc); + + /* Table headers. */ + if (t->l != 0) + fprintf (x->file.file, "Hl%d\n", t->l); + if (t->r != 0) + fprintf (x->file.file, "Hr%d\n", t->r); + if (t->t != 0) + fprintf (x->file.file, "Ht%d\n", t->t); + if (t->b != 0) + fprintf (x->file.file, "Hb%d\n", t->b); + + /* Title. */ + if (!ls_empty_p (&t->title)) + { + putc ('T', x->file.file); + escape_string (x->file.file, ls_value (&t->title), + ls_length (&t->title)); + putc ('\n', x->file.file); + } + + /* Column breaks. */ + if (t->col_style == TAB_COL_DOWN) + fprintf (x->file.file, "B%d-%d/%d\n", t->t, t->nr - t->b, t->col_group); + + /* Table text. */ + { + int r; + unsigned char *ct = t->ct; + + for (r = 0; r < t->nr; r++) + { + int c; + + for (c = 0; c < t->nc; c++, ct++) + { + struct len_string *cc; + struct tab_joined_cell *j; + + if (*ct == TAB_EMPTY) + continue; + + cc = t->cc + c + r * t->nc; + if (*ct & TAB_JOIN) + { + j = (struct tab_joined_cell *) ls_value (cc); + cc = &j->contents; + if (c != j->x1 || r != j->y1) + continue; + } + else + j = NULL; + + putc ('t', x->file.file); + if (j == NULL) + fprintf (x->file.file, "%d,%d", r, c); + else + fprintf (x->file.file, "%d-%d,%d-%d", + j->y1, j->y2, j->x1, j->x2); + putc ((*ct & TAT_NOWRAP) ? 'n' : 'w', x->file.file); + putc ((*ct & TAT_TITLE) ? 'h' : 'b', x->file.file); + if ((*ct & TAB_ALIGN_MASK) == TAB_RIGHT) + putc ('r', x->file.file); + else if ((*ct & TAB_ALIGN_MASK) == TAB_LEFT) + putc ('l', x->file.file); + else + putc ('c', x->file.file); + putc ('t', x->file.file); + escape_string (x->file.file, ls_value (cc), ls_length (cc)); + putc ('\n', x->file.file); + } + } + } + + /* Horizontal lines. */ + { + int r, c; + + for (r = 0; r <= t->nr; r++) + for (c = 0; c < t->nc; c++) + { + int rule = t->rh[c + r * t->nc]; + if (rule != 0) + fprintf (x->file.file, "lh%c%d,%d-%d\n", "nsdt"[rule], r, c, c); + } + } + + /* Vertical lines. */ + { + int r, c; + + for (r = 0; r < t->nr; r++) + for (c = 0; c <= t->nc; c++) + { + int rule = t->rv[c + r * (t->nc + 1)]; + if (rule != 0) + fprintf (x->file.file, "lv%c%d,%d-%d\n", "nsdt"[rule], c, r, r); + } + } + + /* End of table. */ + fputs ("e\n", x->file.file); +} + +/* DEVIND driver class. */ +struct outp_class devind_class = +{ + "devind", + 0xb1e7, + 1, + + devind_open_global, + devind_close_global, + NULL, + + devind_preopen_driver, + devind_option, + devind_postopen_driver, + devind_close_driver, + + devind_open_page, + devind_close_page, + + devind_submit, + + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; diff --git a/src/devind.h b/src/devind.h new file mode 100644 index 0000000000..e8abafd307 --- /dev/null +++ b/src/devind.h @@ -0,0 +1,27 @@ +/* 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 + 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef INCLUDED_DEVIND_H +#define INCLUDED_DEVIND_H 1 + +#include "output.h" + +extern struct outp_class devind_class; + +#endif /* devind.h */ diff --git a/src/frequencies.q b/src/frequencies.q index a9c5850d7b..3f5224d679 100644 --- a/src/frequencies.q +++ b/src/frequencies.q @@ -833,13 +833,12 @@ hash_value_numeric (const void *value_, void *foo unused) /* Hash of string values. */ static unsigned -hash_value_alpha (const void *value_, void *len_ unused) +hash_value_alpha (const void *value_, void *v_) { const struct freq *value = value_; + struct variable *v = v_; - static int len = MAX_SHORT_STRING; - - return hsh_hash_bytes (value->v.s, len); + return hsh_hash_bytes (value->v.s, v->width); } /* Ascending numeric compare of values. */ diff --git a/src/html.c b/src/html.c index 3f7416290b..53add68cd5 100644 --- a/src/html.c +++ b/src/html.c @@ -409,26 +409,6 @@ html_submit (struct outp_driver *this, struct som_table *s) assert (0); } -/* Emit HTML to FILE to change from *OLD_ATTR attributes to NEW_ATTR. - Sets *OLD_ATTR to NEW_ATTR when done. */ -static void -change_attributes (FILE *f, int *old_attr, int new_attr) -{ - if (*old_attr == new_attr) - return; - - if (*old_attr & OUTP_F_B) - fputs ("", f); - if (*old_attr & OUTP_F_I) - fputs ("", f); - if (new_attr & OUTP_F_I) - fputs ("", f); - if (new_attr & OUTP_F_B) - fputs ("", f); - - *old_attr = new_attr; -} - /* Write string S of length LEN to file F, escaping characters as necessary for HTML. */ static void @@ -436,7 +416,6 @@ escape_string (FILE *f, char *s, int len) { char *ep = &s[len]; char *bp, *cp; - int attr = 0; for (bp = cp = s; bp < ep; bp = cp) { @@ -462,9 +441,6 @@ escape_string (FILE *f, char *s, int len) assert (0); } } - - if (attr) - change_attributes (f, &attr, 0); } /* Write table T to THIS output driver. */ @@ -473,8 +449,6 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) { struct html_driver_ext *x = this->ext; - tab_hit++; - if (t->nr == 1 && t->nc == 1) { fputs ("

", x->file.file); @@ -497,7 +471,6 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) { int r; - struct len_string *cc = t->cc; unsigned char *ct = t->ct; for (r = 0; r < t->nr; r++) @@ -505,15 +478,22 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) int c; fputs (" \n", x->file.file); - for (c = 0; c < t->nc; c++, cc++, ct++) + for (c = 0; c < t->nc; c++, ct++) { + struct len_string *cc; int tag; char header[128]; char *cp; + struct tab_joined_cell *j = NULL; - if ((*ct & TAB_JOIN) - && ((struct tab_joined_cell *) ls_value (cc))->hit == tab_hit) - continue; + cc = t->cc + c + r * t->nc; + if (*ct & TAB_JOIN) + { + j = (struct tab_joined_cell *) ls_value (cc); + cc = &j->contents; + if (j->x1 != c || j->y1 != r) + continue; + } if (r < t->t || r >= t->nr - t->b || c < t->l || c >= t->nc - t->r) @@ -539,14 +519,12 @@ output_tab_table (struct outp_driver *this, struct tab_table *t) if (*ct & TAB_JOIN) { - struct tab_joined_cell *j = - (struct tab_joined_cell *) ls_value (cc); - j->hit = tab_hit; - if (j->x2 - j->x1 > 1) cp = spprintf (cp, " COLSPAN=%d", j->x2 - j->x1); if (j->y2 - j->y1 > 1) cp = spprintf (cp, " ROWSPAN=%d", j->y2 - j->y1); + + cc = &j->contents; } strcpy (cp, ">"); diff --git a/src/list.q b/src/list.q index dbdacb573c..578cfe5d0a 100644 --- a/src/list.q +++ b/src/list.q @@ -23,6 +23,7 @@ #include #include "alloc.h" #include "command.h" +#include "devind.h" #include "lexer.h" #include "error.h" #include "magic.h" @@ -30,6 +31,7 @@ #include "htmlP.h" #include "output.h" #include "som.h" +#include "tab.h" #include "var.h" #include "vfm.h" #include "format.h" @@ -271,6 +273,10 @@ write_all_headers (void) fputs (" \n", x->file.file); } + else if (d->class == &devind_class) + { + /* FIXME */ + } else assert (0); } @@ -389,6 +395,10 @@ clean_up (void) fputs ("\n", x->file.file); } } + else if (d->class == &devind_class) + { + /* FIXME */ + } else assert (0); @@ -520,6 +530,12 @@ determine_layout (void) if (d->class == &html_class) continue; + else if (d->class == &devind_class) + { + /* FIXME */ + tab_output_text (TAT_NONE, "(devind not supported on LIST yet)"); + continue; + } assert (d->class->special == 0); @@ -709,6 +725,10 @@ list_cases (struct ccase *c) fputs (" \n", x->file.file); } + else if (d->class == &devind_class) + { + /* FIXME */ + } else assert (0); diff --git a/src/output.c b/src/output.c index f3e0da7ea3..b804978d6d 100644 --- a/src/output.c +++ b/src/output.c @@ -26,8 +26,10 @@ #include #include "alloc.h" #include "approx.h" +#include "devind.h" #include "error.h" #include "filename.h" +#include "htmlP.h" #include "lexer.h" #include "misc.h" #include "settings.h" @@ -226,9 +228,8 @@ outp_init (void) extern struct outp_class postscript_class; extern struct outp_class epsf_class; #endif -#if !NO_HTML extern struct outp_class html_class; -#endif + extern struct outp_class devind_class; char def[] = "default"; @@ -239,6 +240,7 @@ outp_init (void) add_class (&epsf_class); add_class (&postscript_class); #endif + add_class (&devind_class); add_class (&ascii_class); add_name (def, &def[strlen (def)], OUTP_S_INIT_FILE); diff --git a/src/tab.c b/src/tab.c index acfe352506..8dc704ffe6 100644 --- a/src/tab.c +++ b/src/tab.c @@ -802,8 +802,13 @@ tab_output_text (int options, const char *buf, ...) { if (!d->page_open) d->class->open_page (d); - - d->class->text_set_font_by_name (d, "FIXED"); + + if (d->class->text_set_font_by_name != NULL) + d->class->text_set_font_by_name (d, "FIXED"); + else + { + /* FIXME */ + } } } @@ -820,7 +825,12 @@ tab_output_text (int options, const char *buf, ...) struct outp_driver *d; for (d = outp_drivers (NULL); d; d = outp_drivers (d)) - d->class->text_set_font_by_name (d, "PROP"); + if (d->class->text_set_font_by_name != NULL) + d->class->text_set_font_by_name (d, "PROP"); + else + { + /* FIXME */ + } } if (options & TAT_PRINTF) @@ -1147,50 +1157,47 @@ tabi_title (int x, int y) static int render_strip (int x, int y, int r, int c1, int c2, int r1, int r2); -/* Execute BODY for each value of X from A to B exclusive. */ -#define UNROLL_LOOP(X, A, B, BODY) \ - do \ - { \ - for (X = A; X < B; X++) \ - { \ - BODY \ - } \ - } \ - while (0) - -/* Execute PREP, then BODY for each specified value of X: A1...A2, B1...B2, - C1...C2, in each case not including the second value. */ -#define UNROLL_3_LOOPS(X, A1, A2, B1, B2, C1, C2, BODY) \ - do \ - { \ - UNROLL_LOOP (X, A1, A2, BODY); \ - UNROLL_LOOP (X, B1, B2, BODY); \ - UNROLL_LOOP (X, C1, C2, BODY); \ - } \ - while (0) - /* Draws the table region in rectangle (X1,Y1)-(X2,Y2), where column X2 and row Y2 are not included in the rectangle, at the current position on the current output device. Draws headers as well. */ static void tabi_render (int x1, int y1, int x2, int y2) { - int y, r; + int i, y; + int ranges[3][2]; tab_hit++; + y = d->cp_y; if (!(t->flags & SOMF_NO_TITLE)) y += d->font_height; - UNROLL_3_LOOPS (r, 0, t->t * 2 + 1, y1 * 2 + 1, y2 * 2, - (t->nr - t->b) * 2, t->nr * 2 + 1, - - int x = d->cp_x; - x += render_strip (x, y, r, 0, t->l * 2 + 1, y1, y2); - x += render_strip (x, y, r, x1 * 2 + 1, x2 * 2, y1, y2); - x += render_strip (x, y, r, (t->nc - t->r) * 2, - t->nc * 2 + 1, y1, y2); - y += (r & 1) ? t->h[r / 2] : t->hrh[r / 2]; - ); + + /* Top headers. */ + ranges[0][0] = 0; + ranges[0][1] = t->t * 2 + 1; + + /* Requested rows. */ + ranges[1][0] = y1 * 2 + 1; + ranges[1][1] = y2 * 2; + + /* Bottom headers. */ + ranges[2][0] = (t->nr - t->b) * 2; + ranges[2][1] = t->nr * 2 + 1; + + for (i = 0; i < 3; i++) + { + int r; + + for (r = ranges[i][0]; r < ranges[i][1]; r++) + { + int x = d->cp_x; + x += render_strip (x, y, r, 0, t->l * 2 + 1, y1, y2); + x += render_strip (x, y, r, x1 * 2 + 1, x2 * 2, y1, y2); + x += render_strip (x, y, r, (t->nc - t->r) * 2, + t->nc * 2 + 1, y1, y2); + y += (r & 1) ? t->h[r / 2] : t->hrh[r / 2]; + } + } } struct som_table_class tab_table_class = -- 2.30.2