diff options
author | ru <ru@FreeBSD.org> | 2005-10-20 10:45:19 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2005-10-20 10:45:19 +0000 |
commit | 353ac0b339df3493d1950b6527988b77b76bd197 (patch) | |
tree | 8a188846a3f5bd2f2b8cb869cba64e3c470a2b26 /contrib/groff/src/devices | |
parent | c40093b1f1b43dc237b9d272697cdd0842ec64ec (diff) | |
download | FreeBSD-src-353ac0b339df3493d1950b6527988b77b76bd197.zip FreeBSD-src-353ac0b339df3493d1950b6527988b77b76bd197.tar.gz |
Virgin import of FSF groff v1.19.2
Diffstat (limited to 'contrib/groff/src/devices')
53 files changed, 7786 insertions, 844 deletions
diff --git a/contrib/groff/src/devices/grodvi/dvi.cpp b/contrib/groff/src/devices/grodvi/dvi.cpp index df16939..201eb1c 100644 --- a/contrib/groff/src/devices/grodvi/dvi.cpp +++ b/contrib/groff/src/devices/grodvi/dvi.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -17,7 +17,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "nonposix.h" @@ -340,12 +340,12 @@ void dvi_printer::set_color(color *col) do_special(buf); } -void dvi_printer::set_char(int index, font *f, const environment *env, +void dvi_printer::set_char(int idx, font *f, const environment *env, int w, const char *) { if (*env->col != cur_color) set_color(env->col); - int code = f->get_code(index); + int code = f->get_code(idx); if (env->size != cur_point_size || f != cur_font) { cur_font = f; cur_point_size = env->size; @@ -384,7 +384,7 @@ void dvi_printer::set_char(int index, font *f, const environment *env, } possibly_begin_line(); end_h = env->hpos + w; - cur_h += scale(f->get_width(index, UNITWIDTH)/MULTIPLIER, + cur_h += scale(f->get_width(idx, UNITWIDTH)/MULTIPLIER, cur_point_size*RES_7227); if (cur_h > max_h) max_h = cur_h; @@ -709,24 +709,26 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env) fill_flag = 1; // fall through case 'c': - // troff adds an extra argument to C - if (np != 1 && !(code == 'C' && np == 2)) { - error("1 argument required for circle"); + { + // troff adds an extra argument to C + if (np != 1 && !(code == 'C' && np == 2)) { + error("1 argument required for circle"); + break; + } + moveto(env->hpos+p[0]/2, env->vpos); + if (fill_flag) + fill_next(env); + else + set_line_thickness(env); + int rad; + rad = milliinches(p[0]/2); + sprintf(buf, "%s 0 0 %d %d 0 6.28319", + (fill_flag ? "ia" : "ar"), + rad, + rad); + do_special(buf); break; } - moveto(env->hpos+p[0]/2, env->vpos); - if (fill_flag) - fill_next(env); - else - set_line_thickness(env); - int rad; - rad = milliinches(p[0]/2); - sprintf(buf, "%s 0 0 %d %d 0 6.28319", - (fill_flag ? "ia" : "ar"), - rad, - rad); - do_special(buf); - break; case 'l': if (np != 2) { error("2 arguments required for line"); @@ -820,11 +822,11 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env) if (adjust_arc_center(p, c)) { int rad = milliinches(int(sqrt(c[0]*c[0] + c[1]*c[1]) + .5)); moveto(env->hpos + int(c[0]), env->vpos + int(c[1])); - sprintf(buf, "ar 0 0 %d %d %f %f", - rad, - rad, - atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]), - atan2(-c[1], -c[0])); + double start = atan2(p[1] + p[3] - c[1], p[0] + p[2] - c[0]); + double end = atan2(-c[1], -c[0]); + if (end - start < 0) + start -= 2 * 3.14159265358; + sprintf(buf, "ar 0 0 %d %d %f %f", rad, rad, start, end); do_special(buf); } else { @@ -915,7 +917,7 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "dF:lp:vw:", long_options, NULL)) + while ((c = getopt_long(argc, argv, "dF:I:lp:vw:", long_options, NULL)) != EOF) switch(c) { case 'd': @@ -927,6 +929,9 @@ int main(int argc, char **argv) case 'F': font::command_line_font_dir(optarg); break; + case 'I': + // ignore include search path + break; case 'p': if (!font::scan_papersize(optarg, 0, &user_paper_length, &user_paper_width)) diff --git a/contrib/groff/src/devices/grodvi/grodvi.man b/contrib/groff/src/devices/grodvi/grodvi.man index 793bfe2..7c74c32 100644 --- a/contrib/groff/src/devices/grodvi/grodvi.man +++ b/contrib/groff/src/devices/grodvi/grodvi.man @@ -1,5 +1,5 @@ .ig -Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc. +Copyright (C) 1989-2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -17,6 +17,8 @@ translations approved by the Free Software Foundation instead of in the original English. .. . +.do nr grodvi_C \n[.C] +.cp 0 . .ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X .el .ds tx TeX @@ -117,7 +119,7 @@ may not contain a newline. . .LP For inclusion of EPS image files, -.B grodvi +.B \-Tdvi loads .B pspic.tmac automatically, providing the @@ -425,6 +427,8 @@ and widths of rules be rounded. .BR groff_char (@MAN7EXT@), .BR groff_tmac (@MAN5EXT@) . +.cp \n[grodvi_C] +. .\" Local Variables: .\" mode: nroff .\" End: diff --git a/contrib/groff/src/devices/grohtml/grohtml.man b/contrib/groff/src/devices/grohtml/grohtml.man index 976990a..ec82beb 100644 --- a/contrib/groff/src/devices/grohtml/grohtml.man +++ b/contrib/groff/src/devices/grohtml/grohtml.man @@ -1,5 +1,5 @@ .ig -Copyright (C) 1999-2000, 2001, 2002 Free Software Foundation, Inc. +Copyright (C) 1999-2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -16,17 +16,23 @@ versions, except that this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English. .. +. +. .\" Like TP, but if specified indent is more than half .\" the current line-length - indent, use the default indent. .de Tp -.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP -.el .TP "\\$1" +. ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +. el .TP "\\$1" .. +. +. .TH GROHTML @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" . +. .SH NAME grohtml \- html driver for groff . +. .SH SYNOPSIS .nr a \n(.j .ad l @@ -34,22 +40,28 @@ grohtml \- html driver for groff .in +\w'\fBgrohtml 'u .ti \niu .B grohtml +. .de OP -.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" -.el .RB "[\ " "\\$1" "\ ]" +. ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]" +. el .RB "[\ " "\\$1" "\ ]" .. -.OP \-vhlrn +. +.OP \-bhlnprv +.OP \-a \%aa-text-bits .OP \-D dir .OP \-F dir -.OP \-i resolution +.OP \-g \%aa-graphic-bits +.OP \-i \%resolution .OP \-I \%image-stem +.OP \-j \%filename .OP \-o \%image-vertical-offset -.OP \-a \%aa-text-bits -.OP \-a \%aa-graphic-bits +.OP \-s size +.OP \-S level .RI "[\ " files\|.\|.\|. "\ ]" .br .ad \na . +. .SH DESCRIPTION The .B grohtml @@ -84,13 +96,15 @@ using .BR groff 's .B \-P option. +. +. .SH OPTIONS .TP .BI \-a aa-text-bits Number of bits of antialiasing information to be used by .I text when generating png images. -The default is\~4 but legal values are 0, 1, 2, and\~4. +The default is\~4 but valid values are 0, 1, 2, and\~4. Note your version of .B gs needs to support the @@ -102,12 +116,33 @@ A value of\~0 stops .B grohtml from issuing antialiasing commands to .BR gs . +. +.TP +.B \-b +Initialize the background color to white. +. +.TP +.BI \-D dir +Inform +.B grohtml +to place all image files into directory +.IR dir . +. +.TP +.BI \-F dir +Prepend directory +.IB dir /dev name +to the search path for font and device description files; +.I name +is the name of the device, usually +.BR html . +. .TP .BI \-g aa-graphic-bits Number of bits of antialiasing information to be used by .I graphics when generating png images. -The default is\~4 but legal values are 0, 1, 2, and\~4. +The default is\~4 but valid values are 0, 1, 2, and\~4. Note your version of .B gs needs to support the @@ -119,69 +154,93 @@ A value of\~0 stops .B grohtml from issuing antialiasing commands to .BR gs . +. .TP -.B -b -Initialize the background color to white. -.TP -.B -h -Generates section and number headings by using +.B \-h +Generate section and number headings by using .BR <B> .\|.\|. </B> and increasing the font size, rather than using the .BI <H n >\c \&.\|.\|.\c .BI </H n > tags. -.TP -.B -l -Turns off the production of automatic section links at the top of the document. -.TP -.B -r -Turns off the automatic header and footer line (html rule). -.TP -.B -n -Generate simple heading anchors whenever a section/number heading is found. -Without the option the anchor value is the textual heading. -This can cause problems when a heading contains a `?' on some browsers -(netscape). -This flag is automatically turned on if a heading contains an image. -.TP -.B -p -Display page rendering progress to stderr. -.B grohtml -only displays a page number when an image is required. -.TP -.BI \-F dir -Prepend directory -.IB dir /dev name -to the search path for font and device description files; -.I name -is the name of the device, usually -.BR html . +. .TP .BI \-i resolution Select the resolution for all images. By default this is 100 pixels per inch. -Example: -i200 indicates 200 pixels per inch. +Example: +.B \-i200 +indicates 200 pixels per inch. +. .TP .BI \-I stem Determine the image stem name. If omitted grohtml uses -.BI grohtml- XXX +.BI \%grohtml- XXX .RI ( XXX is the process ID). +. +.TP +.BI \-j filename +Inform +.B grohtml +to split the html output into multiple files. +The +.I filename +is the stem and specified section headings +(default is level one) start a new file, named +.IR filename-n.html . +. +.TP +.B \-l +Turn off the production of automatic section links at the top of the +document. +. +.TP +.B \-n +Generate simple heading anchors whenever a section/number heading is found. +Without the option the anchor value is the textual heading. +This can cause problems when a heading contains a `?' on older versions of +some browsers (Netscape). +This flag is automatically turned on if a heading contains an image. +. .TP .BI \-o vertical-offset Specify the vertical offset of images in points. +. .TP -.BI \-D dir -Inform +.B \-p +Display page rendering progress to stderr. .B grohtml -to place all image files into directory -.IR dir . +only displays a page number when an image is required. +. +.TP +.B \-r +Turn off the automatic header and footer line (html rule). +. +.TP +.B \-s size +Set the base point size of the source file. +Thereafter when this point size is used in the source it will correspond +to the html base size. +Every increase of two points in the source will yield a +.B <big> +tag, and conversely when a decrease of two points is seen a +.B <small> +tag is emitted. +. +.TP +.BI \-S level +When splitting html output, +split at the heading level (or higher) defined by +.IR level . +. .TP .B \-v Print the version number. . +. .SH USAGE There are styles called .BR R , @@ -189,11 +248,15 @@ There are styles called .BR B , and .B BI -mounted at font positions 1 to 4. +mounted at font positions 1 to\~4. +. +. .SH DEPENDENCIES .B grohtml is dependent upon the png utilities -.RB ( \&\%pnmcut ,\ \%pnmcrop ,\ \%pnmtopng ) +.RB ( \%pnmcut , +.BR \%pnmcrop , +.BR \%pnmtopng ) and GhostScript .RB ( gs ). .B \%pnmtopng @@ -208,10 +271,14 @@ from the package. Images are generated whenever a table, picture, equation or line is encountered. +. +. .SH BUGS .B Grohtml has been completely redesigned and rewritten. -It is still alpha code. +It is still beta code. +. +. .SH "SEE ALSO" .BR afmtodit (@MAN1EXT@), .BR groff (@MAN1EXT@), diff --git a/contrib/groff/src/devices/grohtml/html-table.cpp b/contrib/groff/src/devices/grohtml/html-table.cpp index 3585cd3..7e5b2dc 100644 --- a/contrib/groff/src/devices/grohtml/html-table.cpp +++ b/contrib/groff/src/devices/grohtml/html-table.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.cpp * @@ -24,7 +24,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "stringclass.h" @@ -32,6 +32,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "html-table.h" #include "ctype.h" #include "html.h" +#include "html-text.h" #if !defined(TRUE) # define TRUE (1==1) @@ -62,7 +63,7 @@ void tabs::delete_list (void) while (p != NULL) { q = p; p = p->next; - free(q); + delete q; } tab = NULL; } @@ -104,7 +105,7 @@ int tabs::compatible (const char *s) while ((*s != (char)0) && isspace(*s)) s++; // collect tab position - total += atoi(s); + total = atoi(s); // move over tab position while ((*s != (char)0) && !isspace(*s)) s++; @@ -149,10 +150,10 @@ void tabs::init (const char *s) while ((*s != (char)0) && !isspace(*s)) s++; if (last == NULL) { - tab = (tab_position *)malloc(sizeof(tab_position)); + tab = new tab_position; last = tab; } else { - last->next = (tab_position *)malloc(sizeof(tab_position)); + last->next = new tab_position; last = last->next; } last->alignment = align; @@ -162,6 +163,16 @@ void tabs::init (const char *s) } /* + * check_init - define tab stops using, s, providing none already exist. + */ + +void tabs::check_init (const char *s) +{ + if (tab == NULL) + init(s); +} + +/* * find_tab - returns the tab number corresponding to the position, pos. */ @@ -228,7 +239,7 @@ void tabs::dump_tabs (void) */ html_table::html_table (simple_output *op, int linelen) - : columns(NULL), out(op), linelength(linelen), last_col(NULL), start_space(FALSE) + : out(op), columns(NULL), linelength(linelen), last_col(NULL), start_space(FALSE) { tab_stops = new tabs(); } @@ -242,7 +253,7 @@ html_table::~html_table () c = columns; while (columns != NULL) { columns = columns->next; - free(c); + delete c; c = columns; } } @@ -258,7 +269,7 @@ void html_table::remove_cols (cols *c) while (c != NULL) { p = c; c = c->next; - free(p); + delete p; } } @@ -322,15 +333,21 @@ void html_table::emit_table_header (int space) last_col = NULL; if (linelength > 0) { - int n = no_columns() + no_gaps(); - out->nl(); out->nl(); - if (space) - out->put_string("<p>"); - start_space = space; - out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"").put_number(n).put_string("\" cellspacing=\"0\" cellpadding=\"0\">").nl(); - out->put_string("<tr valign=\"top\" align=\"left\">").nl(); + + out->put_string("<table width=\"100%\"") + .put_string(" border=0 rules=\"none\" frame=\"void\"\n") + .put_string(" cellspacing=\"0\" cellpadding=\"0\""); + out->put_string(">") + .nl(); + out->put_string("<tr valign=\"top\" align=\"left\""); + if (space) { + out->put_string(" style=\"margin-top: "); + out->put_string(STYLE_VERTICAL_SPACE); + out->put_string("\""); + } + out->put_string(">").nl(); } } @@ -348,6 +365,16 @@ int html_table::get_right (cols *c) } /* + * set_space - assigns start_space. Used to determine the + * vertical alignment when generating the next table row. + */ + +void html_table::set_space (int space) +{ + start_space = space; +} + +/* * emit_col - moves onto column, n. */ @@ -461,18 +488,22 @@ void html_table::finish_row (void) void html_table::emit_new_row (void) { finish_row(); - out->put_string("<tr valign=\"top\" align=\"left\">").nl(); + + out->put_string("<tr valign=\"top\" align=\"left\""); + if (start_space) { + out->put_string(" style=\"margin-top: "); + out->put_string(STYLE_VERTICAL_SPACE); + out->put_string("\""); + } + out->put_string(">").nl(); + start_space = FALSE; last_col = NULL; } void html_table::emit_finish_table (void) { finish_row(); - // out->put_string("linelength = ").put_number(linelength).nl(); out->put_string("</table>"); - if (start_space) - out->put_string("</p>"); - out->nl(); } /* @@ -516,13 +547,23 @@ cols *html_table::get_column (int coln) int html_table::insert_column (int coln, int hstart, int hend, char align) { cols *c = columns; - cols *l = NULL; + cols *l = columns; cols *n = NULL; while (c != NULL && c->no < coln) { l = c; c = c->next; } + if (l != NULL && l->no>coln && hend > l->left) + return FALSE; // new column bumps into previous one + + l = NULL; + c = columns; + while (c != NULL && c->no < coln) { + l = c; + c = c->next; + } + if ((l != NULL) && (hstart < l->right)) return FALSE; // new column bumps into previous one @@ -530,7 +571,7 @@ int html_table::insert_column (int coln, int hstart, int hend, char align) (l->next->left < hend)) return FALSE; // new column bumps into next one - n = (cols *)malloc(sizeof(cols)); + n = new cols; if (l == NULL) { n->next = columns; columns = n; @@ -691,7 +732,6 @@ html_indent::html_indent (simple_output *op, int ind, int pageoffset, int linele in = ind; pg = pageoffset; ll = linelength; - is_used = FALSE; } html_indent::~html_indent (void) @@ -702,18 +742,33 @@ html_indent::~html_indent (void) void html_indent::begin (int space) { - if (! is_used) { - table->emit_table_header(space); - table->emit_col(1); - is_used = TRUE; + if (in + pg == 0) { + if (space) { + table->out->put_string(" style=\"margin-top: "); + table->out->put_string(STYLE_VERTICAL_SPACE); + table->out->put_string("\""); + } + } + else { + // + // we use exactly the same mechanism for calculating + // indentation as html_table::emit_col + // + table->out->put_string(" style=\"margin-left:") + .put_number(((in + pg) * 100 + ll/2) / ll - + (ll/2)/ll) + .put_string("%;"); + + if (space) { + table->out->put_string(" margin-top: "); + table->out->put_string(STYLE_VERTICAL_SPACE); + } + table->out->put_string("\""); } } void html_indent::end (void) { - if (is_used) - table->emit_finish_table(); - is_used = FALSE; } /* diff --git a/contrib/groff/src/devices/grohtml/html-table.h b/contrib/groff/src/devices/grohtml/html-table.h index c26eb6d..dc6cebe 100644 --- a/contrib/groff/src/devices/grohtml/html-table.h +++ b/contrib/groff/src/devices/grohtml/html-table.h @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote html-table.h * @@ -24,7 +24,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "html.h" @@ -45,6 +45,7 @@ public: void clear (void); int compatible (const char *s); void init (const char *s); + void check_init (const char *s); int find_tab (int pos); int get_tab_pos (int n); char get_tab_align (int n); @@ -91,14 +92,15 @@ public: void add_indent (int indent); void finish_row (void); int get_effective_linelength (void); + void set_space (int space); tabs *tab_stops; /* tab stop positions */ + simple_output *out; private: cols *columns; /* column entries */ - simple_output *out; int linelength; cols *last_col; /* last column started */ - int start_space; /* encapsulate with <p> </p> */ + int start_space; /* have we seen a `.sp' tag? */ void remove_cols (cols *c); }; diff --git a/contrib/groff/src/devices/grohtml/html-text.cpp b/contrib/groff/src/devices/grohtml/html-text.cpp index 21a79eb..b58d5e4 100644 --- a/contrib/groff/src/devices/grohtml/html-text.cpp +++ b/contrib/groff/src/devices/grohtml/html-text.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 + * Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cpp * @@ -24,7 +25,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "stringclass.h" @@ -40,6 +41,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "html-text.h" +#undef DEBUGGING // #define DEBUGGING html_text::html_text (simple_output *op) : @@ -145,18 +147,24 @@ void html_text::end_tag (tag_definition *t) case I_TAG: out->put_string("</i>"); break; case B_TAG: out->put_string("</b>"); break; - case P_TAG: out->put_string("</p>"); - if (t->indent != NULL) { + case P_TAG: if (t->indent == NULL) { + out->put_string("</p>"); + } else { delete t->indent; t->indent = NULL; + out->put_string("</p>"); } - out->nl(); out->enable_newlines(FALSE); + out->enable_newlines(FALSE); blank_para = TRUE; break; case SUB_TAG: out->put_string("</sub>"); break; case SUP_TAG: out->put_string("</sup>"); break; case TT_TAG: out->put_string("</tt>"); break; - case PRE_TAG: out->put_string("</pre>"); out->nl(); out->enable_newlines(TRUE); - blank_para = TRUE; break; + case PRE_TAG: out->put_string("</pre>"); out->enable_newlines(TRUE); + blank_para = TRUE; + if (t->indent != NULL) + delete t->indent; + t->indent = NULL; + break; case SMALL_TAG: out->put_string("</small>"); break; case BIG_TAG: out->put_string("</big>"); break; case COLOR_TAG: out->put_string("</font>"); break; @@ -168,19 +176,29 @@ void html_text::end_tag (tag_definition *t) /* * issue_tag - writes out an html tag with argument. + * space == 0 if no space is requested + * space == 1 if a space is requested + * space == 2 if tag should not have a space style */ -void html_text::issue_tag (const char *tagname, const char *arg) +void html_text::issue_tag (const char *tagname, const char *arg, + int space) { - if ((arg == 0) || (strlen(arg) == 0)) { + if ((arg == 0) || (strlen(arg) == 0)) out->put_string(tagname); - out->put_string(">"); - } else { + else { out->put_string(tagname); out->put_string(" "); out->put_string(arg); - out->put_string(">"); } + if (space == TRUE) { + out->put_string(" style=\"margin-top: "); + out->put_string(STYLE_VERTICAL_SPACE); + out->put_string("\""); + } + if (space == TRUE || space == FALSE) + out->put_string(" valign=\"top\""); + out->put_string(">"); } /* @@ -214,29 +232,31 @@ void html_text::start_tag (tag_definition *t) case I_TAG: issue_tag("<i", (char *)t->arg1); break; case B_TAG: issue_tag("<b", (char *)t->arg1); break; - case P_TAG: if (t->indent == NULL) { + case P_TAG: if (t->indent != NULL) { out->nl(); - issue_tag("\n<p", (char *)t->arg1); - } else { - out->nl(); +#if defined(DEBUGGING) out->simple_comment("INDENTATION"); - t->indent->begin(FALSE); - start_space = FALSE; - issue_tag("<p", (char *)t->arg1); +#endif + out->put_string("\n<p"); + t->indent->begin(start_space); + issue_tag("", (char *)t->arg1); + } else { + out->nl(); + issue_tag("\n<p", (char *)t->arg1, start_space); } out->enable_newlines(TRUE); break; case SUB_TAG: issue_tag("<sub", (char *)t->arg1); break; case SUP_TAG: issue_tag("<sup", (char *)t->arg1); break; case TT_TAG: issue_tag("<tt", (char *)t->arg1); break; - case PRE_TAG: if (t->indent != NULL) { - out->nl(); - out->simple_comment("INDENTATION"); - t->indent->begin(FALSE); - start_space = FALSE; - } - out->enable_newlines(TRUE); - out->nl(); issue_tag("<pre", (char *)t->arg1); + case PRE_TAG: out->enable_newlines(TRUE); + out->nl(); out->put_string("<pre"); + if (t->indent == NULL) + issue_tag("", (char *)t->arg1, start_space); + else { + t->indent->begin(start_space); + issue_tag("", (char *)t->arg1); + } out->enable_newlines(FALSE); break; case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break; case BIG_TAG: issue_tag("<big", (char *)t->arg1); break; @@ -264,7 +284,7 @@ void html_text::flush_text (void) } p = stackptr; stackptr = stackptr->next; - free(p); + delete p; } lastptr = NULL; } @@ -285,6 +305,23 @@ int html_text::is_present (HTML_TAG t) return FALSE; } +/* + * uses_indent - returns TRUE if the current paragraph is using a + * html table to effect an indent. + */ + +int html_text::uses_indent (void) +{ + tag_definition *p = stackptr; + + while (p != NULL) { + if (p->indent != NULL) + return TRUE; + p = p->next; + } + return FALSE; +} + extern void stop(); /* @@ -337,7 +374,7 @@ void html_text::do_push (tag_definition *p) void html_text::push_para (HTML_TAG t, void *arg, html_indent *in) { - tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition)); + tag_definition *p= new tag_definition; p->type = t; p->arg1 = arg; @@ -357,7 +394,7 @@ void html_text::push_para (HTML_TAG t) void html_text::push_para (color *c) { - tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition)); + tag_definition *p = new tag_definition; p->type = COLOR_TAG; p->arg1 = NULL; @@ -407,9 +444,11 @@ void html_text::do_pre (void) done_tt(); if (is_present(P_TAG)) { html_indent *i = remove_indent(P_TAG); + int space = retrieve_para_space(); (void)done_para(); if (! is_present(PRE_TAG)) push_para(PRE_TAG, NULL, i); + start_space = space; } else if (! is_present(PRE_TAG)) push_para(PRE_TAG, NULL, NULL); dump_stack(); @@ -475,8 +514,8 @@ char *html_text::shutdown (HTML_TAG t) /* * push tag onto temp stack */ - p->next = temp; - temp = p; + p->next = temp; + temp = p; } /* @@ -495,7 +534,7 @@ char *html_text::shutdown (HTML_TAG t) lastptr = NULL; if (p->indent != NULL) delete p->indent; - free(p); + delete p; } /* @@ -508,7 +547,7 @@ char *html_text::shutdown (HTML_TAG t) push_para(temp->type, temp->arg1, temp->indent); p = temp; temp = temp->next; - free(p); + delete p; } } return arg; @@ -607,7 +646,7 @@ void html_text::check_emit_text (tag_definition *t) void html_text::do_emittext (const char *s, int length) { if ((! is_present(P_TAG)) && (! is_present(PRE_TAG))) - do_para(""); + do_para("", FALSE); if (is_present(BREAK_TAG)) { int text = remove_break(); @@ -615,13 +654,12 @@ void html_text::do_emittext (const char *s, int length) if (text) { if (is_present(PRE_TAG)) { out->nl(); - } else { + } else out->put_string("<br>").nl(); - } } - } else { + } else check_emit_text(stackptr); - } + out->put_string(s, length); space_emitted = FALSE; blank_para = FALSE; @@ -631,38 +669,40 @@ void html_text::do_emittext (const char *s, int length) * do_para - starts a new paragraph */ -void html_text::do_para (const char *arg, html_indent *in) +void html_text::do_para (const char *arg, html_indent *in, int space) { if (! is_present(P_TAG)) { if (is_present(PRE_TAG)) { html_indent *i = remove_indent(PRE_TAG); done_pre(); - if (i == in || in == NULL) + if ((arg == NULL || (strcmp(arg, "") == 0)) && + (i == in || in == NULL)) in = i; else delete i; } remove_sub_sup(); push_para(P_TAG, (void *)arg, in); - space_emitted = TRUE; + start_space = space; } } -void html_text::do_para (const char *arg) +void html_text::do_para (const char *arg, int space) { - do_para(arg, NULL); + do_para(arg, NULL, space); } void html_text::do_para (simple_output *op, const char *arg1, - int indentation, int pageoffset, int linelength) + int indentation_value, int page_offset, + int line_length, int space) { - html_indent *indent; + html_indent *ind; - if (indentation == 0) - indent = NULL; + if (indentation_value == 0) + ind = NULL; else - indent = new html_indent(op, indentation, pageoffset, linelength); - do_para(arg1, indent); + ind = new html_indent(op, indentation_value, page_offset, line_length); + do_para(arg1, ind, space); } /* @@ -671,8 +711,11 @@ void html_text::do_para (simple_output *op, const char *arg1, char *html_text::done_para (void) { + char *result; space_emitted = TRUE; - return shutdown(P_TAG); + result = shutdown(P_TAG); + start_space = FALSE; + return result; } /* @@ -696,25 +739,30 @@ html_indent *html_text::remove_indent (HTML_TAG tag) } /* + * remove_para_space - removes the leading space to a paragraph + * (effectively this trims off a leading `.sp' tag). + */ + +void html_text::remove_para_space (void) +{ + start_space = FALSE; +} + +/* * do_space - issues an end of paragraph */ void html_text::do_space (void) { if (is_in_pre()) { - if (blank_para) - start_space = TRUE; - else { - do_emittext("", 0); - out->nl(); - space_emitted = TRUE; - } + do_emittext("", 0); + out->force_nl(); + space_emitted = TRUE; } else { html_indent *i = remove_indent(P_TAG); - do_para(done_para(), i); + do_para(done_para(), i, TRUE); space_emitted = TRUE; - start_space = TRUE; } } @@ -724,13 +772,11 @@ void html_text::do_space (void) void html_text::do_break (void) { - if (! is_present(PRE_TAG)) { - if (emitted_text()) { - if (! is_present(BREAK_TAG)) { + if (! is_present(PRE_TAG)) + if (emitted_text()) + if (! is_present(BREAK_TAG)) push_para(BREAK_TAG); - } - } - } + space_emitted = TRUE; } @@ -756,7 +802,8 @@ int html_text::emitted_text (void) } /* - * ever_emitted_text - returns TRUE if we have ever emitted text in this paragraph. + * ever_emitted_text - returns TRUE if we have ever emitted text in this + * paragraph. */ int html_text::ever_emitted_text (void) @@ -765,7 +812,7 @@ int html_text::ever_emitted_text (void) } /* - * starts_with_space - returns TRUE if we have start this paragraph with a .sp + * starts_with_space - returns TRUE if we started this paragraph with a .sp */ int html_text::starts_with_space (void) @@ -774,19 +821,34 @@ int html_text::starts_with_space (void) } /* + * retrieve_para_space - returns TRUE, if the paragraph starts with + * a space and text has not yet been emitted. + * If TRUE is returned, then the, start_space, + * variable is set to FALSE. + */ + +int html_text::retrieve_para_space (void) +{ + if (start_space && blank_para) { + start_space = FALSE; + return TRUE; + } + else + return FALSE; +} + +/* * emit_space - writes a space providing that text was written beforehand. */ void html_text::emit_space (void) { - if (space_emitted) { - if (is_present(PRE_TAG)) { - do_emittext(" ", 1); - } - } else { + if (is_present(PRE_TAG)) + do_emittext(" ", 1); + else out->space_or_newline(); - space_emitted = TRUE; - } + + space_emitted = TRUE; } /* @@ -817,7 +879,7 @@ void html_text::remove_def (tag_definition *t) if (l->next == NULL) lastptr = l; } - free(p); + delete p; } } @@ -837,7 +899,8 @@ void html_text::remove_tag (HTML_TAG tag) } /* - * remove_sub_sup - removes a sub or sup tag, should either exist on the stack. + * remove_sub_sup - removes a sub or sup tag, should either exist + * on the stack. */ void html_text::remove_sub_sup (void) @@ -882,7 +945,7 @@ int html_text::remove_break (void) if (l->next == NULL) lastptr = l; } - free(p); + delete p; } /* * now determine whether text was issued before <br> @@ -910,8 +973,9 @@ void html_text::remove_para_align (void) while (p != NULL) { if (p->type == P_TAG && p->arg1 != NULL) { html_indent *i = remove_indent(P_TAG); + int space = retrieve_para_space(); done_para(); - do_para("", i); + do_para("", i, space); return; } p = p->next; @@ -920,6 +984,25 @@ void html_text::remove_para_align (void) } /* + * get_alignment - returns the alignment for the paragraph. + * If no alignment was given then we return "". + */ + +char *html_text::get_alignment (void) +{ + if (is_present(P_TAG)) { + tag_definition *p=stackptr; + + while (p != NULL) { + if (p->type == P_TAG && p->arg1 != NULL) + return (char *)p->arg1; + p = p->next; + } + } + return (char *)""; +} + +/* * do_small - potentially inserts a <small> tag into the html stream. * However we check for a <big> tag, if present then we terminate it. * Otherwise a <small> tag is inserted. @@ -962,4 +1045,3 @@ void html_text::do_sub (void) { push_para(SUB_TAG); } - diff --git a/contrib/groff/src/devices/grohtml/html-text.h b/contrib/groff/src/devices/grohtml/html-text.h index aa4dd80..e0e3cc7 100644 --- a/contrib/groff/src/devices/grohtml/html-text.h +++ b/contrib/groff/src/devices/grohtml/html-text.h @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 + * Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.h * @@ -23,11 +24,13 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "html.h" #include "html-table.h" +#define STYLE_VERTICAL_SPACE "1em" + /* * html tags */ @@ -64,9 +67,10 @@ public: void do_pre (void); void do_small (void); void do_big (void); - void do_para (const char *arg); // used for no indentation + void do_para (const char *arg, int space); // used for no indentation void do_para (simple_output *op, const char *arg1, - int indentation, int pageoffset, int linelength); + int indentation, int pageoffset, int linelength, + int space); void do_sup (void); void do_sub (void); void do_space (void); @@ -87,11 +91,15 @@ public: int emitted_text (void); int ever_emitted_text (void); int starts_with_space (void); + int retrieve_para_space (void); void emit_space (void); int is_in_pre (void); + int uses_indent (void); void remove_tag (HTML_TAG tag); void remove_sub_sup (void); void remove_para_align (void); + void remove_para_space (void); + char *get_alignment (void); private: tag_definition *stackptr; /* the current paragraph state */ @@ -108,7 +116,7 @@ private: int is_present (HTML_TAG t); void end_tag (tag_definition *t); void start_tag (tag_definition *t); - void do_para (const char *arg, html_indent *in); + void do_para (const char *arg, html_indent *in, int space); void push_para (HTML_TAG t); void push_para (HTML_TAG t, void *arg, html_indent *in); void push_para (color *c); @@ -116,7 +124,7 @@ private: char *shutdown (HTML_TAG t); void check_emit_text (tag_definition *t); int remove_break (void); - void issue_tag (const char *tagname, const char *arg); + void issue_tag (const char *tagname, const char *arg, int space=2); void issue_color_begin (color *c); void remove_def (tag_definition *t); html_indent *remove_indent (HTML_TAG tag); diff --git a/contrib/groff/src/devices/grohtml/html.h b/contrib/groff/src/devices/grohtml/html.h index 431647c..b14fb2c 100644 --- a/contrib/groff/src/devices/grohtml/html.h +++ b/contrib/groff/src/devices/grohtml/html.h @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. @@ -16,7 +16,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #if !defined(HTML_H) # define HTML_H @@ -72,6 +72,7 @@ public: simple_output &enable_newlines(int); simple_output &check_newline(int n); simple_output &nl(void); + simple_output &force_nl(void); simple_output &space_or_newline (void); simple_output &begin_tag (void); FILE *get_file(); diff --git a/contrib/groff/src/devices/grohtml/output.cpp b/contrib/groff/src/devices/grohtml/output.cpp index 2705b9e..f253127 100644 --- a/contrib/groff/src/devices/grohtml/output.cpp +++ b/contrib/groff/src/devices/grohtml/output.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote output.cpp * but it owes a huge amount of ideas and raw code from @@ -25,7 +25,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "stringclass.h" @@ -67,7 +67,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ word::word (const char *w, int n) : next(0) { - s = (char *)malloc(n+1); + s = new char[n+1]; strncpy(s, w, n); s[n] = (char)0; } @@ -78,7 +78,7 @@ word::word (const char *w, int n) word::~word () { - free(s); + a_delete s; } /* @@ -253,6 +253,19 @@ simple_output &simple_output::space_or_newline (void) } /* + * force_nl - forces a newline. + */ + +simple_output &simple_output::force_nl (void) +{ + space_or_newline(); + col += last_word.flush(fp); + FPUTC('\n', fp); + col = 0; + return *this ; +} + +/* * nl - writes a newline providing that we * are not in the first column. */ @@ -261,10 +274,8 @@ simple_output &simple_output::nl (void) { space_or_newline(); col += last_word.flush(fp); - if (col != 0) { - FPUTC('\n', fp); - col = 0; - } + FPUTC('\n', fp); + col = 0; return *this ; } diff --git a/contrib/groff/src/devices/grohtml/post-html.cpp b/contrib/groff/src/devices/grohtml/post-html.cpp index 7c96deb..1283e06 100644 --- a/contrib/groff/src/devices/grohtml/post-html.cpp +++ b/contrib/groff/src/devices/grohtml/post-html.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 + * Free Software Foundation, Inc. * * Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cpp * but it owes a huge amount of ideas and raw code from @@ -21,7 +22,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "stringclass.h" @@ -38,6 +39,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <stdio.h> #include <fcntl.h> +#include <string.h> extern "C" const char *Version_string; @@ -50,8 +52,7 @@ extern "C" const char *Version_string; #define MAX_LINE_LENGTH 60 /* maximum characters we want in a line */ #define SIZE_INCREMENT 2 /* font size increment <big> = +2 */ -#define BASE_POINT_SIZE 10 /* 10 points is the base size ie html size 3 */ -#define CENTER_TOLERANCE 2 /* how many pixels off center will we still */ +#define CENTER_TOLERANCE 2 /* how many pixels off center do we allow */ #define ANCHOR_TEMPLATE "heading" /* if simple anchor is set we use this */ #define UNICODE_DESC_START 0x80 /* all character entities above this are */ /* either encoded by their glyph names or if */ @@ -60,7 +61,7 @@ typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT; typedef enum {col_tag, tab_tag, tab0_tag, none} colType; #undef DEBUG_TABLES - +// #define DEBUG_TABLES /* * prototypes @@ -78,6 +79,16 @@ static int simple_anchors = FALSE; /* default to anchors with static int manufacture_headings = FALSE; /* default is to use the Hn html headings, */ /* rather than manufacture our own. */ static color *default_background = NULL; /* has user requested initial bg color? */ +static string job_name; /* if set then the output is split into */ + /* multiple files with `job_name'-%d.html */ +static int multiple_files = FALSE; /* must we the output be divided into */ + /* multiple html files, one for each */ + /* heading? */ +static int base_point_size = 0; /* which troff font size maps onto html */ + /* size 3? */ +static int split_level = 2; /* what heading level to split at? */ +static string head_info; /* user supplied information to be placed */ + /* into <head> </head> */ /* @@ -109,7 +120,7 @@ static int max (int a, int b) static int is_intersection (int a1, int a2, int b1, int b2) { // easier to prove NOT outside limits - return( ! ((a1 > b2) || (a2 < b1)) ); + return ! ((a1 > b2) || (a2 < b1)); } /* @@ -118,7 +129,7 @@ static int is_intersection (int a1, int a2, int b1, int b2) static int is_digit (char ch) { - return( (ch >= '0') && (ch <= '9') ); + return (ch >= '0') && (ch <= '9'); } /* @@ -128,6 +139,9 @@ static int is_digit (char ch) struct file { FILE *fp; file *next; + int new_output_file; + int require_links; + string output_file_name; file (FILE *f); }; @@ -137,21 +151,28 @@ struct file { */ file::file (FILE *f) - : fp(f), next(0) + : fp(f), next(NULL), new_output_file(FALSE), + require_links(FALSE), output_file_name("") { } class files { public: - files (); - FILE *get_file (void); - void start_of_list (void); - void move_next (void); - void add_new_file (FILE *f); + files (); + FILE *get_file (void); + void start_of_list (void); + void move_next (void); + void add_new_file (FILE *f); + void set_file_name (string name); + void set_links_required (void); + int are_links_required (void); + int is_new_output_file (void); + string file_name (void); + string next_file_name (void); private: - file *head; - file *tail; - file *ptr; + file *head; + file *tail; + file *ptr; }; /* @@ -159,7 +180,7 @@ private: */ files::files () - : head(0), tail(0), ptr(0) + : head(NULL), tail(NULL), ptr(NULL) { } @@ -169,11 +190,10 @@ files::files () FILE *files::get_file (void) { - if (ptr) { - return( ptr->fp ); - } else { - return( 0 ); - } + if (ptr) + return ptr->fp; + else + return NULL; } /* @@ -191,7 +211,7 @@ void files::start_of_list (void) void files::move_next (void) { - if (ptr != 0) + if (ptr != NULL) ptr = ptr->next; } @@ -201,7 +221,7 @@ void files::move_next (void) void files::add_new_file (FILE *f) { - if (head == 0) { + if (head == NULL) { head = new file(f); tail = head; } else { @@ -212,6 +232,76 @@ void files::add_new_file (FILE *f) } /* + * set_file_name - sets the final file name to contain the html + * data to name. + */ + +void files::set_file_name (string name) +{ + if (ptr != NULL) { + ptr->output_file_name = name; + ptr->new_output_file = TRUE; + } +} + +/* + * set_links_required - issue links when processing this component + * of the file. + */ + +void files::set_links_required (void) +{ + if (ptr != NULL) + ptr->require_links = TRUE; +} + +/* + * are_links_required - returns TRUE if this section of the file + * requires that links should be issued. + */ + +int files::are_links_required (void) +{ + if (ptr != NULL) + return ptr->require_links; + return FALSE; +} + +/* + * is_new_output_file - returns TRUE if this component of the file + * is the start of a new output file. + */ + +int files::is_new_output_file (void) +{ + if (ptr != NULL) + return ptr->new_output_file; + return FALSE; +} + +/* + * file_name - returns the name of the file. + */ + +string files::file_name (void) +{ + if (ptr != NULL) + return ptr->output_file_name; + return string(""); +} + +/* + * next_file_name - returns the name of the next file. + */ + +string files::next_file_name (void) +{ + if (ptr != NULL && ptr->next != NULL) + return ptr->next->output_file_name; + return string(""); +} + +/* * the class and methods for styles */ @@ -229,7 +319,7 @@ struct style { }; style::style() - : f(0) + : f(NULL) { } @@ -265,14 +355,14 @@ struct char_block { }; char_block::char_block() -: buffer(NULL), used(0), next(0) +: buffer(NULL), used(0), next(NULL) { } char_block::char_block(int length) -: used(0), next(0) +: used(0), next(NULL) { - buffer = (char *)malloc(max(length, char_block::SIZE)); + buffer = new char[max(length, char_block::SIZE)]; if (buffer == NULL) fatal("out of memory error"); } @@ -280,7 +370,7 @@ char_block::char_block(int length) char_block::~char_block() { if (buffer != NULL) - free(buffer); + a_delete buffer; } class char_buffer { @@ -295,13 +385,13 @@ private: }; char_buffer::char_buffer() -: head(0), tail(0) +: head(NULL), tail(NULL) { } char_buffer::~char_buffer() { - while (head != 0) { + while (head != NULL) { char_block *temp = head; head = head->next; delete temp; @@ -316,7 +406,7 @@ char *char_buffer::add_string (const char *s, unsigned int length) if (s == NULL || length == 0) return NULL; - if (tail == 0) { + if (tail == NULL) { tail = new char_block(length+1); head = tail; } else { @@ -341,7 +431,7 @@ char *char_buffer::add_string (const char *s, unsigned int length) // and return start of new string - return( &tail->buffer[old_used] ); + return &tail->buffer[old_used]; } char *char_buffer::add_string (const string &s) @@ -382,7 +472,10 @@ public: int is_in (void); int is_po (void); int is_ti (void); + int is_ll (void); int is_ce (void); + int is_tl (void); + int is_eo_tl (void); int is_eol_ce (void); int is_col (void); int is_tab (void); @@ -392,6 +485,7 @@ public: int is_tab_te (void); int is_nf (void); int is_fi (void); + int is_eo_h (void); int get_arg (void); int get_tab_args (char *align); @@ -423,16 +517,16 @@ text_glob::text_glob (style *s, const char *str, int length, int max_vertical, int max_horizontal, bool is_troff_command, bool is_auto_image, bool is_special_command, - bool is_a_line, int line_thickness) + bool is_a_line_flag, int line_thickness) : text_style(*s), text_string(str), text_length(length), minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal), is_tag(is_troff_command), is_img_auto(is_auto_image), is_special(is_special_command), - is_line(is_a_line), thickness(line_thickness), tab(NULL) + is_line(is_a_line_flag), thickness(line_thickness), tab(NULL) { } text_glob::text_glob () - : text_string(0), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1), + : text_string(NULL), text_length(0), minv(-1), minh(-1), maxv(-1), maxh(-1), is_tag(FALSE), is_special(FALSE), is_line(FALSE), thickness(0), tab(NULL) { } @@ -483,11 +577,11 @@ void text_glob::text_glob_special (style *s, char *str, int length, void text_glob::text_glob_line (style *s, int min_vertical , int min_horizontal, int max_vertical , int max_horizontal, - int thickness) + int thickness_value) { text_glob *g = new text_glob(s, "", 0, min_vertical, min_horizontal, max_vertical, max_horizontal, - FALSE, FALSE, FALSE, TRUE, thickness); + FALSE, FALSE, FALSE, TRUE, thickness_value); *this = *g; delete g; } @@ -565,7 +659,7 @@ int text_glob::is_a_tag (void) int text_glob::is_eol (void) { - return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) ); + return is_tag && (strcmp(text_string, "devtag:.eol") == 0); } /* @@ -574,26 +668,56 @@ int text_glob::is_eol (void) int text_glob::is_eol_ce (void) { - return( is_tag && (strcmp(text_string, "html-tag:eol.ce") == 0) ); + return is_tag && (strcmp(text_string, "devtag:eol.ce") == 0); } +/* + * is_tl - returns TRUE if glob contains the tag .tl + */ + +int text_glob::is_tl (void) +{ + return is_tag && (strcmp(text_string, "devtag:.tl") == 0); +} /* - * is_nf - returns TRUE if glob contains the tag .nf + * is_eo_tl - returns TRUE if glob contains the tag eo.tl + */ + +int text_glob::is_eo_tl (void) +{ + return is_tag && (strcmp(text_string, "devtag:.eo.tl") == 0); +} + +/* + * is_nf - returns TRUE if glob contains the tag .fi 0 */ int text_glob::is_nf (void) { - return( is_tag && (strcmp(text_string, "html-tag:.nf") == 0) ); + return is_tag && (strncmp(text_string, "devtag:.fi", + strlen("devtag:.fi")) == 0) && + (get_arg() == 0); } /* - * is_fi - returns TRUE if glob contains the tag .fi + * is_fi - returns TRUE if glob contains the tag .fi 1 */ int text_glob::is_fi (void) { - return( is_tag && (strcmp(text_string, "html-tag:.fi") == 0) ); + return( is_tag && (strncmp(text_string, "devtag:.fi", + strlen("devtag:.fi")) == 0) && + (get_arg() == 1) ); +} + +/* + * is_eo_h - returns TRUE if glob contains the tag .eo.h + */ + +int text_glob::is_eo_h (void) +{ + return is_tag && (strcmp(text_string, "devtag:.eo.h") == 0); } /* @@ -602,7 +726,8 @@ int text_glob::is_fi (void) int text_glob::is_ce (void) { - return( is_tag && (strcmp(text_string, "html-tag:.ce") == 0) ); + return is_tag && (strncmp(text_string, "devtag:.ce", + strlen("devtag:.ce")) == 0); } /* @@ -611,7 +736,8 @@ int text_glob::is_ce (void) int text_glob::is_in (void) { - return( is_tag && (strncmp(text_string, "html-tag:.in ", strlen("html-tag:.in ")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:.in ", + strlen("devtag:.in ")) == 0); } /* @@ -620,7 +746,8 @@ int text_glob::is_in (void) int text_glob::is_po (void) { - return( is_tag && (strncmp(text_string, "html-tag:.po ", strlen("html-tag:.po ")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:.po ", + strlen("devtag:.po ")) == 0); } /* @@ -629,7 +756,18 @@ int text_glob::is_po (void) int text_glob::is_ti (void) { - return( is_tag && (strncmp(text_string, "html-tag:.ti ", strlen("html-tag:.ti ")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:.ti ", + strlen("devtag:.ti ")) == 0); +} + +/* + * is_ll - returns TRUE if glob contains the tag .ll + */ + +int text_glob::is_ll (void) +{ + return is_tag && (strncmp(text_string, "devtag:.ll ", + strlen("devtag:.ll ")) == 0); } /* @@ -638,7 +776,8 @@ int text_glob::is_ti (void) int text_glob::is_col (void) { - return( is_tag && (strncmp(text_string, "html-tag:.col", strlen("html-tag:.col")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:.col", + strlen("devtag:.col")) == 0); } /* @@ -647,7 +786,7 @@ int text_glob::is_col (void) int text_glob::is_tab_ts (void) { - return( is_tag && (strcmp(text_string, "html-tag:.tab-ts") == 0) ); + return is_tag && (strcmp(text_string, "devtag:.tab-ts") == 0); } /* @@ -656,7 +795,7 @@ int text_glob::is_tab_ts (void) int text_glob::is_tab_te (void) { - return( is_tag && (strcmp(text_string, "html-tag:.tab-te") == 0) ); + return is_tag && (strcmp(text_string, "devtag:.tab-te") == 0); } /* @@ -665,7 +804,8 @@ int text_glob::is_tab_te (void) int text_glob::is_ta (void) { - return( is_tag && (strncmp(text_string, "html-tag:.ta ", strlen("html-tag:.ta ")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:.ta ", + strlen("devtag:.ta ")) == 0); } /* @@ -674,7 +814,8 @@ int text_glob::is_ta (void) int text_glob::is_tab (void) { - return( is_tag && (strncmp(text_string, "html-tag:tab ", strlen("html-tag:tab ")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:tab ", + strlen("devtag:tab ")) == 0); } /* @@ -683,7 +824,8 @@ int text_glob::is_tab (void) int text_glob::is_tab0 (void) { - return( is_tag && (strncmp(text_string, "html-tag:tab0", strlen("html-tag:tab0")) == 0) ); + return is_tag && (strncmp(text_string, "devtag:tab0", + strlen("devtag:tab0")) == 0); } /* @@ -705,14 +847,14 @@ int text_glob::is_auto_img (void) int text_glob::is_br (void) { - return( is_a_tag() && ((strcmp ("html-tag:.br", text_string) == 0) || - (strncmp("html-tag:.sp", text_string, 11) == 0) || - (strcmp ("html-tag:.ce", text_string) == 0)) ); + return is_a_tag() && ((strcmp ("devtag:.br", text_string) == 0) || + (strncmp("devtag:.sp", text_string, + strlen("devtag:.sp")) == 0)); } int text_glob::get_arg (void) { - if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) { + if (strncmp("devtag:", text_string, strlen("devtag:")) == 0) { const char *p = text_string; while ((*p != (char)0) && (!isspace(*p))) @@ -732,7 +874,7 @@ int text_glob::get_arg (void) int text_glob::get_tab_args (char *align) { - if (strncmp("html-tag:", text_string, strlen("html-tag:")) == 0) { + if (strncmp("devtag:", text_string, strlen("devtag:")) == 0) { const char *p = text_string; // firstly the alignment C|R|L @@ -774,10 +916,11 @@ html_table *text_glob::get_table (void) } /* - * the class and methods used to construct ordered double linked lists. - * In a previous implementation we used templates via #include "ordered-list.h", - * but this does assume that all C++ compilers can handle this feature. Pragmatically - * it is safer to assume this is not the case. + * the class and methods used to construct ordered double linked + * lists. In a previous implementation we used templates via + * #include "ordered-list.h", but this does assume that all C++ + * compilers can handle this feature. Pragmatically it is safer to + * assume this is not the case. */ struct element_list { @@ -893,7 +1036,8 @@ int list::is_less (element_list *a, element_list *b) } /* - * add - adds a datum to the list in the order specified by the region position. + * add - adds a datum to the list in the order specified by the + * region position. */ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal) @@ -902,7 +1046,13 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo element_list *t = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); element_list *last; - if (head == 0) { +#if 0 + fprintf(stderr, "[%s %d,%d,%d,%d] ", + in->text_string, min_vertical, min_horizontal, max_vertical, max_horizontal); + fflush(stderr); +#endif + + if (head == NULL) { head = t; tail = t; ptr = t; @@ -911,9 +1061,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo } else { last = tail; - while ((last != head) && (is_less(t, last))) { + while ((last != head) && (is_less(t, last))) last = last->left; - } if (is_less(t, last)) { t->right = last; @@ -921,9 +1070,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo t->left = last->left; last->left = t; // now check for a new head - if (last == head) { + if (last == head) head = t; - } } else { // add t beyond last t->right = last->right; @@ -931,9 +1079,8 @@ void list::add (text_glob *in, int line_number, int min_vertical, int min_horizo last->right->left = t; last->right = t; // now check for a new tail - if (last == tail) { + if (last == tail) tail = t; - } } } } @@ -948,22 +1095,20 @@ void list::sub_move_right (void) element_list *t=ptr->right; if (head == tail) { - head = 0; - if (tail != 0) { + head = NULL; + if (tail != NULL) delete tail; - } - tail = 0; - ptr = 0; + + tail = NULL; + ptr = NULL; } else { - if (head == ptr) { + if (head == ptr) head = head->right; - } - if (tail == ptr) { + if (tail == ptr) tail = tail->left; - } ptr->left->right = ptr->right; ptr->right->left = ptr->left; - ptr=t; + ptr = t; } } @@ -991,7 +1136,7 @@ void list::start_from_tail (void) int list::is_empty (void) { - return( head == 0 ); + return head == NULL; } /* @@ -1000,7 +1145,7 @@ int list::is_empty (void) int list::is_equal_to_tail (void) { - return( ptr == tail ); + return ptr == tail; } /* @@ -1009,7 +1154,7 @@ int list::is_equal_to_tail (void) int list::is_equal_to_head (void) { - return( ptr == head ); + return ptr == head; } /* @@ -1036,7 +1181,7 @@ void list::move_right (void) text_glob* list::get_data (void) { - return( ptr->datum ); + return ptr->datum; } /* @@ -1047,11 +1192,10 @@ text_glob* list::get_data (void) text_glob* list::move_right_get_data (void) { ptr = ptr->right; - if (ptr == head) { - return( 0 ); - } else { - return( ptr->datum ); - } + if (ptr == head) + return NULL; + else + return ptr->datum; } /* @@ -1062,11 +1206,10 @@ text_glob* list::move_right_get_data (void) text_glob* list::move_left_get_data (void) { ptr = ptr->left; - if (ptr == tail) { - return( 0 ); - } else { - return( ptr->datum ); - } + if (ptr == tail) + return NULL; + else + return ptr->datum; } /* @@ -1078,7 +1221,7 @@ void list::insert (text_glob *in) if (is_empty()) fatal("list must not be empty if we are inserting data"); else { - if (ptr == 0) + if (ptr == NULL) ptr = head; element_list *t = new element_list(in, ptr->lineno, ptr->minv, ptr->minh, ptr->maxv, ptr->maxh); @@ -1121,7 +1264,8 @@ public: void add_and_encode (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, - int max_vertical, int max_horizontal); + int max_vertical, int max_horizontal, + int is_tag); void add_line (style *s, int line_number, int x1, int y1, int x2, int y2, @@ -1183,7 +1327,8 @@ void page::add_tag (style *s, const string &str, if (str.length() > 0) { text_glob *g; - if (strncmp((str+'\0').contents(), "html-tag:.auto-image", 20) == 0) { + if (strncmp((str+'\0').contents(), "devtag:.auto-image", + strlen("devtag:.auto-image")) == 0) { g = new text_glob(); g->text_glob_auto_image(s, buffer.add_string(str), str.length(), min_vertical, min_horizontal, max_vertical, max_horizontal); @@ -1202,15 +1347,18 @@ void page::add_tag (style *s, const string &str, void page::add_line (style *s, int line_number, - int x1, int y1, int x2, int y2, + int x_1, int y_1, int x_2, int y_2, int thickness) { - if (y1 == y2) { + if (y_1 == y_2) { text_glob *g = new text_glob(); g->text_glob_line(s, - min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2), + min(y_1, y_2), min(x_1, x_2), + max(y_1, y_2), max(x_1, x_2), thickness); - glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2)); + glyphs.add(g, line_number, + min(y_1, y_2), min(x_1, x_2), + max(y_1, y_2), max(x_1, x_2)); } } @@ -1240,7 +1388,8 @@ static char *to_unicode (unsigned int ch) void page::add_and_encode (style *s, const string &str, int line_number, int min_vertical, int min_horizontal, - int max_vertical, int max_horizontal) + int max_vertical, int max_horizontal, + int is_tag) { string html_string; char *html_glyph; @@ -1267,10 +1416,10 @@ void page::add_and_encode (style *s, const string &str, if (html_glyph) html_string += html_glyph; else { - int index=s->f->name_to_index((troff_charname + '\0').contents()); + int idx=s->f->name_to_index((troff_charname + '\0').contents()); - if (s->f->contains(index) && (index != 0)) - html_string += s->f->get_code(index); + if (s->f->contains(idx) && (idx != 0)) + html_string += s->f->get_code(idx); } } } else @@ -1279,9 +1428,18 @@ void page::add_and_encode (style *s, const string &str, } if (html_string.length() > 0) { text_glob *g=new text_glob(); - g->text_glob_special(s, buffer.add_string(html_string), html_string.length(), - min_vertical, min_horizontal, max_vertical, max_horizontal); - glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal); + if (is_tag) + g->text_glob_tag(s, buffer.add_string(html_string), + html_string.length(), + min_vertical, min_horizontal, + max_vertical, max_horizontal); + else + g->text_glob_special(s, buffer.add_string(html_string), + html_string.length(), + min_vertical, min_horizontal, + max_vertical, max_horizontal); + glyphs.add(g, line_number, min_vertical, + min_horizontal, max_vertical, max_horizontal); } } @@ -1380,18 +1538,21 @@ public: header_desc (); ~header_desc (); - int no_of_headings; // how many headings have we found? - char_buffer headings; // all the headings used in the document - list headers; // list of headers built from .NH and .SH - int header_level; // current header level - int written_header; // have we written the header yet? - string header_buffer; // current header text + int no_of_level_one_headings; // how many .SH or .NH 1 have we found? + int no_of_headings; // how many headings have we found? + char_buffer headings; // all the headings used in the document + list headers; // list of headers built from .NH and .SH + list header_filename; // in which file is this header? + int header_level; // current header level + int written_header; // have we written the header yet? + string header_buffer; // current header text void write_headings (FILE *f, int force); }; header_desc::header_desc () - : no_of_headings(0), header_level(2), written_header(0) + : no_of_level_one_headings(0), no_of_headings(0), + header_level(2), written_header(0) { } @@ -1412,9 +1573,15 @@ void header_desc::write_headings (FILE *f, int force) int h=1; headers.start_from_head(); + header_filename.start_from_head(); do { g = headers.get_data(); - fputs("<a href=\"#", f); + fputs("<a href=\"", f); + if (multiple_files && (! header_filename.is_empty())) { + text_glob *fn = header_filename.get_data(); + fputs(fn->text_string, f); + } + fputs("#", f); if (simple_anchors) { string buffer(ANCHOR_TEMPLATE); @@ -1428,12 +1595,345 @@ void header_desc::write_headings (FILE *f, int force) fputs(g->text_string, f); fputs("</a><br>\n", f); headers.move_right(); + if (multiple_files && (! header_filename.is_empty())) + header_filename.move_right(); } while (! headers.is_equal_to_head()); fputs("\n", f); } } } +struct assert_pos { + assert_pos *next; + const char *val; + const char *id; +}; + +class assert_state { +public: + assert_state (); + ~assert_state (); + + void addx (const char *c, const char *i, const char *v, + const char *f, const char *l); + void addy (const char *c, const char *i, const char *v, + const char *f, const char *l); + void build(const char *c, const char *v, + const char *f, const char *l); + void check_br (int br); + void check_ce (int ce); + void check_fi (int fi); + void check_sp (int sp); + void reset (void); + +private: + int check_br_flag; + int check_ce_flag; + int check_fi_flag; + int check_sp_flag; + const char *val_br; + const char *val_ce; + const char *val_fi; + const char *val_sp; + const char *file_br; + const char *file_ce; + const char *file_fi; + const char *file_sp; + const char *line_br; + const char *line_ce; + const char *line_fi; + const char *line_sp; + + assert_pos *xhead; + assert_pos *yhead; + + void add (assert_pos **h, + const char *c, const char *i, const char *v, + const char *f, const char *l); + void compare(assert_pos *t, + const char *v, const char *f, const char *l); + void close (const char *c); + void set (const char *c, const char *v, + const char *f, const char *l); + void check_value (const char *s, int v, const char *name, + const char *f, const char *l, int *flag); + int check_value_error (int c, int v, const char *s, + const char *name, + const char *f, const char *l, int flag); +}; + +assert_state::assert_state () +{ + reset(); + val_br = NULL; + val_ce = NULL; + val_fi = NULL; + val_sp = NULL; + file_br = NULL; + file_ce = NULL; + file_fi = NULL; + file_sp = NULL; + line_br = NULL; + line_ce = NULL; + line_fi = NULL; + line_sp = NULL; + xhead = NULL; + yhead = NULL; +} + +assert_state::~assert_state () +{ + assert_pos *t; + + while (xhead != NULL) { + t = xhead; + xhead = xhead->next; + a_delete (char *)t->val; + a_delete (char *)t->id; + delete t; + } + while (yhead != NULL) { + t = yhead; + yhead = yhead->next; + a_delete (char *)t->val; + a_delete (char *)t->id; + delete t; + } +} + +void assert_state::reset (void) +{ + check_br_flag = 0; + check_ce_flag = 0; + check_fi_flag = 0; + check_sp_flag = 0; +} + +void assert_state::add (assert_pos **h, + const char *c, const char *i, const char *v, + const char *f, const char *l) +{ + assert_pos *t = *h; + + while (t != NULL) { + if (strcmp(t->id, i) == 0) + break; + t = t->next; + } + if (t != NULL && v != NULL && (v[0] != '=')) + compare(t, v, f, l); + else { + if (t == NULL) { + t = new assert_pos; + t->next = *h; + (*h) = t; + } + if (v == NULL || v[0] != '=') { + if (f == NULL) + f = "stdin"; + if (l == NULL) + l = "<none>"; + if (v == NULL) + v = "no value at all"; + fprintf(stderr, "%s:%s:error in assert format of id=%s expecting value to be prefixed with an `=' got %s\n", + f, l, i, v); + } + t->id = i; + t->val = v; + a_delete (char *)c; + a_delete (char *)f; + a_delete (char *)l; + } +} + +void assert_state::addx (const char *c, const char *i, const char *v, + const char *f, const char *l) +{ + add(&xhead, c, i, v, f, l); +} + +void assert_state::addy (const char *c, const char *i, const char *v, + const char *f, const char *l) +{ + add(&yhead, c, i, v, f, l); +} + +void assert_state::compare(assert_pos *t, + const char *v, const char *f, const char *l) +{ + const char *s=t->val; + + while ((*v) == '=') + v++; + while ((*s) == '=') + s++; + + if (strcmp(v, s) != 0) { + if (f == NULL) + f = "stdin"; + if (l == NULL) + l = "<none>"; + fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %s and was given %s\n", + f, l, t->id, s, v); + } +} + +void assert_state::close (const char *c) +{ + if (strcmp(c, "sp") == 0) + check_sp_flag = 0; + else if (strcmp(c, "br") == 0) + check_br_flag = 0; + else if (strcmp(c, "fi") == 0) + check_fi_flag = 0; + else if (strcmp(c, "nf") == 0) + check_fi_flag = 0; + else if (strcmp(c, "ce") == 0) + check_ce_flag = 0; + else + fprintf(stderr, "internal error: unrecognised tag in grohtml (%s)\n", c); +} + +const char *replace_negate_str (const char *before, char *after) +{ + if (before != NULL) + a_delete (char *)before; + + if (strlen(after) > 0) { + int d = atoi(after); + + if (d < 0 || d > 1) { + fprintf(stderr, "expecting nf/fi value to be 0 or 1 not %d\n", d); + d = 0; + } + if (d == 0) + after[0] = '1'; + else + after[0] = '0'; + after[1] = (char)0; + } + return after; +} + +const char *replace_str (const char *before, const char *after) +{ + if (before != NULL) + a_delete (char *)before; + return after; +} + +void assert_state::set (const char *c, const char *v, + const char *f, const char *l) +{ + if (l == NULL) + l = "<none>"; + if (f == NULL) + f = "stdin"; + + // fprintf(stderr, "%s:%s:setting %s to %s\n", f, l, c, v); + if (strcmp(c, "sp") == 0) { + check_sp_flag = 1; + val_sp = replace_str(val_sp, strsave(v)); + file_sp = replace_str(file_sp, strsave(f)); + line_sp = replace_str(line_sp, strsave(l)); + } else if (strcmp(c, "br") == 0) { + check_br_flag = 1; + val_br = replace_str(val_br, strsave(v)); + file_br = replace_str(file_br, strsave(f)); + line_br = replace_str(line_br, strsave(l)); + } else if (strcmp(c, "fi") == 0) { + check_fi_flag = 1; + val_fi = replace_str(val_fi, strsave(v)); + file_fi = replace_str(file_fi, strsave(f)); + line_fi = replace_str(line_fi, strsave(l)); + } else if (strcmp(c, "nf") == 0) { + check_fi_flag = 1; + val_fi = replace_negate_str(val_fi, strsave(v)); + file_fi = replace_str(file_fi, strsave(f)); + line_fi = replace_str(line_fi, strsave(l)); + } else if (strcmp(c, "ce") == 0) { + check_ce_flag = 1; + val_ce = replace_str(val_ce, strsave(v)); + file_ce = replace_str(file_ce, strsave(f)); + line_ce = replace_str(line_ce, strsave(l)); + } +} + +/* + * build - builds the troff state assertion. + * see tmac/www.tmac for cmd examples. + */ + +void assert_state::build (const char *c, const char *v, + const char *f, const char *l) +{ + if (c[0] == '{') + set(&c[1], v, f, l); + if (c[0] == '}') + close(&c[1]); +} + +int assert_state::check_value_error (int c, int v, const char *s, + const char *name, + const char *f, const char *l, int flag) +{ + if (! c) { + if (f == NULL) + f = "stdin"; + if (l == NULL) + l = "<none>"; + fprintf(stderr, "%s:%s:grohtml (troff state) assertion failed, expected %s to be %s but found it to contain %d\n", + f, l, name, s, v); + return 0; + } + return flag; +} + +void assert_state::check_value (const char *s, int v, const char *name, + const char *f, const char *l, int *flag) +{ + if (strncmp(s, "<=", 2) == 0) + *flag = check_value_error(v <= atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, ">=", 2) == 0) + *flag = check_value_error(v >= atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, "==", 2) == 0) + *flag = check_value_error(v == atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, "!=", 2) == 0) + *flag = check_value_error(v != atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, "<", 1) == 0) + *flag = check_value_error(v < atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, ">", 1) == 0) + *flag = check_value_error(v > atoi(&s[2]), v, s, name, f, l, *flag); + else if (strncmp(s, "=", 1) == 0) + *flag = check_value_error(v == atoi(&s[1]), v, s, name, f, l, *flag); + else + *flag = check_value_error(v == atoi(s), v, s, name, f, l, *flag); +} + +void assert_state::check_sp (int sp) +{ + if (check_sp_flag) + check_value(val_sp, sp, "sp", file_sp, line_sp, &check_sp_flag); +} + +void assert_state::check_fi (int fi) +{ + if (check_fi_flag) + check_value(val_fi, fi, "fi", file_fi, line_fi, &check_fi_flag); +} + +void assert_state::check_br (int br) +{ + if (check_br_flag) + check_value(val_br, br, "br", file_br, line_br, &check_br_flag); +} + +void assert_state::check_ce (int ce) +{ + if (check_ce_flag) + check_value(val_ce, ce, "ce", file_ce, line_ce, &check_ce_flag); +} + class html_printer : public printer { files file_list; simple_output html; @@ -1477,12 +1977,26 @@ class html_printer : public printer { int max_linelength; int linelength; int pageoffset; - int indentation; - int prev_indent; + int troff_indent; + int device_indent; + int temp_indent; int pointsize; int vertical_spacing; int line_number; color *background; + int seen_indent; + int next_indent; + int seen_pageoffset; + int next_pageoffset; + int seen_linelength; + int next_linelength; + int seen_center; + int next_center; + int seen_space; + int seen_break; + int current_column; + int row_space; + assert_state as; void flush_sbuf (); void set_style (const style &); @@ -1508,15 +2022,18 @@ class html_printer : public printer { void start_font (const char *name); void end_font (const char *name); int is_font_courier (font *f); + int is_line_start (int nf); int is_courier_until_eol (void); void start_size (int from, int to); void do_font (text_glob *g); void do_center (char *arg); + void do_check_center (void); void do_break (void); + void do_space (char *arg); void do_eol (void); void do_eol_ce (void); void do_title (void); - void do_fill (int on); + void do_fill (char *arg); void do_heading (char *arg); void write_header (void); void determine_header_level (int level); @@ -1533,6 +2050,9 @@ class html_printer : public printer { void do_auto_image (text_glob *g, const char *filename); void do_links (void); void do_flush (void); + void do_job_name (char *name); + void do_head (char *name); + void insert_split_file (void); int is_in_middle (int left, int right); void do_sup_or_sub (text_glob *g); int start_subscript (text_glob *g); @@ -1563,6 +2083,18 @@ class html_printer : public printer { void remove_courier_tabs (void); void update_min_max (colType type_of_col, int *minimum, int *maximum, text_glob *g); void add_table_end (const char *); + void do_file_components (void); + void write_navigation (const string &top, const string &prev, + const string &next, const string ¤t); + void emit_link (const string &to, const char *name); + int get_troff_indent (void); + void restore_troff_indent (void); + void handle_assertion (int minv, int minh, int maxv, int maxh, const char *s); + void handle_state_assertion (text_glob *g); + void do_end_para (text_glob *g); + int round_width (int x); + void handle_tag_within_title (text_glob *g); + void writeHeadMetaStyle (void); // ADD HERE public: @@ -1570,10 +2102,13 @@ public: ~html_printer (); void set_char (int i, font *f, const environment *env, int w, const char *name); void set_numbered_char(int num, const environment *env, int *widthp); + int set_char_and_width(const char *nm, const environment *env, + int *widthp, font **f); void draw (int code, int *p, int np, const environment *env); void begin_page (int); void end_page (int); void special (char *arg, const environment *env, char type); + void devtag (char *arg, const environment *env, char type); font *make_font (const char *); void end_of_line (); }; @@ -1640,6 +2175,24 @@ void html_printer::emit_line (text_glob *) } /* + * restore_troff_indent - is called when we have temporarily shutdown + * indentation (typically done when we have + * centered an image). + */ + +void html_printer::restore_troff_indent (void) +{ + troff_indent = next_indent; + if (troff_indent > 0) { + /* + * force device indentation + */ + device_indent = 0; + do_indent(get_troff_indent(), pageoffset, linelength); + } +} + +/* * emit_raw - writes the raw html information directly to the device. */ @@ -1650,17 +2203,20 @@ void html_printer::emit_raw (text_glob *g) determine_space(g); current_paragraph->do_emittext(g->text_string, g->text_length); } else { + int space = current_paragraph->retrieve_para_space() || seen_space; + current_paragraph->done_para(); + shutdown_table(); switch (next_tag) { case CENTERED: - current_paragraph->do_para("align=center"); + current_paragraph->do_para("align=center", space); break; case LEFT: - current_paragraph->do_para(&html, "align=left", indentation, pageoffset, linelength); + current_paragraph->do_para(&html, "align=left", get_troff_indent(), pageoffset, linelength, space); break; case RIGHT: - current_paragraph->do_para(&html, "align=right", indentation, pageoffset, linelength); + current_paragraph->do_para(&html, "align=right", get_troff_indent(), pageoffset, linelength, space); break; default: fatal("unknown enumeration"); @@ -1669,39 +2225,37 @@ void html_printer::emit_raw (text_glob *g) current_paragraph->done_para(); next_tag = INLINE; supress_sub_sup = TRUE; - if (indentation > 0) { - /* - * restore indentation - */ - int newin = indentation; - indentation = 0; - do_indent(newin, pageoffset, linelength); - } + seen_space = FALSE; + restore_troff_indent(); } } /* + * handle_tag_within_title - handle a limited number of tags within + * the context of a table. Those tags which + * set values rather than generate spaces + * and paragraphs. + */ + +void html_printer::handle_tag_within_title (text_glob *g) +{ + if (g->is_in() || g->is_ti() || g->is_po() || g->is_ce() || g->is_ll() + || g->is_fi() || g->is_nf()) + troff_tag(g); +} + +/* * do_center - handle the .ce commands from troff. */ void html_printer::do_center (char *arg) { - int n = atoi(arg); - current_paragraph->do_break(); - - if (n > 0) { - current_paragraph->done_para(); - supress_sub_sup = TRUE; - current_paragraph->do_para("align=center"); - end_center += n; - } else { - end_center = 0; - current_paragraph->remove_para_align(); - } + next_center = atoi(arg); + seen_center = TRUE; } /* - * do_centered_image - set a flag such that the next html-tag is + * do_centered_image - set a flag such that the next devtag is * placed inside a centered paragraph. */ @@ -1711,7 +2265,7 @@ void html_printer::do_centered_image (void) } /* - * do_right_image - set a flag such that the next html-tag is + * do_right_image - set a flag such that the next devtag is * placed inside a right aligned paragraph. */ @@ -1721,7 +2275,7 @@ void html_printer::do_right_image (void) } /* - * do_left_image - set a flag such that the next html-tag is + * do_left_image - set a flag such that the next devtag is * placed inside a left aligned paragraph. */ @@ -1759,7 +2313,8 @@ static string &generate_img_src (const char *filename) filename++; } if (exists(filename)) - *s += string("<img src=\"") + filename + "\">"; + *s += string("<img src=\"") + filename + "\" " + + "alt=\"Image " + filename + "\">"; return *s; } @@ -1808,7 +2363,6 @@ void html_printer::do_title (void) { text_glob *t; int removed_from_head; - int eol_ce = 0; if (page_number == 1) { int found_title_start = FALSE; @@ -1830,24 +2384,16 @@ void html_printer::do_title (void) page_contents->glyphs.sub_move_right(); /* move onto next word */ removed_from_head = ((!page_contents->glyphs.is_empty()) && (page_contents->glyphs.is_equal_to_head())); - } else if (t->is_eol_ce()) { - /* process the eol associated with .ce - */ - eol_ce++; - page_contents->glyphs.sub_move_right(); /* move onto next word */ - } else if (t->is_eol()) { + } else if (t->is_eo_tl()) { /* end of title found */ title.has_been_found = TRUE; - outstanding_eol(eol_ce); return; } else if (t->is_a_tag()) { - /* end of title found, but move back so that we read this tag and process it - */ - page_contents->glyphs.move_left(); /* move backwards to last word */ - title.has_been_found = TRUE; - outstanding_eol(eol_ce); - return; + handle_tag_within_title(t); + page_contents->glyphs.sub_move_right(); /* move onto next word */ + removed_from_head = ((!page_contents->glyphs.is_empty()) && + (page_contents->glyphs.is_equal_to_head())); } else if (found_title_start) { title.text += " " + string(t->text_string, t->text_length); page_contents->glyphs.sub_move_right(); /* move onto next word */ @@ -1861,15 +2407,17 @@ void html_printer::do_title (void) removed_from_head = ((!page_contents->glyphs.is_empty()) && (page_contents->glyphs.is_equal_to_head())); } - } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head)); + } while ((! page_contents->glyphs.is_equal_to_head()) || + (removed_from_head)); } - outstanding_eol(eol_ce); } } void html_printer::write_header (void) { if (! header.header_buffer.empty()) { + int space = current_paragraph->retrieve_para_space() || seen_space; + if (header.header_level > 7) { header.header_level = 7; } @@ -1897,7 +2445,7 @@ void html_printer::write_header (void) // lastly we generate a tag - html.nl().put_string("<a name=\""); + html.nl().nl().put_string("<a name=\""); if (simple_anchors) { string buffer(ANCHOR_TEMPLATE); @@ -1937,7 +2485,23 @@ void html_printer::write_header (void) html.put_string(">").nl(); } - current_paragraph->do_para(&html, "", indentation, pageoffset, linelength); + /* and now we save the file name in which this header will occur */ + + style st; // fake style to enable us to use the list data structure + + text_glob *h=new text_glob(); + h->text_glob_html(&st, + header.headings.add_string(file_list.file_name()), + file_list.file_name().length(), + header.no_of_headings, header.header_level, + header.no_of_headings, header.header_level); + + header.header_filename.add(h, + header.no_of_headings, + header.no_of_headings, header.no_of_headings, + header.no_of_headings, header.no_of_headings); + + current_paragraph->do_para(&html, "", get_troff_indent(), pageoffset, linelength, space); } } @@ -1955,6 +2519,10 @@ void html_printer::determine_header_level (int level) } } header.header_level = level+1; + if (header.header_level >= 2 && header.header_level <= split_level) { + header.no_of_level_one_headings++; + insert_split_file(); + } } /* @@ -1964,39 +2532,46 @@ void html_printer::determine_header_level (int level) void html_printer::do_heading (char *arg) { text_glob *g; - text_glob *l = 0; int level=atoi(arg); + int horiz; header.header_buffer.clear(); page_contents->glyphs.move_right(); if (! page_contents->glyphs.is_equal_to_head()) { g = page_contents->glyphs.get_data(); + horiz = g->minh; do { if (g->is_auto_img()) { string img=generate_img_src((char *)(g->text_string + 20)); if (! img.empty()) { simple_anchors = TRUE; // we cannot use full heading anchors with images - if (l != 0) + if (horiz < g->minh) header.header_buffer += " "; - l = g; header.header_buffer += img; } - } else if (! (g->is_a_line() || g->is_a_tag())) { + } + else if (g->is_in() || g->is_ti() || g->is_po() || g->is_ce() || g->is_ll()) + troff_tag(g); + else if (g->is_fi()) + fill_on = 1; + else if (g->is_nf()) + fill_on = 0; + else if (! (g->is_a_line() || g->is_a_tag())) { /* - * we ignore tags commands when constructing a heading + * we ignore the other tag commands when constructing a heading */ - if (l != 0) + if (horiz < g->minh) header.header_buffer += " "; - l = g; + horiz = g->maxh; header.header_buffer += string(g->text_string, g->text_length); } page_contents->glyphs.move_right(); g = page_contents->glyphs.get_data(); } while ((! page_contents->glyphs.is_equal_to_head()) && - (! g->is_br())); + (! g->is_eo_h())); } determine_header_level(level); @@ -2046,8 +2621,8 @@ void html_printer::do_linelength (char *arg) if (max_linelength == -1) max_linelength = atoi(arg); - if (fill_on) - do_indent(indentation, pageoffset, atoi(arg)); + next_linelength = atoi(arg); + seen_linelength = TRUE; } /* @@ -2056,8 +2631,20 @@ void html_printer::do_linelength (char *arg) void html_printer::do_pageoffset (char *arg) { - if (fill_on) - do_indent(indentation, atoi(arg), linelength); + next_pageoffset = atoi(arg); + seen_pageoffset = TRUE; +} + +/* + * get_troff_indent - returns the indent value. + */ + +int html_printer::get_troff_indent (void) +{ + if (end_tempindent > 0) + return temp_indent; + else + return troff_indent; } /* @@ -2066,8 +2653,8 @@ void html_printer::do_pageoffset (char *arg) void html_printer::do_indentation (char *arg) { - if (fill_on) - do_indent(atoi(arg), pageoffset, linelength); + next_indent = atoi(arg); + seen_indent = TRUE; } /* @@ -2077,9 +2664,12 @@ void html_printer::do_indentation (char *arg) void html_printer::do_tempindent (char *arg) { if (fill_on) { - end_tempindent = 1; - prev_indent = indentation; - do_indent(atoi(arg), pageoffset, linelength); + /* + * we set the end_tempindent to 2 as the first .br + * activates the .ti and the second terminates it. + */ + end_tempindent = 2; + temp_indent = atoi(arg); } } @@ -2105,17 +2695,19 @@ void html_printer::shutdown_table (void) void html_printer::do_indent (int in, int pageoff, int linelen) { - if ((indentation != -1) && - (pageoffset+indentation != in+pageoff)) { - + if ((device_indent != -1) && + (pageoffset+device_indent != in+pageoff)) { + + int space = current_paragraph->retrieve_para_space() || seen_space; current_paragraph->done_para(); - indentation = in; + device_indent = in; pageoffset = pageoff; if (linelen <= max_linelength) linelength = linelen; - current_paragraph->do_para(&html, "", indentation, pageoffset, max_linelength); + current_paragraph->do_para(&html, "", device_indent, + pageoffset, max_linelength, space); } } @@ -2134,24 +2726,56 @@ void html_printer::do_verticalspacing (char *arg) void html_printer::do_pointsize (char *arg) { - pointsize = atoi(arg); + /* + * firstly check to see whether this point size is really associated with a .tl tag + */ + + if (! page_contents->glyphs.is_empty()) { + text_glob *g = page_contents->glyphs.get_data(); + text_glob *t = page_contents->glyphs.get_data(); + + while (t->is_a_tag() && (! page_contents->glyphs.is_equal_to_head())) { + if (t->is_tl()) { + /* + * found title therefore ignore this .ps tag + */ + while (t != g) { + page_contents->glyphs.move_left(); + t = page_contents->glyphs.get_data(); + } + return; + } + page_contents->glyphs.move_right(); + t = page_contents->glyphs.get_data(); + } + /* + * move back to original position + */ + while (t != g) { + page_contents->glyphs.move_left(); + t = page_contents->glyphs.get_data(); + } + /* + * collect legal pointsize + */ + pointsize = atoi(arg); + } } /* * do_fill - records whether troff has requested that text be filled. */ -void html_printer::do_fill (int on) +void html_printer::do_fill (char *arg) { - current_paragraph->do_break(); - output_hpos = indentation+pageoffset; + int on = atoi(arg); + + output_hpos = get_troff_indent()+pageoffset; supress_sub_sup = TRUE; if (fill_on != on) { if (on) - current_paragraph->do_para(""); - else - current_paragraph->do_pre(); + current_paragraph->do_para("", seen_space); fill_on = on; } } @@ -2168,7 +2792,53 @@ void html_printer::do_eol (void) current_paragraph->do_break(); } } - output_hpos = indentation+pageoffset; + output_hpos = get_troff_indent()+pageoffset; +} + +/* + * do_check_center - checks to see whether we have seen a `.ce' tag + * during the previous line. + */ + +void html_printer::do_check_center(void) +{ + if (seen_center) { + seen_center = FALSE; + if (next_center > 0) { + if (end_center == 0) { + int space = current_paragraph->retrieve_para_space() || seen_space; + current_paragraph->done_para(); + supress_sub_sup = TRUE; + current_paragraph->do_para("align=center", space); + } else + if (strcmp("align=center", + current_paragraph->get_alignment()) != 0) { + /* + * different alignment, so shutdown paragraph and open + * a new one. + */ + int space = current_paragraph->retrieve_para_space() || seen_space; + current_paragraph->done_para(); + supress_sub_sup = TRUE; + current_paragraph->do_para("align=center", space); + } else + /* + * same alignment, if we have emitted text then issue a break. + */ + if (current_paragraph->emitted_text()) + current_paragraph->do_break(); + } else + /* + * next_center == 0 + */ + if (end_center > 0) { + seen_space = seen_space || current_paragraph->retrieve_para_space(); + current_paragraph->done_para(); + supress_sub_sup = TRUE; + current_paragraph->do_para("", seen_space); + } + end_center = next_center; + } } /* @@ -2205,26 +2875,110 @@ void html_printer::do_flush (void) void html_printer::do_links (void) { - current_paragraph->done_para(); + html.end_line(); // flush line auto_links = FALSE; /* from now on only emit under user request */ file_list.add_new_file(xtmpfile()); + file_list.set_links_required(); html.set_file(file_list.get_file()); } /* + * insert_split_file - + */ + +void html_printer::insert_split_file (void) +{ + if (multiple_files) { + current_paragraph->done_para(); // flush paragraph + html.end_line(); // flush line + html.set_file(file_list.get_file()); // flush current file + file_list.add_new_file(xtmpfile()); + string split_file = job_name; + + split_file += string("-"); + split_file += as_string(header.no_of_level_one_headings); + split_file += string(".html"); + split_file += '\0'; + + file_list.set_file_name(split_file); + html.set_file(file_list.get_file()); + } +} + +/* + * do_job_name - assigns the job_name to name. + */ + +void html_printer::do_job_name (char *name) +{ + if (! multiple_files) { + multiple_files = TRUE; + while (name != NULL && (*name != (char)0) && (*name == ' ')) + name++; + job_name = name; + } +} + +/* + * do_head - adds a string to head_info which is to be included into + * the <head> </head> section of the html document. + */ + +void html_printer::do_head (char *name) +{ + head_info += string(name); + head_info += '\n'; +} + +/* * do_break - handles the ".br" request and also - * undoes an outstanding ".ti" command. + * undoes an outstanding ".ti" command + * and calls indent if the indentation + * related registers have changed. */ void html_printer::do_break (void) { + int seen_temp_indent = FALSE; + current_paragraph->do_break(); if (end_tempindent > 0) { end_tempindent--; - if (end_tempindent == 0) - do_indent(prev_indent, pageoffset, linelength); + if (end_tempindent > 0) + seen_temp_indent = TRUE; + } + if (seen_indent || seen_pageoffset || seen_linelength || seen_temp_indent) { + if (seen_indent && (! seen_temp_indent)) + troff_indent = next_indent; + if (! seen_pageoffset) + next_pageoffset = pageoffset; + if (! seen_linelength) + next_linelength = linelength; + do_indent(get_troff_indent(), next_pageoffset, next_linelength); + } + seen_indent = seen_temp_indent; + seen_linelength = FALSE; + seen_pageoffset = FALSE; + do_check_center(); + output_hpos = get_troff_indent()+pageoffset; + supress_sub_sup = TRUE; +} + +void html_printer::do_space (char *arg) +{ + int n = atoi(arg); + + seen_space = atoi(arg); + as.check_sp(seen_space); +#if 0 + if (n>0 && table) + table->set_space(TRUE); +#endif + + while (n>0) { + current_paragraph->do_space(); + n--; } - output_hpos = indentation+pageoffset; supress_sub_sup = TRUE; } @@ -2237,14 +2991,24 @@ void html_printer::do_tab_ts (text_glob *g) html_table *t = g->get_table(); if (t != NULL) { + current_column = 0; current_paragraph->done_pre(); current_paragraph->done_para(); + current_paragraph->remove_para_space(); +#if defined(DEBUG_TABLES) html.simple_comment("TABS"); +#endif t->set_linelength(max_linelength); t->add_indent(pageoffset); +#if 0 + t->emit_table_header(seen_space); +#else t->emit_table_header(FALSE); + row_space = current_paragraph->retrieve_para_space() || seen_space; + seen_space = FALSE; +#endif } table = t; @@ -2258,23 +3022,16 @@ void html_printer::do_tab_te (void) { if (table) { current_paragraph->done_para(); + current_paragraph->remove_para_space(); table->emit_finish_table(); } table = NULL; - - if (indentation > 0) { - /* - * restore indentation - */ - int newin = indentation; - indentation = 0; - do_indent(newin, pageoffset, linelength); - } + restore_troff_indent(); } /* - * do_tab - handle the "html-tag:tab" tag + * do_tab - handle the "devtag:tab" tag */ void html_printer::do_tab (char *s) @@ -2283,7 +3040,7 @@ void html_printer::do_tab (char *s) while (isspace(*s)) s++; s++; - int col = table->find_column(atoi(s) + pageoffset + indentation); + int col = table->find_column(atoi(s) + pageoffset + get_troff_indent()); if (col > 0) { current_paragraph->done_para(); table->emit_col(col); @@ -2292,13 +3049,13 @@ void html_printer::do_tab (char *s) } /* - * do_tab0 - handle the "html-tag:tab0" tag + * do_tab0 - handle the "devtag:tab0" tag */ void html_printer::do_tab0 (void) { if (table) { - int col = table->find_column(pageoffset+indentation); + int col = table->find_column(pageoffset+get_troff_indent()); if (col > 0) { current_paragraph->done_para(); table->emit_col(col); @@ -2313,33 +3070,40 @@ void html_printer::do_tab0 (void) void html_printer::do_col (char *s) { if (table) { + if (atoi(s) < current_column) + row_space = seen_space; + + current_column = atoi(s); current_paragraph->done_para(); - table->emit_col(atoi(s)); + table->emit_col(current_column); + current_paragraph->do_para("", row_space); } } /* - * troff_tag - processes the troff tag and manipulates the troff state machine. + * troff_tag - processes the troff tag and manipulates the troff + * state machine. */ void html_printer::troff_tag (text_glob *g) { /* - * firstly skip over html-tag: + * firstly skip over devtag: */ - char *t=(char *)g->text_string+9; + char *t=(char *)g->text_string+strlen("devtag:"); - if (g->is_eol()) { + if (strncmp(g->text_string, "html</p>:", strlen("html</p>:")) == 0) { + do_end_para(g); + } else if (g->is_eol()) { do_eol(); } else if (g->is_eol_ce()) { do_eol_ce(); } else if (strncmp(t, ".sp", 3) == 0) { - if (g->get_arg() > 0) - current_paragraph->do_space(); - else - current_paragraph->do_break(); - supress_sub_sup = TRUE; + char *a = (char *)t+3; + do_space(a); } else if (strncmp(t, ".br", 3) == 0) { + seen_break = 1; + as.check_br(1); do_break(); } else if (strcmp(t, ".centered-image") == 0) { do_centered_image(); @@ -2354,7 +3118,7 @@ void html_printer::troff_tag (text_glob *g) char *a = (char *)t+3; supress_sub_sup = TRUE; do_center(a); - } else if (strncmp(t, ".tl", 3) == 0) { + } else if (g->is_tl()) { supress_sub_sup = TRUE; title.with_h1 = TRUE; do_title(); @@ -2363,9 +3127,8 @@ void html_printer::troff_tag (text_glob *g) title.with_h1 = FALSE; do_title(); } else if (strncmp(t, ".fi", 3) == 0) { - do_fill(TRUE); - } else if (strncmp(t, ".nf", 3) == 0) { - do_fill(FALSE); + char *a = (char *)t+3; + do_fill(a); } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) { char *a = (char *)t+3; do_heading(a); @@ -2389,6 +3152,12 @@ void html_printer::troff_tag (text_glob *g) do_pointsize(a); } else if (strcmp(t, ".links") == 0) { do_links(); + } else if (strncmp(t, ".job-name", 9) == 0) { + char *a = (char *)t+9; + do_job_name(a); + } else if (strncmp(t, ".head", 5) == 0) { + char *a = (char *)t+5; + do_head(a); } else if (strcmp(t, ".no-auto-rule") == 0) { auto_rule = FALSE; } else if (strcmp(t, ".tab-ts") == 0) { @@ -2412,7 +3181,8 @@ void html_printer::troff_tag (text_glob *g) int html_printer::is_in_middle (int left, int right) { - return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) <= CENTER_TOLERANCE ); + return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) + <= CENTER_TOLERANCE ); } /* @@ -2427,17 +3197,31 @@ void html_printer::flush_globs (void) page_contents->glyphs.start_from_head(); do { g = page_contents->glyphs.get_data(); +#if 0 + fprintf(stderr, "[%s:%d:%d:%d:%d]", + g->text_string, g->minv, g->minh, g->maxv, g->maxh) ; + fflush(stderr); +#endif + + handle_state_assertion(g); if (strcmp(g->text_string, "XXXXXXX") == 0) stop(); - if (g->is_a_tag()) { + if (g->is_a_tag()) troff_tag(g); - } else if (g->is_a_line()) { + else if (g->is_a_line()) emit_line(g); - } else { + else { + as.check_sp(seen_space); + as.check_br(seen_break); + seen_break = 0; + seen_space = 0; emit_html(g); } + + as.check_fi(fill_on); + as.check_ce(end_center); /* * after processing the title (and removing it) the glyph list might be empty */ @@ -2456,11 +3240,16 @@ void html_printer::flush_globs (void) int html_printer::calc_nf (text_glob *g, int nf) { if (g != NULL) { - if (g->is_fi()) + if (g->is_fi()) { + as.check_fi(TRUE); return FALSE; - if (g->is_nf()) + } + if (g->is_nf()) { + as.check_fi(FALSE); return TRUE; + } } + as.check_fi(! nf); return nf; } @@ -2471,16 +3260,15 @@ int html_printer::calc_nf (text_glob *g, int nf) void html_printer::calc_po_in (text_glob *g, int nf) { if (g->is_in()) - indentation = g->get_arg(); + troff_indent = g->get_arg(); else if (g->is_po()) pageoffset = g->get_arg(); else if (g->is_ti()) { - prev_indent = indentation; - indentation = g->get_arg(); - end_tempindent = 1; - } else if (g->is_br() && ((end_tempindent > 0) || (nf && g->is_eol()))) { - end_tempindent = 0; - indentation = prev_indent; + temp_indent = g->get_arg(); + end_tempindent = 2; + } else if (g->is_br() || (nf && g->is_eol())) { + if (end_tempindent > 0) + end_tempindent--; } } @@ -2491,13 +3279,15 @@ void html_printer::calc_po_in (text_glob *g, int nf) int html_printer::next_horiz_pos (text_glob *g, int nf) { - int next = -1; + int next = -1; if ((g != NULL) && (g->is_br() || (nf && g->is_eol()))) if (! page_contents->glyphs.is_empty()) { page_contents->glyphs.move_right_get_data(); - if (g == NULL) + if (g == NULL) { page_contents->glyphs.start_from_head(); + as.reset(); + } else { next = g->minh; page_contents->glyphs.move_left(); @@ -2517,7 +3307,7 @@ text_glob *html_printer::insert_tab_ts (text_glob *where) page_contents->glyphs.move_to(where); page_contents->glyphs.move_left(); - page_contents->insert_tag(string("html-tag:.tab-ts")); // tab table start + page_contents->insert_tag(string("devtag:.tab-ts")); // tab table start page_contents->glyphs.move_right(); start_of_table = page_contents->glyphs.get_data(); page_contents->glyphs.move_to(old_pos); @@ -2537,7 +3327,7 @@ void html_printer::insert_tab_te (void) while (page_contents->glyphs.get_data()->is_a_tag()) page_contents->glyphs.move_left(); - page_contents->insert_tag(string("html-tag:.tab-te")); // tab table end + page_contents->insert_tag(string("devtag:.tab-te")); // tab table end while (g != page_contents->glyphs.get_data()) page_contents->glyphs.move_right(); page_contents->dump_page(); @@ -2553,7 +3343,7 @@ void html_printer::insert_tab_0 (text_glob *where) page_contents->glyphs.move_to(where); page_contents->glyphs.move_left(); - page_contents->insert_tag(string("html-tag:tab0")); // tab0 start of line + page_contents->insert_tag(string("devtag:tab0")); // tab0 start of line page_contents->glyphs.move_right(); page_contents->glyphs.move_to(old_pos); } @@ -2595,10 +3385,11 @@ void html_printer::remove_courier_tabs (void) if (! page_contents->glyphs.is_empty()) { page_contents->glyphs.start_from_head(); + as.reset(); line_start = TRUE; do { g = page_contents->glyphs.get_data(); - + handle_state_assertion(g); nf = calc_nf(g, nf); if (line_start) { @@ -2608,7 +3399,8 @@ void html_printer::remove_courier_tabs (void) } } - line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol()); + // line_start = g->is_br() || g->is_nf() || g->is_fi() || (nf && g->is_eol()); + line_start = g->is_br() || (nf && g->is_eol()); page_contents->glyphs.move_right(); } while (! page_contents->glyphs.is_equal_to_head()); } @@ -2624,10 +3416,11 @@ void html_printer::insert_tab0_foreach_tab (void) if (! page_contents->glyphs.is_empty()) { page_contents->glyphs.start_from_head(); + as.reset(); start_of_line = page_contents->glyphs.get_data(); do { g = page_contents->glyphs.get_data(); - + handle_state_assertion(g); nf = calc_nf(g, nf); if (g->is_tab()) @@ -2640,6 +3433,7 @@ void html_printer::insert_tab0_foreach_tab (void) do { page_contents->glyphs.move_right(); g = page_contents->glyphs.get_data(); + handle_state_assertion(g); nf = calc_nf(g, nf); if (page_contents->glyphs.is_equal_to_head()) { if (seen_tab && !seen_col) @@ -2707,7 +3501,8 @@ void html_printer::add_table_end (const char * } /* - * lookahead_for_tables - checks for .col tags and inserts table start/end tags + * lookahead_for_tables - checks for .col tags and inserts table + * start/end tags */ void html_printer::lookahead_for_tables (void) @@ -2721,9 +3516,9 @@ void html_printer::lookahead_for_tables (void) int found_col = FALSE; int seen_text = FALSE; int ncol = 0; - int colmin; - int colmax; - html_table *table = new html_table(&html, -1); + int colmin = 0; // pacify compiler + int colmax = 0; // pacify compiler + html_table *tbl = new html_table(&html, -1); const char *tab_defs = NULL; char align = 'L'; int nf = FALSE; @@ -2735,7 +3530,28 @@ void html_printer::lookahead_for_tables (void) page_contents->dump_page(); if (! page_contents->glyphs.is_empty()) { page_contents->glyphs.start_from_head(); + as.reset(); g = page_contents->glyphs.get_data(); + if (g->is_br()) { + g = page_contents->glyphs.move_right_get_data(); + handle_state_assertion(g); + if (page_contents->glyphs.is_equal_to_head()) { + if (tbl != NULL) { + delete tbl; + tbl = NULL; + } + return; + } + + start_of_line = g; + seen_text = FALSE; + ncol = 0; + left = next_horiz_pos(g, nf); + if (found_col) + last = g; + found_col = FALSE; + } + do { #if defined(DEBUG_TABLES) fprintf(stderr, " [") ; @@ -2752,11 +3568,11 @@ void html_printer::lookahead_for_tables (void) if (type_of_col == tab_tag && start_of_table != NULL) { page_contents->glyphs.move_left(); insert_tab_te(); - start_of_table->remember_table(table); - table = new html_table(&html, -1); + start_of_table->remember_table(tbl); + tbl = new html_table(&html, -1); page_contents->insert_tag(string("*** TAB -> COL ***")); if (tab_defs != NULL) - table->tab_stops->init(tab_defs); + tbl->tab_stops->init(tab_defs); start_of_table = NULL; last = NULL; } @@ -2770,28 +3586,28 @@ void html_printer::lookahead_for_tables (void) type_of_col = tab_tag; colmin = g->get_tab_args(&align); align = 'L'; // for now as 'C' and 'R' are broken - ncol = table->find_tab_column(colmin); - colmin += pageoffset + indentation; - colmax = table->get_tab_pos(ncol+1); + ncol = tbl->find_tab_column(colmin); + colmin += pageoffset + get_troff_indent(); + colmax = tbl->get_tab_pos(ncol+1); if (colmax > 0) - colmax += pageoffset + indentation; + colmax += pageoffset + get_troff_indent(); } else if (g->is_tab0()) { if (type_of_col == col_tag && start_of_table != NULL) { page_contents->glyphs.move_left(); insert_tab_te(); - start_of_table->remember_table(table); - table = new html_table(&html, -1); + start_of_table->remember_table(tbl); + tbl = new html_table(&html, -1); page_contents->insert_tag(string("*** COL -> TAB ***")); start_of_table = NULL; last = NULL; } if (tab_defs != NULL) - table->tab_stops->init(tab_defs); + tbl->tab_stops->init(tab_defs); type_of_col = tab0_tag; ncol = 1; colmin = 0; - colmax = table->get_tab_pos(2) + pageoffset + indentation; + colmax = tbl->get_tab_pos(2) + pageoffset + get_troff_indent(); } else if (! g->is_a_tag()) update_min_max(type_of_col, &colmin, &colmax, g); @@ -2805,34 +3621,39 @@ void html_printer::lookahead_for_tables (void) seen_text = FALSE; } else if (g->is_ce() && (start_of_table != NULL)) { add_table_end("*** CE ***"); - start_of_table->remember_table(table); + start_of_table->remember_table(tbl); + tbl = new html_table(&html, -1); start_of_table = NULL; last = NULL; } else if (g->is_ta()) { tab_defs = g->text_string; - if (!table->tab_stops->compatible(tab_defs)) { + + if (type_of_col == col_tag) + tbl->tab_stops->check_init(tab_defs); + + if (!tbl->tab_stops->compatible(tab_defs)) { if (start_of_table != NULL) { add_table_end("*** TABS ***"); - start_of_table->remember_table(table); - table = new html_table(&html, -1); + start_of_table->remember_table(tbl); + tbl = new html_table(&html, -1); start_of_table = NULL; type_of_col = none; last = NULL; } - table->tab_stops->init(tab_defs); + tbl->tab_stops->init(tab_defs); } } if (((! g->is_a_tag()) || g->is_tab()) && (start_of_table != NULL)) { // we are in a table and have a glyph - if ((ncol == 0) || (! table->add_column(ncol, colmin, colmax, align))) { + if ((ncol == 0) || (! tbl->add_column(ncol, colmin, colmax, align))) { if (ncol == 0) add_table_end("*** NCOL == 0 ***"); else add_table_end("*** CROSSED COLS ***"); - start_of_table->remember_table(table); - table = new html_table(&html, -1); + start_of_table->remember_table(tbl); + tbl = new html_table(&html, -1); start_of_table = NULL; type_of_col = none; last = NULL; @@ -2843,16 +3664,19 @@ void html_printer::lookahead_for_tables (void) * move onto next glob, check whether we are starting a new line */ g = page_contents->glyphs.move_right_get_data(); + handle_state_assertion(g); if (g == NULL) { if (found_col) { page_contents->glyphs.start_from_head(); + as.reset(); last = g; found_col = FALSE; } } else if (g->is_br() || (nf && g->is_eol())) { do { g = page_contents->glyphs.move_right_get_data(); + handle_state_assertion(g); nf = calc_nf(g, nf); } while ((g != NULL) && (g->is_br() || (nf && g->is_eol()))); start_of_line = g; @@ -2876,18 +3700,20 @@ void html_printer::lookahead_for_tables (void) page_contents->glyphs.move_left(); insert_tab_te(); - start_of_table->remember_table(table); - table = NULL; + start_of_table->remember_table(tbl); + tbl = NULL; page_contents->insert_tag(string("*** LAST ***")); } } - if (table != NULL) - delete table; + if (tbl != NULL) { + delete tbl; + tbl = NULL; + } // and reset the registers pageoffset = old_pageoffset; - indentation = 0; - prev_indent = 0; + troff_indent = 0; + temp_indent = 0; end_tempindent = 0; } @@ -2935,6 +3761,37 @@ void html_printer::determine_space (text_glob *g) } /* + * is_line_start - returns TRUE if we are at the start of a line. + */ + +int html_printer::is_line_start (int nf) +{ + int line_start = FALSE; + int result = TRUE; + text_glob *orig = page_contents->glyphs.get_data(); + text_glob *g; + + if (! page_contents->glyphs.is_equal_to_head()) { + do { + page_contents->glyphs.move_left(); + g = page_contents->glyphs.get_data(); + result = g->is_a_tag(); + if (g->is_fi()) + nf = FALSE; + else if (g->is_nf()) + nf = TRUE; + line_start = g->is_col() || g->is_br() || (nf && g->is_eol()); + } while ((!line_start) && (result)); + /* + * now restore our previous position. + */ + while (page_contents->glyphs.get_data() != orig) + page_contents->glyphs.move_right(); + } + return result; +} + +/* * is_font_courier - returns TRUE if the font, f, is courier. */ @@ -2945,7 +3802,7 @@ int html_printer::is_font_courier (font *f) return( (fontname != 0) && (fontname[0] == 'C') ); } - return( FALSE ); + return FALSE; } /* @@ -2994,24 +3851,28 @@ void html_printer::start_font (const char *fontname) current_paragraph->do_bold(); current_paragraph->do_italic(); } else if (strcmp(fontname, "CR") == 0) { - if ((! fill_on) && (is_courier_until_eol())) { + if ((! fill_on) && (is_courier_until_eol()) && + is_line_start(! fill_on)) { current_paragraph->do_pre(); } current_paragraph->do_tt(); } else if (strcmp(fontname, "CI") == 0) { - if ((! fill_on) && (is_courier_until_eol())) { + if ((! fill_on) && (is_courier_until_eol()) && + is_line_start(! fill_on)) { current_paragraph->do_pre(); } current_paragraph->do_tt(); current_paragraph->do_italic(); } else if (strcmp(fontname, "CB") == 0) { - if ((! fill_on) && (is_courier_until_eol())) { + if ((! fill_on) && (is_courier_until_eol()) && + is_line_start(! fill_on)) { current_paragraph->do_pre(); } current_paragraph->do_tt(); current_paragraph->do_bold(); } else if (strcmp(fontname, "CBI") == 0) { - if ((! fill_on) && (is_courier_until_eol())) { + if ((! fill_on) && (is_courier_until_eol()) && + is_line_start(! fill_on)) { current_paragraph->do_pre(); } current_paragraph->do_tt(); @@ -3164,6 +4025,23 @@ void html_printer::do_sup_or_sub (text_glob *g) } /* + * do_end_para - writes out the html text after shutting down the + * current paragraph. + */ + +void html_printer::do_end_para (text_glob *g) +{ + do_font(g); + current_paragraph->done_para(); + current_paragraph->remove_para_space(); + html.put_string(g->text_string+9); + output_vpos = g->minv; + output_hpos = g->maxh; + output_vpos_max = g->maxv; + supress_sub_sup = FALSE; +} + +/* * emit_html - write out the html text */ @@ -3187,6 +4065,7 @@ void html_printer::flush_sbuf() if (sbuf.length() > 0) { int r=font::res; // resolution of the device set_style(sbuf_style); + if (overstrike_detected && (! is_bold(sbuf_style.f))) { font *bold_font = make_bold(sbuf_style.f); if (bold_font != NULL) @@ -3297,11 +4176,24 @@ html_printer::html_printer() max_linelength(-1), linelength(0), pageoffset(0), - indentation(0), - prev_indent(0), - pointsize(0), + troff_indent(0), + device_indent(0), + temp_indent(0), + pointsize(base_point_size), line_number(0), - background(default_background) + background(default_background), + seen_indent(FALSE), + next_indent(0), + seen_pageoffset(FALSE), + next_pageoffset(0), + seen_linelength(FALSE), + next_linelength(0), + seen_center(FALSE), + next_center(0), + seen_space(0), + seen_break(0), + current_column(0), + row_space(FALSE) { file_list.add_new_file(xtmpfile()); html.set_file(file_list.get_file()); @@ -3336,17 +4228,17 @@ html_printer::html_printer() * add_to_sbuf - adds character code or name to the sbuf. */ -void html_printer::add_to_sbuf (int index, const string &s) +void html_printer::add_to_sbuf (int idx, const string &s) { if (sbuf_style.f == NULL) return; char *html_glyph = NULL; - unsigned int code = sbuf_style.f->get_code(index); + unsigned int code = sbuf_style.f->get_code(idx); if (s.empty()) { - if (sbuf_style.f->contains(index)) - html_glyph = (char *)sbuf_style.f->get_special_device_encoding(index); + if (sbuf_style.f->contains(idx)) + html_glyph = (char *)sbuf_style.f->get_special_device_encoding(idx); else html_glyph = NULL; @@ -3362,7 +4254,7 @@ void html_printer::add_to_sbuf (int index, const string &s) sbuf += html_glyph; } -int html_printer::sbuf_continuation (int index, const char *name, +int html_printer::sbuf_continuation (int idx, const char *name, const environment *env, int w) { /* @@ -3372,7 +4264,7 @@ int html_printer::sbuf_continuation (int index, const char *name, || ((sbuf_prev_hpos < sbuf_end_hpos) && (env->hpos < sbuf_end_hpos) && ((sbuf_end_hpos-env->hpos < env->hpos-sbuf_prev_hpos)))) { - add_to_sbuf(index, name); + add_to_sbuf(idx, name); sbuf_prev_hpos = sbuf_end_hpos; sbuf_end_hpos += w + sbuf_kern; return TRUE; @@ -3384,7 +4276,7 @@ int html_printer::sbuf_continuation (int index, const char *name, */ if (env->hpos-sbuf_end_hpos < space_width) { - add_to_sbuf(index, name); + add_to_sbuf(idx, name); sbuf_prev_hpos = sbuf_end_hpos; sbuf_end_hpos = env->hpos + w; return TRUE; @@ -3401,18 +4293,18 @@ int html_printer::sbuf_continuation (int index, const char *name, char *get_html_translation (font *f, const string &name) { - int index; + int idx; if ((f == 0) || name.empty()) return NULL; else { - index = f->name_to_index((char *)(name + '\0').contents()); - if (index == 0) { + idx = f->name_to_index((char *)(name + '\0').contents()); + if (idx == 0) { error("character `%s' not found", (name + '\0').contents()); return NULL; } else - if (f->contains(index)) - return (char *)f->get_special_device_encoding(index); + if (f->contains(idx)) + return (char *)f->get_special_device_encoding(idx); else return NULL; } @@ -3425,7 +4317,7 @@ char *get_html_translation (font *f, const string &name) * is flushed. */ -int html_printer::overstrike(int index, const char *name, const environment *env, int w) +int html_printer::overstrike(int idx, const char *name, const environment *env, int w) { if ((env->hpos < sbuf_end_hpos) || ((sbuf_kern != 0) && (sbuf_end_hpos - sbuf_kern < env->hpos))) { @@ -3435,7 +4327,7 @@ int html_printer::overstrike(int index, const char *name, const environment *env if (overstrike_detected) { /* already detected, remove previous glyph and use this glyph */ sbuf.set_length(last_sbuf_length); - add_to_sbuf(index, name); + add_to_sbuf(idx, name); sbuf_end_hpos = env->hpos + w; return TRUE; } else { @@ -3444,7 +4336,7 @@ int html_printer::overstrike(int index, const char *name, const environment *env if (! is_bold(sbuf_style.f)) flush_sbuf(); overstrike_detected = TRUE; - add_to_sbuf(index, name); + add_to_sbuf(idx, name); sbuf_end_hpos = env->hpos + w; return TRUE; } @@ -3453,11 +4345,13 @@ int html_printer::overstrike(int index, const char *name, const environment *env } /* - * set_char - adds a character into the sbuf if it is a continuation with the previous - * word otherwise flush the current sbuf and add character anew. + * set_char - adds a character into the sbuf if it is a continuation + * with the previous word otherwise flush the current sbuf + * and add character anew. */ -void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name) +void html_printer::set_char(int i, font *f, const environment *env, + int w, const char *name) { style sty(f, env->size, env->height, env->slant, env->fontno, *env->col); if (sty.slant != 0) { @@ -3471,6 +4365,8 @@ void html_printer::set_char(int i, font *f, const environment *env, int w, const return; flush_sbuf(); + if (sbuf_style.f == NULL) + sbuf_style = sty; add_to_sbuf(i, name); sbuf_end_hpos = env->hpos + w; sbuf_start_hpos = env->hpos; @@ -3516,11 +4412,44 @@ void html_printer::set_numbered_char(int num, const environment *env, w = nbsp_width; else w = f->get_width(i, env->size); + w = round_width(w); if (widthp) *widthp = w; set_char(i, f, env, w, 0); } +int html_printer::set_char_and_width(const char *nm, const environment *env, + int *widthp, font **f) +{ + int i = font::name_to_index(nm); + int fn = env->fontno; + if (fn < 0 || fn >= nfonts) { + error("bad font position `%1'", fn); + return -1; + } + *f = font_table[fn]; + if (*f == 0) { + error("no font mounted at `%1'", fn); + return -1; + } + if (!(*f)->contains(i)) { + if (nm[0] != '\0' && nm[1] == '\0') + error("font `%1' does not contain ascii character `%2'", + (*f)->get_name(), + nm[0]); + else + error("font `%1' does not contain special character `%2'", + (*f)->get_name(), + nm); + return -1; + } + int w = (*f)->get_width(i, env->size); + w = round_width(w); + if (widthp) + *widthp = w; + return i; +} + /* * write_title - writes the title to this document */ @@ -3573,8 +4502,8 @@ void html_printer::begin_page(int n) output_vpos = -1; output_vpos_max = -1; current_paragraph = new html_text(&html); - do_indent(indentation, pageoffset, linelength); - current_paragraph->do_para(""); + do_indent(get_troff_indent(), pageoffset, linelength); + current_paragraph->do_para("", FALSE); } void html_printer::end_page(int) @@ -3606,6 +4535,133 @@ void html_printer::do_body (void) } } +/* + * emit_link - generates: <a href="to">name</a> + */ + +void html_printer::emit_link (const string &to, const char *name) +{ + fputs("<a href=\"", stdout); + fputs(to.contents(), stdout); + fputs("\">", stdout); + fputs(name, stdout); + fputs("</a>", stdout); +} + +/* + * write_navigation - writes out the links which navigate between + * file fragments. + */ + +void html_printer::write_navigation (const string &top, const string &prev, + const string &next, const string ¤t) +{ + int need_bar = FALSE; + + if (multiple_files) { + write_rule(); + fputs("[ ", stdout); + if ((strcmp(prev.contents(), "") != 0) && prev != top && prev != current) { + emit_link(prev, "prev"); + need_bar = TRUE; + } + if ((strcmp(next.contents(), "") != 0) && next != top && next != current) { + if (need_bar) + fputs(" | ", stdout); + emit_link(next, "next"); + need_bar = TRUE; + } + if (top != "<standard input>" && (strcmp(top.contents(), "") != 0) && top != current) { + if (need_bar) + fputs(" | ", stdout); + emit_link(top, "top"); + } + fputs(" ]\n", stdout); + write_rule(); + } +} + +/* + * do_file_components - scan the file list copying each temporary + * file in turn. This is used twofold: + * + * firstly to emit section heading links, + * between file fragments if required and + * secondly to generate jobname file fragments + * if required. + */ + +void html_printer::do_file_components (void) +{ + int fragment_no = 1; + string top; + string prev; + string next; + string current; + + file_list.start_of_list(); + top = string(job_name); + top += string(".html"); + top += '\0'; + next = file_list.next_file_name(); + next += '\0'; + current = next; + while (file_list.get_file() != 0) { + if (fseek(file_list.get_file(), 0L, 0) < 0) + fatal("fseek on temporary file failed"); + html.copy_file(file_list.get_file()); + fclose(file_list.get_file()); + + file_list.move_next(); + if (file_list.is_new_output_file()) { + if (fragment_no > 1) + write_navigation(top, prev, next, current); + prev = current; + current = next; + next = file_list.next_file_name(); + next += '\0'; + string split_file = file_list.file_name(); + split_file += '\0'; + fflush(stdout); + freopen(split_file.contents(), "w", stdout); + fragment_no++; + writeHeadMetaStyle(); + write_navigation(top, prev, next, current); + } + if (file_list.are_links_required()) + header.write_headings(stdout, TRUE); + } + if (fragment_no > 1) + write_navigation(top, prev, next, current); + else + write_rule(); +} + +/* + * writeHeadMetaStyle - emits the <head> <meta> and <style> tags and + * related information. + */ + +void html_printer::writeHeadMetaStyle (void) +{ + fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout); + fputs("\"http://www.w3.org/TR/html4/loose.dtd\">\n", stdout); + + fputs("<html>\n", stdout); + fputs("<head>\n", stdout); + fputs("<meta name=\"generator\" " + "content=\"groff -Thtml, see www.gnu.org\">\n", stdout); + fputs("<meta http-equiv=\"Content-Type\" " + "content=\"text/html; charset=US-ASCII\">\n", stdout); + fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout); + + fputs("<style type=\"text/css\">\n", stdout); + fputs(" p { margin-top: 0; margin-bottom: 0; }\n", stdout); + fputs(" pre { margin-top: 0; margin-bottom: 0; }\n", stdout); + fputs(" table { margin-top: 0; margin-bottom: 0; }\n", stdout); + fputs("</style>\n", stdout); +} + html_printer::~html_printer() { #ifdef LONG_FOR_TIME_T @@ -3628,17 +4684,11 @@ html_printer::~html_printer() .put_string(ctime(&t), strlen(ctime(&t))-1) .end_comment(); - fputs("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n", stdout); - fputs("\"http://www.w3.org/TR/html4/loose.dtd\">\n", stdout); + writeHeadMetaStyle(); - fputs("<html>\n", stdout); - fputs("<head>\n", stdout); - fputs("<meta name=\"generator\" " - "content=\"groff -Thtml, see www.gnu.org\">\n", stdout); - fputs("<meta http-equiv=\"Content-Type\" " - "content=\"text/html; charset=US-ASCII\">\n", stdout); - fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout); write_title(TRUE); + head_info += '\0'; + fputs(head_info.contents(), stdout); fputs("</head>\n", stdout); do_body(); @@ -3650,28 +4700,131 @@ html_printer::~html_printer() #endif html.end_line(); html.end_line(); - /* - * now run through the file list copying each temporary file in turn and emitting the links. - */ - file_list.start_of_list(); - while (file_list.get_file() != 0) { - if (fseek(file_list.get_file(), 0L, 0) < 0) - fatal("fseek on temporary file failed"); - html.copy_file(file_list.get_file()); - fclose(file_list.get_file()); - file_list.move_next(); - if (file_list.get_file() != 0) - header.write_headings(stdout, TRUE); + + if (multiple_files) { + fputs("</body>\n", stdout); + fputs("</html>\n", stdout); + do_file_components(); + } else { + do_file_components(); + fputs("</body>\n", stdout); + fputs("</html>\n", stdout); } - write_rule(); - fputs("</body>\n", stdout); - fputs("</html>\n", stdout); } /* - * special - handle all x X requests from troff. For post-html they allow users - * to pass raw html commands, turn auto linked headings off/on and - * also allow troff to emit tags to indicate when a: .br, .sp etc occurs. + * get_str - returns a dupicate of string, s. The duplicate + * string is terminated at the next ',' or ']'. + */ + +static char *get_str (const char *s, char **n) +{ + int i=0; + char *v; + + while ((s[i] != (char)0) && (s[i] != ',') && (s[i] != ']')) + i++; + if (i>0) { + v = new char[i+1]; + memcpy(v, s, i+1); + v[i] = (char)0; + if (s[i] == ',') + (*n) = (char *)&s[i+1]; + else + (*n) = (char *)&s[i]; + return v; + } + if (s[i] == ',') + (*n) = (char *)&s[1]; + else + (*n) = (char *)s; + return NULL; +} + +/* + * make_val - creates a string from if s is NULL. + */ + +char *make_val (char *s, int v, char *id, char *f, char *l) +{ + if (s == NULL) { + char buf[30]; + + sprintf(buf, "%d", v); + return strsave(buf); + } + else { + /* + * check that value, s, is the same as, v. + */ + char *t = s; + + while (*t == '=') + t++; + if (atoi(t) != v) { + if (f == NULL) + f = (char *)"stdin"; + if (l == NULL) + l = (char *)"<none>"; + fprintf(stderr, "%s:%s: grohtml assertion failed at id%s expecting %d and was given %s\n", + f, l, id, v, s); + } + return s; + } +} + +/* + * handle_assertion - handles the assertions created via .www:ASSERT + * in www.tmac. See www.tmac for examples. + * This method should be called as we are + * parsing the ditroff input. It checks the x, y + * position assertions. It does _not_ check the + * troff state assertions as these are unknown at this + * point. + */ + +void html_printer::handle_assertion (int minv, int minh, int maxv, int maxh, const char *s) +{ + char *n; + char *cmd = get_str(s, &n); + char *id = get_str(n, &n); + char *val = get_str(n, &n); + char *file= get_str(n, &n); + char *line= get_str(n, &n); + + if (strcmp(cmd, "assertion:[x") == 0) + as.addx(cmd, id, make_val(val, minh, id, file, line), file, line); + else if (strcmp(cmd, "assertion:[y") == 0) + as.addy(cmd, id, make_val(val, minv, id, file, line), file, line); + else + if (strncmp(cmd, "assertion:[", strlen("assertion:[")) == 0) + page_contents->add_tag(&sbuf_style, string(s), + line_number, minv, minh, maxv, maxh); +} + +/* + * build_state_assertion - builds the troff state assertions. + */ + +void html_printer::handle_state_assertion (text_glob *g) +{ + if (g != NULL && g->is_a_tag() && + (strncmp(g->text_string, "assertion:[", 11) == 0)) { + char *n = (char *)&g->text_string[11]; + char *cmd = get_str(n, &n); + char *val = get_str(n, &n); + (void)get_str(n, &n); // unused + char *file= get_str(n, &n); + char *line= get_str(n, &n); + + as.build(cmd, val, file, line); + } +} + +/* + * special - handle all x X requests from troff. For post-html they + * allow users to pass raw html commands, turn auto linked + * headings off/on etc. */ void html_printer::special(char *s, const environment *env, char type) @@ -3702,16 +4855,73 @@ void html_printer::special(char *s, const environment *env, char type) page_contents->add_and_encode(&sbuf_style, string(&s[5]), line_number, env->vpos-env->size*r/72, env->hpos, - env->vpos , env->hpos); + env->vpos , env->hpos, + FALSE); /* - * assume that the html command has no width, if it does then hopefully troff - * will have fudged this in a macro by requesting that the formatting move right by - * the appropriate amount. + * assume that the html command has no width, if it does then + * hopefully troff will have fudged this in a macro by + * requesting that the formatting move right by the appropriate + * amount. + */ + } else if (strncmp(s, "html</p>:", 9) == 0) { + int r=font::res; /* resolution of the device */ + font *f=sbuf_style.f; + + if (f == NULL) { + int found=FALSE; + + f = font::load_font("TR", &found); + } + + /* + * need to pass all of string through to html output during flush + */ + page_contents->add_and_encode(&sbuf_style, string(s), + line_number, + env->vpos-env->size*r/72, env->hpos, + env->vpos , env->hpos, + TRUE); + + /* + * assume that the html command has no width, if it does then + * hopefully troff will have fudged this in a macro by + * requesting that the formatting move right by the appropriate + * amount. */ } else if (strncmp(s, "index:", 6) == 0) { cutoff_heading = atoi(&s[6]); - } else if (strncmp(s, "html-tag:", 9) == 0) { + } else if (strncmp(s, "assertion:[", 11) == 0) { + int r=font::res; /* resolution of the device */ + + handle_assertion(env->vpos-env->size*r/72, env->hpos, + env->vpos, env->hpos, s); + } + } +} + +/* + * devtag - handles device troff tags sent from the `troff'. + * These include the troff state machine tags: + * .br, .sp, .in, .tl, .ll etc + * + * (see man 5 grohtml_tags). + */ + +void html_printer::devtag (char *s, const environment *env, char type) +{ + if (type != 'p') + return; + + if (s != 0) { + flush_sbuf(); + if (env->fontno >= 0) { + style sty(get_font_from_index(env->fontno), env->size, env->height, + env->slant, env->fontno, *env->col); + sbuf_style = sty; + } + + if (strncmp(s, "devtag:", strlen("devtag:")) == 0) { int r=font::res; /* resolution of the device */ page_contents->add_tag(&sbuf_style, string(s), @@ -3722,6 +4932,26 @@ void html_printer::special(char *s, const environment *env, char type) } } + +/* + * taken from number.cpp in src/roff/troff, [hunits::hunits(units x)] + */ + +int html_printer::round_width(int x) +{ + int r = font::hor; + int n; + + // don't depend on the rounding direction for division of negative integers + if (r == 1) + n = x; + else + n = (x < 0 + ? -((-x + r/2 - 1)/r) + : (x + r/2 - 1)/r); + return n * r; +} + int main(int argc, char **argv) { program_name = argv[0]; @@ -3733,58 +4963,69 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "a:g:o:i:I:D:F:vbdhlrnp", long_options, NULL)) + while ((c = getopt_long(argc, argv, "a:bdD:F:g:hi:I:j:lno:prs:S:v", + long_options, NULL)) != EOF) switch(c) { - case 'v': - printf("GNU post-grohtml (groff) version %s\n", Version_string); - exit(0); - break; case 'a': /* text antialiasing bits - handled by pre-html */ break; - case 'g': - /* graphic antialiasing bits - handled by pre-html */ - break; case 'b': // set background color to white default_background = new color; default_background->set_gray(color::MAX_COLOR_VAL); break; - case 'F': - font::command_line_font_dir(optarg); + case 'd': + /* handled by pre-html */ break; - case 'l': - auto_links = FALSE; + case 'D': + /* handled by pre-html */ break; - case 'r': - auto_rule = FALSE; + case 'F': + font::command_line_font_dir(optarg); break; - case 'd': - /* handled by pre-html */ + case 'g': + /* graphic antialiasing bits - handled by pre-html */ break; case 'h': /* do not use the Hn headings of html, but manufacture our own */ manufacture_headings = TRUE; break; - case 'o': - /* handled by pre-html */ - break; - case 'p': - /* handled by pre-html */ - break; case 'i': /* handled by pre-html */ break; case 'I': /* handled by pre-html */ break; - case 'D': - /* handled by pre-html */ + case 'j': + multiple_files = TRUE; + job_name = optarg; + break; + case 'l': + auto_links = FALSE; break; case 'n': simple_anchors = TRUE; break; + case 'o': + /* handled by pre-html */ + break; + case 'p': + /* handled by pre-html */ + break; + case 'r': + auto_rule = FALSE; + break; + case 's': + base_point_size = atoi(optarg); + break; + case 'S': + split_level = atoi(optarg) + 1; + break; + case 'v': + printf("GNU post-grohtml (groff) version %s\n", Version_string); + exit(0); + break; case CHAR_MAX + 1: // --help usage(stdout); exit(0); diff --git a/contrib/groff/src/devices/grolbp/lbp.cpp b/contrib/groff/src/devices/grolbp/lbp.cpp index b34a1e0..081ab99 100644 --- a/contrib/groff/src/devices/grolbp/lbp.cpp +++ b/contrib/groff/src/devices/grolbp/lbp.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 1994, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1994, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by Francisco Andrés Verdú <pandres@dragonet.es> with many ideas taken from the other groff drivers. @@ -18,16 +19,13 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ /* TODO - Add X command to include bitmaps */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif #include "driver.h" #include "lbp.h" @@ -93,21 +91,6 @@ private: int paperwidth; }; -// Compatibility section. -// -// Here we define some functions not present in some of the targets -// platforms -#ifndef HAVE_STRSEP -// Solaris 8 doesn't have the strsep function -static char *strsep(char **pcadena, const char *delim) -{ - char *p; - p = strtok(*pcadena, delim); - *pcadena = strtok(NULL, delim); - return p; -} -#endif - lbp_font::lbp_font(const char *nm) : font(nm) { @@ -231,7 +214,7 @@ inline void lbp_printer::set_line_thickness(int size,const environment *env) /* fprintf(stderr, "thickness: %d == %d, size %d, %d \n", size, line_thickness, env->size,req_linethickness); */ return; -}; // lbp_printer::set_line_thickness +} // lbp_printer::set_line_thickness void lbp_printer::begin_page(int) { @@ -294,10 +277,10 @@ char *lbp_printer::font_name(const lbp_font *f, const int siz) return bfont_name; } -void lbp_printer::set_char(int index, font *f, const environment *env, +void lbp_printer::set_char(int idx, font *f, const environment *env, int w, const char *) { - int code = f->get_code(index); + int code = f->get_code(idx); unsigned char ch = code & 0xff; unsigned short symbol_set = code >> 8; if (f != cur_font) { @@ -441,9 +424,9 @@ void lbp_printer::draw(int code, int *p, int np, const environment *env) if (np != 1 && np != 2) { error("0 or 1 argument required for thickness"); break; - }; + } set_line_thickness(p[0],env); - }; + } break; case 'l': // Line if (np != 2) { @@ -663,12 +646,15 @@ int main(int argc, char **argv) int c = 0; int option_index = 0; while (c >= 0) { - c = getopt_long (argc, argv, "F:p:lvo:c:hw:", + c = getopt_long (argc, argv, "c:F:hI:lo:p:vw:", long_options, &option_index); switch (c) { case 'F': font::command_line_font_dir(optarg); break; + case 'I': + // ignore include path arguments + break; case 'p': { const char *s; @@ -694,7 +680,7 @@ int main(int argc, char **argv) orientation = 1; else error("unknown orientation '%1'", optarg); - }; + } break; case 'c': { diff --git a/contrib/groff/src/devices/grolbp/lbp.h b/contrib/groff/src/devices/grolbp/lbp.h index e669ff2..b3171cf 100644 --- a/contrib/groff/src/devices/grolbp/lbp.h +++ b/contrib/groff/src/devices/grolbp/lbp.h @@ -1,5 +1,6 @@ // -*- C -*- -/* Copyright (C) 1994, 2000, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1994, 2000, 2001, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by Francisco Andrés Verdú <pandres@dragonet.es> groff is free software; you can redistribute it and/or modify it under @@ -14,7 +15,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ /* This file contains a set of utility functions to use canon CAPSL printers * (lbp-4 and lbp-8 series printers) */ @@ -28,14 +29,15 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static FILE *lbpoutput = NULL; static FILE *vdmoutput = NULL; + static inline void lbpinit(FILE *outfile) { lbpoutput = outfile; -}; +} -static inline void +static void lbpprintf(const char *format, ... ) { /* Taken from cjet */ va_list stuff; @@ -43,68 +45,78 @@ lbpprintf(const char *format, ... ) va_start(stuff, format); vfprintf(lbpoutput, format, stuff); va_end(stuff); -}; +} + static inline void lbpputs(const char *data) { fputs(data,lbpoutput); -}; +} + static inline void lbpputc(unsigned char c) { fputc(c,lbpoutput); -}; +} static inline void -lbpsavestatus(int index ) +lbpsavestatus(int idx ) { - fprintf(lbpoutput,"\033[%d%%y",index); -}; + fprintf(lbpoutput,"\033[%d%%y",idx); +} + static inline void -lbprestorestatus(int index ) +lbprestorestatus(int idx ) { - fprintf(lbpoutput,"\033[%d%cz",index ,'%'); -}; + fprintf(lbpoutput,"\033[%d%cz",idx ,'%'); +} + static inline void -lbpsavepos(int index) +lbpsavepos(int idx) { - fprintf(lbpoutput,"\033[1;%d;0x",index); -}; + fprintf(lbpoutput,"\033[1;%d;0x",idx); +} + static inline void -lbprestorepos(int index) +lbprestorepos(int idx) { - fprintf(lbpoutput,"\033[0;%d;0x",index); -}; + fprintf(lbpoutput,"\033[0;%d;0x",idx); +} + static inline void -lbprestoreposx(int index) +lbprestoreposx(int idx) { - fprintf(lbpoutput,"\033[0;%d;1x",index); -}; + fprintf(lbpoutput,"\033[0;%d;1x",idx); +} + static inline void lbpmoverel(int despl, char direction) { fprintf(lbpoutput,"\033[%d%c",despl,direction); -}; +} + static inline void lbplinerel(int width,int despl,char direction ) { fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction); -}; +} + static inline void lbpmoveabs(int x, int y) { fprintf(lbpoutput,"\033[%d;%df",y,x); -}; +} + static inline void lbplineto(int x,int y, int width ) @@ -112,7 +124,8 @@ lbplineto(int x,int y, int width ) fprintf(lbpoutput,"\033[%d;0;9{",width); lbpmoveabs(x,y); fprintf(lbpoutput,"\033[9}\n"); -}; +} + static inline void lbpruleabs(int x, int y, int hsize, int vsize) @@ -121,9 +134,11 @@ lbpruleabs(int x, int y, int hsize, int vsize) fprintf(lbpoutput,"\033[0;9;000s"); lbpmoveabs(x+hsize,y+vsize); fprintf(lbpoutput,"\033[9r"); -}; +} + + +static void vdmprintf(const char *format, ... ); -static inline void vdmprintf(const char *format, ... ); static inline char * vdmnum(int num,char *result) @@ -147,7 +162,8 @@ vdmnum(int num,char *result) *p++ = b3; *p = 0x00; /* End of the resulting string */ return result; -}; +} + static inline void vdmorigin(int newx, int newy) @@ -155,7 +171,7 @@ vdmorigin(int newx, int newy) char nx[4],ny[4]; vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny)); -}; /* vdmorigin */ +} static inline FILE * @@ -170,15 +186,17 @@ vdminit(FILE *vdmfile) vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend)); return vdmoutput; -}; +} + static inline void vdmend() { vdmprintf("}p\x1e"); -}; +} -static inline void + +static void vdmprintf(const char *format, ... ) { /* Taken from cjet */ va_list stuff; @@ -187,7 +205,8 @@ vdmprintf(const char *format, ... ) va_start(stuff, format); vfprintf(vdmoutput, format, stuff); va_end(stuff); -}; +} + static inline void vdmsetfillmode(int pattern,int perimeter, int inverted) @@ -200,7 +219,8 @@ vdmsetfillmode(int pattern,int perimeter, int inverted) vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\ vdmnum(perimeter,perim),vdmnum(0,rot), vdmnum(0,espejo),vdmnum(inverted,inv)); -}; +} + static inline void vdmcircle(int centerx, int centery, int radius) @@ -209,7 +229,8 @@ vdmcircle(int centerx, int centery, int radius) vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\ vdmnum(radius,rad)); -}; +} + static inline void vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen) @@ -220,7 +241,8 @@ vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style, vdmnum(centerx,x),vdmnum(centery,y),\ vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\ vdmnum(style,styl)); -}; +} + static inline void vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\ @@ -228,11 +250,12 @@ vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, i { char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4]; - vdmprintf("}6%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ + vdmprintf("}6%s%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ vdmnum(centerx,x),vdmnum(centery,y),\ vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\ vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl)); -}; +} + static inline void vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation) @@ -242,7 +265,8 @@ vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation) vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\ vdmnum(radiusx,radx),vdmnum(radiusy,rady),\ vdmnum(rotation,rotat)); -}; +} + static inline void vdmsetlinetype(int lintype) @@ -251,7 +275,8 @@ vdmsetlinetype(int lintype) vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact)); -}; +} + static inline void vdmsetlinestyle(int lintype, int pattern,int unionstyle) @@ -265,7 +290,8 @@ vdmsetlinestyle(int lintype, int pattern,int unionstyle) vdmnum(pattern,patt),vdmnum(0,rot), vdmnum(0,espejo),vdmnum(0,in)); vdmprintf("}F%s",vdmnum(unionstyle,rot)); -}; +} + static inline void vdmlinewidth(int width) @@ -273,7 +299,8 @@ vdmlinewidth(int width) char wh[4]; vdmprintf("F1%s\x1e",vdmnum(width,wh)); -}; +} + static inline void vdmrectangle(int origx, int origy,int dstx, int dsty) @@ -282,7 +309,8 @@ vdmrectangle(int origx, int origy,int dstx, int dsty) vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\ vdmnum(origy,ycoord),vdmnum(dsty,sdsty)); -}; /* polyline */ +} + static inline void vdmpolyline(int numpoints, int *points) @@ -296,10 +324,11 @@ vdmpolyline(int numpoints, int *points) for (i = 1; i < numpoints ; i++) { vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); p += 2; - }; /* for */ + } /* for */ vdmprintf("\x1e\n"); -}; /* polyline */ +} + static inline void vdmpolygon(int numpoints, int *points) { @@ -312,10 +341,10 @@ vdmpolygon(int numpoints, int *points) for (i = 1; i < numpoints ; i++) { vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); p += 2; - }; /* for */ + } /* for */ vdmprintf("\x1e\n"); -}; /* vdmpolygon */ +} /************************************************************************ @@ -325,7 +354,7 @@ static inline int vdminited() { return (vdmoutput != NULL); -}; /* vdminited */ +} static inline void @@ -340,7 +369,8 @@ vdmline(int startx, int starty, int sizex, int sizey) vdmpolyline(2,points); -}; +} + /*#define THRESHOLD .05 */ /* inch */ #define THRESHOLD 1 /* points (1/300 inch) */ @@ -348,13 +378,13 @@ static inline void splinerel(double px,double py,int flush) { static int lx = 0 ,ly = 0; - static float pend = 0.0; + static double pend = 0.0; static int dy = 0, despx = 0, despy = 0, sigpend = 0; - int dxnew ,dynew, sg; + int dxnew = 0, dynew = 0, sg; char xcoord[4],ycoord[4]; - float npend ; + double npend ; - if (flush == -1) {lx = (int)px; ly = (int)py; return;}; + if (flush == -1) {lx = (int)px; ly = (int)py; return;} if (flush == 0) { dxnew = (int)px -lx; @@ -366,7 +396,7 @@ splinerel(double px,double py,int flush) despx = dxnew; if ((sg == sigpend) && (dy == 0)){ return; - }; + } dy = 0; } else { @@ -377,9 +407,9 @@ splinerel(double px,double py,int flush) else { sigpend = sg; pend = npend; - }; /* else (( npend == pend) && ... */ - }; /* else (if (dynew == 0)) */ - }; /* if (!flush ) */ + } /* else (( npend == pend) && ... */ + } /* else (if (dynew == 0)) */ + } /* if (!flush ) */ /* if we've changed direction we must draw the line */ /* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/ @@ -390,7 +420,7 @@ splinerel(double px,double py,int flush) if (flush) { dxnew = dy = despx = despy = 0; return; - }; /* if (flush) */ + } /* if (flush) */ dxnew -= despx; dynew -= despy; if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\ @@ -401,111 +431,116 @@ splinerel(double px,double py,int flush) lx = (int)px; ly = (int)py; dxnew = dy = despx = despy = 0; -}; /* splinerel */ +} + /********************************************************************** * The following code to draw splines is adapted from the transfig package */ static void -quadratic_spline(double a1,double b1, double a2, double b2, \ - double a3, double b3, double a4, double b4) -{ - double x1, y1, x4, y4; - double xmid, ymid; - - x1 = a1; y1 = b1; - x4 = a4; y4 = b4; - xmid = (a2 + a3)/2.0; - ymid = (b2 + b3)/2.0; - if ((fabs(x1 - xmid) < THRESHOLD) && (fabs(y1 - ymid) < THRESHOLD)) { - splinerel(xmid,ymid,0); -/* fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);*/ +quadratic_spline(double a_1, double b_1, double a_2, double b_2, \ + double a_3, double b_3, double a_4, double b_4) +{ + double x_1, y_1, x_4, y_4; + double x_mid, y_mid; + + x_1 = a_1; y_1 = b_1; + x_4 = a_4; y_4 = b_4; + x_mid = (a_2 + a_3)/2.0; + y_mid = (b_2 + b_3)/2.0; + if ((fabs(x_1 - x_mid) < THRESHOLD) + && (fabs(y_1 - y_mid) < THRESHOLD)) { + splinerel(x_mid, y_mid, 0); +/* fprintf(tfp, "PA%.4f,%.4f;\n", x_mid, y_mid);*/ } else { - quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0), - ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid); - } + quadratic_spline(x_1, y_1, ((x_1+a_2)/2.0), ((y_1+b_2)/2.0), + ((3.0*a_2+a_3)/4.0), ((3.0*b_2+b_3)/4.0), x_mid, y_mid); + } - if ((fabs(xmid - x4) < THRESHOLD) && (fabs(ymid - y4) < THRESHOLD)) { - splinerel(x4,y4,0); -/* fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);*/ + if ((fabs(x_mid - x_4) < THRESHOLD) + && (fabs(y_mid - y_4) < THRESHOLD)) { + splinerel(x_4, y_4, 0); +/* fprintf(tfp, "PA%.4f,%.4f;\n", x_4, y_4);*/ } else { - quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0), - ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4); - }; -}; /* quadratic_spline */ + quadratic_spline(x_mid, y_mid, + ((a_2+3.0*a_3)/4.0), ((b_2+3.0*b_3)/4.0), + ((a_3+x_4)/2.0), ((b_3+y_4)/2.0), x_4, y_4); + } +} + #define XCOORD(i) numbers[(2*i)] #define YCOORD(i) numbers[(2*i)+1] static void -vdmspline(int numpoints, int ox,int oy, int *numbers) +vdmspline(int numpoints, int o_x, int o_y, int *numbers) { - double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4; - double x1, y1, x2, y2; + double cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4; + double x_1, y_1, x_2, y_2; char xcoord[4],ycoord[4]; int i; /*p = s->points; - x1 = p->x/ppi;*/ - x1 = ox; - y1 = oy; + x_1 = p->x/ppi;*/ + x_1 = o_x; + y_1 = o_y; /* p = p->next; - x2 = p->x/ppi; - y2 = p->y/ppi;*/ - x2 = ox + XCOORD(0); - y2 = oy + YCOORD(0); - cx1 = (x1 + x2)/2.0; - cy1 = (y1 + y2)/2.0; - cx2 = (x1 + 3.0*x2)/4.0; - cy2 = (y1 + 3.0*y2)/4.0; - -/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x1,(int)y1);*/ - vdmprintf("1%s%s",vdmnum((int)x1,xcoord),vdmnum((int)y1,ycoord)); - splinerel(x1,y1,-1); - splinerel(cx1,cy1,0); + x_2 = p->x/ppi; + y_2 = p->y/ppi;*/ + x_2 = o_x + XCOORD(0); + y_2 = o_y + YCOORD(0); + cx_1 = (x_1 + x_2)/2.0; + cy_1 = (y_1 + y_2)/2.0; + cx_2 = (x_1 + 3.0*x_2)/4.0; + cy_2 = (y_1 + 3.0*y_2)/4.0; + +/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x_1,(int)y_1);*/ + vdmprintf("1%s%s",vdmnum((int)x_1,xcoord),vdmnum((int)y_1,ycoord)); + splinerel(x_1,y_1,-1); + splinerel(cx_1,cy_1,0); /* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n", - x1, y1, cx1, cy1);*/ + x_1, y_1, cx_1, cy_1);*/ /*for (p = p->next; p != NULL; p = p->next) {*/ for (i = 1; i < (numpoints); i++) { - x1 = x2; - y1 = y2; -/* x2 = p->x/ppi; - y2 = p->y/ppi;*/ - x2 = x1 + XCOORD(i); - y2 = y1 + YCOORD(i); - cx3 = (3.0*x1 + x2)/4.0; - cy3 = (3.0*y1 + y2)/4.0; - cx4 = (x1 + x2)/2.0; - cy4 = (y1 + y2)/2.0; - /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x1,(int)(y1),(int)x2,(int)y2);*/ - quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4); - cx1 = cx4; - cy1 = cy4; - cx2 = (x1 + 3.0*x2)/4.0; - cy2 = (y1 + 3.0*y2)/4.0; - } - x1 = x2; - y1 = y2; -/* p = s->points->next; - x2 = p->x/ppi; - y2 = p->y/ppi;*/ - x2 = ox + XCOORD(0); - y2 = oy + YCOORD(0); - cx3 = (3.0*x1 + x2)/4.0; - cy3 = (3.0*y1 + y2)/4.0; - cx4 = (x1 + x2)/2.0; - cy4 = (y1 + y2)/2.0; - splinerel(x1,y1,0); - splinerel(x1,y1,1); - /*vdmprintf("%s%s",vdmnum((int)(x1-lx),xcoord),\ - vdmnum((int)(y1-ly),ycoord));*/ + x_1 = x_2; + y_1 = y_2; +/* x_2 = p->x/ppi; + y_2 = p->y/ppi;*/ + x_2 = x_1 + XCOORD(i); + y_2 = y_1 + YCOORD(i); + cx_3 = (3.0*x_1 + x_2)/4.0; + cy_3 = (3.0*y_1 + y_2)/4.0; + cx_4 = (x_1 + x_2)/2.0; + cy_4 = (y_1 + y_2)/2.0; + /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x_1,(int)(y_1),(int)x_2,(int)y_2);*/ + quadratic_spline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4); + cx_1 = cx_4; + cy_1 = cy_4; + cx_2 = (x_1 + 3.0*x_2)/4.0; + cy_2 = (y_1 + 3.0*y_2)/4.0; + } + x_1 = x_2; + y_1 = y_2; +/* p = s->points->next; + x_2 = p->x/ppi; + y_2 = p->y/ppi;*/ + x_2 = o_x + XCOORD(0); + y_2 = o_y + YCOORD(0); + cx_3 = (3.0*x_1 + x_2)/4.0; + cy_3 = (3.0*y_1 + y_2)/4.0; + cx_4 = (x_1 + x_2)/2.0; + cy_4 = (y_1 + y_2)/2.0; + splinerel(x_1, y_1, 0); + splinerel(x_1, y_1, 1); + /*vdmprintf("%s%s",vdmnum((int)(x_1-lx),xcoord),\ + vdmnum((int)(y_1-ly),ycoord));*/ vdmprintf("\x1e\n"); -/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);*/ +/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x_1, y_1);*/ -}; /* vdmspline */ +} #endif diff --git a/contrib/groff/src/devices/grolj4/Makefile.sub b/contrib/groff/src/devices/grolj4/Makefile.sub index 9899b7a..1216a49 100644 --- a/contrib/groff/src/devices/grolj4/Makefile.sub +++ b/contrib/groff/src/devices/grolj4/Makefile.sub @@ -1,5 +1,6 @@ PROG=grolj4$(EXEEXT) MAN1=grolj4.n +MAN5=lj4_font.n XLIBS=$(LIBDRIVER) $(LIBGROFF) MLIB=$(LIBM) OBJS=lj4.$(OBJEXT) diff --git a/contrib/groff/src/devices/grolj4/grolj4.man b/contrib/groff/src/devices/grolj4/grolj4.man index 267c621..260a619 100644 --- a/contrib/groff/src/devices/grolj4/grolj4.man +++ b/contrib/groff/src/devices/grolj4/grolj4.man @@ -1,5 +1,5 @@ .ig -Copyright (C) 1994-2000, 2001, 2002 Free Software Foundation, Inc. +Copyright (C) 1994-2000, 2001, 2002, 2004 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -140,6 +140,7 @@ Macros for use with .SH BUGS Small dots. .SH "SEE ALSO" +.BR lj4_font (@MAN5EXT@), .BR groff (@MAN1EXT@), .BR @g@troff (@MAN1EXT@), .BR groff_out (@MAN5EXT@), diff --git a/contrib/groff/src/devices/grolj4/lj4.cpp b/contrib/groff/src/devices/grolj4/lj4.cpp index 1332e19..1284954 100644 --- a/contrib/groff/src/devices/grolj4/lj4.cpp +++ b/contrib/groff/src/devices/grolj4/lj4.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 1994, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1994, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. @@ -16,7 +17,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ /* TODO @@ -277,10 +278,10 @@ int is_unprintable(unsigned char c) return c < 32 && (c == 0 || (7 <= c && c <= 15) || c == 27); } -void lj4_printer::set_char(int index, font *f, const environment *env, +void lj4_printer::set_char(int idx, font *f, const environment *env, int w, const char *) { - int code = f->get_code(index); + int code = f->get_code(idx); unsigned char ch = code & 0xff; unsigned short symbol_set = code >> 8; @@ -611,18 +612,21 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, ":F:p:d:lvw:c:", long_options, NULL)) + while ((c = getopt_long(argc, argv, "c:d:F:I:lp:vw:", long_options, NULL)) != EOF) switch(c) { case 'l': landscape_flag = 1; break; + case 'I': + // ignore include search path + break; case ':': if (optopt == 'd') { fprintf(stderr, "duplex assumed to be long-side\n"); duplex_flag = 1; } else - fprintf(stderr, "option -%c requires an operand\n", optopt); + fprintf(stderr, "option -%c requires an argument\n", optopt); fflush(stderr); break; case 'd': @@ -644,11 +648,9 @@ int main(int argc, char **argv) break; } case 'v': - { - printf("GNU grolj4 (groff) version %s\n", Version_string); - exit(0); - break; - } + printf("GNU grolj4 (groff) version %s\n", Version_string); + exit(0); + break; case 'F': font::command_line_font_dir(optarg); break; diff --git a/contrib/groff/src/devices/grolj4/lj4_font.man b/contrib/groff/src/devices/grolj4/lj4_font.man new file mode 100644 index 0000000..e82edff --- /dev/null +++ b/contrib/groff/src/devices/grolj4/lj4_font.man @@ -0,0 +1,167 @@ +.tr ~ +.ig +Copyright (C) 2004 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. +.. +.\" Like TP, but if specified indent is more than half +.\" the current line-length - indent, use the default indent. +.de Tp +.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +.el .TP "\\$1" +.. +.tr ~ +.TH LJ4_FONT @MAN5EXT@ "@MDATE@" "Groff Version @VERSION@" +.\" -------------------------------------------------------------------------- +.SH NAME +.\" -------------------------------------------------------------------------- +lj4_font \- groff fonts for use with devlj4 +.\" -------------------------------------------------------------------------- +.SH DESCRIPTION +.\" -------------------------------------------------------------------------- +Nominally, all Hewlett-Packard LaserJet~4\(enseries and newer printers +have the same internal fonts: 45 scalable fonts and one bitmapped +Lineprinter font. +The scalable fonts are available in sizes between 0.25 point and 999.75 +points, in 0.25-point increments; the Lineprinter font is available only +in 8.5-point size. +.LP +The LaserJet font files included with +.B groff +assume that all printers since the LaserJet~4 are identical. +There are some differences between fonts in the earlier and more recent +printers, however. +The LaserJet~4 printer used Agfa Intellifont technology for 35 of the +internal scalable fonts; the remaining 10 scalable fonts were TrueType. +Beginning with the LaserJet~4000\(enseries printers introduced in 1997, +all scalable internal fonts have been TrueType. +The number of printable glyphs differs slightly between Intellifont and +TrueType fonts (generally, the TrueType fonts include more glyphs), and +there are some minor differences in glyph metrics. +Differences among printer models are described in the +.I "PCL~5 Comparison Guide" +and the +.I "PCL~5 Comparison Guide Addendum" +(for printers introduced since approximately 2001). +.LP +LaserJet printers reference a glyph by a combination of a 256-glyph +symbol set and an index within that symbol set. +Many glyphs appear in more than one symbol set; all combinations of +symbol set and index that reference the same glyph are equivalent. +For each glyph, +.BR hpftodit (@MAN1EXT@) +searches a list of symbol sets, and selects the first set that contains +the glyph. +The printing code generated by +.BR hpftodit (@MAN1EXT@) +is an integer that encodes a numerical value for the symbol set in the +high byte(s), and the index in the low byte. +See +.BR groff_font (@MAN5EXT@) +for a complete description of the font file format; symbol sets are +described in greater detail in the +.IR "PCL~5 Printer Language Technical Reference Manual" . +.LP +Two of the scalable fonts, Symbol and Wingdings, are bound to +256-glyph symbol sets; the remaining scalable fonts, as well as the +Lineprinter font, support numerous symbol sets, sufficient to enable +printing of more than 600 glyphs. +.LP +The metrics generated by +.BR hpftodit (@MAN1EXT@) +assume that the DESC file contains values of 1200 for res and 6350 for +unitwidth (or any combination (e.g., 2400 and 3175) for which +res~\(mu~unitwidth~=~7\|620\|000). +Although HP PCL~5 LaserJet printers support an internal resolution of +7200 units per inch, they use a 16-bit signed integer for cursor +positioning; if +.B devlj4 +is to support U.S. ledger paper (11\(sd~\(mu~17\(sd), the maximum usable +resolution is 32\|767~/~17, or 1927, units per inch, which rounds down to +1200 units per inch. +If the largest required paper size is less (e.g., 8.5\(sd~\(mu~11\(sd or +A5), a greater resolution (and lesser unitwidth) can be specified. +.\" -------------------------------------------------------------------------- +.SH LIMITATIONS +.\" -------------------------------------------------------------------------- +Font metrics for Intellifont fonts were provided by Tagged Font Metric +(TFM) files originally developed by Agfa/Compugraphic. +The TFM files provided for these fonts supported 600+ glyphs and +contained extensive lists of kern pairs. +.LP +To accommodate developers who had become accustomed to TFM files, HP also +provided TFM files for the 10 TrueType fonts included in the LaserJet~4. +The TFM files for TrueType fonts generally included less information +than the Intellifont TFMs, supporting fewer glyphs, and in most cases, +providing no kerning information. +By the time the LaserJet~4000 printer was introduced, most +developers had migrated to other means of obtaining font metrics, +and support for new TFM files was very limited. +The TFM files provided for the TrueType fonts in the LaserJet~4000 +support only the Latin 2 (ISO 8859-2) symbol set, and include no kerning +information; consequently, they are of little value for any but the most +rudimentary documents. +.LP +Because the Intellifont TFM files contain considerably more information, +they generally are preferable to the TrueType TFM files even for use +with the TrueType fonts in the newer printers. +The metrics for the TrueType fonts are very close, though not identical, +to those for the earlier Intellifont fonts of the same names. +Although most output using the Intellifont metrics with the newer +printers is quite acceptable, a few glyphs may fail to print as +expected. +The differences in glyph metrics may be particularly noticeable with +composite parentheses, brackets, and braces used by +.BR eqn (@MAN1EXT@) . +A script, located in +.BR @FONTDIR@/devlj4/generate , +can be used to adjust the metrics for these glyphs in the special font S +for use with printers that have all TrueType fonts. +.LP +At the time HP last supported TFM files, only Version 1 of the Unicode +standard was available. +Consequently, many glyphs lacking assigned code points were assigned by +HP to the Private Use Area (PUA). +Later versions of the Unicode standard included code points outside the +PUA for many of these glyphs. +The HP-supplied TrueType TFM files use the PUA assignments; +TFM files generated from more recent TrueType font files require the +later Unicode values to access the same glyphs. +Consequently, two different mapping files may be required: one for the +HP-supplied TFM files, and one for more recent TFM files. +.\" -------------------------------------------------------------------------- +.SH FILES +.\" -------------------------------------------------------------------------- +.Tp \w'\fB@FONTDIR@/devlj4/DESC'u+2n +.B @FONTDIR@/devlj4/DESC +Device description file. +.TP +.BI @FONTDIR@/devlj4/ F +Font description file for font +.IR F . +.\" -------------------------------------------------------------------------- +.SH "SEE ALSO" +.\" -------------------------------------------------------------------------- +.ad 0 +.BR groff (@MAN1EXT@), +.BR groff_diff (@MAN1EXT@), +.BR hpftodit (@MAN1EXT@), +.BR grolj4 (@MAN1EXT@), +.BR groff_font (@MAN5EXT@) +. +.\" Local Variables: +.\" mode: nroff +.\" End: diff --git a/contrib/groff/src/devices/grops/grops.man b/contrib/groff/src/devices/grops/grops.man index e9f8f02..0ff2579 100644 --- a/contrib/groff/src/devices/grops/grops.man +++ b/contrib/groff/src/devices/grops/grops.man @@ -1,5 +1,6 @@ .ig -Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc. +Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -17,6 +18,9 @@ translations approved by the Free Software Foundation instead of in the original English. .. . +.do nr grops_C \n[.C] +.cp 0 +. .mso www.tmac . . @@ -62,6 +66,7 @@ grops \- PostScript driver for groff .OP \-b n .OP \-c n .OP \-F dir +.OP \-I dir .OP \-p papersize .OP \-P prologue .OP \-w n @@ -112,6 +117,15 @@ using the .B \-P option. . +.PP +Note that +.B grops +doesn't produce a valid document structure (conforming to the Document +Structuring Convention) if called with multiple file arguments. +. +To print such concatenated output it is necessary to deactivate DSC +handling in the printing program or previewer. +. . .SH OPTIONS .TP @@ -184,6 +198,9 @@ PostScript command). This was the behaviour of groff version 1.18.1 and earlier; it is needed for older printers which don't understand PostScript LanguageLevel\~2. . +It is also necessary if the output is further processed to get an +encapsulated PS (EPS) file -- see below. +. .IP The default value can be specified by a . @@ -225,6 +242,19 @@ This option allows you to generate documents that can be printed both on letter (8.5\(mu11) paper and on A4 paper without change. . .TP +.BI \-I dir +This option may be used to specify a directory to search for +files on the command line and files named in +.B \eX'ps: import' +and +.B \eX'ps: file' +escapes. +The current directory is always searched first. +This option may be specified more than once; +the directories will be searched in the order specified. +No directory search is performed for files specified using an absolute path. +. +.TP .B \-l Print the document in landscape format. . @@ -754,7 +784,7 @@ commands. .RS .LP For example, -.B gxditview +.B \%gxditview is not able to display a proper .B \[rs](em character because the standard X11 fonts do not provide it; @@ -772,7 +802,7 @@ request . .LP In this case, -.B gxditview +.B \%gxditview will be unable to display the .B \[rs](em character and will draw the line, @@ -783,10 +813,10 @@ will print the character and ignore the line (this code is already in file .B Xps.tmac -which will be loaded if a documented intended for +which will be loaded if a document intended for .B grops is previewed with -.BR gxditview ). +.BR \%gxditview ). .RE . .LP @@ -1002,6 +1032,32 @@ comments) should be used. . . +.SS Encapsulated PostScript +.B grops +itself doesn't emit bounding box information. +. +With the help of GhostScript the following commands will produce an +encapsulated PS file +.B foo.eps +from input file +.BR foo : +. +.IP +.B +groff -P-b16 foo > foo.ps +.br +.B +gs -dNOPAUSE -sDEVICE=bbox -- foo.ps 2> foo.bbox +.br +.B +cat foo.ps | sed \-e '/%%Orientation/rfoo.bbx' > foo.eps +.br +.B +rm foo.bbx +.br +. +. +. .SS TrueType fonts TrueType fonts can be used with .B grops @@ -1103,6 +1159,12 @@ Temporary file. .BR groff_char (@MAN7EXT@), .BR groff_tmac (@MAN5EXT@) . +.PP +.URL "http://\:partners.adobe.com/\:public/\:developer/\:en/\:ps/\:5001.DSC_Spec.pdf" \ + "PostScript Language Document Structuring Conventions Specification" +. +.cp \n[grops_C] +. .\" Local Variables: .\" mode: nroff .\" End: diff --git a/contrib/groff/src/devices/grops/ps.cpp b/contrib/groff/src/devices/grops/ps.cpp index f1c094b..b6a5403 100644 --- a/contrib/groff/src/devices/grops/ps.cpp +++ b/contrib/groff/src/devices/grops/ps.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -17,7 +17,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ /* * PostScript documentation: @@ -42,6 +42,9 @@ extern "C" { extern "C" const char *Version_string; +// search path defaults to the current directory +search_path include_search_path(0, 0, 0, 1); + static int landscape_flag = 0; static int manual_feed_flag = 0; static int ncopies = 1; @@ -326,9 +329,14 @@ ps_output &ps_output::put_fix_number(int i) ps_output &ps_output::put_float(double d) { char buf[128]; - sprintf(buf, "%.3g", d); - int len = strlen(buf); - if (col > 0 && col + len + need_space > max_line_length) { + sprintf(buf, "%.4f", d); + int last = strlen(buf) - 1; + while (buf[last] == '0') + last--; + if (buf[last] == '.') + last--; + buf[++last] = '\0'; + if (col > 0 && col + last + need_space > max_line_length) { putc('\n', fp); col = 0; need_space = 0; @@ -338,7 +346,7 @@ ps_output &ps_output::put_float(double d) col++; } fputs(buf, fp); - col += len; + col += last; need_space = 1; return *this; } @@ -789,7 +797,7 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index) p++; if (*p != '#' && *p != '\0' && (p = strtok(buf, WS)) != 0) { char *q = strtok(0, WS); - int n; + int n = 0; // pacify compiler if (q == 0 || sscanf(q, "%d", &n) != 1 || n < 0 || n >= 256) fatal_with_file_and_line(path, lineno, "bad second field"); vec[n] = new char[strlen(p) + 1]; @@ -1790,7 +1798,7 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "b:c:F:glmp:P:vw:", long_options, NULL)) + while ((c = getopt_long(argc, argv, "b:c:F:gI:lmp:P:vw:", long_options, NULL)) != EOF) switch(c) { case 'b': @@ -1810,6 +1818,9 @@ int main(int argc, char **argv) case 'g': guess_flag = 1; break; + case 'I': + include_search_path.command_line_dir(optarg); + break; case 'l': landscape_flag = 1; break; @@ -1864,6 +1875,7 @@ int main(int argc, char **argv) static void usage(FILE *stream) { fprintf(stream, - "usage: %s [-glmv] [-b n] [-c n] [-w n] [-P prologue] [-F dir] [files ...]\n", +"usage: %s [-glmv] [-b n] [-c n] [-w n] [-I dir] [-P prologue]\n" +" [-F dir] [files ...]\n", program_name); } diff --git a/contrib/groff/src/devices/grops/ps.h b/contrib/groff/src/devices/grops/ps.h index a4b4169..fabf47d 100644 --- a/contrib/groff/src/devices/grops/ps.h +++ b/contrib/groff/src/devices/grops/ps.h @@ -17,7 +17,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ class ps_output { public: @@ -123,3 +123,7 @@ enum { USE_PS_ADOBE_2_0 = 010, NO_PAPERSIZE = 020 }; + +#include "searchpath.h" + +extern search_path include_search_path; diff --git a/contrib/groff/src/devices/grops/psrm.cpp b/contrib/groff/src/devices/grops/psrm.cpp index ab94ffe..f1894f5 100644 --- a/contrib/groff/src/devices/grops/psrm.cpp +++ b/contrib/groff/src/devices/grops/psrm.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -17,7 +17,7 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "stringclass.h" @@ -347,7 +347,7 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp, r->flags |= resource::BUSY; if (rank > r->rank) r->rank = rank; - char *path; + char *path = 0; // pacify compiler FILE *fp = 0; if (r->filename != 0) { if (r->type == RESOURCE_FONT) { @@ -360,7 +360,7 @@ void resource_manager::supply_resource(resource *r, int rank, FILE *outfp, } else { errno = 0; - fp = fopen(r->filename, "r"); + fp = include_search_path.open_file_cautious(r->filename); if (!fp) { error("can't open `%1': %2", r->filename, strerror(errno)); a_delete r->filename; diff --git a/contrib/groff/src/devices/grotty/grotty.man b/contrib/groff/src/devices/grotty/grotty.man index 198ca47..6c56457 100644 --- a/contrib/groff/src/devices/grotty/grotty.man +++ b/contrib/groff/src/devices/grotty/grotty.man @@ -1,5 +1,5 @@ .ig -Copyright (C) 1989-2000, 2001, 2002 Free Software Foundation, Inc. +Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -17,6 +17,8 @@ translations approved by the Free Software Foundation instead of in the original English. .. . +.do nr grotty_C \n[.C] +.cp 0 . .TH GROTTY @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" .SH NAME @@ -414,6 +416,8 @@ cell, affecting all subsequent operations. .BR man (1), .BR less (1) . +.cp \n[grotty_C] +. .\" Local Variables: .\" mode: nroff .\" End: diff --git a/contrib/groff/src/devices/grotty/tty.cpp b/contrib/groff/src/devices/grotty/tty.cpp index 812ebf8..a959461 100644 --- a/contrib/groff/src/devices/grotty/tty.cpp +++ b/contrib/groff/src/devices/grotty/tty.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. @@ -16,14 +17,16 @@ for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "device.h" #include "ptable.h" -declare_ptable(char) -implement_ptable(char) +typedef signed char schar; + +declare_ptable(schar) +implement_ptable(schar) extern "C" const char *Version_string; @@ -41,25 +44,38 @@ extern "C" const char *Version_string; static int horizontal_tab_flag = 0; static int form_feed_flag = 0; -static int bold_flag = 1; -static int underline_flag = 1; +static int bold_flag_option = 1; +static int bold_flag; +static int underline_flag_option = 1; +static int underline_flag; static int overstrike_flag = 1; static int draw_flag = 1; -static int italic_flag = 0; -static int reverse_flag = 0; +static int italic_flag_option = 0; +static int italic_flag; +static int reverse_flag_option = 0; +static int reverse_flag; static int old_drawing_scheme = 0; +static void update_options(); +static void usage(FILE *stream); + +static int hline_char = '-'; +static int vline_char = '|'; + enum { UNDERLINE_MODE = 0x01, BOLD_MODE = 0x02, VDRAW_MODE = 0x04, HDRAW_MODE = 0x08, CU_MODE = 0x10, - COLOR_CHANGE = 0x20 + COLOR_CHANGE = 0x20, + START_LINE = 0x40, + END_LINE = 0x80 }; // Mode to use for bold-underlining. -static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; +static unsigned char bold_underline_mode_option = BOLD_MODE|UNDERLINE_MODE; +static unsigned char bold_underline_mode; #ifndef IS_EBCDIC_HOST #define CSI "\033[" @@ -77,7 +93,7 @@ static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; #define SGR_REVERSE CSI "7m" #define SGR_NO_REVERSE CSI "27m" // many terminals can't handle `CSI 39 m' and `CSI 49 m' to reset -// the foreground and bachground color, respectively; thus we use +// the foreground and background color, respectively; we thus use // `CSI 0 m' exclusively #define SGR_DEFAULT CSI "0m" @@ -105,13 +121,14 @@ tty_font *tty_font::load_tty_font(const char *s) const char *num = f->get_internal_name(); long n; if (num != 0 && (n = strtol(num, 0, 0)) != 0) - f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE)); + f->mode = (unsigned char)(n & (BOLD_MODE|UNDERLINE_MODE)); if (!underline_flag) f->mode &= ~UNDERLINE_MODE; if (!bold_flag) f->mode &= ~BOLD_MODE; if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE)) - f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode; + f->mode = (unsigned char)((f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) + | bold_underline_mode); return f; } @@ -138,11 +155,12 @@ class glyph { static glyph *free_list; public: glyph *next; - short hpos; + int w; + int hpos; unsigned int code; unsigned char mode; - char back_color_idx; - char fore_color_idx; + schar back_color_idx; + schar fore_color_idx; void *operator new(size_t); void operator delete(void *); inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); } @@ -181,19 +199,19 @@ class tty_printer : public printer { int nlines; int cached_v; int cached_vpos; - char curr_fore_idx; - char curr_back_idx; + schar curr_fore_idx; + schar curr_back_idx; int is_underline; int is_bold; int cu_flag; - PTABLE(char) tty_colors; - void make_underline(); - void make_bold(unsigned int); - char color_to_idx(color *col); - void add_char(unsigned int, int, int, color *, color *, unsigned char); + PTABLE(schar) tty_colors; + void make_underline(int); + void make_bold(unsigned int, int); + schar color_to_idx(color *col); + void add_char(unsigned int, int, int, int, color *, color *, unsigned char); char *make_rgb_string(unsigned int, unsigned int, unsigned int); - int tty_color(unsigned int, unsigned int, unsigned int, char *, - char = DEFAULT_COLOR_IDX); + int tty_color(unsigned int, unsigned int, unsigned int, schar *, + schar = DEFAULT_COLOR_IDX); public: tty_printer(const char *device); ~tty_printer(); @@ -203,7 +221,7 @@ public: void change_color(const environment * const env); void change_fill_color(const environment * const env); void put_char(unsigned int); - void put_color(char, int); + void put_color(schar, int); void begin_page(int) { } void end_page(int page_length); font *make_font(const char *); @@ -233,14 +251,14 @@ char *tty_printer::make_rgb_string(unsigned int r, int tty_printer::tty_color(unsigned int r, unsigned int g, - unsigned int b, char *idx, char value) + unsigned int b, schar *idx, schar value) { int unknown_color = 0; char *s = make_rgb_string(r, g, b); - char *i = tty_colors.lookup(s); + schar *i = tty_colors.lookup(s); if (!i) { unknown_color = 1; - i = new char[1]; + i = new schar[1]; *i = value; tty_colors.define(s, i); } @@ -249,10 +267,14 @@ int tty_printer::tty_color(unsigned int r, return unknown_color; } -tty_printer::tty_printer(const char *device) : cached_v(0) +tty_printer::tty_printer(const char *dev) : cached_v(0) { - is_utf8 = !strcmp(device, "utf8"); - char dummy; + is_utf8 = !strcmp(dev, "utf8"); + if (is_utf8) { + hline_char = 0x2500; + vline_char = 0x2502; + } + schar dummy; // black, white (void)tty_color(0, 0, 0, &dummy, 0); (void)tty_color(color::MAX_COLOR_VAL, @@ -278,11 +300,18 @@ tty_printer::~tty_printer() a_delete lines; } -void tty_printer::make_underline() +void tty_printer::make_underline(int w) { if (old_drawing_scheme) { - putchar('_'); - putchar('\b'); + if (!w) + warning("can't underline zero-width character"); + else { + int n = w / font::hor; + for (int i = 0; i < n; i++) + putchar('_'); + for (int j = 0; j < n; j++) + putchar('\b'); + } } else { if (!is_underline) { @@ -297,11 +326,17 @@ void tty_printer::make_underline() } } -void tty_printer::make_bold(unsigned int c) +void tty_printer::make_bold(unsigned int c, int w) { if (old_drawing_scheme) { - put_char(c); - putchar('\b'); + if (!w) + warning("can't print zero-width character in bold"); + else { + int n = w / font::hor; + put_char(c); + for (int i = 0; i < n; i++) + putchar('\b'); + } } else { if (!is_bold) @@ -310,13 +345,13 @@ void tty_printer::make_bold(unsigned int c) } } -char tty_printer::color_to_idx(color *col) +schar tty_printer::color_to_idx(color *col) { if (col->is_default()) return DEFAULT_COLOR_IDX; unsigned int r, g, b; col->get_rgb(&r, &g, &b); - char idx; + schar idx; if (tty_color(r, g, b, &idx)) { char *s = col->print_color(); error("Unknown color (%1) mapped to default", s); @@ -328,15 +363,15 @@ char tty_printer::color_to_idx(color *col) void tty_printer::set_char(int i, font *f, const environment *env, int w, const char *) { - if (w != font::hor) - fatal("width of character not equal to horizontal resolution"); - add_char(f->get_code(i), + if (w % font::hor != 0) + fatal("width of character not a multiple of horizontal resolution"); + add_char(f->get_code(i), w, env->hpos, env->vpos, env->col, env->fill, ((tty_font *)f)->get_mode()); } -void tty_printer::add_char(unsigned int c, +void tty_printer::add_char(unsigned int c, int w, int h, int v, color *fore, color *back, unsigned char mode) @@ -377,6 +412,7 @@ void tty_printer::add_char(unsigned int c, cached_vpos = vpos; } glyph *g = new glyph; + g->w = w; g->hpos = hpos; g->code = c; g->fore_color_idx = color_to_idx(fore); @@ -400,7 +436,8 @@ void tty_printer::add_char(unsigned int c, void tty_printer::special(char *arg, const environment *env, char type) { if (type == 'u') { - add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE); + add_char(*arg - '0', 0, env->hpos, env->vpos, env->col, env->fill, + CU_MODE); return; } if (type != 'p') @@ -433,17 +470,18 @@ void tty_printer::special(char *arg, const environment *env, char type) old_drawing_scheme = 1; else old_drawing_scheme = 0; + update_options(); } } void tty_printer::change_color(const environment * const env) { - add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); + add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); } void tty_printer::change_fill_color(const environment * const env) { - add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); + add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); } void tty_printer::draw(int code, int *p, int np, const environment *env) @@ -462,10 +500,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env) v += len; len = -len; } - while (len >= 0) { - add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE); + if (len >= 0 && len <= font::vert) + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE|END_LINE); + else { + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE); len -= font::vert; v += font::vert; + while (len > 0) { + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE|END_LINE); + len -= font::vert; + v += font::vert; + } + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|END_LINE); } } if (p[1] == 0) { @@ -476,10 +526,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env) h += len; len = -len; } - while (len >= 0) { - add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE); + if (len >= 0 && len <= font::hor) + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE|END_LINE); + else { + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE); len -= font::hor; h += font::hor; + while (len > 0) { + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE|END_LINE); + len -= font::hor; + h += font::hor; + } + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|END_LINE); } } } @@ -511,7 +573,7 @@ void tty_printer::put_char(unsigned int wc) putchar(wc); } -void tty_printer::put_color(char color_index, int back) +void tty_printer::put_color(schar color_index, int back) { if (color_index == DEFAULT_COLOR_IDX) { putstring(SGR_DEFAULT); @@ -541,6 +603,20 @@ void tty_printer::put_color(char color_index, int back) } } +// The possible Unicode combinations for crossing characters. +// +// ` ' = 0, ` -' = 4, `- ' = 8, `--' = 12, +// +// ` ' = 0, ` ' = 1, `|' = 2, `|' = 3 +// | | + +static int crossings[4*4] = { + 0x0000, 0x2577, 0x2575, 0x2502, + 0x2576, 0x250C, 0x2514, 0x251C, + 0x2574, 0x2510, 0x2518, 0x2524, + 0x2500, 0x252C, 0x2534, 0x253C +}; + void tty_printer::end_page(int page_length) { if (page_length % font::vert != 0) @@ -588,7 +664,12 @@ void tty_printer::end_page(int page_length) if (nextp && p->hpos == nextp->hpos) { if (p->draw_mode() == HDRAW_MODE && nextp->draw_mode() == VDRAW_MODE) { - nextp->code = '+'; + if (is_utf8) + nextp->code = + crossings[((p->mode & (START_LINE|END_LINE)) >> 4) + + ((nextp->mode & (START_LINE|END_LINE)) >> 6)]; + else + nextp->code = '+'; continue; } if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) { @@ -611,7 +692,7 @@ void tty_printer::end_page(int page_length) if (next_tab_pos > p->hpos) break; if (cu_flag) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -627,7 +708,7 @@ void tty_printer::end_page(int page_length) } for (; hpos < p->hpos; hpos++) { if (cu_flag) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -655,7 +736,7 @@ void tty_printer::end_page(int page_length) continue; } if (p->mode & UNDERLINE_MODE) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -666,7 +747,7 @@ void tty_printer::end_page(int page_length) is_underline = 0; } if (p->mode & BOLD_MODE) - make_bold(p->code); + make_bold(p->code, p->w); else if (!old_drawing_scheme && is_bold) { putstring(SGR_NO_BOLD); is_bold = 0; @@ -682,7 +763,7 @@ void tty_printer::end_page(int page_length) } } put_char(p->code); - hpos++; + hpos += p->w / font::hor; } if (!old_drawing_scheme && (is_bold || is_underline @@ -711,7 +792,23 @@ printer *make_printer() return new tty_printer(device); } -static void usage(FILE *stream); +static void update_options() +{ + if (old_drawing_scheme) { + italic_flag = 0; + reverse_flag = 0; + bold_underline_mode = bold_underline_mode_option; + bold_flag = bold_flag_option; + underline_flag = underline_flag_option; + } + else { + italic_flag = italic_flag_option; + reverse_flag = reverse_flag_option; + bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; + bold_flag = 1; + underline_flag = 1; + } +} int main(int argc, char **argv) { @@ -726,7 +823,7 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "bBcdfF:hioruUv", long_options, NULL)) + while ((c = getopt_long(argc, argv, "bBcdfF:hiI:oruUv", long_options, NULL)) != EOF) switch(c) { case 'v': @@ -735,11 +832,14 @@ int main(int argc, char **argv) break; case 'i': // Use italic font instead of underlining. - italic_flag = 1; + italic_flag_option = 1; + break; + case 'I': + // ignore include search path break; case 'b': // Do not embolden by overstriking. - bold_flag = 0; + bold_flag_option = 0; break; case 'c': // Use old scheme for emboldening and underline. @@ -747,7 +847,7 @@ int main(int argc, char **argv) break; case 'u': // Do not underline. - underline_flag = 0; + underline_flag_option = 0; break; case 'o': // Do not overstrike (other than emboldening and underlining). @@ -755,15 +855,15 @@ int main(int argc, char **argv) break; case 'r': // Use reverse mode instead of underlining. - reverse_flag = 1; + reverse_flag_option = 1; break; case 'B': // Do bold-underlining as bold. - bold_underline_mode = BOLD_MODE; + bold_underline_mode_option = BOLD_MODE; break; case 'U': // Do bold-underlining as underlining. - bold_underline_mode = UNDERLINE_MODE; + bold_underline_mode_option = UNDERLINE_MODE; break; case 'h': // Use horizontal tabs. @@ -790,15 +890,7 @@ int main(int argc, char **argv) default: assert(0); } - if (old_drawing_scheme) { - italic_flag = 0; - reverse_flag = 0; - } - else { - bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; - bold_flag = 1; - underline_flag = 1; - } + update_options(); if (optind >= argc) do_file("-"); else { diff --git a/contrib/groff/src/devices/xditview/ChangeLog b/contrib/groff/src/devices/xditview/ChangeLog new file mode 100644 index 0000000..41ea31c --- /dev/null +++ b/contrib/groff/src/devices/xditview/ChangeLog @@ -0,0 +1,542 @@ +2004-05-29 Werner LEMBERG <wl@gnu.org> + + gxditview and xtotroff have been integrated into the normal groff + directory structure; future changes are logged in the main + ChangeLog file. + +2004-05-13 Werner LEMBERG <wl@gnu.org> + +Version 1.19.1 released +======================= + +2004-04-17 Werner LEMBERG <wl@gnu.org> + + * device.c (scale_round): Round correctly for negative values + (this is the same function as in src/libs/libgroff/font.c). + Found by Paul Eggert. + +2003-11-10 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in: s/@top_srcdir@/@abs_top_srcdir@/, + s/@groff_top_builddir@/@abs_top_builddir@/. + +Version 1.19 released +===================== + +2003-03-03 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in (extraclean): Added gxditview._man. + +2003-01-28 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in (SEP): New variable; set to @PATH_SEPARATOR@. + (GROFF_FONTPATH): Use it. + +2003-01-07 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (Adobe_Symbol_map): Add `sqrt'. + +2003-01-06 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (Adobe_Symbol_map): Add `integral'. + +2002-12-29 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map): Remove `ap' and `eq'. + +2002-12-20 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (Adobe_Symbol_map): Don't include `or'. + * draw.c (AdjustCharDeltas): Apply correction only if nadj > 1. + (DoCharacter): Call FlushCharCache if font size and font number + differ. + Reset `dw->dvi.cache.adjustable' properly. + +2002-12-09 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map): Use `tno' symbol instead of `no'. + +2002-12-01 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in: Use `InstallAppDefaultsLong' instead of + `InstallAppDefaults' to make it work if build directory isn't + $srcdir. + +2002-11-24 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (Adobe_Symbol_map): Add glyph `braceex'. + +2002-11-14 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map): Don't include `or'. + +Version 1.18.1 released +======================= + +2002-09-16 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in (GROFF_LOCALFONTDIR): New variable. + (GROFF_FONTPATH): Use it. + Remove /usr/local/lib/font. + +Version 1.18.0 released +======================= + +2002-06-22 Werner LEMBERG <wl@gnu.org> + + * gxditview.c (main): Handle `-help' and `--help' correctly. + +2002-06-17 Colin Watson <cjwatson@debian.org> + + * Imakefile.in: s/@top_builddir@/@groff_top_builddir@/. + +2002-04-06 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map, Adobe_Symbol_map): Remove all + characters > 0x80. + * parse.c (ParseInput): Ignore `m' command. + (ParseDrawFunction): Don't move for unknown drawing functions. + Don't move for `f' drawing function. + +2002-03-25 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map): Use `t+-', `tmu', and `tdi' symbols + instead of `+-', `mu', and `di', respectively. + +2002-02-23 Werner LEMBERG <wl@gnu.org> + + * DviChar.c (ISO_8859_1_map): Add `mc' symbol. + +2001-09-22 Werner LEMBERG <wl@gnu.org> + + * Imakefile.in: Redefine `ProgramTargetHelper' as + `ProgramTargetHelperNoMan' and add a call to `InstallManPageLong' + to make the `install.man' target work if the build directory isn't + $srcdir. + +Version 1.17.2 released +======================= + +Version 1.17.1 released +======================= + +2001-04-21 Albert Chin-A-Young <china@thewrittenword.com> + + * Imakefile.in: Add support for recent HP architectures. + +Version 1.17 released +===================== + +2001-01-04 Rob Daasch <daasch@ece.pdx.edu> + + * parse.c (ParseInput): Added 'F' to command switch to swallow + filename strings as ignored comments. + +2000-12-02 Werner LEMBERG <wl@gnu.org> + + * device.c (find_file): Remove home directory in search path. + +2000-11-14 Werner LEMBERG <wl@gnu.org> + + * device.c (open_device_file): Remove `path' parameter. + (find_file): Construct font path similar to groff: First the contents + of GROFF_FONT_PATH, then the home directory, and finally the default + font path. + * Imakefile.in: Fix GROFF_DATAPROGRAMDIR and GROFF_FONTPATH. + +2000-10-23 Werner LEMBERG <wl@gnu.org> + + Change installation structure for data files from .../groff/... to + .../groff/<version><revision>/... to be conform with other GNU + programs. + + * Imakefile.in: Implement it. + +Version 1.16.1 released +======================= + +Version 1.16 released +===================== + +2000-05-18 Werner LEMBERG <wl@gnu.org> + + * DviChar.c: Adding `cq' as an alias for "'" in latin-1 map. + +2000-05-03 Werner LEMBERG <wl@gnu.org> + + * DviChar.c: Adding `dq' as an alias for `"' in latin-1 map. + +2000-04-28 Werner LEMBERG <wl@gnu.org> + + * DviChar.c: Replacing `md' glyph name with `pc' in latin-1 map to + make it distinct from the `md' glyph in the symbol font. + +2000-03-03 Werner LEMBERG <wl@gnu.org> + + * Imakefile replaced with Imakefile.in which will be configured by + the main configure script of groff. This will set the correct font + path, and it will make it possible to build xditview in a directory + different from $srcdir. + +2000-03-01 Colin Phipps <crp22@cam.ac.uk> + + * Dvi.c (OpenFile): Use tmpdir() for security reasons. + * xtotroff.c (MapFont): Avoid race while opening file. + +2000-02-06 Werner LEMBERG <wl@gnu.org> + + * Imakefile: Adapted to new directory structure. + + * README: Updated. + +Version 1.15 released +===================== + +1999-12-21 Werner LEMBERG <wl@gnu.org> + + * README: Fixed ftp GNU address. + +1999-12-13 Werner LEMBERG <wl@gnu.org> + + * device.c: Use extern declarations of strtok(), strchr(), and + getenv() only if not defined as macros. + +1999-11-18 Larry Jones <larry.jones@sdrc.com> + + * xditview.c: Add fallback_resources to allow running without + access to the app-defaults file. + + * Imakefile: Added rule to create app-defaults to a C header file. + + * GXditview-ad.h: New file containing fallback default resources. + + * ad2c: New file to do the app-defaults -> C header file + conversion. + +1999-10-27 Larry Jones <larry.jones@sdrc.com> + + * font.c (DisposeFontSizes): If there's a problem loading a font, + xditview will fall-back and use the default font, but it hasn't + checked before unloading fonts which could result in unloading the + default font (possibly multiple times) and then X errors. + +1999-09-13 Werner LEMBERG <wl@gnu.org> + + * Imakefile (extraclean): Added Makefile. + + * xditview.c (main, MakePrompt): Fixing compilation warnings. + + * TODO: Imakefile should be replaced with a configure script. + +1999-09-13 Werner LEMBERG <wl@gnu.org> + + * Makefile: Removed. + +1999-09-12 Werner LEMBERG <wl@gnu.org> + + * Imakefile (GROFF_FONTPATH): Another addition. + + * device.c (FONTPATH): Update to match current groff version. + +1999-09-11 Larry Jones <larry.jones@sdrc.com> + + * Imakefile (GROFF_LIBDIR, GROFF_FONTPATH): Update to match + current groff version. + + * Dvi.c (Realize, Destroy), DviP.h, draw.c (setFillGC), gray*.bm: + Allow 8 levels of gray rather than just 1. + + * draw.c (DrawFilledCircle, DrawFilledEllipse, DrawFilledPolygon): + Draw outlines to prevent gaps between abutting figures. + +1999-05-27 Werner LEMBERG <wl@gnu.org> + + * xtotroff.c (usage): Fixed typo. + +Mon Sep 11 10:40:33 1995 James Clark <jjc@jclark.com> + + * device.c (INT_MIN, INT_MAX): Don't define if already defined. + +Mon Aug 8 11:14:11 1994 James Clark (jjc@jclark.com) + + * DviChar.c (Adobe_Symbol_map): Use \(nb for notsubset. + +Tue Apr 19 04:41:16 1994 James Clark (jjc@jclark.com) + + * Dvi.c (resources): Change default for background and foreground + to "XtDefaultBackground" and "XtDefaultForeground". + +Sat Feb 12 10:38:47 1994 James Clark (jjc@jclark.com) + + * DviChar.c (Adobe_Symbol_map): Rename radicalex to rn. + +Thu May 27 20:30:12 1993 James Clark (jjc@jclark.com) + + * device.c (isascii): Define if necessary. + (canonicalize_name): Cast argument to isdigit() to unsigned char. + +Thu Apr 29 18:36:57 1993 James Clark (jjc at jclark.com) + + * xditview.c: Include <X11/Xos.h>. + (NewFile): Don't declare rindex(). Use strrchr() rather than + rindex(). + +Tue Mar 30 15:12:09 1993 James Clark (jjc at jclark) + + * draw.c (charExists): Check that fi->per_char is not NULL. + +Sat Dec 12 17:42:40 1992 James Clark (jjc at jclark) + + * Dvi.c (SetGeometry): Cast XtMakeGeometryRequest arguments. + + * draw.c (DrawPolygon, DrawFilledPolygon): Cast Xtfree argument. + + * font.c (DisposeFontSizes): Add declaration. + + * draw.c (FakeCharacter): Add declaration. + +Wed Oct 28 13:24:00 1992 James Clark (jjc at jclark) + + * Imakefile (install.dev): Deleted. + (fonts): New target. + +Mon Oct 12 10:50:44 1992 James Clark (jjc at jclark) + + * Imakefile (install.dev): Say when we're installing devX*-12. + + * Imakefile (install.dev): Depends on DESC and FontMap. + +Thu Oct 1 20:03:45 1992 James Clark (jjc at jclark) + + * xditview.c (Syntax): Mention -filename option. + +Sat Aug 15 12:56:39 1992 James Clark (jjc at jclark) + + * GXditview.ad: Bind space and return to NextPage. Bind backspace + and delete to previous page. + + * DviChar.c (Adobe_Symbol_map): Add `an'. + + * DviChar.c (Adobe_Symbol_map): Add arrowvertex, arrowverttp, and + arrowvertbt. + +Mon Aug 10 11:54:27 1992 James Clark (jjc at jclark) + + * FontMap: Add m/p fields to the fonts names. + +Sat Aug 8 12:00:28 1992 James Clark (jjc at jclark) + + * DESC: Leave font positions 5-9 blank. + +Tue Jul 28 11:37:05 1992 James Clark (jjc at jclark) + + * Imakefile: Don't use gendef. Pass definition of FONTPATH using + DEFINES. + (path.h): Deleted. + (device.c): Don't include path.h. Provide default definition of + FONTPATH. + +Mon Jul 6 14:06:53 1992 James Clark (jjc at jclark) + + * Imakefile: Don't install tmac.X and tmac.Xps. + * tmac.X, tmac.Xps: Moved to ../macros. + + * Imakefile: Don't install eqnchar. + * eqnchar: Deleted. + +Sun Jun 14 12:55:02 1992 James Clark (jjc@jclark) + + * tmac.Xps: Handle OE, oe, lq, rq. + * draw.c (FakeCharacter): Don't handle these. + + * draw.c (FakeCharacter): Don't handle f/. + +Mon Jun 8 11:46:37 1992 James Clark (jjc@jclark) + + * tmac.X: Translate char160 to space. + +Sun Jun 7 14:39:53 1992 James Clark (jjc@jclark) + + * tmac.X: Do `mso tmac.psic' before restoring compatibility mode. + + * tmac.X: Add \(OE, \(oe, \(ah, \(ao, \(ho. + + * tmac.Xps: Make it work in compatibility mode. + Redo existing character definitions with .Xps-char. + Add more character definitions. + (Xps-char): New macro. + +Sat Jun 6 21:46:03 1992 James Clark (jjc@jclark) + + * DviChar.c (Adobe_Symbol_map): Add +h, +f, +p, Fn, lz. + * tmac.X: Add \(bq, \(Bq, \(aq. + * tmac.Xps: Handle \(aq, \(bq, \(Bq, \(Fn. + +Wed Jun 3 11:11:15 1992 James Clark (jjc@jclark) + + * DviChar.c (Adobe_Symbol_map): Add wp. + +Tue Apr 21 09:21:59 1992 James Clark (jjc at jclark) + + * GXditview.ad: Bind n, p, q keys to NextPage, PreviousPage and + Quit actions. + + * xditview.c (RerasterizeAction): New function. + (xditview_actions): Add RerasterizeAction. + * GXditview.ad: Bind r key to Rerasterize action. + +Fri Apr 17 08:25:36 1992 James Clark (jjc at jclark) + + * xditview.c: Add -filename option. + (main): Copy any -filename argument into current_file_name. + +Mon Mar 16 10:21:58 1992 James Clark (jjc at jclark) + + * tmac.X: Load tmac.pspic. + +Sun Mar 8 11:27:19 1992 James Clark (jjc at jclark) + + * Lex.c (GetLine, GetWord, GetNumber): Rewrite. + +Sat Oct 12 22:58:52 1991 James Clark (jjc at jclark) + + * Dvi.c (SetDevice): If the size change request is refused but a + larger geometry is offered, request that. + +Wed Oct 9 12:27:48 1991 James Clark (jjc at jclark) + + * font.c (InstallFontSizes): Ignore FontNameAverageWidth component. + + * Dvi.c (default_font_map): Add `adobe' to font names to avoid + ambiguity. + + * FontMap: New file. + * FontMap.X100, FontMap.X75: Deleted. + * xtotroff.c (main, usage): Add -s and -r options. + (MapFont): Change the font pattern to have the selected resolution and + size. + * Imakefile (install.dev): Use FontMap and supply appropriate -s + and -r options. + + * xtotroff.c (MapFont): Check for ambiguity by comparing canonicalized + font names. + + * DviP.h (DviFontList): Add initialized and scalable members. + (font.c): Add support for scalable fonts based on R5 xditview. + + * DviChar.c: Use xmalloc rather than malloc. + * xditview.c (xmalloc): New function. + * xtotroff.c (xmalloc): New function. + * other files: Use XtMalloc and XtFree instead of malloc and free. + +Thu Aug 29 20:15:31 1991 James Clark (jjc at jclark) + + * draw.c (setGC): Do multiplication in floating point to avoid + overflow. + +Tue Aug 13 12:04:41 1991 James Clark (jjc at jclark) + + * draw.c (FakeCharacter): Remove casts in defintion of pack2. + +Tue Jul 30 11:42:39 1991 James Clark (jjc at jclark) + + * tmac.Xps: New file. + * Imakefile (install): Install tmac.Xps. + +Tue Jul 2 09:31:37 1991 James Clark (jjc at jclark) + + * xtotroff.c (main): Pass argv[0] to usage(). + +Sun Jun 30 12:34:06 1991 James Clark (jjc at jclark) + + * xtotroff.c (MapFont): Handle the case where XLoadQueryFont + returns NULL. + +Sat Jun 29 12:32:52 1991 James Clark (jjc at jclark) + + * Imakefile: Use ../gendef to generate path.h. + +Sun Jun 16 13:26:34 1991 James Clark (jjc at jclark) + + * Imakefile (depend.o): Change to device.o. + +Sun Jun 2 12:17:56 1991 James Clark (jjc at jclark) + + * Imakefile: Remove spaces from the beginning of variable + assignment lines. + +Sun May 26 14:14:01 1991 James Clark (jjc at jclark) + + * xditview.c (Syntax): Update. + + * Dvi.c (DviSaveToFile, SaveToFile): New functions. + (FindPage): Check that we're not readingTmp before checking for + end of file of normal input file. + (ClassPartInitialize): New function. + * Dvi.h: Add declaration of DviSaveToFile. + * DviP.h: Add save method to DviClassPart. Declare + InheritSaveToFile. + * xditview.c (DoPrint, Print, PrintAction): New functions. + * xditview.c: Add print menu entry. + * xditview.c: Provide printCommand application resource. + * lex.c: Don't output EOF to temporary file. + + * Dvi.c (QueryGeometry): Check request->request_mode. + + * Dvi.c (SetDevice): New function. + (SetDeviceResolution): Deleted. + + * Dvi.c: Add resolution resource. + * DviP.h: Add definitions of XtNResolution and XtCResolution. + * xditview.c: Add -resolution argument. + * GXditview.ad: Add default for GXditview.height. + * Dvi.c (Initialize, SetDevice): Use default_resolution. + + * Dvi.c: Make MY_HEIGHT and MY_WIDTH use the paperlength and + paperwidth commands in the DESC file. + + * Dvi.c: Add SS font to default font map. + + * draw.c: Rewritten so as not to assume device and display + resolution is the same. + * DviP.h: Include device.h. Add device_font member to DviFontList. + Add adjustable array to DviCharCache. Add text_x_width, + text_device_width, word_flag, device_font, device_font_number, + device, native, device_resolution, display_resolution, + paperlength, paperwidth, scale_factor, sizescale members. + * Dvi.c (Initialize): Initialize new variable used by draw.c. + (Destroy): Call device_destroy. + * font.c (MaxFontPosition): New function. + (LookupFontSizeBySize): Handle sizescale. + (InstallFont): Load the device font. + (ForgetFonts): New function. + (QueryDeviceFont): New function. + * parse.c (ParseInput): Handle t and u commands. Split off + character output into draw.c. + (ParseDeviceControl): Ignore res command. Use the device argument + to the T command. + + * font.c (MapXNameToDviName): Ifdefed out. + + * path.h: New file. + * device.c, device.h: New files. + + * DviChar.c: Add entries for lB, rB, oq, lC, rC, md. + + * INSTALL: New file. + + * libxdvi: Merged into main directory. + * xtotroff.c, xditview.c: Change includes accordingly. + + * devX75, devX100: Merged into main directory. + * xditview.man: Renamed to gxditview.man. + + * Xditview.ad: Renamed to GXditview.ad. + * xditview.c (main): Use class of GXditview rather than xditview. + + * Imakefile: New file. + * Makefile: Deleted. + + * xtotroff.c (MapFont): Unlink output file before opening it. + + * Started separate ChangeLog. diff --git a/contrib/groff/src/devices/xditview/DESC.in b/contrib/groff/src/devices/xditview/DESC.in new file mode 100644 index 0000000..172170c --- /dev/null +++ b/contrib/groff/src/devices/xditview/DESC.in @@ -0,0 +1,9 @@ +styles R I B BI +fonts 6 0 0 0 0 0 S +sizes 8 10 12 14 18 24 0 +res 75 +X11 +hor 1 +vert 1 +unitwidth 10 +postpro gxditview diff --git a/contrib/groff/src/devices/xditview/Dvi.c b/contrib/groff/src/devices/xditview/Dvi.c new file mode 100644 index 0000000..f849fb1 --- /dev/null +++ b/contrib/groff/src/devices/xditview/Dvi.c @@ -0,0 +1,611 @@ +#ifndef SABER +#ifndef lint +static char Xrcsid[] = "$XConsortium: Dvi.c,v 1.9 89/12/10 16:12:25 rws Exp $"; +#endif /* lint */ +#endif /* SABER */ + +/* + * Dvi.c - Dvi display widget + * + */ + +#define XtStrlen(s) ((s) ? strlen(s) : 0) + + /* The following are defined for the reader's convenience. Any + Xt..Field macro in this code just refers to some field in + one of the substructures of the WidgetRec. */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Converters.h> +#include <stdio.h> +#include <ctype.h> +#include "DviP.h" + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +static char default_font_map_1[] = "\ +TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ +TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ +TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ +TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ +CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ +CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ +CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ +CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ +"; +static char default_font_map_2[] = "\ +HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ +HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\ +HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ +HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\ +"; +static char default_font_map_3[] = "\ +NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\ +NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\ +NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\ +NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\ +S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ +SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\ +"; + +#define offset(field) XtOffset(DviWidget, field) + +#define MY_WIDTH(dw) ((int)(dw->dvi.paperwidth * dw->dvi.scale_factor + .5)) +#define MY_HEIGHT(dw) ((int)(dw->dvi.paperlength * dw->dvi.scale_factor + .5)) + +static XtResource resources[] = { + {(String)XtNfontMap, (String)XtCFontMap, (String)XtRString, + sizeof (char *), offset(dvi.font_map_string), + (String)XtRString, NULL /* set in code */}, + {(String)XtNforeground, (String)XtCForeground, (String)XtRPixel, + sizeof (unsigned long), offset(dvi.foreground), + (String)XtRString, (XtPointer)"XtDefaultForeground"}, + {(String)XtNbackground, (String)XtCBackground, (String)XtRPixel, + sizeof (unsigned long), offset(dvi.background), + (String)XtRString, (XtPointer)"XtDefaultBackground"}, + {(String)XtNpageNumber, (String)XtCPageNumber, (String)XtRInt, + sizeof (int), offset(dvi.requested_page), + (String)XtRString, (XtPointer)"1"}, + {(String)XtNlastPageNumber, (String)XtCLastPageNumber, (String)XtRInt, + sizeof (int), offset (dvi.last_page), + (String)XtRString, (XtPointer)"0"}, + {(String)XtNfile, (String)XtCFile, (String)XtRFile, + sizeof (FILE *), offset (dvi.file), + (String)XtRFile, (XtPointer)0}, + {(String)XtNseek, (String)XtCSeek, (String)XtRBoolean, + sizeof (Boolean), offset(dvi.seek), + (String)XtRString, (XtPointer)"false"}, + {(String)XtNfont, (String)XtCFont, (String)XtRFontStruct, + sizeof (XFontStruct *), offset(dvi.default_font), + (String)XtRString, (XtPointer)"xtdefaultfont"}, + {(String)XtNbackingStore, (String)XtCBackingStore, (String)XtRBackingStore, + sizeof (int), offset(dvi.backing_store), + (String)XtRString, (XtPointer)"default"}, + {(String)XtNnoPolyText, (String)XtCNoPolyText, (String)XtRBoolean, + sizeof (Boolean), offset(dvi.noPolyText), + (String)XtRString, (XtPointer)"false"}, + {(String)XtNresolution, (String)XtCResolution, (String)XtRInt, + sizeof(int), offset(dvi.default_resolution), + (String)XtRString, (XtPointer)"75"}, +}; + +#undef offset + +static void ClassInitialize (void); +static void ClassPartInitialize(WidgetClass); +static void Initialize(Widget, Widget, ArgList, Cardinal *); +static void Realize (Widget, XtValueMask *, XSetWindowAttributes *); +static void Destroy (Widget); +static void Redisplay (Widget, XEvent *, Region); +static Boolean SetValues (Widget, Widget, Widget, + ArgList, Cardinal *); +static Boolean SetValuesHook (Widget, ArgList, Cardinal *); +static XtGeometryResult QueryGeometry (Widget, XtWidgetGeometry *, + XtWidgetGeometry *); +static void ShowDvi (DviWidget); +static void CloseFile (DviWidget); +static void OpenFile (DviWidget); +static void FindPage (DviWidget); + +static void SaveToFile (Widget, FILE *); + +/* font.c */ +extern void ParseFontMap(DviWidget); +extern void DestroyFontMap(DviFontMap *); +extern void ForgetFonts(DviWidget); + +/* page.c */ +extern void DestroyFileMap(DviFileMap *); +extern long SearchPagePosition(DviWidget, int); +extern void FileSeek(DviWidget, long); +extern void ForgetPagePositions(DviWidget); + +/* parse.c */ +extern int ParseInput(register DviWidget); + +DviClassRec dviClassRec = { +{ + &widgetClassRec, /* superclass */ + (String)"Dvi", /* class_name */ + sizeof(DviRec), /* size */ + ClassInitialize, /* class_initialize */ + ClassPartInitialize, /* class_part_initialize */ + FALSE, /* class_inited */ + Initialize, /* initialize */ + NULL, /* initialize_hook */ + Realize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* resource_count */ + NULLQUARK, /* xrm_class */ + FALSE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave */ + FALSE, /* visible_interest */ + Destroy, /* destroy */ + NULL, /* resize */ + Redisplay, /* expose */ + SetValues, /* set_values */ + SetValuesHook, /* set_values_hook */ + NULL, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + 0, /* tm_table */ + QueryGeometry, /* query_geometry */ + NULL, /* display_accelerator */ + NULL /* extension */ +},{ + SaveToFile, /* save */ +}, +}; + +WidgetClass dviWidgetClass = (WidgetClass) &dviClassRec; + +static void ClassInitialize (void) +{ + int len1 = strlen(default_font_map_1); + int len2 = strlen(default_font_map_2); + int len3 = strlen(default_font_map_3); + char *dfm = XtMalloc(len1 + len2 + len3 + 1); + char *ptr = dfm; + strcpy(ptr, default_font_map_1); ptr += len1; + strcpy(ptr, default_font_map_2); ptr += len2; + strcpy(ptr, default_font_map_3); + resources[0].default_addr = dfm; + + XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0 ); +} + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +/* ARGSUSED */ +static void Initialize(Widget request, Widget new_wd, + ArgList args, Cardinal *num_args) +{ + DviWidget dw = (DviWidget) new_wd; + + dw->dvi.current_page = 0; + dw->dvi.font_map = 0; + dw->dvi.cache.index = 0; + dw->dvi.text_x_width = 0; + dw->dvi.text_device_width = 0; + dw->dvi.word_flag = 0; + dw->dvi.file = 0; + dw->dvi.tmpFile = 0; + dw->dvi.state = 0; + dw->dvi.readingTmp = 0; + dw->dvi.cache.char_index = 0; + dw->dvi.cache.font_size = -1; + dw->dvi.cache.font_number = -1; + dw->dvi.cache.adjustable[0] = 0; + dw->dvi.file_map = 0; + dw->dvi.fonts = 0; + dw->dvi.seek = False; + dw->dvi.device_resolution = dw->dvi.default_resolution; + dw->dvi.display_resolution = dw->dvi.default_resolution; + dw->dvi.paperlength = dw->dvi.default_resolution*11; + dw->dvi.paperwidth = (dw->dvi.default_resolution*8 + + dw->dvi.default_resolution/2); + dw->dvi.scale_factor = 1.0; + dw->dvi.sizescale = 1; + dw->dvi.line_thickness = -1; + dw->dvi.line_width = 1; + dw->dvi.fill = DVI_FILL_MAX; + dw->dvi.device_font = 0; + dw->dvi.device_font_number = -1; + dw->dvi.device = 0; + dw->dvi.native = 0; + + request = request; /* unused; suppress compiler warning */ + args = args; + num_args = num_args; +} + +#include "gray1.bm" +#include "gray2.bm" +#include "gray3.bm" +#include "gray4.bm" +#include "gray5.bm" +#include "gray6.bm" +#include "gray7.bm" +#include "gray8.bm" + +static void +Realize (Widget w, XtValueMask *valueMask, XSetWindowAttributes *attrs) +{ + DviWidget dw = (DviWidget) w; + XGCValues values; + + if (dw->dvi.backing_store != Always + WhenMapped + NotUseful) { + attrs->backing_store = dw->dvi.backing_store; + *valueMask |= CWBackingStore; + } + XtCreateWindow (w, (unsigned)InputOutput, (Visual *) CopyFromParent, + *valueMask, attrs); + values.foreground = dw->dvi.foreground; + values.cap_style = CapRound; + values.join_style = JoinRound; + values.line_width = dw->dvi.line_width; + dw->dvi.normal_GC = XCreateGC (XtDisplay (w), XtWindow (w), + GCForeground|GCCapStyle|GCJoinStyle + |GCLineWidth, + &values); + dw->dvi.gray[0] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray1_bits, + gray1_width, gray1_height); + dw->dvi.gray[1] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray2_bits, + gray2_width, gray2_height); + dw->dvi.gray[2] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray3_bits, + gray3_width, gray3_height); + dw->dvi.gray[3] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray4_bits, + gray4_width, gray4_height); + dw->dvi.gray[4] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray5_bits, + gray5_width, gray5_height); + dw->dvi.gray[5] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray6_bits, + gray6_width, gray6_height); + dw->dvi.gray[6] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray7_bits, + gray7_width, gray7_height); + dw->dvi.gray[7] = XCreateBitmapFromData(XtDisplay (w), XtWindow (w), + gray8_bits, + gray8_width, gray8_height); + values.background = dw->dvi.background; + values.stipple = dw->dvi.gray[5]; + dw->dvi.fill_GC = XCreateGC (XtDisplay (w), XtWindow (w), + GCForeground|GCBackground|GCStipple, + &values); + + dw->dvi.fill_type = 9; + + if (dw->dvi.file) + OpenFile (dw); + ParseFontMap (dw); +} + +static void +Destroy(Widget w) +{ + DviWidget dw = (DviWidget) w; + + XFreeGC (XtDisplay (w), dw->dvi.normal_GC); + XFreeGC (XtDisplay (w), dw->dvi.fill_GC); + XFreePixmap (XtDisplay (w), dw->dvi.gray[0]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[1]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[2]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[3]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[4]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[5]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[6]); + XFreePixmap (XtDisplay (w), dw->dvi.gray[7]); + DestroyFontMap (dw->dvi.font_map); + DestroyFileMap (dw->dvi.file_map); + device_destroy (dw->dvi.device); +} + +/* + * Repaint the widget window + */ + +/* ARGSUSED */ +static void +Redisplay(Widget w, XEvent *event, Region region) +{ + DviWidget dw = (DviWidget) w; + XRectangle extents; + + XClipBox (region, &extents); + dw->dvi.extents.x1 = extents.x; + dw->dvi.extents.y1 = extents.y; + dw->dvi.extents.x2 = extents.x + extents.width; + dw->dvi.extents.y2 = extents.y + extents.height; + ShowDvi (dw); + + event = event; /* unused; suppress compiler warning */ +} + +/* + * Set specified arguments into widget + */ +/* ARGSUSED */ +static Boolean +SetValues (Widget wcurrent, Widget wrequest, Widget wnew, + ArgList args, Cardinal *num_args) +{ + Boolean redisplay = FALSE; + char *new_map; + int cur, req; + DviWidget current = (DviWidget)wcurrent; + DviWidget request = (DviWidget)wrequest; + DviWidget new_wd = (DviWidget)wnew; + + if (current->dvi.font_map_string != request->dvi.font_map_string) { + new_map = XtMalloc (strlen (request->dvi.font_map_string) + 1); + if (new_map) { + redisplay = TRUE; + strcpy (new_map, request->dvi.font_map_string); + new_wd->dvi.font_map_string = new_map; + if (current->dvi.font_map_string) + XtFree (current->dvi.font_map_string); + current->dvi.font_map_string = 0; + ParseFontMap (new_wd); + } + } + + req = request->dvi.requested_page; + cur = current->dvi.requested_page; + if (cur != req) { + if (!request->dvi.file) + req = 0; + else { + if (req < 1) + req = 1; + if (current->dvi.last_page != 0 && + req > current->dvi.last_page) + req = current->dvi.last_page; + } + if (cur != req) + redisplay = TRUE; + new_wd->dvi.requested_page = req; + if (current->dvi.last_page == 0 && req > cur) + FindPage (new_wd); + } + + args = args; /* unused; suppress compiler warning */ + num_args = num_args; + + return redisplay; +} + +/* + * use the set_values_hook entry to check when + * the file is set + */ + +static Boolean +SetValuesHook (Widget wdw, ArgList args, Cardinal *num_argsp) +{ + Cardinal i; + DviWidget dw = (DviWidget)wdw; + + for (i = 0; i < *num_argsp; i++) { + if (!strcmp (args[i].name, XtNfile)) { + CloseFile (dw); + OpenFile (dw); + return TRUE; + } + } + return FALSE; +} + +static void CloseFile (DviWidget dw) +{ + if (dw->dvi.tmpFile) + fclose (dw->dvi.tmpFile); + ForgetPagePositions (dw); +} + +static void OpenFile (DviWidget dw) +{ + dw->dvi.tmpFile = 0; + if (!dw->dvi.seek) + dw->dvi.tmpFile = tmpfile(); + dw->dvi.requested_page = 1; + dw->dvi.last_page = 0; +} + +static XtGeometryResult +QueryGeometry (Widget w, XtWidgetGeometry *request, + XtWidgetGeometry *geometry_return) +{ + XtGeometryResult ret; + DviWidget dw = (DviWidget) w; + + ret = XtGeometryYes; + if (((request->request_mode & CWWidth) + && request->width < MY_WIDTH(dw)) + || ((request->request_mode & CWHeight) + && request->height < MY_HEIGHT(dw))) + ret = XtGeometryAlmost; + geometry_return->width = MY_WIDTH(dw); + geometry_return->height = MY_HEIGHT(dw); + geometry_return->request_mode = CWWidth|CWHeight; + return ret; +} + +void +SetDevice (DviWidget dw, const char *name) +{ + XtWidgetGeometry request, reply; + XtGeometryResult ret; + + ForgetFonts (dw); + dw->dvi.device = device_load (name); + if (!dw->dvi.device) + return; + dw->dvi.sizescale = dw->dvi.device->sizescale; + dw->dvi.device_resolution = dw->dvi.device->res; + dw->dvi.native = dw->dvi.device->X11; + dw->dvi.paperlength = dw->dvi.device->paperlength; + dw->dvi.paperwidth = dw->dvi.device->paperwidth; + if (dw->dvi.native) { + dw->dvi.display_resolution = dw->dvi.device_resolution; + dw->dvi.scale_factor = 1.0; + } + else { + dw->dvi.display_resolution = dw->dvi.default_resolution; + dw->dvi.scale_factor = ((double)dw->dvi.display_resolution + / dw->dvi.device_resolution); + } + request.request_mode = CWWidth|CWHeight; + request.width = MY_WIDTH(dw); + request.height = MY_HEIGHT(dw); + ret = XtMakeGeometryRequest ((Widget)dw, &request, &reply); + if (ret == XtGeometryAlmost + && reply.height >= request.height + && reply.width >= request.width) { + request.width = reply.width; + request.height = reply.height; + XtMakeGeometryRequest ((Widget)dw, &request, &reply); + } +} + +static void +ShowDvi (DviWidget dw) +{ + if (!dw->dvi.file) { + static char Error[] = "No file selected"; + + XSetFont (XtDisplay(dw), dw->dvi.normal_GC, + dw->dvi.default_font->fid); + XDrawString (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + 20, 20, Error, strlen (Error)); + return; + } + + FindPage (dw); + + dw->dvi.display_enable = 1; + ParseInput (dw); + if (dw->dvi.last_page && dw->dvi.requested_page > dw->dvi.last_page) + dw->dvi.requested_page = dw->dvi.last_page; +} + +static void +FindPage (DviWidget dw) +{ + int i; + long file_position; + + if (dw->dvi.requested_page < 1) + dw->dvi.requested_page = 1; + + if (dw->dvi.last_page != 0 && dw->dvi.requested_page > dw->dvi.last_page) + dw->dvi.requested_page = dw->dvi.last_page; + + file_position = SearchPagePosition (dw, dw->dvi.requested_page); + if (file_position != -1) { + FileSeek(dw, file_position); + dw->dvi.current_page = dw->dvi.requested_page; + } else { + for (i=dw->dvi.requested_page; i > 0; i--) { + file_position = SearchPagePosition (dw, i); + if (file_position != -1) + break; + } + if (file_position == -1) + file_position = 0; + FileSeek (dw, file_position); + + dw->dvi.current_page = i; + + dw->dvi.display_enable = 0; + while (dw->dvi.current_page != dw->dvi.requested_page) { + dw->dvi.current_page = ParseInput (dw); + /* + * at EOF, seek back to the beginning of this page. + */ + if (!dw->dvi.readingTmp && feof (dw->dvi.file)) { + file_position = SearchPagePosition (dw, + dw->dvi.current_page); + if (file_position != -1) + FileSeek (dw, file_position); + dw->dvi.requested_page = dw->dvi.current_page; + break; + } + } + } +} + +void DviSaveToFile(Widget w, FILE *fp) +{ + XtCheckSubclass(w, dviWidgetClass, NULL); + (*((DviWidgetClass) XtClass(w))->command_class.save)(w, fp); +} + +static +void SaveToFile(Widget w, FILE *fp) +{ + DviWidget dw = (DviWidget)w; + long pos; + int c; + + if (dw->dvi.tmpFile) { + pos = ftell(dw->dvi.tmpFile); + if (dw->dvi.ungot) { + pos--; + dw->dvi.ungot = 0; + /* The ungot character is in the tmpFile, so we don't + want to read it from file. */ + (void)getc(dw->dvi.file); + } + } + else + pos = ftell(dw->dvi.file); + FileSeek(dw, 0L); + while (DviGetC(dw, &c) != EOF) + if (putc(c, fp) == EOF) { + /* XXX print error message */ + break; + } + FileSeek(dw, pos); +} + +static +void ClassPartInitialize(WidgetClass widget_class) +{ + DviWidgetClass wc = (DviWidgetClass)widget_class; + DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass; + if (wc->command_class.save == InheritSaveToFile) + wc->command_class.save = super->command_class.save; +} + +/* +Local Variables: +c-indent-level: 8 +c-continued-statement-offset: 8 +c-brace-offset: -8 +c-argdecl-indent: 8 +c-label-offset: -8 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/Dvi.h b/contrib/groff/src/devices/xditview/Dvi.h new file mode 100644 index 0000000..bf97374 --- /dev/null +++ b/contrib/groff/src/devices/xditview/Dvi.h @@ -0,0 +1,46 @@ +/* +* $XConsortium: Dvi.h,v 1.4 89/07/21 14:22:06 jim Exp $ +*/ + +#ifndef _XtDvi_h +#define _XtDvi_h + +/*********************************************************************** + * + * Dvi Widget + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background pixel White + foreground Foreground Pixel Black + fontMap FontMap char * ... + pageNumber PageNumber int 1 +*/ + +#define XtNfontMap (String)"fontMap" +#define XtNpageNumber (String)"pageNumber" +#define XtNlastPageNumber (String)"lastPageNumber" +#define XtNnoPolyText (String)"noPolyText" +#define XtNseek (String)"seek" +#define XtNresolution (String)"resolution" + +#define XtCFontMap (String)"FontMap" +#define XtCPageNumber (String)"PageNumber" +#define XtCLastPageNumber (String)"LastPageNumber" +#define XtCNoPolyText (String)"NoPolyText" +#define XtCSeek (String)"Seek" +#define XtCResolution (String)"Resolution" + +typedef struct _DviRec *DviWidget; /* completely defined in DviP.h */ +typedef struct _DviClassRec *DviWidgetClass; /* completely defined in DviP.h */ + +extern WidgetClass dviWidgetClass; + +void DviSaveToFile(Widget, FILE *); + +#endif /* _XtDvi_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/contrib/groff/src/devices/xditview/DviP.h b/contrib/groff/src/devices/xditview/DviP.h new file mode 100644 index 0000000..00f32c8 --- /dev/null +++ b/contrib/groff/src/devices/xditview/DviP.h @@ -0,0 +1,233 @@ +/* + * $XConsortium: DviP.h,v 1.5 89/07/22 19:44:08 keith Exp $ + */ + +/* + * DviP.h - Private definitions for Dvi widget + */ + +#ifndef _XtDviP_h +#define _XtDviP_h + +#include "Dvi.h" +#include "DviChar.h" +#include "device.h" + +/*********************************************************************** + * + * Dvi Widget Private Data + * + ***********************************************************************/ + +/************************************ + * + * Class structure + * + ***********************************/ + +/* Type for save method. */ + +typedef void (*DviSaveProc)(Widget, FILE *); + +/* + * New fields for the Dvi widget class record + */ + + +typedef struct _DviClass { + DviSaveProc save; +} DviClassPart; + +/* + * Full class record declaration + */ + +typedef struct _DviClassRec { + CoreClassPart core_class; + DviClassPart command_class; +} DviClassRec; + +extern DviClassRec dviClassRec; + +/*************************************** + * + * Instance (widget) structure + * + **************************************/ + +/* + * a list of fonts we've used for this widget + */ + +typedef struct _dviFontSizeList { + struct _dviFontSizeList *next; + int size; + char *x_name; + XFontStruct *font; + int doesnt_exist; +} DviFontSizeList; + +typedef struct _dviFontList { + struct _dviFontList *next; + char *dvi_name; + char *x_name; + int dvi_number; + Boolean initialized; + Boolean scalable; + DviFontSizeList *sizes; + DviCharNameMap *char_map; + DeviceFont *device_font; +} DviFontList; + +typedef struct _dviFontMap { + struct _dviFontMap *next; + char *dvi_name; + char *x_name; +} DviFontMap; + +#define DVI_TEXT_CACHE_SIZE 256 +#define DVI_CHAR_CACHE_SIZE 1024 + +typedef struct _dviCharCache { + XTextItem cache[DVI_TEXT_CACHE_SIZE]; + char adjustable[DVI_TEXT_CACHE_SIZE]; + char char_cache[DVI_CHAR_CACHE_SIZE]; + int index; + int max; + int char_index; + int font_size; + int font_number; + XFontStruct *font; + int start_x, start_y; + int x, y; +} DviCharCache; + +typedef struct _dviState { + struct _dviState *next; + int font_size; + int font_number; + int x; + int y; +} DviState; + +typedef struct _dviFileMap { + struct _dviFileMap *next; + long position; + int page_number; +} DviFileMap; + +/* + * New fields for the Dvi widget record + */ + +typedef struct { + /* + * resource specifiable items + */ + char *font_map_string; + unsigned long foreground; + unsigned long background; + int requested_page; + int last_page; + XFontStruct *default_font; + FILE *file; + Boolean noPolyText; + Boolean seek; /* file is "seekable" */ + int default_resolution; + /* + * private state + */ + FILE *tmpFile; /* used when reading stdin */ + char readingTmp; /* reading now from tmp */ + char ungot; /* have ungetc'd a char */ + GC normal_GC; + GC fill_GC; + DviFileMap *file_map; + DviFontList *fonts; + DviFontMap *font_map; + int current_page; + int font_size; + int font_number; + DeviceFont *device_font; + int device_font_number; + Device *device; + int native; + int device_resolution; + int display_resolution; + int paperlength; + int paperwidth; + double scale_factor; /* display res / device res */ + int sizescale; + int line_thickness; + int line_width; + +#define DVI_FILL_MAX 1000 + + int fill; +#define DVI_FILL_WHITE 0 +#define DVI_FILL_GRAY 1 +#define DVI_FILL_BLACK 2 + int fill_type; + Pixmap gray[8]; + int backing_store; + XFontStruct *font; + int display_enable; + struct ExposedExtents { + int x1, y1, x2, y2; + } extents; + DviState *state; + DviCharCache cache; + int text_x_width; + int text_device_width; + int word_flag; +} DviPart; + +int DviGetAndPut(DviWidget, int *); +#define DviGetIn(dw,cp)\ + (dw->dvi.tmpFile ? (\ + DviGetAndPut (dw, cp) \ + ) :\ + (*cp = getc (dw->dvi.file))\ +) + +#define DviGetC(dw, cp)\ + (dw->dvi.readingTmp ? (\ + ((*cp = getc (dw->dvi.tmpFile)) == EOF) ? (\ + fseek (dw->dvi.tmpFile, 0l, 2),\ + (dw->dvi.readingTmp = 0),\ + DviGetIn (dw,cp)\ + ) : (\ + *cp\ + )\ + ) : (\ + DviGetIn(dw,cp)\ + )\ +) + +#define DviUngetC(dw, c)\ + (dw->dvi.readingTmp ? (\ + ungetc (c, dw->dvi.tmpFile)\ + ) : ( \ + (dw->dvi.ungot = 1),\ + ungetc (c, dw->dvi.file))) + +/* + * Full widget declaration + */ + +typedef struct _DviRec { + CorePart core; + DviPart dvi; +} DviRec; + +#define InheritSaveToFile ((DviSaveProc)_XtInherit) + +XFontStruct *QueryFont (DviWidget, int, int); + +DviCharNameMap *QueryFontMap (DviWidget, int); + +DeviceFont *QueryDeviceFont (DviWidget, int); + +char *GetWord(DviWidget, char *, int); +char *GetLine(DviWidget, char *, int); +#endif /* _XtDviP_h */ diff --git a/contrib/groff/src/devices/xditview/FontMap b/contrib/groff/src/devices/xditview/FontMap new file mode 100644 index 0000000..90911f0 --- /dev/null +++ b/contrib/groff/src/devices/xditview/FontMap @@ -0,0 +1,17 @@ +TR -adobe-times-medium-r-normal--*-*-*-*-p-*-iso8859-1 +TI -adobe-times-medium-i-normal--*-*-*-*-p-*-iso8859-1 +TB -adobe-times-bold-r-normal--*-*-*-*-p-*-iso8859-1 +TBI -adobe-times-bold-i-normal--*-*-*-*-p-*-iso8859-1 +CR -adobe-courier-medium-r-normal--*-*-*-*-m-*-iso8859-1 +CI -adobe-courier-medium-o-normal--*-*-*-*-m-*-iso8859-1 +CB -adobe-courier-bold-r-normal--*-*-*-*-m-*-iso8859-1 +CBI -adobe-courier-bold-o-normal--*-*-*-*-m-*-iso8859-1 +HR -adobe-helvetica-medium-r-normal--*-*-*-*-p-*-iso8859-1 +HI -adobe-helvetica-medium-o-normal--*-*-*-*-p-*-iso8859-1 +HB -adobe-helvetica-bold-r-normal--*-*-*-*-p-*-iso8859-1 +HBI -adobe-helvetica-bold-o-normal--*-*-*-*-p-*-iso8859-1 +NR -adobe-new century schoolbook-medium-r-normal--*-*-*-*-p-*-iso8859-1 +NI -adobe-new century schoolbook-medium-i-normal--*-*-*-*-p-*-iso8859-1 +NB -adobe-new century schoolbook-bold-r-normal--*-*-*-*-p-*-iso8859-1 +NBI -adobe-new century schoolbook-bold-i-normal--*-*-*-*-p-*-iso8859-1 +S -adobe-symbol-medium-r-normal--*-*-*-*-p-*-adobe-fontspecific diff --git a/contrib/groff/src/devices/xditview/GXditview.ad b/contrib/groff/src/devices/xditview/GXditview.ad new file mode 100644 index 0000000..e99ff5e --- /dev/null +++ b/contrib/groff/src/devices/xditview/GXditview.ad @@ -0,0 +1,57 @@ +GXditview.height: 840 + +GXditview.paned.allowResize: true +GXditview.paned.viewport.allowVert: true +GXditview.paned.viewport.allowHoriz: true +GXditview.paned.viewport.skipAdjust: false +GXditview.paned.viewport.width: 600 +GXditview.paned.viewport.height: 800 +GXditview.paned.viewport.showGrip: false +GXditview.paned.label.skipAdjust: true + +GXditview.paned.viewport.dvi.translations: #augment \ + <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\ + <Key>Next: NextPage()\n\ + <Key>n: NextPage()\n\ + <Key>space: NextPage()\n\ + <Key>Return: NextPage()\n\ + <Key>Prior: PreviousPage()\n\ + <Key>p: PreviousPage()\n\ + <Key>BackSpace: PreviousPage()\n\ + <Key>Delete: PreviousPage()\n\ + <Key>Select: SelectPage()\n\ + <Key>Find: OpenFile()\n\ + <Key>r: Rerasterize()\n\ + <Key>q: Quit() +GXditview.paned.label.translations: #augment \ + <Btn1Down>: XawPositionSimpleMenu(menu) MenuPopup(menu)\n\ + <Key>Next: NextPage()\n\ + <Key>n: NextPage()\n\ + <Key>space: NextPage()\n\ + <Key>Return: NextPage()\n\ + <Key>Prior: PreviousPage()\n\ + <Key>p: PreviousPage()\n\ + <Key>BackSpace: PreviousPage()\n\ + <Key>Delete: PreviousPage()\n\ + <Key>Select: SelectPage()\n\ + <Key>Find: OpenFile()\n\ + <Key>r: Rerasterize()\n\ + <Key>q: Quit() +GXditview.menu.nextPage.label: Next Page +GXditview.menu.previousPage.label: Previous Page +GXditview.menu.selectPage.label: Select Page +GXditview.menu.print.label: Print +GXditview.menu.openFile.label: Open +GXditview.menu.quit.label: Quit + +GXditview.promptShell.allowShellResize: true +GXditview.promptShell.promptDialog.value.translations: #override \ + <Key>Return: Accept() + +GXditview.promptShell.promptDialog.accept.label: Accept +GXditview.promptShell.promptDialog.accept.translations: #override \ + <BtnUp>: Accept() unset() + +GXditview.promptShell.promptDialog.cancel.label: Cancel +GXditview.promptShell.promptDialog.cancel.translations: #override \ + <BtnUp>: Cancel() unset() diff --git a/contrib/groff/src/devices/xditview/Makefile.sub b/contrib/groff/src/devices/xditview/Makefile.sub new file mode 100644 index 0000000..f403020 --- /dev/null +++ b/contrib/groff/src/devices/xditview/Makefile.sub @@ -0,0 +1,47 @@ +PROG=gxditview$(EXEEXT) +MAN1=gxditview.n +MLIB=$(LIBM) +XLIBS=$(LIBXUTIL) +EXTRA_CFLAGS=$(X_CFLAGS) +EXTRA_LDFLAGS=$(X_LIBS) $(X_PRE_LIBS) -lXaw -lXmu -lXt -lX11 $(X_EXTRA_LIBS) +OBJS=\ + device.$(OBJEXT) \ + draw.$(OBJEXT) \ + Dvi.$(OBJEXT) \ + font.$(OBJEXT) \ + lex.$(OBJEXT) \ + page.$(OBJEXT) \ + parse.$(OBJEXT) \ + xditview.$(OBJEXT) +CSRCS=\ + $(srcdir)/device.c \ + $(srcdir)/draw.c \ + $(srcdir)/Dvi.c \ + $(srcdir)/font.c \ + $(srcdir)/lex.c \ + $(srcdir)/page.c \ + $(srcdir)/parse.c \ + $(srcdir)/xditview.c +HDRS=\ + $(srcdir)/device.h \ + $(srcdir)/Dvi.h \ + $(srcdir)/DviP.h \ + $(srcdir)/Menu.h +GENHDRS=GXditview-ad.h + +all depend: $(GENHDRS) + +GXditview-ad.h: $(srcdir)/GXditview.ad + @echo Making $@ + @-rm -f $@ + $(SHELL) $(srcdir)/ad2c $(srcdir)/GXditview.ad >GXditview-ad.h + +install_data: $(srcdir)/GXditview.ad + -test -d $(appresdir) || $(mkinstalldirs) $(appresdir) + if test -f $(appresdir)/GXditview; then \ + mv $(appresdir)/GXditview $(appresdir)/GXditview.old; \ + fi + $(INSTALL_DATA) $(srcdir)/GXditview.ad $(appresdir)/GXditview + +uninstall_sub: + -rm -f $(appresdir)/GXditview diff --git a/contrib/groff/src/devices/xditview/Menu.h b/contrib/groff/src/devices/xditview/Menu.h new file mode 100644 index 0000000..c306b27 --- /dev/null +++ b/contrib/groff/src/devices/xditview/Menu.h @@ -0,0 +1,46 @@ +/* + * $XConsortium: Menu.h,v 1.2 89/07/21 14:22:10 jim Exp $ + */ + +#ifndef _XtMenu_h +#define _XtMenu_h + +/*********************************************************************** + * + * Menu Widget + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background pixel White + border BorderColor pixel Black + borderWidth BorderWidth int 1 + height Height int 120 + mappedWhenManaged MappedWhenManaged Boolean True + reverseVideo ReverseVideo Boolean False + width Width int 120 + x Position int 0 + y Position int 0 + +*/ + +#define XtNmenuEntries "menuEntries" +#define XtNhorizontalPadding "horizontalPadding" +#define XtNverticalPadding "verticalPadding" +#define XtNselection "Selection" + +#define XtCMenuEntries "MenuEntries" +#define XtCPadding "Padding" +#define XtCSelection "Selection" + +typedef struct _MenuRec *MenuWidget; /* completely defined in MenuPrivate.h */ +typedef struct _MenuClassRec *MenuWidgetClass; /* completely defined in MenuPrivate.h */ + +extern WidgetClass menuWidgetClass; + +extern Widget XawMenuCreate (); +#endif /* _XtMenu_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/contrib/groff/src/devices/xditview/README b/contrib/groff/src/devices/xditview/README new file mode 100644 index 0000000..1461b5a --- /dev/null +++ b/contrib/groff/src/devices/xditview/README @@ -0,0 +1,13 @@ +This is gxditview, an X11 previewer for groff based on MIT's xditview. +This version can be used with the output of gtroff -Tps as well as +with -TX75 and -TX100. You will need X11R5 or newer to install it (it +might work on X11R4, but I haven't tested it.) + +Previously, gxditview was installed in the usual place for X binaries +(e.g., /usr/bin/X11); you have to remove it manually. + +xditview is copyrighted by MIT under the usual X terms (see +gxditview.man); the changes to that which come along with the groff package +are in the public domain. + +Please report bugs to bug-groff@gnu.org. diff --git a/contrib/groff/src/devices/xditview/TODO b/contrib/groff/src/devices/xditview/TODO new file mode 100644 index 0000000..161a7cf --- /dev/null +++ b/contrib/groff/src/devices/xditview/TODO @@ -0,0 +1,17 @@ +Replace Imakefile with a configure script. + +Better error handling. + +Resource and command-line option to specify font path. + +Resource to specify name of environment variable from which to get the +font path. + +Have character substitutions (currently done in draw.c:FakeCharacter) +specified in a resource (similar format to FontMap). + +The initial width of the dialog box should expand to accommodate the +default value. + +Option in Print dialog to specify that only the current page should be +printed. diff --git a/contrib/groff/src/devices/xditview/ad2c b/contrib/groff/src/devices/xditview/ad2c new file mode 100644 index 0000000..ad5d121 --- /dev/null +++ b/contrib/groff/src/devices/xditview/ad2c @@ -0,0 +1,64 @@ +#! /bin/sh +# +# ad2c : Convert app-defaults file to C strings decls. +# +# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990. +# 19 Mar 1991: gf +# Made it self-contained. +# 6 Jan 1992: mycroft@gnu.ai.mit.edu (Charles Hannum) +# Removed use of "-n" and ":read" label since Gnu and +# IBM sed print pattern space on "n" command. Still works +# with Sun sed, of course. +# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier) +# Escape quotes after escaping backslashes. +# 8 Jul 1992: Version 1.6 +# Manpage fixes. +# 19 Apr 1993: Version 1.7 +# Remove comments that were inside the sed command since +# some versions of sed don't like them. The comments are +# now given here in the header. +# 31 May 2004: Werner Lemberg <wl@gnu.org> +# Force casts to `String'. +# +# Comments on the script by line: +# /^!/d Remove comments +# /^$/d Remove blanks +# s/\\/\\\\/g Escape backslashes... +# s/\\$//g ...except the line continuation ones +# s/"/\\"/g Escape quotes +# s/^/"/ Add leading quote and cast +# : test Establish label for later branch +# /\\$/b slash Branch to label "slash" if line ends in backslash +# s/$/",/ Otherwise add closing quote and comma... +# p ...output the line... +# d ...and clear the pattern space so it's not printed again +# : slash Branch comes here if line ends in backslash +# n Read next line, append to pattern space +# [...] The "d" and "s" commands that follow just delete +# comments and blank lines and escape control sequences +# b test Branch up to see if the line ends in backslash or not +# + +sed ' +/^!/d +/^$/d +s/\\/\\\\/g +s/\\$//g +s/"/\\"/g +s/^/(String)"/ +: test +/\\$/b slash +s/$/",/ +p +d +: slash +n +/^!/d +/^$/d +s/"/\\"/g +s/\\\\/\\/g +s/\\n/\\\\n/g +s/\\t/\\\\t/g +s/\\f/\\\\f/g +s/\\b/\\\\b/g +b test' "$@" diff --git a/contrib/groff/src/devices/xditview/device.c b/contrib/groff/src/devices/xditview/device.c new file mode 100644 index 0000000..2cb2219 --- /dev/null +++ b/contrib/groff/src/devices/xditview/device.c @@ -0,0 +1,565 @@ +/* device.c */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include <X11/Xos.h> +#include <X11/Intrinsic.h> + +#include "device.h" +#include "defs.h" + +#ifndef isascii +#define isascii(c) (1) +#endif + +/* Name of environment variable containing path to be used for +searching for device and font description files. */ +#define FONTPATH_ENV_VAR "GROFF_FONT_PATH" + +#define WS " \t\r\n" + +#ifndef INT_MIN +/* Minimum and maximum values a `signed int' can hold. */ +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 2147483647 +#endif + +#define CHAR_TABLE_SIZE 307 + +struct _DeviceFont { + char *name; + int special; + DeviceFont *next; + Device *dev; + struct charinfo *char_table[CHAR_TABLE_SIZE]; + struct charinfo *code_table[256]; +}; + +struct charinfo { + int width; + int code; + struct charinfo *next; + struct charinfo *code_next; + char name[1]; +}; + +static char *current_filename = 0; +static int current_lineno = -1; + +static void error(const char *s); +static FILE *open_device_file(const char *, const char *, char **); +static DeviceFont *load_font(Device *, const char *); +static Device *new_device(const char *); +static DeviceFont *new_font(const char *, Device *); +static void delete_font(DeviceFont *); +static unsigned hash_name(const char *); +static struct charinfo *add_char(DeviceFont *, const char *, int, int); +static int read_charset_section(DeviceFont *, FILE *); +static char *canonicalize_name(const char *); +static int scale_round(int, int, int); + +static +Device *new_device(const char *name) +{ + Device *dev; + + dev = XtNew(Device); + dev->sizescale = 1; + dev->res = 0; + dev->unitwidth = 0; + dev->fonts = 0; + dev->X11 = 0; + dev->paperlength = 0; + dev->paperwidth = 0; + dev->name = XtNewString(name); + return dev; +} + +void device_destroy(Device *dev) +{ + DeviceFont *f; + + if (!dev) + return; + f = dev->fonts; + while (f) { + DeviceFont *tem = f; + f = f->next; + delete_font(tem); + } + + XtFree(dev->name); + XtFree((char *)dev); +} + +Device *device_load(const char *name) +{ + Device *dev; + FILE *fp; + int err = 0; + char buf[256]; + + fp = open_device_file(name, "DESC", ¤t_filename); + if (!fp) + return 0; + dev = new_device(name); + current_lineno = 0; + while (fgets(buf, sizeof(buf), fp)) { + char *p; + current_lineno++; + p = strtok(buf, WS); + if (p) { + int *np = 0; + char *q; + + if (strcmp(p, "charset") == 0) + break; + if (strcmp(p, "X11") == 0) + dev->X11 = 1; + else if (strcmp(p, "sizescale") == 0) + np = &dev->sizescale; + else if (strcmp(p, "res") == 0) + np = &dev->res; + else if (strcmp(p, "unitwidth") == 0) + np = &dev->unitwidth; + else if (strcmp(p, "paperwidth") == 0) + np = &dev->paperwidth; + else if (strcmp(p, "paperlength") == 0) + np = &dev->paperlength; + + if (np) { + q = strtok((char *)0, WS); + if (!q || sscanf(q, "%d", np) != 1 || *np <= 0) { + error("bad argument"); + err = 1; + break; + } + } + } + } + fclose(fp); + current_lineno = -1; + if (!err) { + if (dev->res == 0) { + error("missing res line"); + err = 1; + } + else if (dev->unitwidth == 0) { + error("missing unitwidth line"); + err = 1; + } + } + if (dev->paperlength == 0) + dev->paperlength = dev->res*11; + if (dev->paperwidth == 0) + dev->paperwidth = dev->res*8 + dev->res/2; + if (err) { + device_destroy(dev); + dev = 0; + } + XtFree(current_filename); + current_filename = 0; + return dev; +} + + +DeviceFont *device_find_font(Device *dev, const char *name) +{ + DeviceFont *f; + + if (!dev) + return 0; + for (f = dev->fonts; f; f = f->next) + if (strcmp(f->name, name) == 0) + return f; + return load_font(dev, name); +} + +static +DeviceFont *load_font(Device *dev, const char *name) +{ + FILE *fp; + char buf[256]; + DeviceFont *f; + int special = 0; + + fp = open_device_file(dev->name, name, ¤t_filename); + if (!fp) + return 0; + current_lineno = 0; + for (;;) { + char *p; + + if (!fgets(buf, sizeof(buf), fp)) { + error("no charset line"); + return 0; + } + current_lineno++; + p = strtok(buf, WS); + /* charset must be on a line by itself */ + if (p && strcmp(p, "charset") == 0 && strtok((char *)0, WS) == 0) + break; + if (p && strcmp(p, "special") == 0) + special = 1; + } + f = new_font(name, dev); + f->special = special; + if (!read_charset_section(f, fp)) { + delete_font(f); + f = 0; + } + else { + f->next = dev->fonts; + dev->fonts = f; + } + fclose(fp); + XtFree(current_filename); + current_filename = 0; + return f; +} + +static +DeviceFont *new_font(const char *name, Device *dev) +{ + int i; + DeviceFont *f; + + f = XtNew(DeviceFont); + f->name = XtNewString(name); + f->dev = dev; + f->special = 0; + f->next = 0; + for (i = 0; i < CHAR_TABLE_SIZE; i++) + f->char_table[i] = 0; + for (i = 0; i < 256; i++) + f->code_table[i] = 0; + return f; +} + +static +void delete_font(DeviceFont *f) +{ + int i; + + if (!f) + return; + XtFree(f->name); + for (i = 0; i < CHAR_TABLE_SIZE; i++) { + struct charinfo *ptr = f->char_table[i]; + while (ptr) { + struct charinfo *tem = ptr; + ptr = ptr->next; + XtFree((char *)tem); + } + } + XtFree((char *)f); +} + + +static +unsigned hash_name(const char *name) +{ + unsigned n = 0; + /* XXX do better than this */ + while (*name) + n = (n << 1) ^ *name++; + + return n; +} + +static +int scale_round(int n, int x, int y) +{ + int y2; + + if (x == 0) + return 0; + y2 = y/2; + if (n >= 0) { + if (n <= (INT_MAX - y2)/x) + return (n*x + y2)/y; + return (int)(n*(double)x/(double)y + .5); + } + else { + if (-(unsigned)n <= (-(unsigned)INT_MIN - y2)/x) + return (n*x - y2)/y; + return (int)(n*(double)x/(double)y + .5); + } +} + +static +char *canonicalize_name(const char *s) +{ + static char ch[2]; + if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') { + const char *p; + int n; + + for (p = s + 4; *p; p++) + if (!isascii(*p) || !isdigit((unsigned char)*p)) + return (char *)s; + n = atoi(s + 4); + if (n >= 0 && n <= 0xff) { + ch[0] = (char)n; + return ch; + } + } + return (char *)s; +} + +/* Return 1 if the character is present in the font; widthp gets the +width if non-null. */ + +int device_char_width(DeviceFont *f, int ps, const char *name, int *widthp) +{ + struct charinfo *p; + + name = canonicalize_name(name); + for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) { + if (!p) + return 0; + if (strcmp(p->name, name) == 0) + break; + } + *widthp = scale_round(p->width, ps, f->dev->unitwidth); + return 1; +} + +int device_code_width(DeviceFont *f, int ps, int code, int *widthp) +{ + struct charinfo *p; + + for (p = f->code_table[code & 0xff];; p = p->code_next) { + if (!p) + return 0; + if (p->code == code) + break; + } + *widthp = scale_round(p->width, ps, f->dev->unitwidth); + return 1; +} + +char *device_name_for_code(DeviceFont *f, int code) +{ + static struct charinfo *state = 0; + if (f) + state = f->code_table[code & 0xff]; + for (; state; state = state->code_next) + if (state->code == code && state->name[0] != '\0') { + char *name = state->name; + state = state->code_next; + return name; + } + return 0; +} + +int device_font_special(DeviceFont *f) +{ + return f->special; +} + +static +struct charinfo *add_char(DeviceFont *f, const char *name, int width, int code) +{ + struct charinfo **pp; + struct charinfo *ci; + + name = canonicalize_name(name); + if (strcmp(name, "---") == 0) + name = ""; + + ci = (struct charinfo *)XtMalloc(XtOffsetOf(struct charinfo, name[0]) + + strlen(name) + 1); + + strcpy(ci->name, name); + ci->width = width; + ci->code = code; + + if (*name != '\0') { + pp = &f->char_table[hash_name(name) % CHAR_TABLE_SIZE]; + ci->next = *pp; + *pp = ci; + } + pp = &f->code_table[code & 0xff]; + ci->code_next = *pp; + *pp = ci; + return ci; +} + +/* Return non-zero for success. */ + +static +int read_charset_section(DeviceFont *f, FILE *fp) +{ + struct charinfo *last_charinfo = 0; + char buf[256]; + + while (fgets(buf, sizeof(buf), fp)) { + char *name; + int width; + int code; + char *p; + + current_lineno++; + name = strtok(buf, WS); + if (!name) + continue; /* ignore blank lines */ + p = strtok((char *)0, WS); + if (!p) /* end of charset section */ + break; + if (strcmp(p, "\"") == 0) { + if (!last_charinfo) { + error("first line of charset section cannot use `\"'"); + return 0; + } + else + (void)add_char(f, name, + last_charinfo->width, last_charinfo->code); + } + else { + char *q; + if (sscanf(p, "%d", &width) != 1) { + error("bad width field"); + return 0; + } + p = strtok((char *)0, WS); + if (!p) { + error("missing type field"); + return 0; + } + p = strtok((char *)0, WS); + if (!p) { + error("missing code field"); + return 0; + } + code = (int)strtol(p, &q, 0); + if (q == p) { + error("bad code field"); + return 0; + } + last_charinfo = add_char(f, name, width, code); + } + } + return 1; +} + +static +FILE *find_file(const char *file, char **result) +{ + char *buf = NULL; + int bufsiz = 0; + int flen; + FILE *fp; + char *path; + char *env; + + env = getenv(FONTPATH_ENV_VAR); + path = XtMalloc(((env && *env) ? strlen(env) + 1 : 0) + + strlen(FONTPATH) + 1); + *path = '\0'; + if (env && *env) { + strcat(path, env); + strcat(path, ":"); + } + strcat(path, FONTPATH); + + *result = NULL; + + if (file == NULL) + return NULL; + if (*file == '\0') + return NULL; + + if (*file == '/') { + fp = fopen(file, "r"); + if (fp) + *result = XtNewString(file); + return fp; + } + + flen = strlen(file); + + while (*path) { + int len; + char *start, *end; + + start = path; + end = strchr(path, ':'); + if (end) + path = end + 1; + else + path = end = strchr(path, '\0'); + if (start >= end) + continue; + if (end[-1] == '/') + --end; + len = (end - start) + 1 + flen + 1; + if (len > bufsiz) { + if (buf) + buf = XtRealloc(buf, len); + else + buf = XtMalloc(len); + bufsiz = len; + } + memcpy(buf, start, end - start); + buf[end - start] = '/'; + strcpy(buf + (end - start) + 1, file); + fp = fopen(buf, "r"); + if (fp) { + *result = buf; + return fp; + } + } + XtFree(buf); + return NULL; +} + +static +FILE *open_device_file(const char *device_name, const char *file_name, + char **result) +{ + char *buf; + FILE *fp; + + buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1); + sprintf(buf, "dev%s/%s", device_name, file_name); + fp = find_file(buf, result); + if (!fp) { + fprintf(stderr, "can't find device file `%s'\n", file_name); + fflush(stderr); + } + XtFree(buf); + return fp; +} + +static +void error(const char *s) +{ + if (current_filename) { + fprintf(stderr, "%s:", current_filename); + if (current_lineno > 0) + fprintf(stderr, "%d:", current_lineno); + putc(' ', stderr); + } + fputs(s, stderr); + putc('\n', stderr); + fflush(stderr); +} + +/* +Local Variables: +c-indent-level: 4 +c-continued-statement-offset: 4 +c-brace-offset: -4 +c-argdecl-indent: 4 +c-label-offset: -4 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/device.h b/contrib/groff/src/devices/xditview/device.h new file mode 100644 index 0000000..6f2944b --- /dev/null +++ b/contrib/groff/src/devices/xditview/device.h @@ -0,0 +1,21 @@ + +typedef struct _DeviceFont DeviceFont; + +typedef struct _Device { + char *name; + int sizescale; + int res; + int unitwidth; + int paperlength; + int paperwidth; + int X11; + DeviceFont *fonts; +} Device; + +void device_destroy(Device *); +Device *device_load(const char *); +DeviceFont *device_find_font(Device *, const char *); +int device_char_width(DeviceFont *, int, const char *, int *); +char *device_name_for_code(DeviceFont *, int); +int device_code_width(DeviceFont *, int, int, int *); +int device_font_special(DeviceFont *); diff --git a/contrib/groff/src/devices/xditview/draw.c b/contrib/groff/src/devices/xditview/draw.c new file mode 100644 index 0000000..a808aba --- /dev/null +++ b/contrib/groff/src/devices/xditview/draw.c @@ -0,0 +1,699 @@ +/* + * draw.c + * + * accept dvi function calls and translate to X + */ + +#include <X11/Xos.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <stdio.h> +#include <ctype.h> +#include <math.h> + +/* math.h on a Sequent doesn't define M_PI, apparently */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include "DviP.h" + +#define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5)) +#define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \ + (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width) +#define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y)) + +static int FakeCharacter(DviWidget, char *, int); + +/* font.c */ +extern int MaxFontPosition(DviWidget); + +void +HorizontalMove(DviWidget dw, int delta) +{ + dw->dvi.state->x += delta; +} + +void +HorizontalGoto(DviWidget dw, int NewPosition) +{ + dw->dvi.state->x = NewPosition; +} + +void +VerticalMove(DviWidget dw, int delta) +{ + dw->dvi.state->y += delta; +} + +void +VerticalGoto(DviWidget dw, int NewPosition) +{ + dw->dvi.state->y = NewPosition; +} + +void +AdjustCacheDeltas (DviWidget dw) +{ + int extra; + int nadj; + int i; + + nadj = 0; + extra = DeviceToX(dw, dw->dvi.text_device_width) + - dw->dvi.text_x_width; + if (extra == 0) + return; + for (i = 0; i <= dw->dvi.cache.index; i++) + if (dw->dvi.cache.adjustable[i]) + ++nadj; + dw->dvi.text_x_width += extra; + if (nadj <= 1) + return; + for (i = 0; i <= dw->dvi.cache.index; i++) + if (dw->dvi.cache.adjustable[i]) { + int x; + int *deltap; + + x = extra/nadj; + deltap = &dw->dvi.cache.cache[i].delta; +#define MIN_DELTA 2 + if (*deltap > 0 && x + *deltap < MIN_DELTA) { + x = MIN_DELTA - *deltap; + if (x <= 0) + *deltap = MIN_DELTA; + else + x = 0; + } + else + *deltap += x; + extra -= x; + --nadj; + dw->dvi.cache.adjustable[i] = 0; + } +} + +void +FlushCharCache (DviWidget dw) +{ + if (dw->dvi.cache.char_index != 0) { + AdjustCacheDeltas (dw); + XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + dw->dvi.cache.start_x, dw->dvi.cache.start_y, + dw->dvi.cache.cache, dw->dvi.cache.index + 1); + } + dw->dvi.cache.index = 0; + dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE; +#if 0 + if (dw->dvi.noPolyText) + dw->dvi.cache.max = 1; +#endif + dw->dvi.cache.char_index = 0; + dw->dvi.cache.cache[0].nchars = 0; + dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw); + dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw); +} + +void +Newline (DviWidget dw) +{ + FlushCharCache (dw); + dw->dvi.text_x_width = dw->dvi.text_device_width = 0; + dw->dvi.word_flag = 0; +} + +void +Word (DviWidget dw) +{ + dw->dvi.word_flag = 1; +} + +#define charWidth(fi,c) (\ + (fi)->per_char ?\ + (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\ + :\ + (fi)->max_bounds.width\ +) + + +static +int charExists (XFontStruct *fi, int c) +{ + XCharStruct *p; + + /* `c' is always >= 0 */ + if (fi->per_char == NULL + || (unsigned int)c < fi->min_char_or_byte2 + || (unsigned int)c > fi->max_char_or_byte2) + return 0; + p = fi->per_char + (c - fi->min_char_or_byte2); + return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0 + || p->ascent != 0 || p->descent != 0 || p->attributes != 0); +} + +/* `wid' is in device units */ +static void +DoCharacter (DviWidget dw, int c, int wid) +{ + register XFontStruct *font; + register XTextItem *text; + int x, y; + + x = XPos(dw); + y = YPos(dw); + + /* + * quick and dirty extents calculation: + */ + if (!(y + 24 >= dw->dvi.extents.y1 + && y - 24 <= dw->dvi.extents.y2 +#if 0 + && x + 24 >= dw->dvi.extents.x1 + && x - 24 <= dw->dvi.extents.x2 +#endif + )) + return; + + if (y != dw->dvi.cache.y + || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) { + FlushCharCache (dw); + x = dw->dvi.cache.x; + dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0; + } + /* + * load a new font, if the current block is not empty, + * step to the next. + */ + if (dw->dvi.cache.font_size != dw->dvi.state->font_size || + dw->dvi.cache.font_number != dw->dvi.state->font_number) + { + FlushCharCache (dw); + x = dw->dvi.cache.x; + dw->dvi.cache.font_size = dw->dvi.state->font_size; + dw->dvi.cache.font_number = dw->dvi.state->font_number; + dw->dvi.cache.font = QueryFont (dw, + dw->dvi.cache.font_number, + dw->dvi.cache.font_size); + if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { + ++dw->dvi.cache.index; + if (dw->dvi.cache.index >= dw->dvi.cache.max) + FlushCharCache (dw); + dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; + dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0; + } + } + if (x != dw->dvi.cache.x || dw->dvi.word_flag) { + if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) { + ++dw->dvi.cache.index; + if (dw->dvi.cache.index >= dw->dvi.cache.max) + FlushCharCache (dw); + dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0; + dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0; + } + dw->dvi.cache.adjustable[dw->dvi.cache.index] + = dw->dvi.word_flag; + dw->dvi.word_flag = 0; + } + font = dw->dvi.cache.font; + text = &dw->dvi.cache.cache[dw->dvi.cache.index]; + if (text->nchars == 0) { + text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index]; + text->delta = x - dw->dvi.cache.x; + if (font != dw->dvi.font) { + text->font = font->fid; + dw->dvi.font = font; + } else + text->font = None; + dw->dvi.cache.x += text->delta; + } + if (charExists(font, c)) { + int w; + dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c; + ++text->nchars; + w = charWidth(font, c); + dw->dvi.cache.x += w; + if (wid != 0) { + dw->dvi.text_x_width += w; + dw->dvi.text_device_width += wid; + } + } +} + +static +int FindCharWidth (DviWidget dw, char *buf, int *widp) +{ + int maxpos; + int i; + + if (dw->dvi.device_font == 0 + || dw->dvi.state->font_number != dw->dvi.device_font_number) { + dw->dvi.device_font_number = dw->dvi.state->font_number; + dw->dvi.device_font + = QueryDeviceFont (dw, dw->dvi.device_font_number); + } + if (dw->dvi.device_font + && device_char_width (dw->dvi.device_font, + dw->dvi.state->font_size, buf, widp)) + return 1; + + maxpos = MaxFontPosition (dw); + for (i = 1; i <= maxpos; i++) { + DeviceFont *f = QueryDeviceFont (dw, i); + if (f && device_font_special (f) + && device_char_width (f, dw->dvi.state->font_size, + buf, widp)) { + dw->dvi.state->font_number = i; + return 1; + } + } + return 0; +} + +/* Return the width of the character in device units. */ + +int PutCharacter (DviWidget dw, char *buf) +{ + int prevFont; + int c = -1; + int wid = 0; + DviCharNameMap *map; + + if (!dw->dvi.display_enable) + return 0; /* The width doesn't matter in this case. */ + prevFont = dw->dvi.state->font_number; + if (!FindCharWidth (dw, buf, &wid)) + return 0; + map = QueryFontMap (dw, dw->dvi.state->font_number); + if (map) + c = DviCharIndex (map, buf); + if (c >= 0) + DoCharacter (dw, c, wid); + else + (void) FakeCharacter (dw, buf, wid); + dw->dvi.state->font_number = prevFont; + return wid; +} + +/* Return 1 if we can fake it; 0 otherwise. */ + +static +int FakeCharacter (DviWidget dw, char *buf, int wid) +{ + int oldx, oldw; + char ch[2]; + const char *chars = 0; + + if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0') + return 0; +#define pack2(c1, c2) (((c1) << 8) | (c2)) + + switch (pack2(buf[0], buf[1])) { + case pack2('f', 'i'): + chars = "fi"; + break; + case pack2('f', 'l'): + chars = "fl"; + break; + case pack2('f', 'f'): + chars = "ff"; + break; + case pack2('F', 'i'): + chars = "ffi"; + break; + case pack2('F', 'l'): + chars = "ffl"; + break; + } + if (!chars) + return 0; + oldx = dw->dvi.state->x; + oldw = dw->dvi.text_device_width; + ch[1] = '\0'; + for (; *chars; chars++) { + ch[0] = *chars; + dw->dvi.state->x += PutCharacter (dw, ch); + } + dw->dvi.state->x = oldx; + dw->dvi.text_device_width = oldw + wid; + return 1; +} + +void +PutNumberedCharacter (DviWidget dw, int c) +{ + char *name; + int wid; + DviCharNameMap *map; + + if (!dw->dvi.display_enable) + return; + + if (dw->dvi.device_font == 0 + || dw->dvi.state->font_number != dw->dvi.device_font_number) { + dw->dvi.device_font_number = dw->dvi.state->font_number; + dw->dvi.device_font + = QueryDeviceFont (dw, dw->dvi.device_font_number); + } + + if (dw->dvi.device_font == 0 + || !device_code_width (dw->dvi.device_font, + dw->dvi.state->font_size, c, &wid)) + return; + if (dw->dvi.native) { + DoCharacter (dw, c, wid); + return; + } + map = QueryFontMap (dw, dw->dvi.state->font_number); + if (!map) + return; + for (name = device_name_for_code (dw->dvi.device_font, c); + name; + name = device_name_for_code ((DeviceFont *)0, c)) { + int code = DviCharIndex (map, name); + if (code >= 0) { + DoCharacter (dw, code, wid); + break; + } + if (FakeCharacter (dw, name, wid)) + break; + } +} + +void +ClearPage (DviWidget dw) +{ + XClearWindow (XtDisplay (dw), XtWindow (dw)); +} + +static void +setGC (DviWidget dw) +{ + int desired_line_width; + + if (dw->dvi.line_thickness < 0) + desired_line_width = (int)(((double)dw->dvi.device_resolution + * dw->dvi.state->font_size) + / (10.0*72.0*dw->dvi.sizescale)); + else + desired_line_width = dw->dvi.line_thickness; + + if (desired_line_width != dw->dvi.line_width) { + XGCValues values; + values.line_width = DeviceToX(dw, desired_line_width); + if (values.line_width == 0) + values.line_width = 1; + XChangeGC(XtDisplay (dw), dw->dvi.normal_GC, + GCLineWidth, &values); + dw->dvi.line_width = desired_line_width; + } +} + +static void +setFillGC (DviWidget dw) +{ + int fill_type; + unsigned long mask = GCFillStyle | GCForeground; + + fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1); + if (dw->dvi.fill_type != fill_type) { + XGCValues values; + if (fill_type <= 0) { + values.foreground = dw->dvi.background; + values.fill_style = FillSolid; + } else if (fill_type >= 9) { + values.foreground = dw->dvi.foreground; + values.fill_style = FillSolid; + } else { + values.foreground = dw->dvi.foreground; + values.fill_style = FillOpaqueStippled; + values.stipple = dw->dvi.gray[fill_type - 1]; + mask |= GCStipple; + } + XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values); + dw->dvi.fill_type = fill_type; + } +} + +void +DrawLine (DviWidget dw, int x, int y) +{ + int xp, yp; + + AdjustCacheDeltas (dw); + setGC (dw); + xp = XPos (dw); + yp = YPos (dw); + XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + xp, yp, + xp + DeviceToX (dw, x), yp + DeviceToX (dw, y)); +} + +void +DrawCircle (DviWidget dw, int diam) +{ + int d; + + AdjustCacheDeltas (dw); + setGC (dw); + d = DeviceToX (dw, diam); + XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + XPos (dw), YPos (dw) - d/2, + d, d, 0, 64*360); +} + +void +DrawFilledCircle (DviWidget dw, int diam) +{ + int d; + + AdjustCacheDeltas (dw); + setFillGC (dw); + d = DeviceToX (dw, diam); + XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + XPos (dw), YPos (dw) - d/2, + d, d, 0, 64*360); + XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + XPos (dw), YPos (dw) - d/2, + d, d, 0, 64*360); +} + +void +DrawEllipse (DviWidget dw, int a, int b) +{ + AdjustCacheDeltas (dw); + setGC (dw); + XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + XPos (dw), YPos (dw) - DeviceToX (dw, b/2), + DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360); +} + +void +DrawFilledEllipse (DviWidget dw, int a, int b) +{ + AdjustCacheDeltas (dw); + setFillGC (dw); + XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + XPos (dw), YPos (dw) - DeviceToX (dw, b/2), + DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360); + XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + XPos (dw), YPos (dw) - DeviceToX (dw, b/2), + DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360); +} + +void +DrawArc (DviWidget dw, int x_0, int y_0, int x_1, int y_1) +{ + int angle1, angle2; + int rad = (int)((sqrt ((double)x_0*x_0 + (double)y_0*y_0) + + sqrt ((double)x_1*x_1 + (double)y_1*y_1) + + 1.0)/2.0); + if ((x_0 == 0 && y_0 == 0) || (x_1 == 0 && y_1 == 0)) + return; + angle1 = (int)(atan2 ((double)y_0, (double)-x_0)*180.0*64.0/M_PI); + angle2 = (int)(atan2 ((double)-y_1, (double)x_1)*180.0*64.0/M_PI); + + angle2 -= angle1; + if (angle2 < 0) + angle2 += 64*360; + + AdjustCacheDeltas (dw); + setGC (dw); + + rad = DeviceToX (dw, rad); + XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + XPos (dw) + DeviceToX (dw, x_0) - rad, + YPos (dw) + DeviceToX (dw, y_0) - rad, + rad*2, rad*2, angle1, angle2); +} + +void +DrawPolygon (DviWidget dw, int *v, int n) +{ + XPoint *p; + int i; + int dx, dy; + + n /= 2; + + AdjustCacheDeltas (dw); + setGC (dw); + p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint)); + p[0].x = XPos (dw); + p[0].y = YPos (dw); + dx = 0; + dy = 0; + for (i = 0; i < n; i++) { + dx += v[2*i]; + p[i + 1].x = DeviceToX (dw, dx) + p[0].x; + dy += v[2*i + 1]; + p[i + 1].y = DeviceToX (dw, dy) + p[0].y; + } + p[n+1].x = p[0].x; + p[n+1].y = p[0].y; + XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + p, n + 2, CoordModeOrigin); + XtFree((char *)p); +} + +void +DrawFilledPolygon (DviWidget dw, int *v, int n) +{ + XPoint *p; + int i; + int dx, dy; + + n /= 2; + if (n < 2) + return; + + AdjustCacheDeltas (dw); + setFillGC (dw); + p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint)); + p[0].x = p[n+1].x = XPos (dw); + p[0].y = p[n+1].y = YPos (dw); + dx = 0; + dy = 0; + for (i = 0; i < n; i++) { + dx += v[2*i]; + p[i + 1].x = DeviceToX (dw, dx) + p[0].x; + dy += v[2*i + 1]; + p[i + 1].y = DeviceToX (dw, dy) + p[0].y; + } + XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + p, n + 1, Complex, CoordModeOrigin); + XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC, + p, n + 2, CoordModeOrigin); + XtFree((char *)p); +} + +#define POINTS_MAX 10000 + +static void +appendPoint(XPoint *points, int *pointi, int x, int y) +{ + if (*pointi < POINTS_MAX) { + points[*pointi].x = x; + points[*pointi].y = y; + *pointi += 1; + } +} + +#define FLATNESS 1 + +static void +flattenCurve(XPoint *points, int *pointi, + int x_2, int y_2, int x_3, int y_3, int x_4, int y_4) +{ + int x_1, y_1, dx, dy, n1, n2, n; + + x_1 = points[*pointi - 1].x; + y_1 = points[*pointi - 1].y; + + dx = x_4 - x_1; + dy = y_4 - y_1; + + n1 = dy*(x_2 - x_1) - dx*(y_2 - y_1); + n2 = dy*(x_3 - x_1) - dx*(y_3 - y_1); + if (n1 < 0) + n1 = -n1; + if (n2 < 0) + n2 = -n2; + n = n1 > n2 ? n1 : n2; + + if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS) + appendPoint (points, pointi, x_4, y_4); + else { + flattenCurve (points, pointi, + (x_1 + x_2)/2, + (y_1 + y_2)/2, + (x_1 + x_2*2 + x_3)/4, + (y_1 + y_2*2 + y_3)/4, + (x_1 + 3*x_2 + 3*x_3 + x_4)/8, + (y_1 + 3*y_2 + 3*y_3 + y_4)/8); + flattenCurve (points, pointi, + (x_2 + x_3*2 + x_4)/4, + (y_2 + y_3*2 + y_4)/4, + (x_3 + x_4)/2, + (y_3 + y_4)/2, + x_4, + y_4); + } +} + +void +DrawSpline (DviWidget dw, int *v, int n) +{ + int sx, sy, tx, ty; + int ox, oy, dx, dy; + int i; + int pointi; + XPoint points[POINTS_MAX]; + + if (n == 0 || (n & 1) != 0) + return; + AdjustCacheDeltas (dw); + setGC (dw); + ox = XPos (dw); + oy = YPos (dw); + dx = v[0]; + dy = v[1]; + sx = ox; + sy = oy; + tx = sx + DeviceToX (dw, dx); + ty = sy + DeviceToX (dw, dy); + + pointi = 0; + + appendPoint (points, &pointi, sx, sy); + appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2); + + for (i = 2; i < n; i += 2) { + int ux = ox + DeviceToX (dw, dx += v[i]); + int uy = oy + DeviceToX (dw, dy += v[i+1]); + flattenCurve (points, &pointi, + (sx + tx*5)/6, (sy + ty*5)/6, + (tx*5 + ux)/6, (ty*5 + uy)/6, + (tx + ux)/2, (ty + uy)/2); + sx = tx; + sy = ty; + tx = ux; + ty = uy; + } + + appendPoint (points, &pointi, tx, ty); + + XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC, + points, pointi, CoordModeOrigin); +} + + +/* +Local Variables: +c-indent-level: 8 +c-continued-statement-offset: 8 +c-brace-offset: -8 +c-argdecl-indent: 8 +c-label-offset: -8 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/font.c b/contrib/groff/src/devices/xditview/font.c new file mode 100644 index 0000000..c111a7b --- /dev/null +++ b/contrib/groff/src/devices/xditview/font.c @@ -0,0 +1,442 @@ +/* + * font.c + * + * map dvi fonts to X fonts + */ + +#include <X11/Xos.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include "DviP.h" +#include "XFontName.h" + +static void DisposeFontSizes(DviWidget, DviFontSizeList *); +void DestroyFontMap(DviFontMap *); + +static char * +savestr (const char *s) +{ + char *n; + + if (!s) + return 0; + n = XtMalloc (strlen (s) + 1); + if (n) + strcpy (n, s); + return n; +} + +static DviFontList * +LookupFontByPosition (DviWidget dw, int position) +{ + DviFontList *f; + + for (f = dw->dvi.fonts; f; f = f->next) + if (f->dvi_number == position) + break; + return f; +} + +int +MaxFontPosition (DviWidget dw) +{ + DviFontList *f; + int n = -1; + + for (f = dw->dvi.fonts; f; f = f->next) + if (f->dvi_number > n) + n = f->dvi_number; + return n; +} + +static DviFontSizeList * +LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size) +{ + DviFontSizeList *fs, *best = 0, *smallest = 0; + int bestsize = 0; + XFontName fontName; + unsigned int fontNameAttributes; + char fontNameString[2048]; + int decipointsize; + + if (f->scalable) { + decipointsize = (10*size)/dw->dvi.sizescale; + for (best = f->sizes; best; best = best->next) + if (best->size == decipointsize) + return best; + best = (DviFontSizeList *) XtMalloc(sizeof *best); + best->next = f->sizes; + best->size = decipointsize; + f->sizes = best; + XParseFontName (f->x_name, &fontName, &fontNameAttributes); + fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth); + fontNameAttributes |= FontNameResolutionX; + fontNameAttributes |= FontNameResolutionY; + fontNameAttributes |= FontNamePointSize; + fontName.ResolutionX = dw->dvi.display_resolution; + fontName.ResolutionY = dw->dvi.display_resolution; + fontName.PointSize = decipointsize; + XFormatFontName (&fontName, fontNameAttributes, fontNameString); + best->x_name = savestr (fontNameString); + best->doesnt_exist = 0; + best->font = 0; + return best; + } + for (fs = f->sizes; fs; fs=fs->next) { + if (dw->dvi.sizescale*fs->size <= 10*size + && fs->size >= bestsize) { + best = fs; + bestsize = fs->size; + } + if (smallest == 0 || fs->size < smallest->size) + smallest = fs; + } + return best ? best : smallest; +} + +static char * +SkipFontNameElement (char *n) +{ + while (*n != '-') + if (!*++n) + return 0; + return n+1; +} + +# define SizePosition 8 +# define EncodingPosition 13 + +static int +ConvertFontNameToSize (char *n) +{ + int i, size; + + for (i = 0; i < SizePosition; i++) { + n = SkipFontNameElement (n); + if (!n) + return -1; + } + size = atoi (n); + return size; +} + +static char * +ConvertFontNameToEncoding (char *n) +{ + int i; + for (i = 0; i < EncodingPosition; i++) { + n = SkipFontNameElement (n); + if (!n) + return 0; + } + return n; +} + +DviFontSizeList * +InstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep) +{ + char fontNameString[2048]; + char **fonts; + int i, count; + int size; + DviFontSizeList *sizes, *new_size; + XFontName fontName; + unsigned int fontNameAttributes; + + *scalablep = FALSE; + if (!XParseFontName ((XFontNameString)x_name, &fontName, + &fontNameAttributes)) + return 0; + fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize + |FontNameAverageWidth); + fontNameAttributes |= FontNameResolutionX; + fontNameAttributes |= FontNameResolutionY; + fontName.ResolutionX = dw->dvi.display_resolution; + fontName.ResolutionY = dw->dvi.display_resolution; + XFormatFontName (&fontName, fontNameAttributes, fontNameString); + fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count); + sizes = 0; + for (i = 0; i < count; i++) { + size = ConvertFontNameToSize (fonts[i]); + if (size == 0) { + DisposeFontSizes (dw, sizes); + sizes = 0; + *scalablep = TRUE; + break; + } + if (size != -1) { + new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size); + new_size->next = sizes; + new_size->size = size; + new_size->x_name = savestr (fonts[i]); + new_size->doesnt_exist = 0; + new_size->font = 0; + sizes = new_size; + } + } + XFreeFontNames (fonts); + return sizes; +} + +static void +DisposeFontSizes (DviWidget dw, DviFontSizeList *fs) +{ + DviFontSizeList *next; + + for (; fs; fs=next) { + next = fs->next; + if (fs->x_name) + XtFree (fs->x_name); + if (fs->font && fs->font != dw->dvi.default_font) { + XUnloadFont (XtDisplay (dw), fs->font->fid); + XFree ((char *)fs->font); + } + XtFree ((char *) fs); + } +} + +static DviFontList * +InstallFont (DviWidget dw, int position, + const char *dvi_name, const char *x_name) +{ + DviFontList *f; + char *encoding; + + if ((f = LookupFontByPosition (dw, position)) != NULL) { + /* + * ignore gratuitous font loading + */ + if (!strcmp (f->dvi_name, dvi_name) && + !strcmp (f->x_name, x_name)) + return f; + + DisposeFontSizes (dw, f->sizes); + if (f->dvi_name) + XtFree (f->dvi_name); + if (f->x_name) + XtFree (f->x_name); + f->device_font = 0; + } else { + f = (DviFontList *) XtMalloc (sizeof (*f)); + f->next = dw->dvi.fonts; + dw->dvi.fonts = f; + } + f->initialized = FALSE; + f->dvi_name = savestr (dvi_name); + f->device_font = device_find_font (dw->dvi.device, dvi_name); + f->x_name = savestr (x_name); + f->dvi_number = position; + f->sizes = 0; + f->scalable = FALSE; + if (f->x_name) { + encoding = ConvertFontNameToEncoding (f->x_name); + f->char_map = DviFindMap (encoding); + } else + f->char_map = 0; + /* + * force requery of fonts + */ + dw->dvi.font = 0; + dw->dvi.font_number = -1; + dw->dvi.cache.font = 0; + dw->dvi.cache.font_number = -1; + dw->dvi.device_font = 0; + dw->dvi.device_font_number = -1; + return f; +} + +void +ForgetFonts (DviWidget dw) +{ + DviFontList *f = dw->dvi.fonts; + + while (f) { + DviFontList *tem = f; + + if (f->sizes) + DisposeFontSizes (dw, f->sizes); + if (f->dvi_name) + XtFree (f->dvi_name); + if (f->x_name) + XtFree (f->x_name); + f = f->next; + XtFree ((char *) tem); + } + + /* + * force requery of fonts + */ + dw->dvi.font = 0; + dw->dvi.font_number = -1; + dw->dvi.cache.font = 0; + dw->dvi.cache.font_number = -1; + dw->dvi.device_font = 0; + dw->dvi.device_font_number = -1; + dw->dvi.fonts = 0; +} + + +static char * +MapDviNameToXName (DviWidget dw, const char *dvi_name) +{ + DviFontMap *fm; + + for (fm = dw->dvi.font_map; fm; fm=fm->next) + if (!strcmp (fm->dvi_name, dvi_name)) + return fm->x_name; + return 0; +} + +#if 0 +static char * +MapXNameToDviName (DviWidget dw, const char *x_name) +{ + DviFontMap *fm; + + for (fm = dw->dvi.font_map; fm; fm=fm->next) + if (!strcmp (fm->x_name, x_name)) + return fm->dvi_name; + return 0; +} +#endif + +void +ParseFontMap (DviWidget dw) +{ + char dvi_name[1024]; + char x_name[2048]; + char *m, *s; + DviFontMap *fm, *new_map; + + if (dw->dvi.font_map) + DestroyFontMap (dw->dvi.font_map); + fm = 0; + m = dw->dvi.font_map_string; + while (*m) { + s = m; + while (*m && !isspace (*m)) + ++m; + strncpy (dvi_name, s, m-s); + dvi_name[m-s] = '\0'; + while (isspace (*m)) + ++m; + s = m; + while (*m && *m != '\n') + ++m; + strncpy (x_name, s, m-s); + x_name[m-s] = '\0'; + new_map = (DviFontMap *) XtMalloc (sizeof *new_map); + new_map->x_name = savestr (x_name); + new_map->dvi_name = savestr (dvi_name); + new_map->next = fm; + fm = new_map; + ++m; + } + dw->dvi.font_map = fm; +} + +void +DestroyFontMap (DviFontMap *font_map) +{ + DviFontMap *next; + + for (; font_map; font_map = next) { + next = font_map->next; + if (font_map->x_name) + XtFree (font_map->x_name); + if (font_map->dvi_name) + XtFree (font_map->dvi_name); + XtFree ((char *) font_map); + } +} + +/* ARGSUSED */ + +void +SetFontPosition (DviWidget dw, int position, + const char *dvi_name, const char *extra) +{ + char *x_name; + + x_name = MapDviNameToXName (dw, dvi_name); + if (x_name) + (void) InstallFont (dw, position, dvi_name, x_name); + + extra = extra; /* unused; suppress compiler warning */ +} + +XFontStruct * +QueryFont (DviWidget dw, int position, int size) +{ + DviFontList *f; + DviFontSizeList *fs; + + f = LookupFontByPosition (dw, position); + if (!f) + return dw->dvi.default_font; + if (!f->initialized) { + f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable); + f->initialized = TRUE; + } + fs = LookupFontSizeBySize (dw, f, size); + if (!fs) + return dw->dvi.default_font; + if (!fs->font) { + if (fs->x_name) + fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name); + if (!fs->font) + fs->font = dw->dvi.default_font; + } + return fs->font; +} + +DeviceFont * +QueryDeviceFont (DviWidget dw, int position) +{ + DviFontList *f; + + f = LookupFontByPosition (dw, position); + if (!f) + return 0; + return f->device_font; +} + +DviCharNameMap * +QueryFontMap (DviWidget dw, int position) +{ + DviFontList *f; + + f = LookupFontByPosition (dw, position); + if (f) + return f->char_map; + else + return 0; +} + +#if 0 +LoadFont (DviWidget dw, int position, int size) +{ + XFontStruct *font; + + font = QueryFont (dw, position, size); + dw->dvi.font_number = position; + dw->dvi.font_size = size; + dw->dvi.font = font; + XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid); + return; +} +#endif + +/* +Local Variables: +c-indent-level: 8 +c-continued-statement-offset: 8 +c-brace-offset: -8 +c-argdecl-indent: 8 +c-label-offset: -8 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/gray1.bm b/contrib/groff/src/devices/xditview/gray1.bm new file mode 100644 index 0000000..c40a95e --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray1.bm @@ -0,0 +1,4 @@ +#define gray1_width 3 +#define gray1_height 3 +static char gray1_bits[] = { + 0x00, 0x02, 0x00}; diff --git a/contrib/groff/src/devices/xditview/gray2.bm b/contrib/groff/src/devices/xditview/gray2.bm new file mode 100644 index 0000000..e87a1bc --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray2.bm @@ -0,0 +1,4 @@ +#define gray2_width 3 +#define gray2_height 3 +static char gray2_bits[] = { + 0x00, 0x03, 0x00}; diff --git a/contrib/groff/src/devices/xditview/gray3.bm b/contrib/groff/src/devices/xditview/gray3.bm new file mode 100644 index 0000000..d9313eb --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray3.bm @@ -0,0 +1,4 @@ +#define gray3_width 3 +#define gray3_height 3 +static char gray3_bits[] = { + 0x00, 0x03, 0x02}; diff --git a/contrib/groff/src/devices/xditview/gray4.bm b/contrib/groff/src/devices/xditview/gray4.bm new file mode 100644 index 0000000..dad142a --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray4.bm @@ -0,0 +1,4 @@ +#define gray4_width 3 +#define gray4_height 3 +static char gray4_bits[] = { + 0x00, 0x07, 0x02}; diff --git a/contrib/groff/src/devices/xditview/gray5.bm b/contrib/groff/src/devices/xditview/gray5.bm new file mode 100644 index 0000000..5f57618 --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray5.bm @@ -0,0 +1,4 @@ +#define gray5_width 3 +#define gray5_height 3 +static char gray5_bits[] = { + 0x04, 0x07, 0x02}; diff --git a/contrib/groff/src/devices/xditview/gray6.bm b/contrib/groff/src/devices/xditview/gray6.bm new file mode 100644 index 0000000..b76701d --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray6.bm @@ -0,0 +1,4 @@ +#define gray6_width 3 +#define gray6_height 3 +static char gray6_bits[] = { + 0x04, 0x07, 0x03}; diff --git a/contrib/groff/src/devices/xditview/gray7.bm b/contrib/groff/src/devices/xditview/gray7.bm new file mode 100644 index 0000000..ef47bc6 --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray7.bm @@ -0,0 +1,4 @@ +#define gray7_width 3 +#define gray7_height 3 +static char gray7_bits[] = { + 0x05, 0x07, 0x03}; diff --git a/contrib/groff/src/devices/xditview/gray8.bm b/contrib/groff/src/devices/xditview/gray8.bm new file mode 100644 index 0000000..12de7cb --- /dev/null +++ b/contrib/groff/src/devices/xditview/gray8.bm @@ -0,0 +1,4 @@ +#define gray8_width 3 +#define gray8_height 3 +static char gray8_bits[] = { + 0x05, 0x07, 0x07}; diff --git a/contrib/groff/src/devices/xditview/gxditview.man b/contrib/groff/src/devices/xditview/gxditview.man new file mode 100644 index 0000000..2c1302b --- /dev/null +++ b/contrib/groff/src/devices/xditview/gxditview.man @@ -0,0 +1,410 @@ +.TH GXDITVIEW @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" +. +. +.SH NAME +gxditview \- display groff intermediate output files +. +. +.SH SYNOPSIS +.B \%gxditview +.RI [\fB\- toolkitoption\ .\|.\|.\|] +.RI [\fB\- option\ .\|.\|.\|] +.RI [ filename ] +. +. +.SH DESCRIPTION +The +.B \%gxditview +program displays the +.I groff intermediate +.IR output , +see +.BR groff_out (@MAN5EXT@), +on an X\~display. +. +It uses the standard X11 fonts, so it does not require access to the +server machine for font loading. +. +There are several ways to use +.BR \%gxditview . +. +. +.PP +The +.I groff intermediate output +can be generated by +.BR groff\~\-Z . +This can be viewed by explicity calling +.B \%gxditview +.IR \%filename . +If +.I filename +is +.BR \- , +.B \%gxditview +will read the standard input; +.I \%filename +cannot be omitted. +. +The +.I groff intermediate output +is different for all devices. +. +.B \%gxditview +can view it for all devices, but the quality is not always good. +. +. +.PP +The best result is achieved with the +.BR X * +devices for +.BR groff 's +option +.BR \-T . +. +There are four +.BR X * +devices: +.BR \%\-TX75 , +.BR \%\-TX75\-12 , +.BR \%\-TX100 , +.BR \%\-TX100\-12 . +They differ by the X\~resolution (75dpi or 100dpi) and the used base font +size (10pt or 12pt). +. +They are especially built for +.BR \%gxditview . +When using one of them +.B groff +generates the +.I intermediate output +for this device and calls +.B \%gxditview +automatically for viewing. +. +. +.PP +.BR groff 's +option +.B \-X +should be considered obsolete today; it produces +.I intermediate output +for +.I Postscript +and uses +.B \%gxditview +as a viewer for it, but with a bad quality. +. +Simply don't use it. +. +. +.PP +During the run of +.BR \%gxditview , +the left mouse button brings up a menu with the following entries: +. +.TP 8 +.B "Next Page" +Display the next page. +. +.TP +.B "Previous Page" +Display the previous page. +. +.TP +.B "Select Page" +Select a particular numbered page specified by a dialog box. +. +.TP +.B Print +Print the +.I groff intermediate output +using a command specified by a dialog box. +. +The default command initially displayed is controlled by the +.B printCommand +application resource, and by the +.B \-printCommand +option. +. +.TP +.B Open +Open for display a new file specified by a dialog box. +. +The file should contain some +.I groff intermediate +.IR output . +If the filename starts with +.B | +it will be taken to be a command to read from. +. +.TP +.B Quit +Exit from +.BR \%gxditview . +. +. +.PP +The +.IR n , +.I Space +and +.I Return +keys are bound to the +.B Next\ Page +action. +. +The +.IR p , +.I BackSpace +and +.I Delete +keys are bound to the +.B Previous\ Page +action. +. +The +.I q +key is bound to the +.B Quit +action. +. +The +.I r +key is bound to the +.B Rerasterize +action which rereads the current file, and redisplays the current +page; if the current file is a command, the command will be +reexecuted. +. +. +.PP +The +.B paperlength +and +.B paperwidth +commands in the DESC file specify the length and width in machine units +of the virtual page displayed by +.BR \%gxditview . +. +. +.SH OPTIONS +The +.B \%gxditview +program accepts all of the standard X\~Toolkit command line options +along with the additional options listed below: +. +.TP 8 +.B \-help +This option indicates that a brief summary of the allowed options should be +printed. +. +.TP +.B \-page +This option specifies the page number of the document to be displayed. +. +.TP +.BI \-backingStore\ backing-store-type +Redisplay of the +.I groff intermediate output +window can take up to a second or so, this option causes the server to +save the window contents so that when it is scrolled around the +viewport, the window is painted from contents saved in backing store. +.I backing-store-type +can be one of +.BR Always , +.B WhenMapped +or +.BR NotUseful . +. +.TP +.BI \-printCommand\ command +The default command displayed in the dialog box for the +.B Print +menu entry will be +.IR command . +. +.TP +.BI \-resolution\ res +The +.I groff intermediate output +file will be displayed at a resolution of +.I res +dpi, unless the DESC file contains the +.B X11 +command, in which case the device resolution will be used. +. +This corresponds to the +.I Dvi +widget's +.B resolution +resource. +. +The default is 75. +. +.TP +.BI \-filename\ string +The default filename displayed in the dialog box for the +.B Open +menu entry will be +.IR string . +This can be either a filename, or a command starting with +.BR | . +. +. +.PP +The following standard X\~Toolkit command line arguments are commonly used +with +.BR \%gxditview : +. +.TP 8 +.BI \-bg\ color +This option specifies the color to use for the background of the window. +. +The default is \fIwhite\fP. +. +.TP +.BI \-bd\ color +This option specifies the color to use for the border of the window. +. +The default is \fIblack\fP. +. +.TP +.BI \-bw\ number +This option specifies the width in pixels of the border surrounding the +window. +. +.TP +.BI \-fg\ color +This option specifies the color to use for displaying text. +. +The default is +\fIblack\fP. +. +.TP +.BI \-fn\ font +This option specifies the font to be used for displaying widget text. +. +The default is \fIfixed\fP. +. +.TP +.B \-rv +This option indicates that reverse video should be simulated by swapping +the foreground and background colors. +. +.TP +.BI \-geometry\ geometry +This option specifies the preferred size and position of the window. +. +.TP +.BI \-display\ host : display +This option specifies the X\~server to contact. +. +.TP +.BI \-xrm\ resourcestring +This option specifies a resource string to be used. +. +. +.SH X DEFAULTS +This program uses the +.I Dvi +widget in the X\~Toolkit. +. +It understands all of the core resource names and classes as well as: +. +.TP 8 +.BR width\ (class\ Width ) +Specifies the width of the window. +. +.TP +.BR height\ (class\ Height ) +Specifies the height of the window. +. +.TP +.BR foreground\ (class\ Foreground ) +Specifies the default foreground color. +. +.TP +.BR font\ (class\ Font ) +Specifies the font to be used for error messages. +. +.TP +.BR fontMap\ (class\ FontMap ) +Specifies the mapping from +.I groff +font names to X\~font names. +. +This must be a string containing a sequence of lines. +. +Each line contains two whitespace separated fields: first the +.I groff +font name, and secondly the X\~font name. +. +The default is +.nf +"\e +TR -adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e +TI -adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e +TB -adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e +TBI -adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e +CR -adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e +CI -adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e +CB -adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e +CBI -adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e +HR -adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e +HI -adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\en\e +HB -adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e +HBI -adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\en\e +NR -adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\en\e +NI -adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\en\e +NB -adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\en\e +NBI -adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\en\e +S -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e +SS -adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\en\e +" +.fi +. +. +.SH "SEE ALSO" +.BR X (1), +.BR xrdb (1), +.BR xditview (1), +.BR groff (@MAN1EXT@), +.BR groff_out (@MAN5EXT@) +. +. +.SH ORIGIN +This program is derived from +.BR \%xditview ; +portions of +.B \%xditview +originated in +.B \%xtroff +which was derived from +.BR \%suntroff . +. +. +.SH COPYRIGHT +Copyright 1989, Massachusetts Institute of Technology. +.br +See +.BR X (1) +for a full statement of rights and permissions. +. +. +.SH AUTHORS +Keith Packard (MIT X Consortium) +.br +Richard L. Hyde (Purdue) +.br +David Slattengren (Berkeley) +.br +Malcolm Slaney (Schlumberger Palo Alto Research) +.br +Mark Moraes (University of Toronto) +.br +James Clark +. +.\" Local Variables: +.\" mode: nroff +.\" End: diff --git a/contrib/groff/src/devices/xditview/lex.c b/contrib/groff/src/devices/xditview/lex.c new file mode 100644 index 0000000..dfe1e0d --- /dev/null +++ b/contrib/groff/src/devices/xditview/lex.c @@ -0,0 +1,96 @@ +#include <X11/Xos.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <stdio.h> +#include "DviP.h" + +int +DviGetAndPut(DviWidget dw, int *cp) +{ + if (dw->dvi.ungot) { + dw->dvi.ungot = 0; + *cp = getc (dw->dvi.file); + } + else { + *cp = getc (dw->dvi.file); + if (*cp != EOF) + putc (*cp, dw->dvi.tmpFile); + } + return *cp; +} + +char * +GetLine(DviWidget dw, char *Buffer, int Length) +{ + int i = 0, c; + + Length--; /* Save room for final '\0' */ + + while (DviGetC (dw, &c) != EOF) { + if (Buffer && i < Length) + Buffer[i++] = c; + if (c == '\n') { + DviUngetC(dw, c); + break; + } + } + if (Buffer) + Buffer[i] = '\0'; + return Buffer; +} + +char * +GetWord(DviWidget dw, char *Buffer, int Length) +{ + int i = 0, c; + + Length--; /* Save room for final '\0' */ + while (DviGetC(dw, &c) == ' ' || c == '\n') + ; + while (c != EOF) { + if (Buffer && i < Length) + Buffer[i++] = c; + if (DviGetC(dw, &c) == ' ' || c == '\n') { + DviUngetC(dw, c); + break; + } + } + if (Buffer) + Buffer[i] = '\0'; + return Buffer; +} + +int +GetNumber(DviWidget dw) +{ + int i = 0, c; + int negative = 0; + + while (DviGetC(dw, &c) == ' ' || c == '\n') + ; + if (c == '-') { + negative = 1; + DviGetC(dw, &c); + } + + for (; c >= '0' && c <= '9'; DviGetC(dw, &c)) { + if (negative) + i = i*10 - (c - '0'); + else + i = i*10 + c - '0'; + } + if (c != EOF) + DviUngetC(dw, c); + return i; +} + +/* +Local Variables: +c-indent-level: 8 +c-continued-statement-offset: 8 +c-brace-offset: -8 +c-argdecl-indent: 8 +c-label-offset: -8 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/page.c b/contrib/groff/src/devices/xditview/page.c new file mode 100644 index 0000000..d1c5c9f --- /dev/null +++ b/contrib/groff/src/devices/xditview/page.c @@ -0,0 +1,82 @@ +/* + * page.c + * + * map page numbers to file position + */ + +#include <X11/Xos.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <stdio.h> +#include <ctype.h> +#include "DviP.h" + +#ifdef X_NOT_STDC_ENV +extern long ftell(); +#endif + +static DviFileMap * +MapPageNumberToFileMap (DviWidget dw, int number) +{ + DviFileMap *m; + + for (m = dw->dvi.file_map; m; m=m->next) + if (m->page_number == number) + break; + return m; +} + +void +DestroyFileMap (DviFileMap *m) +{ + DviFileMap *next; + + for (; m; m = next) { + next = m->next; + XtFree ((char *) m); + } +} + +void +ForgetPagePositions (DviWidget dw) +{ + DestroyFileMap (dw->dvi.file_map); + dw->dvi.file_map = 0; +} + +void +RememberPagePosition(DviWidget dw, int number) +{ + DviFileMap *m; + + if (!(m = MapPageNumberToFileMap (dw, number))) { + m = (DviFileMap *) XtMalloc (sizeof *m); + m->page_number = number; + m->next = dw->dvi.file_map; + dw->dvi.file_map = m; + } + if (dw->dvi.tmpFile) + m->position = ftell (dw->dvi.tmpFile); + else + m->position = ftell (dw->dvi.file); +} + +long +SearchPagePosition (DviWidget dw, int number) +{ + DviFileMap *m; + + if (!(m = MapPageNumberToFileMap (dw, number))) + return -1; + return m->position; +} + +void +FileSeek(DviWidget dw, long position) +{ + if (dw->dvi.tmpFile) { + dw->dvi.readingTmp = 1; + fseek (dw->dvi.tmpFile, position, 0); + } else + fseek (dw->dvi.file, position, 0); +} diff --git a/contrib/groff/src/devices/xditview/parse.c b/contrib/groff/src/devices/xditview/parse.c new file mode 100644 index 0000000..de7d6ba --- /dev/null +++ b/contrib/groff/src/devices/xditview/parse.c @@ -0,0 +1,366 @@ +/* + * parse.c + * + * parse dvi input + */ + +#include <X11/Xos.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <stdio.h> +#include <ctype.h> +#include "DviP.h" + +static int StopSeen = 0; +static void ParseDrawFunction(DviWidget, char *); +static void ParseDeviceControl(DviWidget); +static void push_env(DviWidget); +static void pop_env(DviWidget); + +/* draw.c */ +extern int PutCharacter(DviWidget, char *); +extern int PutNumberedCharacter(DviWidget, int); +extern void HorizontalGoto(DviWidget, int); +extern void Word(DviWidget); +extern void VerticalGoto(DviWidget, int); +extern void VerticalMove(DviWidget, int); +extern void FlushCharCache(DviWidget); +extern void Newline(DviWidget); +extern void DrawLine(DviWidget, int, int); +extern void DrawCircle(DviWidget, int); +extern void DrawFilledCircle(DviWidget, int); +extern void DrawEllipse(DviWidget, int, int); +extern void DrawFilledEllipse(DviWidget, int, int); +extern void DrawArc(DviWidget, int, int, int, int); +extern void DrawPolygon(DviWidget, int *, int); +extern void DrawFilledPolygon(DviWidget, int *, int); +extern void DrawSpline(DviWidget, int *, int); + +/* Dvi.c */ +extern void SetDevice(DviWidget, const char *); + +/* page.c */ +extern void RememberPagePosition(DviWidget, int); + +/* font.c */ +extern void SetFontPosition(DviWidget, int, const char *, const char *); + +/* lex.c */ +extern int GetNumber(DviWidget); + +#define HorizontalMove(dw, delta) ((dw)->dvi.state->x += (delta)) + + +int +ParseInput(register DviWidget dw) +{ + int n, k; + int c; + char Buffer[BUFSIZ]; + int NextPage; + int otherc; + + StopSeen = 0; + + /* + * make sure some state exists + */ + + if (!dw->dvi.state) + push_env (dw); + for (;;) { + switch (DviGetC(dw, &c)) { + case '\n': + break; + case ' ': /* when input is text */ + case 0: /* occasional noise creeps in */ + break; + case '{': /* push down current environment */ + push_env(dw); + break; + case '}': + pop_env(dw); + break; + /* + * two motion digits plus a character + */ + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + HorizontalMove(dw, (c-'0')*10 + + DviGetC(dw,&otherc)-'0'); + /* fall through */ + case 'c': /* single ascii character */ + DviGetC(dw,&c); + if (c == ' ') + break; + Buffer[0] = c; + Buffer[1] = '\0'; + (void) PutCharacter (dw, Buffer); + break; + case 'C': + GetWord (dw, Buffer, BUFSIZ); + (void) PutCharacter (dw, Buffer); + break; + case 't': + Buffer[1] = '\0'; + while (DviGetC (dw, &c) != EOF + && c != ' ' && c != '\n') { + Buffer[0] = c; + HorizontalMove (dw, PutCharacter (dw, Buffer)); + } + break; + case 'u': + n = GetNumber(dw); + Buffer[1] = '\0'; + while (DviGetC (dw, &c) == ' ') + ; + while (c != EOF && c != ' ' && c != '\n') { + Buffer[0] = c; + HorizontalMove (dw, + PutCharacter (dw, Buffer) + n); + DviGetC (dw, &c); + } + break; + + case 'D': /* draw function */ + (void) GetLine(dw, Buffer, BUFSIZ); + if (dw->dvi.display_enable) + ParseDrawFunction(dw, Buffer); + break; + case 's': /* ignore fractional sizes */ + n = GetNumber(dw); + dw->dvi.state->font_size = n; + break; + case 'f': + n = GetNumber(dw); + dw->dvi.state->font_number = n; + break; + case 'H': /* absolute horizontal motion */ + k = GetNumber(dw); + HorizontalGoto(dw, k); + break; + case 'h': /* relative horizontal motion */ + k = GetNumber(dw); + HorizontalMove(dw, k); + break; + case 'w': /* word space */ + Word (dw); + break; + case 'V': + n = GetNumber(dw); + VerticalGoto(dw, n); + break; + case 'v': + n = GetNumber(dw); + VerticalMove(dw, n); + break; + case 'P': /* new spread */ + break; + case 'p': /* new page */ + (void) GetNumber(dw); + NextPage = dw->dvi.current_page + 1; + RememberPagePosition(dw, NextPage); + FlushCharCache (dw); + return(NextPage); + case 'N': + n = GetNumber(dw); + PutNumberedCharacter (dw, n); + break; + case 'n': /* end of line */ + GetNumber(dw); + GetNumber(dw); + Newline (dw); + HorizontalGoto(dw, 0); + break; + case 'F': /* input files */ + case '+': /* continuation of X device control */ + case 'm': /* color */ + case '#': /* comment */ + GetLine(dw, NULL, 0); + break; + case 'x': /* device control */ + ParseDeviceControl(dw); + break; + case EOF: + dw->dvi.last_page = dw->dvi.current_page; + FlushCharCache (dw); + return dw->dvi.current_page; + default: + break; + } + } +} + +static void +push_env(DviWidget dw) +{ + DviState *new_state; + + new_state = (DviState *) XtMalloc (sizeof (*new_state)); + if (dw->dvi.state) + *new_state = *(dw->dvi.state); + else { + new_state->font_size = 10; + new_state->font_number = 1; + new_state->x = 0; + new_state->y = 0; + } + new_state->next = dw->dvi.state; + dw->dvi.state = new_state; +} + +static void +pop_env(DviWidget dw) +{ + DviState *old; + + old = dw->dvi.state; + dw->dvi.state = old->next; + XtFree ((char *) old); +} + +static void +InitTypesetter (DviWidget dw) +{ + while (dw->dvi.state) + pop_env (dw); + push_env (dw); + FlushCharCache (dw); +} + +#define DRAW_ARGS_MAX 128 + +static void +ParseDrawFunction(DviWidget dw, char *buf) +{ + int v[DRAW_ARGS_MAX]; + int i, no_move = 0; + char *ptr; + + v[0] = v[1] = v[2] = v[3] = 0; + + if (buf[0] == '\0') + return; + ptr = buf+1; + + for (i = 0; i < DRAW_ARGS_MAX; i++) { + if (sscanf(ptr, "%d", v + i) != 1) + break; + while (*ptr == ' ') + ptr++; + while (*ptr != '\0' && *ptr != ' ') + ptr++; + } + + switch (buf[0]) { + case 'l': /* draw a line */ + DrawLine(dw, v[0], v[1]); + break; + case 'c': /* circle */ + DrawCircle(dw, v[0]); + break; + case 'C': + DrawFilledCircle(dw, v[0]); + break; + case 'e': /* ellipse */ + DrawEllipse(dw, v[0], v[1]); + break; + case 'E': + DrawFilledEllipse(dw, v[0], v[1]); + break; + case 'a': /* arc */ + DrawArc(dw, v[0], v[1], v[2], v[3]); + break; + case 'p': + DrawPolygon(dw, v, i); + break; + case 'P': + DrawFilledPolygon(dw, v, i); + break; + case '~': /* wiggly line */ + DrawSpline(dw, v, i); + break; + case 't': + dw->dvi.line_thickness = v[0]; + break; + case 'f': + if (i > 0 && v[0] >= 0 && v[0] <= DVI_FILL_MAX) + dw->dvi.fill = v[0]; + no_move = 1; + break; + default: +#if 0 + warning("unknown drawing function %s", buf); +#endif + no_move = 1; + break; + } + + if (!no_move) { + if (buf[0] == 'e') { + if (i > 0) + dw->dvi.state->x += v[0]; + } + else { + while (--i >= 0) { + if (i & 1) + dw->dvi.state->y += v[i]; + else + dw->dvi.state->x += v[i]; + } + } + } +} + +static void +ParseDeviceControl(DviWidget dw) /* Parse the x commands */ +{ + char str[20], str1[50]; + int c, n; + + GetWord (dw, str, 20); + switch (str[0]) { /* crude for now */ + case 'T': /* output device */ + GetWord (dw, str, 20); + SetDevice (dw, str); + break; + case 'i': /* initialize */ + InitTypesetter (dw); + break; + case 't': /* trailer */ + break; + case 'p': /* pause -- can restart */ + break; + case 's': /* stop */ + StopSeen = 1; + return; + case 'r': /* resolution when prepared */ + break; + case 'f': /* font used */ + n = GetNumber (dw); + GetWord (dw, str, 20); + GetLine (dw, str1, 50); + SetFontPosition (dw, n, str, str1); + break; + case 'H': /* char height */ + break; + case 'S': /* slant */ + break; + } + while (DviGetC (dw, &c) != '\n') /* skip rest of input line */ + if (c == EOF) + return; + return; +} + + +/* +Local Variables: +c-indent-level: 8 +c-continued-statement-offset: 8 +c-brace-offset: -8 +c-argdecl-indent: 8 +c-label-offset: -8 +c-tab-always-indent: nil +End: +*/ diff --git a/contrib/groff/src/devices/xditview/xdit.bm b/contrib/groff/src/devices/xditview/xdit.bm new file mode 100644 index 0000000..0c7aa8c --- /dev/null +++ b/contrib/groff/src/devices/xditview/xdit.bm @@ -0,0 +1,14 @@ +#define xdit_width 32 +#define xdit_height 32 +static unsigned char xdit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x03, 0x02, 0x00, 0x00, 0x02, + 0x8a, 0xa2, 0xfc, 0x03, 0x52, 0x14, 0x03, 0x04, 0x02, 0x80, 0x00, 0x08, + 0x52, 0x54, 0x00, 0x10, 0x8a, 0x22, 0x8f, 0x23, 0x02, 0x20, 0x06, 0x21, + 0x8a, 0x12, 0x8c, 0x40, 0x52, 0x14, 0x8c, 0x40, 0x02, 0x10, 0x58, 0x40, + 0x52, 0x14, 0x30, 0x40, 0x8a, 0x12, 0x30, 0x40, 0x02, 0x10, 0x70, 0x40, + 0x8a, 0x12, 0xc8, 0x40, 0x52, 0x24, 0xc4, 0xe0, 0x02, 0x20, 0x84, 0xe1, + 0x52, 0x54, 0xce, 0xf3, 0x8a, 0xa2, 0x00, 0xf8, 0x02, 0x00, 0x03, 0xfc, + 0x8a, 0x22, 0xfc, 0xf3, 0x52, 0x14, 0x00, 0xc2, 0x02, 0x00, 0x00, 0x02, + 0x52, 0x14, 0x45, 0x02, 0x8a, 0xa2, 0x28, 0x02, 0x02, 0x00, 0x00, 0x02, + 0x02, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/contrib/groff/src/devices/xditview/xdit_mask.bm b/contrib/groff/src/devices/xditview/xdit_mask.bm new file mode 100644 index 0000000..a584629 --- /dev/null +++ b/contrib/groff/src/devices/xditview/xdit_mask.bm @@ -0,0 +1,14 @@ +#define xdit_mask_width 32 +#define xdit_mask_height 32 +static unsigned char xdit_mask_bits[] = { + 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, + 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f, + 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xc7, + 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, + 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/contrib/groff/src/devices/xditview/xditview.c b/contrib/groff/src/devices/xditview/xditview.c new file mode 100644 index 0000000..7afdb47 --- /dev/null +++ b/contrib/groff/src/devices/xditview/xditview.c @@ -0,0 +1,657 @@ +/* + * Copyright 1991 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ +/* + * xditview -- + * + * Display ditroff output in an X window + */ + +#ifndef SABER +#ifndef lint +static char rcsid[] = "$XConsortium: xditview.c,v 1.17 89/12/10 17:05:08 rws Exp $"; +#endif /* lint */ +#endif /* SABER */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <X11/Xatom.h> +#include <X11/Xlib.h> +#include <X11/Xos.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xaw/Paned.h> +#include <X11/Xaw/Viewport.h> +#include <X11/Xaw/Box.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Dialog.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/SimpleMenu.h> +#include <X11/Xaw/SmeBSB.h> + +#include <stdlib.h> +#include <signal.h> +#include <stdio.h> + +#include "Dvi.h" + +#include "xdit.bm" +#include "xdit_mask.bm" + +#ifdef NEED_DECLARATION_POPEN +FILE *popen(const char *, const char *); +#endif /* NEED_DECLARATION_POPEN */ + +#ifdef NEED_DECLARATION_PCLOSE +int pclose (FILE *); +#endif /* NEED_DECLARATION_PCLOSE */ + +typedef void (*MakePromptFunc)(const char *); + +static String fallback_resources[] = { +#include "GXditview-ad.h" + NULL +}; + +static struct app_resources { + char *print_command; + char *filename; +} app_resources; + +#define offset(field) XtOffset(struct app_resources *, field) + +/* Application resources. */ + +static XtResource resources[] = { + {(String)"printCommand", (String)"PrintCommand", (String)XtRString, + sizeof(char*), offset(print_command), (String)XtRString, NULL}, + {(String)"filename", (String)"Filename", (String)XtRString, + sizeof(char*), offset(filename), (String)XtRString, NULL}, +}; + +#undef offset + +/* Command line options table. Only resources are entered here...there is a + pass over the remaining options after XtParseCommand is let loose. */ + +static XrmOptionDescRec options[] = { +{(char *)"-page", (char *)"*dvi.pageNumber", + XrmoptionSepArg, NULL}, +{(char *)"-backingStore", (char *)"*dvi.backingStore", + XrmoptionSepArg, NULL}, +{(char *)"-resolution", (char *)"*dvi.resolution", + XrmoptionSepArg, NULL}, +{(char *)"-printCommand", (char *)".printCommand", + XrmoptionSepArg, NULL}, +{(char *)"-filename", (char *)".filename", + XrmoptionSepArg, NULL}, +{(char *)"-noPolyText", (char *)"*dvi.noPolyText", + XrmoptionNoArg, (XPointer)"TRUE"}, +}; + +static char current_print_command[1024]; + +static char current_file_name[1024]; +static FILE *current_file; + +/* + * Report the syntax for calling xditview. + */ + +static void +Syntax(const char *call) +{ + (void) printf ("Usage: %s [-fg <color>] [-bg <color>]\n", call); + (void) printf (" [-bd <color>] [-bw <pixels>] [-help]\n"); + (void) printf (" [-display displayname] [-geometry geom]\n"); + (void) printf (" [-page <page-number>] [-backing <backing-store>]\n"); + (void) printf (" [-resolution <res>] [-print <command>]\n"); + (void) printf (" [-filename <file>] [filename]\n\n"); + exit(1); +} + +static void NewFile (const char *); +static void SetPageNumber (int); +static Widget toplevel, paned, viewport, dvi; +static Widget page; +static Widget simpleMenu; + +static void NextPage(Widget, XtPointer, XtPointer); +static void PreviousPage(Widget, XtPointer, XtPointer); +static void SelectPage(Widget, XtPointer, XtPointer); +static void OpenFile(Widget, XtPointer, XtPointer); +static void Quit(Widget, XtPointer, XtPointer); +static void Print(Widget, XtPointer, XtPointer); + +static struct menuEntry { + const char *name; + XtCallbackProc function; +} menuEntries[] = { + {"nextPage", NextPage}, + {"previousPage", PreviousPage}, + {"selectPage", SelectPage}, + {"print", Print}, + {"openFile", OpenFile}, + {"quit", Quit}, +}; + +static void NextPageAction(Widget, XEvent *, String *, Cardinal *); +static void PreviousPageAction(Widget, XEvent *, String *, Cardinal *); +static void SelectPageAction(Widget, XEvent *, String *, Cardinal *); +static void OpenFileAction(Widget, XEvent *, String *, Cardinal *); +static void QuitAction(Widget, XEvent *, String *, Cardinal *); +static void AcceptAction(Widget, XEvent *, String *, Cardinal *); +static void CancelAction(Widget, XEvent *, String *, Cardinal *); +static void PrintAction(Widget, XEvent *, String *, Cardinal *); +static void RerasterizeAction(Widget, XEvent *, String *, Cardinal *); + +static void MakePrompt(Widget, const char *, MakePromptFunc, const char *); + +XtActionsRec xditview_actions[] = { + {(String)"NextPage", NextPageAction}, + {(String)"PreviousPage", PreviousPageAction}, + {(String)"SelectPage", SelectPageAction}, + {(String)"Print", PrintAction}, + {(String)"OpenFile", OpenFileAction}, + {(String)"Rerasterize", RerasterizeAction}, + {(String)"Quit", QuitAction}, + {(String)"Accept", AcceptAction}, + {(String)"Cancel", CancelAction}, +}; + +#define MenuNextPage 0 +#define MenuPreviousPage 1 +#define MenuSelectPage 2 +#define MenuPrint 3 +#define MenuOpenFile 4 +#define MenuQuit 5 + +static char pageLabel[256] = "Page <none>"; + +int main(int argc, char **argv) +{ + char *file_name = 0; + Cardinal i; + static Arg labelArgs[] = { + {XtNlabel, (XtArgVal) pageLabel}, + }; + XtAppContext xtcontext; + Arg topLevelArgs[2]; + Widget entry; + Arg pageNumberArgs[1]; + int page_number; + + toplevel = XtAppInitialize(&xtcontext, "GXditview", + options, XtNumber (options), + &argc, argv, fallback_resources, NULL, 0); + if (argc > 2 + || (argc == 2 && (!strcmp(argv[1], "-help") + || !strcmp(argv[1], "--help")))) + Syntax(argv[0]); + + XtGetApplicationResources(toplevel, (XtPointer)&app_resources, + resources, XtNumber(resources), + NULL, (Cardinal) 0); + if (app_resources.print_command) + strcpy(current_print_command, app_resources.print_command); + + XtAppAddActions(xtcontext, xditview_actions, XtNumber (xditview_actions)); + + XtSetArg (topLevelArgs[0], XtNiconPixmap, + XCreateBitmapFromData (XtDisplay (toplevel), + XtScreen(toplevel)->root, + (char *)xdit_bits, + xdit_width, xdit_height)); + + XtSetArg (topLevelArgs[1], XtNiconMask, + XCreateBitmapFromData (XtDisplay (toplevel), + XtScreen(toplevel)->root, + (char *)xdit_mask_bits, + xdit_mask_width, xdit_mask_height)); + XtSetValues (toplevel, topLevelArgs, 2); + if (argc > 1) + file_name = argv[1]; + + /* + * create the menu and insert the entries + */ + simpleMenu = XtCreatePopupShell ("menu", simpleMenuWidgetClass, toplevel, + NULL, 0); + for (i = 0; i < XtNumber (menuEntries); i++) { + entry = XtCreateManagedWidget(menuEntries[i].name, + smeBSBObjectClass, simpleMenu, + NULL, (Cardinal) 0); + XtAddCallback(entry, XtNcallback, menuEntries[i].function, NULL); + } + + paned = XtCreateManagedWidget("paned", panedWidgetClass, toplevel, + NULL, (Cardinal) 0); + viewport = XtCreateManagedWidget("viewport", viewportWidgetClass, paned, + NULL, (Cardinal) 0); + dvi = XtCreateManagedWidget ("dvi", dviWidgetClass, viewport, NULL, 0); + page = XtCreateManagedWidget ("label", labelWidgetClass, paned, + labelArgs, XtNumber (labelArgs)); + XtSetArg (pageNumberArgs[0], XtNpageNumber, &page_number); + XtGetValues (dvi, pageNumberArgs, 1); + if (file_name) + NewFile (file_name); + /* NewFile modifies current_file_name, so do this here. */ + if (app_resources.filename) + strcpy(current_file_name, app_resources.filename); + XtRealizeWidget (toplevel); + if (file_name) + SetPageNumber (page_number); + XtAppMainLoop(xtcontext); + return 0; +} + +static void +SetPageNumber (int number) +{ + Arg arg[2]; + int actual_number, last_page; + + XtSetArg (arg[0], XtNpageNumber, number); + XtSetValues (dvi, arg, 1); + XtSetArg (arg[0], XtNpageNumber, &actual_number); + XtSetArg (arg[1], XtNlastPageNumber, &last_page); + XtGetValues (dvi, arg, 2); + if (actual_number == 0) + sprintf (pageLabel, "Page <none>"); + else if (last_page > 0) + sprintf (pageLabel, "Page %d of %d", actual_number, last_page); + else + sprintf (pageLabel, "Page %d", actual_number); + XtSetArg (arg[0], XtNlabel, pageLabel); + XtSetValues (page, arg, 1); +} + +static void +SelectPageNumber (const char *number_string) +{ + SetPageNumber (atoi(number_string)); +} + +static int hadFile = 0; + +static void +NewFile (const char *name) +{ + Arg arg[2]; + char *n; + FILE *new_file; + Boolean seek = 0; + + if (current_file) { + if (!strcmp (current_file_name, "-")) + ; + else if (current_file_name[0] == '|') + pclose (current_file); + else + fclose (current_file); + } + if (!strcmp (name, "-")) + new_file = stdin; + else if (name[0] == '|') + new_file = popen (name+1, "r"); + else { + new_file = fopen (name, "r"); + seek = 1; + } + if (!new_file) { + /* XXX display error message */ + return; + } + XtSetArg (arg[0], XtNfile, new_file); + XtSetArg (arg[1], XtNseek, seek); + XtSetValues (dvi, arg, 2); + if (hadFile || name[0] != '-' || name[1] != '\0') { + XtSetArg (arg[0], XtNtitle, name); + if (name[0] != '/' && (n = strrchr (name, '/'))) + n = n + 1; + else + n = (char *)name; + XtSetArg (arg[1], XtNiconName, n); + XtSetValues (toplevel, arg, 2); + } + hadFile = 1; + SelectPageNumber ("1"); + strcpy (current_file_name, name); + current_file = new_file; +} + +static char fileBuf[1024]; + +static void +ResetMenuEntry (Widget entry) +{ + Arg arg[1]; + + XtSetArg (arg[0], (String)XtNpopupOnEntry, entry); + XtSetValues (XtParent(entry) , arg, (Cardinal) 1); +} + +/*ARGSUSED*/ + +static void +NextPage (Widget entry, XtPointer name, XtPointer data) +{ + name = name; /* unused; suppress compiler warning */ + data = data; + + NextPageAction((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); + ResetMenuEntry (entry); +} + +static void +NextPageAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + Arg args[1]; + int number; + + XtSetArg (args[0], XtNpageNumber, &number); + XtGetValues (dvi, args, 1); + SetPageNumber (number+1); + + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; +} + +/*ARGSUSED*/ + +static void +PreviousPage (Widget entry, XtPointer name, XtPointer data) +{ + name = name; /* unused; suppress compiler warning */ + data = data; + + PreviousPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0, + (Cardinal *) 0); + ResetMenuEntry (entry); +} + +static void +PreviousPageAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + Arg args[1]; + int number; + + XtSetArg (args[0], XtNpageNumber, &number); + XtGetValues (dvi, args, 1); + SetPageNumber (number-1); + + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; +} + +/* ARGSUSED */ + +static void +SelectPage (Widget entry, XtPointer name, XtPointer data) +{ + name = name; /* unused; suppress compiler warning */ + data = data; + + SelectPageAction ((Widget)NULL, (XEvent *) 0, (String *) 0, + (Cardinal *) 0); + ResetMenuEntry (entry); +} + +static void +SelectPageAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; + + MakePrompt (toplevel, "Page number", SelectPageNumber, ""); +} + + +static void +DoPrint (const char *name) +{ + FILE *print_file; + RETSIGTYPE (*handler)(int); + + /* Avoid dieing because of an invalid command. */ + handler = signal(SIGPIPE, SIG_IGN); + + print_file = popen(name, "w"); + if (!print_file) + /* XXX print error message */ + return; + DviSaveToFile(dvi, print_file); + pclose(print_file); + signal(SIGPIPE, handler); + strcpy(current_print_command, name); +} + +static void +RerasterizeAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + Arg args[1]; + int number; + + if (current_file_name[0] == 0) { + /* XXX display an error message */ + return; + } + XtSetArg (args[0], XtNpageNumber, &number); + XtGetValues (dvi, args, 1); + NewFile(current_file_name); + SetPageNumber (number); + + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; +} + +/* ARGSUSED */ + +static void +Print (Widget entry, XtPointer name, XtPointer data) +{ + name = name; /* unused; suppress compiler warning */ + data = data; + + PrintAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); + ResetMenuEntry (entry); +} + +static void +PrintAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; + + if (current_print_command[0]) + strcpy (fileBuf, current_print_command); + else + fileBuf[0] = '\0'; + MakePrompt (toplevel, "Print command:", DoPrint, fileBuf); +} + + +/* ARGSUSED */ + +static void +OpenFile (Widget entry, XtPointer name, XtPointer data) +{ + name = name; /* unused; suppress compiler warning */ + data = data; + + OpenFileAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); + ResetMenuEntry (entry); +} + +static void +OpenFileAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; + + if (current_file_name[0]) + strcpy (fileBuf, current_file_name); + else + fileBuf[0] = '\0'; + MakePrompt (toplevel, "File to open:", NewFile, fileBuf); +} + +/* ARGSUSED */ + +static void +Quit (Widget entry, XtPointer closure, XtPointer data) +{ + entry = entry; /* unused; suppress compiler warning */ + closure = closure; + data = data; + + QuitAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); +} + +static void +QuitAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; + + exit (0); +} + +Widget promptShell, promptDialog; +MakePromptFunc promptfunction; + +/* ARGSUSED */ +static +void CancelAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + widget = widget; /* unused; suppress compiler warning */ + event = event; + params = params; + num_params = num_params; + + if (promptShell) { + XtSetKeyboardFocus(toplevel, (Widget) None); + XtDestroyWidget(promptShell); + promptShell = (Widget) 0; + } +} + +static +void AcceptAction (Widget widget, XEvent *event, + String *params, Cardinal *num_params) +{ + (*promptfunction)(XawDialogGetValueString(promptDialog)); + CancelAction (widget, event, params, num_params); +} + +static void +MakePrompt(Widget centerw, const char *prompt, + MakePromptFunc func, const char *def) +{ + static Arg dialogArgs[] = { + {XtNlabel, 0}, + {XtNvalue, 0}, + }; + Arg valueArgs[1]; + Arg centerArgs[2]; + Position source_x, source_y; + Position dest_x, dest_y; + Dimension center_width, center_height; + Dimension prompt_width, prompt_height; + Widget valueWidget; + + CancelAction ((Widget)NULL, (XEvent *) 0, (String *) 0, (Cardinal *) 0); + promptShell = XtCreatePopupShell ("promptShell", transientShellWidgetClass, + toplevel, NULL, (Cardinal) 0); + dialogArgs[0].value = (XtArgVal)prompt; + dialogArgs[1].value = (XtArgVal)def; + promptDialog = XtCreateManagedWidget( "promptDialog", dialogWidgetClass, + promptShell, dialogArgs, XtNumber (dialogArgs)); + XawDialogAddButton(promptDialog, "accept", NULL, (XtPointer) 0); + XawDialogAddButton(promptDialog, "cancel", NULL, (XtPointer) 0); + valueWidget = XtNameToWidget (promptDialog, "value"); + if (valueWidget) { + XtSetArg (valueArgs[0], (String)XtNresizable, TRUE); + XtSetValues (valueWidget, valueArgs, 1); + /* + * as resizable isn't set until just above, the + * default value will be displayed incorrectly. + * rectify the situation by resetting the values + */ + XtSetValues (promptDialog, dialogArgs, XtNumber (dialogArgs)); + } + XtSetKeyboardFocus (promptDialog, valueWidget); + XtSetKeyboardFocus (toplevel, valueWidget); + XtRealizeWidget (promptShell); + /* + * place the widget in the center of the "parent" + */ + XtSetArg (centerArgs[0], XtNwidth, ¢er_width); + XtSetArg (centerArgs[1], XtNheight, ¢er_height); + XtGetValues (centerw, centerArgs, 2); + XtSetArg (centerArgs[0], XtNwidth, &prompt_width); + XtSetArg (centerArgs[1], XtNheight, &prompt_height); + XtGetValues (promptShell, centerArgs, 2); + source_x = (center_width - prompt_width) / 2; + source_y = (center_height - prompt_height) / 3; + XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y); + XtSetArg (centerArgs[0], XtNx, dest_x); + XtSetArg (centerArgs[1], XtNy, dest_y); + XtSetValues (promptShell, centerArgs, 2); + XtMapWidget(promptShell); + promptfunction = func; +} + +/* +Local Variables: +c-indent-level: 4 +c-continued-statement-offset: 4 +c-brace-offset: -4 +c-argdecl-indent: 4 +c-label-offset: -4 +c-tab-always-indent: nil +End: +*/ |