2010-03-08 04:55:21 -06:00
|
|
|
/* HTML-PSformat.c - Module for NCSA's Mosaic software
|
|
|
|
*
|
|
|
|
* Purpose: to parse Hypertext widget contents into appropriate PostScript
|
|
|
|
*
|
|
|
|
* Author: Ameet A. Raval & Frans van Hoesel & Andrew Ford
|
2013-03-09 18:59:42 -06:00
|
|
|
* (aar@gfdl.gov & hoesel@chem.rug.nl).
|
2010-03-08 04:55:21 -06:00
|
|
|
* send bugreports to hoesel@chem.rug.nl
|
|
|
|
*
|
|
|
|
* Institution: for Ameet A. Raval:
|
|
|
|
* Geophysical Fluid Dynamics Laboratory,
|
|
|
|
* National Oceanic and Atmospheric Administration,
|
|
|
|
* U.S. Department of Commerce
|
|
|
|
* P.O. Box 308
|
|
|
|
* Princeton, NJ 08542
|
|
|
|
* for Frans van Hoesel:
|
|
|
|
* Xtreme graphics software
|
|
|
|
* Herepoortenmolendrift 36
|
|
|
|
* 9711 DH Groningen
|
|
|
|
* The Netherlands
|
|
|
|
* also:
|
|
|
|
* Andrew Ford
|
|
|
|
* Independent Software Consultant
|
|
|
|
* 30 Upper Cheltenham Place,
|
|
|
|
* Montpelier, Bristol, BS6 5HR, GB
|
|
|
|
* E-mail: andrew@icarus.demon.co.uk
|
|
|
|
*
|
2013-03-09 18:59:42 -06:00
|
|
|
* Date: 1 aug 1993
|
2010-03-08 04:55:21 -06:00
|
|
|
* Modification: 8 nov 1993
|
|
|
|
* o added support for bold/italics courier
|
|
|
|
* o removed unused or no longer needed stuff
|
|
|
|
* o fixed the font alignment problem
|
|
|
|
* 23 nov 1993
|
|
|
|
* o added support for horizontal ruler
|
|
|
|
* o on request of Ameet, added a specific
|
|
|
|
* line about whome to send bugreports to
|
|
|
|
* 15 jun 1994
|
|
|
|
* o add headers, footers and footnotes to convey
|
|
|
|
* title, page number, url of document, date (of
|
|
|
|
* printing) and urls of links.
|
|
|
|
* o use A4 or US Letter size paper (currently hard coded)
|
|
|
|
*
|
|
|
|
* 9 may 1995 (Andrew Ford)
|
|
|
|
* o general overhaul
|
|
|
|
*
|
|
|
|
* Copyright: This work is the product of the United States Government,
|
|
|
|
* and is precluded from copyright protection. It is hereby
|
|
|
|
* released into the public domain.
|
|
|
|
*
|
|
|
|
* WE MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
|
|
|
|
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED
|
|
|
|
* WARRANTY. WE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE
|
2013-03-09 18:59:42 -06:00
|
|
|
* USERS OF THIS SOFTWARE.
|
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* pieces of code are taken from xvps by kind
|
|
|
|
* permission of John Bradley.
|
|
|
|
*
|
|
|
|
* To-do:
|
|
|
|
* * printing of tables and forms fields (and any new features that appear)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include "../config.h"
|
|
|
|
#include <varargs.h>
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <math.h>
|
|
|
|
#ifdef __bsdi__
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#else
|
|
|
|
#ifndef VAXC
|
|
|
|
#include <malloc.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include "HTMLP.h"
|
|
|
|
|
|
|
|
/* Fix thanks to robm. */
|
|
|
|
#ifdef __alpha
|
|
|
|
#include <Xm/VaSimpleP.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define CR '\015'
|
|
|
|
#define LF '\012'
|
|
|
|
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
extern int htmlwTrace;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern int SwapElements();
|
|
|
|
|
|
|
|
#define USLETTER 0
|
|
|
|
#define A4 1
|
|
|
|
|
|
|
|
#if !defined(DEFAULT_PAGE_SIZE)
|
|
|
|
#define DEFAULT_PAGE_SIZE USLETTER
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define F_FULLCOLOR 0
|
|
|
|
#define F_GREYSCALE 1
|
|
|
|
#define F_BWDITHER 2
|
|
|
|
#define F_REDUCED 3
|
|
|
|
|
|
|
|
#define L_PAREN '('
|
|
|
|
#define R_PAREN ')'
|
|
|
|
#define B_SLASH '\\'
|
|
|
|
#define MAX_ASCII '\177'
|
|
|
|
|
|
|
|
|
|
|
|
/* MONO returns total intensity of r,g,b components .33R+ .5G+ .17B */
|
|
|
|
#define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 13)
|
|
|
|
|
|
|
|
/* PSconst_out outputs to the postscript buffer an array of constant
|
|
|
|
* strings
|
|
|
|
*/
|
|
|
|
#define PSconst_out(txt) { \
|
|
|
|
int n=(sizeof txt)/(sizeof txt[0]); \
|
|
|
|
int i; \
|
|
|
|
for (i=0; i<n; i++) { \
|
|
|
|
PSprintf("%s\n", txt[i]) ; \
|
|
|
|
} \
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* STREQ tests whether two strings are equal. */
|
|
|
|
#define STREQ(a, b) (strcmp((a), (b)) == 0)
|
|
|
|
|
|
|
|
/* for regular-font, bold-font, italic-font, fixed-font */
|
|
|
|
typedef enum { RF, BF, IF, FF, FB, FI } PS_fontstyle;
|
|
|
|
|
|
|
|
static int PS_size, PS_len, PS_offset, PS_curr_page, PS_start_y, PS_hexi;
|
|
|
|
static int PS_page_offset;
|
|
|
|
static char *PS_string;
|
|
|
|
static float Points_Pixel;
|
|
|
|
static int Pixels_Page;
|
|
|
|
static PS_fontstyle PS_oldfn = RF;
|
|
|
|
static int PS_fontascent = 0;
|
|
|
|
static int PS_oldfs = 0;
|
|
|
|
|
|
|
|
static XColor fg_color, bg_color;
|
|
|
|
|
|
|
|
|
|
|
|
static int footnote_space = 8; /* Space from main text to footnotes */
|
|
|
|
static int footnote_ptsize = 8; /* Point size for footnote text */
|
|
|
|
static int cur_ftn_no; /* Current footnote number */
|
|
|
|
static int n_saved_ftns; /* Number of saved footnotes on page */
|
|
|
|
static int ftn_array_size=0; /* Size of allocated footnote array */
|
|
|
|
static char **footnotes=NULL; /* Pointer to array of footnote pointers */
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
double page_height;
|
|
|
|
double page_width;
|
|
|
|
double top_margin;
|
|
|
|
double bot_margin;
|
|
|
|
double left_margin;
|
|
|
|
double right_margin;
|
|
|
|
double text_height;
|
|
|
|
double text_width;
|
|
|
|
}
|
|
|
|
PAGE_DIMENS_T;
|
|
|
|
|
|
|
|
#define INCH 72
|
|
|
|
#define MM INCH / 25.4
|
|
|
|
|
|
|
|
PAGE_DIMENS_T page_dimens;
|
|
|
|
PAGE_DIMENS_T a4_page_dimens = {
|
|
|
|
297 * MM,
|
2013-03-09 18:59:42 -06:00
|
|
|
210 * MM,
|
2010-03-08 04:55:21 -06:00
|
|
|
20 * MM,
|
|
|
|
20 * MM,
|
|
|
|
20 * MM,
|
|
|
|
20 * MM
|
|
|
|
};
|
|
|
|
|
|
|
|
PAGE_DIMENS_T us_letter_page_dimens = {
|
|
|
|
11 * INCH, /* page_height */
|
|
|
|
8.5 * INCH, /* page_width */
|
|
|
|
0.9 * INCH, /* top_margin */
|
|
|
|
0.7 * INCH,
|
|
|
|
0.9 * INCH,
|
|
|
|
0.9 * INCH
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Globals to get button value in print dialog -- swp/AF */
|
|
|
|
|
|
|
|
int HTML_Print_Headers = 1; /* Flag whether page headers enabled */
|
|
|
|
int HTML_Print_Footers = 1; /* Flag whether footnote printing enabled */
|
|
|
|
|
|
|
|
/* Paper format (currently either A4 or letter). This should be generalized. */
|
|
|
|
|
|
|
|
int HTML_Print_Paper_Size_A4 = DEFAULT_PAGE_SIZE;
|
|
|
|
|
|
|
|
extern int installed_colormap;
|
|
|
|
extern Colormap installed_cmap;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GetDpi - return Dots-per-inch of the screen
|
|
|
|
*
|
|
|
|
* calculate the pixel density in dots per inch on the current widget
|
|
|
|
* screen
|
|
|
|
*
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static float
|
2010-03-08 04:55:21 -06:00
|
|
|
GetDpi(HTMLWidget hw)
|
|
|
|
{
|
|
|
|
Screen *s = XtScreen(hw);
|
|
|
|
float dpi;
|
|
|
|
|
|
|
|
dpi = 25.4 * WidthOfScreen(s) / WidthMMOfScreen(s);
|
|
|
|
if (dpi<1.0 || dpi>10000.0)
|
|
|
|
dpi = 72.0;
|
|
|
|
return dpi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSprintf - dynamic string concatenation function.
|
|
|
|
*
|
|
|
|
* In successive calls, the formatted string will be appended to the global
|
|
|
|
* output string Sp.
|
|
|
|
* It assumes that on each call, the length of the text appended to Sp
|
|
|
|
* is less than 1024.
|
|
|
|
* The format string is used as in printf, so you can use additional
|
|
|
|
* arguments.
|
|
|
|
*
|
|
|
|
* When successful, PSprintf returns the number of characters printed
|
|
|
|
* in this call, otherwise it returns EOF (just as printf does)
|
|
|
|
*
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static int
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf(format, va_alist)
|
|
|
|
char* format;
|
|
|
|
va_dcl
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *s;
|
|
|
|
va_list args;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (PS_size - PS_len < 1024)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_size += 1024;
|
2013-03-09 18:59:42 -06:00
|
|
|
if ((s = (char *) realloc(PS_string, PS_size)) == NULL)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr, "PSprintf malloc failed\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return(EOF);
|
|
|
|
}
|
|
|
|
PS_string = s;
|
|
|
|
}
|
|
|
|
va_start(args);
|
|
|
|
len = vsprintf(PS_string+PS_len, format, args);
|
|
|
|
/* this is a hack to make it work on systems were vsprintf(s,...)
|
|
|
|
* returns s, instead of the len.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
if (len != EOF && len != 0)
|
2010-03-08 04:55:21 -06:00
|
|
|
PS_len += strlen(PS_string+PS_len);
|
|
|
|
va_end(args);
|
|
|
|
return(len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PShex - output hex byte
|
|
|
|
*
|
|
|
|
* Append the byte "val" to an internal string buffer in hexadecimal
|
|
|
|
* format. If the argument "flush" is True, or if the buffer has filled
|
|
|
|
* up, flush the buffer to the larger postscript output buffer (using
|
|
|
|
* PSprintf).
|
|
|
|
*
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static int
|
2010-03-08 04:55:21 -06:00
|
|
|
PShex(unsigned char val, int flush)
|
|
|
|
{
|
|
|
|
static unsigned char hexline[80];
|
|
|
|
static char digit[] = "0123456789abcdef";
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (!flush)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
hexline[PS_hexi++] = (char) digit[((unsigned) val >>
|
|
|
|
(unsigned) 4) & (unsigned) 0x0f];
|
|
|
|
hexline[PS_hexi++] = (char) digit[(unsigned) val &
|
|
|
|
(unsigned) 0x0f];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Changed from ">78" to ">77" on advice of
|
|
|
|
debra@info.win.tue.nl (Paul De Bra). */
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if ((flush && PS_hexi) || (PS_hexi>77))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
hexline[PS_hexi] = '\0';
|
|
|
|
PS_hexi=0;
|
|
|
|
return (PSprintf("%s\n", hexline));
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSfont - change font
|
|
|
|
*
|
|
|
|
* change local font in buf to "font"
|
|
|
|
* fontfamily indicates if the overall style is times, helvetica, century
|
|
|
|
* schoolbook or lucida.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PSfont(HTMLWidget hw, XFontStruct *font, int fontfamily)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_fontstyle fn;
|
|
|
|
int style, size;
|
|
|
|
int fs;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
static PS_fontstyle fontstyle[17] =
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
RF, IF, BF, FF, BF, BF, BF, BF, BF,
|
|
|
|
BF, IF, FF, FF, FB, FI, FB, FI
|
|
|
|
};
|
|
|
|
|
|
|
|
static char fnchar[6][3] = {"RF", "BF", "IF", "FF", "FB", "FI"};
|
|
|
|
|
|
|
|
/* fontsizes as set in gui.c and in HTML.c (listing font is only
|
|
|
|
* defined in HTML.c)
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static int fontsizes[4][3][17] =
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* times font sizes */
|
|
|
|
{
|
|
|
|
{14, 14, 14, 14, 18, 17, 14, 12, 10, 8, 14, 12, 12, 14, 14, 12, 12},
|
|
|
|
{17, 17, 17, 17, 24, 18, 17, 14, 12, 10, 17, 14, 12, 17, 17, 14, 14},
|
|
|
|
{20, 20, 20, 20, 25, 24, 20, 18, 17, 14, 20, 18, 12, 20, 20, 18, 18}
|
|
|
|
},
|
|
|
|
/* helvetica sizes */
|
|
|
|
{
|
|
|
|
{14, 14, 14, 14, 18, 17, 14, 12, 10, 8, 14, 12, 12, 14, 14, 12, 12},
|
|
|
|
{17, 17, 17, 17, 24, 18, 17, 14, 12, 10, 17, 14, 12, 17, 17, 14, 14},
|
|
|
|
{20, 20, 20, 20, 25, 24, 20, 18, 17, 14, 20, 18, 12, 20, 20, 18, 18}
|
|
|
|
},
|
|
|
|
/* new century schoolbook sizes */
|
|
|
|
{
|
|
|
|
{14, 14, 14, 14, 18, 17, 14, 12, 10, 8, 14, 12, 12, 14, 14, 12, 12},
|
|
|
|
{18, 18, 18, 18, 24, 18, 17, 14, 12, 10, 18, 14, 12, 18, 18, 14, 14},
|
|
|
|
{20, 20, 20, 20, 25, 24, 20, 18, 17, 14, 20, 18, 12, 20, 20, 18, 18}
|
|
|
|
},
|
|
|
|
/* lucida sizes */
|
|
|
|
{
|
|
|
|
{14, 14, 14, 14, 18, 17, 14, 12, 11, 10, 14, 12, 12, 14, 14, 12, 12},
|
|
|
|
{17, 17, 17, 17, 24, 18, 17, 14, 12, 10, 17, 14, 12, 17, 17, 14, 14},
|
|
|
|
{20, 20, 20, 20, 25, 24, 20, 18, 17, 14, 20, 18, 12, 20, 20, 18, 18}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* next is for each fontfamily the ascent value as given by the
|
2010-03-08 04:55:21 -06:00
|
|
|
* medium sized bold x-font (the regular font has the same
|
|
|
|
* ascent value for both the medium and the large size Century
|
|
|
|
* font).
|
|
|
|
* it is use in the check for the fontsize (small, medium, large)
|
|
|
|
*/
|
|
|
|
static int medium_fontascent[4] = {
|
|
|
|
14, 14, 16, 15
|
|
|
|
};
|
|
|
|
|
|
|
|
/* for each fontfamily, for each fontsize, and for each font style
|
|
|
|
* give the ascent value, so the output from Postscript is correct.
|
|
|
|
* If the value is given between parenthesis, then it is different
|
|
|
|
* from the value as stored in the x-font.
|
|
|
|
* Note that this is a fix, and need to be changed, if the browser
|
|
|
|
* is fixed (in the current version 1.2 the baseline of various fonts
|
|
|
|
* is not aligned very well).
|
|
|
|
*/
|
|
|
|
static int fontascent[4][3][17] = {
|
|
|
|
/*rg, itl, bld, fix, h1, h2, h3, h4, h5, h6,
|
|
|
|
add, pla, lis, fixbold, fixital, plabold, plaital, */
|
|
|
|
/* times */
|
|
|
|
{
|
|
|
|
{12, 11, 12, 10, 15, 14, 12, 10, 8, 6, 11, 9, 10, 10, 10, 9, 9},
|
|
|
|
{13, 13, 14, 12, 20, 15, 14, 12, 10, 8, 13, 10, 10, 12, 12, 10, 10},
|
|
|
|
{16, 15, 15, 13, 21, 20, 15, 15, 14, 12, 15, 13, 10, 13, 13, 13, 13}
|
|
|
|
},
|
|
|
|
/* helvetica */
|
|
|
|
{
|
|
|
|
{12, 12, 12, 10, 15, 14, 12, 10, 9, 7, 12, 9, 10, 10, 10, 9, 9},
|
|
|
|
{14, 14, 14, 12, 22, 15, 14, 12, 10, 9, 14, 10, 10, 12, 12, 10, 10},
|
|
|
|
{16, 16, 16, 13, 22, 22, 16, 15, 14, 12, 16, 13, 10, 13, 13, 13, 13}
|
|
|
|
},
|
|
|
|
/* new century schoolbook */
|
|
|
|
{
|
|
|
|
{12, 12, 13, 10, 16, 14, 13, 10, 9, 7, 12, 9, 10, 10, 10, 9, 9},
|
|
|
|
{16, 14, 16, 13, 22, 16, 14, 13, 10, 9, 14, 10, 10, 13, 13, 10, 10},
|
|
|
|
{17, 16, 17, 13, 22, 22, 17, 16, 14, 13, 16, 13, 10, 13, 13, 13, 13}
|
|
|
|
},
|
|
|
|
/* lucida bright */
|
|
|
|
{
|
|
|
|
{11, 11, 11, 11, 15, 14, 11, 10, 9, 7, 11, 9, 10, 11, 10, 9, 9},
|
|
|
|
{14, 15, 14, 13, 20, 15, 14, 11, 10, 7, 15, 11, 10, 13, 13, 11, 10},
|
|
|
|
{17, 17, 17, 16, 21, 20, 17, 15, 14, 11, 17, 14, 10, 16, 13, 14, 13}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* NULL case - reflush old font or the builtin default: */
|
|
|
|
if ((hw == NULL) || (font == NULL))
|
|
|
|
{
|
|
|
|
if (PS_oldfs != 0)
|
|
|
|
PSprintf( "%2s %d SF\n", fnchar[PS_oldfn], PS_oldfs);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* added the next line in case xmosaic version 199.4 has more fonts */
|
|
|
|
style = 3;
|
|
|
|
|
|
|
|
if (font == hw->html.font) {
|
|
|
|
style = 0;
|
|
|
|
} else if (font == hw->html.italic_font) {
|
|
|
|
style = 1;
|
|
|
|
} else if (font == hw->html.bold_font) {
|
|
|
|
style = 2;
|
|
|
|
} else if (font == hw->html.fixed_font) {
|
|
|
|
style = 3;
|
|
|
|
} else if (font == hw->html.header1_font) {
|
|
|
|
style = 4;
|
|
|
|
} else if (font == hw->html.header2_font) {
|
|
|
|
style = 5;
|
|
|
|
} else if (font == hw->html.header3_font) {
|
|
|
|
style = 6;
|
|
|
|
} else if (font == hw->html.header4_font) {
|
|
|
|
style = 7;
|
|
|
|
} else if (font == hw->html.header5_font) {
|
|
|
|
style = 8;
|
|
|
|
} else if (font == hw->html.header6_font) {
|
|
|
|
style = 9;
|
|
|
|
} else if (font == hw->html.address_font) {
|
|
|
|
style = 10;
|
|
|
|
} else if (font == hw->html.plain_font) {
|
|
|
|
style = 11;
|
|
|
|
} else if (font == hw->html.listing_font) {
|
|
|
|
style = 12;
|
|
|
|
} else if (font == hw->html.fixedbold_font) {
|
|
|
|
style = 13;
|
|
|
|
} else if (font == hw->html.fixeditalic_font) {
|
|
|
|
style = 14;
|
|
|
|
} else if (font == hw->html.plainbold_font) {
|
|
|
|
style = 15;
|
|
|
|
} else if (font == hw->html.plainitalic_font) {
|
|
|
|
style = 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check size, by looking at the size of the regular font */
|
|
|
|
size = 1;
|
2013-03-09 18:59:42 -06:00
|
|
|
if (hw->html.bold_font->ascent > medium_fontascent[fontfamily])
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* large font */
|
|
|
|
size = 2;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else if (hw->html.bold_font->ascent < medium_fontascent[fontfamily])
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* small font */
|
|
|
|
size = 0;
|
|
|
|
}
|
|
|
|
fn = fontstyle[style];
|
|
|
|
fs = fontsizes[fontfamily][size][style];
|
|
|
|
PS_fontascent = fontascent[fontfamily][size][style];
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (fn != PS_oldfn || fs != PS_oldfs)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSprintf( "%2s %d SF\n", fnchar[fn], fs);
|
|
|
|
PS_oldfn=fn, PS_oldfs=fs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSshowpage - end of page function
|
|
|
|
*
|
|
|
|
* show the current page and restore any changes to the printer state.
|
|
|
|
* Any accumulated footnotes are output and the outstanding footnote count
|
|
|
|
* reset to zero. Footnotes are preceded by a footnote rule and each footnote
|
|
|
|
* is consists of a raised mark and the footnote text (i.e. the url). The mark
|
2013-03-09 18:59:42 -06:00
|
|
|
* is in a smaller font than the text. The ideas are filched from LaTeX.
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PSshowpage(void)
|
|
|
|
{
|
|
|
|
PSprintf("restore\n");
|
2013-03-09 18:59:42 -06:00
|
|
|
if (n_saved_ftns > 0)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
PSprintf("gsave 0.2 setlinewidth newpath %.2f %.2f M %.2f 0 RL stroke\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
page_dimens.left_margin,
|
|
|
|
(page_dimens.bot_margin + (footnote_ptsize * n_saved_ftns) + 4),
|
|
|
|
(page_dimens.text_width * 0.4));
|
2013-03-09 18:59:42 -06:00
|
|
|
for (i = 0; n_saved_ftns; n_saved_ftns--, i++)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
PSprintf("newpath %.2f %.2f M RF %.2f SF (%d) S 3 -2 R RF %d SF (%s) S\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
page_dimens.left_margin,
|
|
|
|
page_dimens.bot_margin + 5 + (n_saved_ftns - 1) * footnote_ptsize,
|
2013-03-09 18:59:42 -06:00
|
|
|
(0.7 * footnote_ptsize), cur_ftn_no - n_saved_ftns,
|
2010-03-08 04:55:21 -06:00
|
|
|
footnote_ptsize, footnotes[i]);
|
|
|
|
}
|
|
|
|
PSprintf("grestore\n");
|
|
|
|
}
|
|
|
|
PSprintf("showpage\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSnewpage - begin a fresh page
|
|
|
|
*
|
|
|
|
* increment the page count and handle the structured comment
|
|
|
|
* conventions
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PSnewpage(void)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_curr_page++;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* the PostScript reference Manual states that the Page: Tag
|
|
|
|
should have a label and a ordinal; otherwise programs like
|
|
|
|
psutils fail -gustaf */
|
|
|
|
|
|
|
|
PSprintf("%%%%Page: %d %d\n", PS_curr_page, PS_curr_page);
|
|
|
|
PSprintf("save\n");
|
|
|
|
if (HTML_Print_Headers)
|
|
|
|
PSprintf("%d ", PS_curr_page);
|
|
|
|
PSprintf("NP\n");
|
|
|
|
PSfont( NULL, NULL, 0); /* force re-flush of last font used */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSinit_latin1 - handle ISO encoding
|
|
|
|
*
|
|
|
|
* print out initializing PostScript text for ISO Latin1 font encoding
|
2013-03-09 18:59:42 -06:00
|
|
|
* This code is copied from the Idraw program (from Stanford's InterViews
|
2010-03-08 04:55:21 -06:00
|
|
|
* package), courtesy of Steinar Kjaernsr|d, steinar@ifi.uio.no
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PSinit_latin1(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
static char *txt[] = {
|
|
|
|
|
|
|
|
"/reencodeISO {",
|
|
|
|
"dup dup findfont dup length dict begin",
|
|
|
|
"{ 1 index /FID ne { def }{ pop pop } ifelse } forall",
|
|
|
|
"/Encoding ISOLatin1Encoding D",
|
|
|
|
"currentdict end definefont",
|
|
|
|
"} D",
|
|
|
|
"/ISOLatin1Encoding [",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright",
|
|
|
|
"/parenleft/parenright/asterisk/plus/comma/minus/period/slash",
|
|
|
|
"/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon",
|
|
|
|
"/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N",
|
|
|
|
"/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright",
|
|
|
|
"/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m",
|
|
|
|
"/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef",
|
|
|
|
"/.notdef/dotlessi/grave/acute/circumflex/tilde/macron/breve",
|
|
|
|
"/dotaccent/dieresis/.notdef/ring/cedilla/.notdef/hungarumlaut",
|
|
|
|
"/ogonek/caron/space/exclamdown/cent/sterling/currency/yen/brokenbar",
|
|
|
|
"/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot",
|
|
|
|
"/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior",
|
|
|
|
"/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine",
|
|
|
|
"/guillemotright/onequarter/onehalf/threequarters/questiondown",
|
|
|
|
"/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla",
|
|
|
|
"/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex",
|
|
|
|
"/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis",
|
|
|
|
"/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute",
|
|
|
|
"/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis",
|
|
|
|
"/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave",
|
|
|
|
"/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex",
|
|
|
|
"/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis",
|
|
|
|
"/yacute/thorn/ydieresis",
|
|
|
|
"] D",
|
|
|
|
"[RF BF IF FF FB FI] {reencodeISO D} forall"
|
|
|
|
};
|
|
|
|
|
|
|
|
PSconst_out(txt);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSinit - initialize Postscript output
|
|
|
|
*
|
|
|
|
* does the initialization per html document
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PSinit(void)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_size = PS_len = PS_offset = PS_hexi = PS_page_offset = 0;
|
|
|
|
PS_start_y = 0;
|
|
|
|
PS_string = (char *) malloc(1);
|
|
|
|
PS_oldfs = 0;
|
|
|
|
PS_oldfn = RF;
|
|
|
|
PS_curr_page = 0 ;
|
|
|
|
n_saved_ftns = 0;
|
|
|
|
cur_ftn_no = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSheader - initialize Postscript output
|
|
|
|
*
|
|
|
|
* Prints out the prolog. The following PostScript macros are defined
|
|
|
|
* D def - define a macro
|
|
|
|
* E exch - exhange parameters
|
|
|
|
* M moveto
|
|
|
|
* R rmoveto
|
|
|
|
* L lineto
|
|
|
|
* RL rlineto
|
|
|
|
* SQ draw a unit square
|
|
|
|
* U underline a string
|
|
|
|
* B draw a bullet
|
|
|
|
* OB draw an open bullet
|
|
|
|
* HR draw a horizontal rule
|
|
|
|
* SF set font
|
|
|
|
* RF roman font (dependent on font family)
|
|
|
|
* BF bold font (dependent on font family)
|
|
|
|
* IF italic font (dependent on font family)
|
|
|
|
* FF fixed font (courier)
|
|
|
|
* FB fixed bold font (courier bold)
|
|
|
|
* FI fixed italic font (courier oblique)
|
|
|
|
* nstr buffer for creating page number string
|
|
|
|
* pageno literal "Page "
|
|
|
|
* url URL of document
|
|
|
|
* title title of document
|
|
|
|
* date date modified/printed
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static void
|
|
|
|
PSheader(char *title, int font, char *url, char *time_str)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
static char *notitle="Untitled";
|
|
|
|
int set_to_null=0;
|
|
|
|
static char *fontname[] = {
|
|
|
|
/* in order: regular, bold, italic */
|
|
|
|
"Times-Roman", "Times-Bold", "Times-Italic",
|
|
|
|
"Helvetica", "Helvetica-Bold", "Helvetica-Oblique",
|
|
|
|
"NewCenturySchlbk-Roman", "NewCenturySchlbk-Bold",
|
|
|
|
"NewCenturySchlbk-Italic",
|
|
|
|
/* this is a nasty trick, I have put Times in place of
|
|
|
|
* Lucida, because most printers don't have Lucida font
|
|
|
|
*/
|
|
|
|
"Times-Roman", "Times-Bold", "Times-Italic"
|
|
|
|
/* "Lucida", "Lucida-Bold", "Lucida-Italic" */
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *txt[] = {
|
|
|
|
"/M {moveto} D",
|
|
|
|
"/S {show} D",
|
|
|
|
"/R {rmoveto} D",
|
|
|
|
"/L {lineto} D",
|
|
|
|
"/RL {rlineto} D",
|
|
|
|
"/SQ {newpath 0 0 M 0 1 L 1 1 L 1 0 L closepath} D",
|
|
|
|
"/U {gsave currentpoint currentfont /FontInfo get /UnderlinePosition get",
|
|
|
|
" 0 E currentfont /FontMatrix get dtransform E pop add newpath moveto",
|
|
|
|
" dup stringwidth rlineto stroke grestore S } D",
|
|
|
|
"/B {/r E D gsave -13 0 R currentpoint ",
|
|
|
|
" newpath r 0 360 arc closepath fill grestore } D",
|
|
|
|
"/OB {/r E D gsave -13 0 R currentpoint ",
|
|
|
|
" newpath r 0 360 arc closepath stroke grestore } D",
|
|
|
|
"/HR {/l E D gsave 0 1 RL l 0 RL 0 -1 RL l neg 0 RL stroke grestore } D",
|
|
|
|
"/SF {E findfont E scalefont setfont } D",
|
|
|
|
"/FF {/Courier } D",
|
|
|
|
"/FB {/Courier-Bold } D",
|
|
|
|
"/FI {/Courier-Oblique } D"
|
|
|
|
};
|
|
|
|
|
|
|
|
char time_buf[40];
|
|
|
|
time_t clock = time(NULL);
|
|
|
|
|
|
|
|
#if !defined(VMS) || defined (__DECC)
|
2013-03-09 18:59:42 -06:00
|
|
|
strftime(time_buf, sizeof(time_buf),
|
2010-03-08 04:55:21 -06:00
|
|
|
"Printed %a %b %e %T %Y", localtime(&clock));
|
|
|
|
#else
|
|
|
|
sprintf(time_buf,"Printed %s",asctime(localtime(&clock)));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Always show the print date -- SWP */
|
|
|
|
time_str = time_buf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (!time_str || (time_str[0] == '\0'))
|
|
|
|
{
|
|
|
|
time_str = time_buf;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
PSprintf("%%!PS-Adobe-1.0\n");
|
|
|
|
PSprintf("%%%%Creator: NCSA Mosaic, Postscript by Ameet Raval, Frans van Hoesel\n");
|
|
|
|
PSprintf("%%%% and Andrew Ford\n");
|
|
|
|
|
|
|
|
if (!title) {
|
|
|
|
title=notitle;
|
|
|
|
set_to_null=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
char *tmp;
|
|
|
|
for (tmp = title; *tmp; tmp++)
|
|
|
|
if (*tmp == CR || *tmp == LF)
|
|
|
|
*tmp = ' ';
|
|
|
|
PSprintf("%%%%Title: %s\n", title);
|
|
|
|
}
|
|
|
|
|
|
|
|
PSprintf("%%%%CreationDate: %s\n", time_buf + 8);
|
|
|
|
PSprintf("%%%%Pages: (atend)\n");
|
|
|
|
PSprintf("%%%%PageOrder: Ascend\n");
|
|
|
|
PSprintf("%%%%BoundingBox: %d %d %d %d\n",
|
|
|
|
(int)page_dimens.left_margin,
|
|
|
|
(int)(page_dimens.bot_margin - 12),
|
|
|
|
(int)(page_dimens.left_margin + page_dimens.text_width + 0.5),
|
|
|
|
(int)(page_dimens.bot_margin + page_dimens.text_height + 12.5));
|
|
|
|
PSprintf("%%%%DocumentFonts: %s %s %s Courier Courier-Bold Courier-Oblique\n",
|
|
|
|
fontname[font*3], fontname[font*3+1], fontname[font*3+2]);
|
|
|
|
PSprintf("%%%%EndComments\n");
|
|
|
|
PSprintf("save /D {def} def /E {exch} D\n");
|
|
|
|
PSprintf("/RF {/%s} D\n", fontname[font*3]);
|
|
|
|
PSprintf("/BF {/%s} D\n", fontname[font*3+1]);
|
|
|
|
PSprintf("/IF {/%s} D\n", fontname[font*3+2]);
|
|
|
|
PSprintf("/nstr 6 string D /pgno (Page ) D\n");
|
|
|
|
PSprintf("/url (%s) D\n", url);
|
|
|
|
PSprintf("/title (%s) D\n", title);
|
|
|
|
PSprintf("/date (%s) D\n", time_str);
|
|
|
|
PSconst_out(txt);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* Output the newpage definition. */
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf("/NP {");
|
2013-03-09 18:59:42 -06:00
|
|
|
if (HTML_Print_Headers)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSprintf("gsave 0.4 setlinewidth\n");
|
2013-03-09 18:59:42 -06:00
|
|
|
PSprintf(" newpath %.2f %.2f M %.2f 0 RL stroke",
|
2010-03-08 04:55:21 -06:00
|
|
|
page_dimens.left_margin,
|
2013-03-09 18:59:42 -06:00
|
|
|
(page_dimens.bot_margin + page_dimens.text_height),
|
2010-03-08 04:55:21 -06:00
|
|
|
page_dimens.text_width);
|
|
|
|
PSprintf(" newpath %.2f %.2f M %.2f 0 RL stroke\n",
|
|
|
|
page_dimens.left_margin, page_dimens.bot_margin,
|
|
|
|
page_dimens.text_width);
|
|
|
|
PSprintf(" BF 12 SF %.2f %.2f M (%s) S\n",
|
|
|
|
page_dimens.left_margin,
|
|
|
|
(page_dimens.bot_margin + page_dimens.text_height + 6), title);
|
|
|
|
PSprintf(" nstr cvs dup stringwidth pop pgno stringwidth pop add\n");
|
|
|
|
PSprintf(" %.2f E sub %.2f M pgno S S\n",
|
2013-03-09 18:59:42 -06:00
|
|
|
(page_dimens.left_margin + page_dimens.text_width),
|
2010-03-08 04:55:21 -06:00
|
|
|
(page_dimens.bot_margin + page_dimens.text_height + 6));
|
|
|
|
PSprintf(" BF 10 SF %.2f %.2f M (%s) S\n",
|
|
|
|
page_dimens.left_margin, page_dimens.bot_margin - 12, url);
|
|
|
|
PSprintf(" (%s) dup stringwidth pop %.2f E sub %.2f M S grestore\n",
|
|
|
|
time_str, page_dimens.left_margin + page_dimens.text_width,
|
|
|
|
page_dimens.bot_margin - 12);
|
|
|
|
}
|
|
|
|
PSprintf(" %.2f %.2f translate %.5f %.5f scale } D\n",
|
2013-03-09 18:59:42 -06:00
|
|
|
page_dimens.left_margin,
|
2010-03-08 04:55:21 -06:00
|
|
|
page_dimens.bot_margin + page_dimens.text_height,
|
|
|
|
Points_Pixel, Points_Pixel);
|
|
|
|
PSinit_latin1();
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf("%%%%EndProlog\n");
|
|
|
|
|
|
|
|
if (set_to_null) {
|
|
|
|
title=NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PStrailer - write postscript trailer
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PStrailer(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
PSprintf("%%%%Trailer\n");
|
|
|
|
PSprintf("restore\n");
|
|
|
|
PSprintf("%%%%Pages: %d\n", PS_curr_page);
|
|
|
|
if (footnotes)
|
|
|
|
{
|
|
|
|
free(footnotes);
|
|
|
|
footnotes = NULL;
|
|
|
|
ftn_array_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSmoveto - move to new x,y location
|
|
|
|
*
|
|
|
|
* if the Y value does not fit on the current page, begin a new page
|
|
|
|
* (I think in the current implementation, this never happens)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PSmoveto(int x, int y)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
if (y > PS_start_y + Pixels_Page)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_start_y = y;
|
|
|
|
PSshowpage();
|
|
|
|
PSnewpage();
|
|
|
|
}
|
|
|
|
PS_offset = 0;
|
|
|
|
PSprintf( "%d %d M\n", x, -(y - PS_start_y));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSmove_offset - set Y-offset
|
|
|
|
*
|
|
|
|
* do a relative vertical move, whenever the offset changes
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PSmove_offset(int offset)
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
if (offset != PS_offset)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSprintf("0 %d R\n", PS_offset - offset );
|
|
|
|
PS_offset = offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return an indication of whether or not the current element has a footnote.
|
|
|
|
*
|
|
|
|
* an element has a footnote if it is text or an image and its anchorHRef is not null.
|
2013-03-09 18:59:42 -06:00
|
|
|
* If the element is a textual element with an anchorHRef, that has been split across
|
2010-03-08 04:55:21 -06:00
|
|
|
* lines then it should be followed by a linefeed element and a text element with the
|
|
|
|
* same anchorHRef. In this case say that the element doesn't have a footnote so as
|
|
|
|
* to avoid duplicate footnotes.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static int
|
2010-03-08 04:55:21 -06:00
|
|
|
has_footnote(struct ele_rec *el)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
struct ele_rec *next;
|
|
|
|
char *anchorHRef;
|
|
|
|
|
|
|
|
if (el == NULL) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
anchorHRef = el->anchorHRef;
|
|
|
|
|
|
|
|
if (anchorHRef != NULL)
|
|
|
|
{
|
|
|
|
switch (el->type)
|
|
|
|
{
|
|
|
|
case E_TEXT:
|
|
|
|
case E_IMAGE:
|
|
|
|
for (next = el->next; el; el = next, next = el->next)
|
|
|
|
{
|
|
|
|
if (next == NULL)
|
|
|
|
{
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (next->anchorHRef == NULL) {
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (!STREQ(next->anchorHRef, anchorHRef))
|
|
|
|
{
|
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if ( (next->type == E_TEXT)
|
|
|
|
|| (next->type == E_IMAGE))
|
|
|
|
{
|
|
|
|
rc = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSfootnote - output a footnote mark and store the footnote
|
|
|
|
*
|
|
|
|
* the footnote mark is placed at the current point, enclosed in a gsave/grestore
|
|
|
|
* pair so that the position of the following output is not affected.
|
|
|
|
* The reference is stored in a malloced array (which may need to be expanded), to
|
|
|
|
* be output at the end of the page.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PSfootnote(char *href, double height)
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
PSprintf("gsave 0 %.2f R RF %d SF (%d) S grestore\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
height, footnote_ptsize, cur_ftn_no++);
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (n_saved_ftns == ftn_array_size)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
ftn_array_size += 16;
|
|
|
|
if (!footnotes) {
|
|
|
|
footnotes = (char **)calloc(ftn_array_size,sizeof(char *));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
footnotes = (char **)realloc((void *)footnotes,
|
|
|
|
(ftn_array_size * sizeof(char *)));
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
if (footnotes == NULL)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr, "PSfootnote realloc failed\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
footnotes[n_saved_ftns++] = href;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PStext - output text
|
|
|
|
*
|
|
|
|
* show text "t", and protect special characters if needed
|
|
|
|
* if Underline is non-zero, the text is underlined.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PStext(HTMLWidget hw, struct ele_rec *eptr, int fontfamily, String s)
|
|
|
|
{
|
|
|
|
String s2;
|
|
|
|
String stmp;
|
|
|
|
unsigned char ch;
|
|
|
|
int underline = eptr->underline_number;
|
|
|
|
int ascent;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSfont(hw, eptr->font, fontfamily); /* set font */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (PS_fontascent == 0)
|
2010-03-08 04:55:21 -06:00
|
|
|
ascent = eptr->font->ascent;
|
|
|
|
else
|
|
|
|
ascent = PS_fontascent;
|
|
|
|
PSmove_offset(eptr->y_offset + ascent);
|
|
|
|
|
|
|
|
|
|
|
|
/* Allocate a string long enough to hold the original string with
|
|
|
|
every character stored as an octal escape (worst case scenario). */
|
|
|
|
|
|
|
|
s2 = (String) malloc(strlen(s) * 4 + 1);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (s2 == NULL)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr, "PStext malloc failed\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For each char in s, if it is a special char, insert "\"
|
|
|
|
* into the new string s2, then insert the actual char
|
|
|
|
*/
|
|
|
|
for (stmp = s2; (ch = *s++) != '\0';)
|
|
|
|
{
|
|
|
|
if ((ch == L_PAREN) || (ch == R_PAREN) || (ch == B_SLASH))
|
|
|
|
{
|
|
|
|
*stmp++ = B_SLASH;
|
|
|
|
*stmp++ = ch;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else if (ch > (unsigned char) MAX_ASCII)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* convert to octal */
|
|
|
|
*stmp++ = B_SLASH;
|
|
|
|
*stmp++ = ((ch >> 6) & 007) + '0';
|
|
|
|
*stmp++ = ((ch >> 3) & 007) + '0';
|
|
|
|
*stmp++ = (ch & 007) + '0';
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
*stmp++ = ch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*(stmp) = '\0';
|
|
|
|
PSprintf("(%s)%c\n", s2, (underline)?'U':'S');
|
2013-03-09 18:59:42 -06:00
|
|
|
if (HTML_Print_Footers && has_footnote(eptr))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSfootnote(eptr->anchorHRef, 0.7 * ascent);
|
|
|
|
}
|
|
|
|
free(s2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSbullet - output a bullet
|
|
|
|
*
|
|
|
|
* The bullet is normally filled, except for a bullet with an indent level
|
|
|
|
* of two. The size of the higher level bullets is just somewhat smaller
|
|
|
|
*
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
static void
|
2010-03-08 04:55:21 -06:00
|
|
|
PSbullet(HTMLWidget hw, struct ele_rec *eptr, int fontfamily)
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
int width = ( eptr->font->max_bounds.lbearing
|
2010-03-08 04:55:21 -06:00
|
|
|
+ eptr->font->max_bounds.rbearing);
|
|
|
|
int offset = eptr->y_offset + eptr->font->ascent;
|
|
|
|
int level = eptr->indent_level;
|
|
|
|
double size = eptr->line_height / 5.5;
|
|
|
|
|
|
|
|
if (size < 1.1) size = 1.1;
|
|
|
|
if (level > 2) size /= 1.33333;
|
|
|
|
|
|
|
|
/* the next line is a hack to get a good position of the
|
|
|
|
* bullet in most practical cases, otherwise the
|
|
|
|
* bullet may appear just a bit too low (for large fonts)
|
|
|
|
* What is does is to compare the lineheight with
|
|
|
|
* the lineheight of the next element, to correct
|
|
|
|
* for the possibly too large y_offset
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ( (eptr->next != NULL)
|
|
|
|
&& ( (eptr->next->type == E_TEXT)
|
|
|
|
|| (eptr->next->type == E_IMAGE)))
|
|
|
|
{
|
|
|
|
offset += (eptr->line_height - eptr->next->line_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
PSfont(hw, eptr->font, fontfamily);
|
|
|
|
PSmove_offset(offset - width/4);
|
|
|
|
PSprintf(" %f %s\n", size, (level == 2) ? "OB" : "B");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PShrule - draw a horizontal line with the given width
|
|
|
|
*
|
|
|
|
* nothing special, just draw a line, from the current position to
|
|
|
|
* the right side of the paper.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PShrule(HTMLWidget hw, struct ele_rec *eptr, int fontfamily)
|
|
|
|
{
|
|
|
|
int length = hw->html.doc_width;
|
|
|
|
|
|
|
|
PSmove_offset(eptr->y_offset);
|
|
|
|
PSprintf("%d HR\n", length);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PStable - draw a table
|
|
|
|
*
|
|
|
|
* Currently just draw a box of the dimensions of the table.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PStable(HTMLWidget hw, struct ele_rec *eptr, int fontfamily)
|
|
|
|
{
|
|
|
|
struct table_rec *tptr = eptr->table_data;
|
|
|
|
int width = tptr->width;
|
|
|
|
int height = tptr->height;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
PSmove_offset(eptr->y_offset);
|
|
|
|
PSprintf("gsave currentpoint %d sub translate ", height);
|
|
|
|
PSprintf("%d %d scale\n", width, height);
|
|
|
|
PSprintf("SQ stroke\n");
|
|
|
|
PSprintf("grestore\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSwidget - draw a widget (form field)
|
|
|
|
*
|
|
|
|
* Currently just draw a grey box of the dimensions of the field.
|
|
|
|
* This is nowhere near complete but is a first step.
|
|
|
|
* The widget record type field gives the type of field:
|
|
|
|
* 0 textfield
|
|
|
|
* 1 checkbox
|
|
|
|
* 2 radiobox
|
|
|
|
* 3 pushbutton
|
|
|
|
* 4 password
|
|
|
|
* 5 option menu
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
PSwidget(HTMLWidget hw, struct ele_rec *eptr, int fontfamily)
|
|
|
|
{
|
|
|
|
struct wid_rec *wptr = eptr->widget_data;
|
|
|
|
int w = wptr->width;
|
|
|
|
int h = wptr->height;
|
|
|
|
|
|
|
|
#if 1 /* Comment out? */
|
|
|
|
PSmove_offset(eptr->y_offset);
|
|
|
|
PSprintf("gsave currentpoint %d sub translate ", h);
|
|
|
|
PSprintf("%d %d scale\n", w, h);
|
|
|
|
PSprintf("SQ 0.9 setgray fill\n");
|
|
|
|
PSprintf("grestore\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSrle_encode - perform run length encoding
|
|
|
|
*
|
|
|
|
* does the run-length encoding. This is done to reduce the file size and
|
|
|
|
* therefore the time to send the file to the printer. You get longer
|
|
|
|
* processing time instead.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* rle is encoded as such:
|
|
|
|
* <count> <value> # 'run' of count+1 equal pixels
|
|
|
|
* <count | 0x80> <count+1 data bytes> # count+1 non-equal pixels
|
|
|
|
* count can range between 0 and 127
|
|
|
|
*
|
|
|
|
* returns length of the rleline vector
|
|
|
|
*
|
2013-03-09 18:59:42 -06:00
|
|
|
*/
|
2010-03-08 04:55:21 -06:00
|
|
|
static int
|
2013-03-09 18:59:42 -06:00
|
|
|
PSrle_encode(unsigned char *scanline,
|
2010-03-08 04:55:21 -06:00
|
|
|
unsigned char *rleline,
|
2013-03-09 18:59:42 -06:00
|
|
|
int wide)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
int i, j, blocklen, isrun, rlen;
|
|
|
|
unsigned char block[256], pix;
|
|
|
|
|
|
|
|
blocklen = isrun = rlen = 0;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
for (i = 0; i < wide; i++)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* there are 5 possible states:
|
|
|
|
* 0: block empty.
|
|
|
|
* 1: block is a run, current pix == previous pix
|
|
|
|
* 2: block is a run, current pix != previous pix
|
|
|
|
* 3: block not a run, current pix == previous pix
|
|
|
|
* 4: block not a run, current pix != previous pix
|
|
|
|
*/
|
|
|
|
|
|
|
|
pix = scanline[i];
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (!blocklen)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* case 0: empty */
|
|
|
|
block[blocklen++] = pix;
|
|
|
|
isrun = 1;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else if (isrun)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
if (pix == block[blocklen-1])
|
2013-03-09 18:59:42 -06:00
|
|
|
{
|
2010-03-08 04:55:21 -06:00
|
|
|
/* case 1: isrun, prev==cur */
|
|
|
|
block[blocklen++] = pix;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* case 2: isrun, prev!=cur */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (blocklen>1)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* we have a run block to flush */
|
|
|
|
rleline[rlen++] = blocklen-1;
|
|
|
|
rleline[rlen++] = block[0];
|
|
|
|
/* start new run block with pix */
|
|
|
|
block[0] = pix;
|
|
|
|
blocklen = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* blocklen<=1, turn into non-run */
|
|
|
|
isrun = 0;
|
|
|
|
block[blocklen++] = pix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2013-03-09 18:59:42 -06:00
|
|
|
{
|
2010-03-08 04:55:21 -06:00
|
|
|
/* not a run */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (pix == block[blocklen-1])
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* case 3: non-run, prev==cur */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (blocklen>1)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* have a non-run block to flush */
|
|
|
|
rleline[rlen++] = (blocklen-1) | 0x80;
|
|
|
|
for (j=0; j<blocklen; j++)
|
|
|
|
rleline[rlen++] = block[j];
|
|
|
|
/* start new run block with pix */
|
|
|
|
block[0] = pix;
|
|
|
|
blocklen = isrun = 1;
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* blocklen<=1 turn into a run */
|
|
|
|
isrun = 1;
|
|
|
|
block[blocklen++] = pix;
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
else
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* case 4: non-run, prev!=cur */
|
|
|
|
block[blocklen++] = pix;
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* max block length. flush */
|
|
|
|
if (blocklen == 128)
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
if (isrun)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
rleline[rlen++] = blocklen-1;
|
|
|
|
rleline[rlen++] = block[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rleline[rlen++] = (blocklen-1) | 0x80;
|
|
|
|
for (j=0; j<blocklen; j++)
|
|
|
|
rleline[rlen++] = block[j];
|
|
|
|
}
|
|
|
|
blocklen = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* flush last block */
|
|
|
|
if (blocklen)
|
|
|
|
{
|
|
|
|
if (isrun)
|
|
|
|
{
|
|
|
|
rleline[rlen++] = blocklen-1;
|
|
|
|
rleline[rlen++] = block[0];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rleline[rlen++] = (blocklen-1) | 0x80;
|
|
|
|
for (j=0; j<blocklen; j++)
|
|
|
|
rleline[rlen++] = block[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2013-03-09 18:59:42 -06:00
|
|
|
* PScolor_image - created postscript colorimage operator
|
2010-03-08 04:55:21 -06:00
|
|
|
*
|
|
|
|
* spits out code that checks if the PostScript device in question
|
|
|
|
* knows about the 'colorimage' operator. If it doesn't, it defines
|
|
|
|
* 'colorimage' in terms of image (ie, generates a greyscale image from
|
|
|
|
* RGB data)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
static void
|
|
|
|
PScolor_image(void)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
static char *txt[] = {
|
|
|
|
|
|
|
|
"% define 'colorimage' if it isn't defined",
|
|
|
|
"% ('colortogray' and 'mergeprocs' come from xwd2ps",
|
|
|
|
"% via xgrab)",
|
|
|
|
"/colorimage where % do we know about 'colorimage'?",
|
|
|
|
" { pop } % yes: pop off the 'dict' returned",
|
|
|
|
" { % no: define one",
|
|
|
|
" /colortogray { % define an RGB->I function",
|
|
|
|
" /rgbdata exch store % call input 'rgbdata'",
|
|
|
|
" rgbdata length 3 idiv",
|
|
|
|
" /npixls exch store",
|
|
|
|
" /rgbindx 0 store",
|
|
|
|
" /grays npixls string store % str to hold the result",
|
|
|
|
" 0 1 npixls 1 sub {",
|
|
|
|
" grays exch",
|
|
|
|
" rgbdata rgbindx get 20 mul % Red",
|
|
|
|
" rgbdata rgbindx 1 add get 32 mul % Green",
|
|
|
|
" rgbdata rgbindx 2 add get 12 mul % Blue",
|
|
|
|
" add add 64 idiv % I = .5G + .31R + .18B",
|
|
|
|
" put",
|
|
|
|
" /rgbindx rgbindx 3 add store",
|
|
|
|
" } for",
|
|
|
|
" grays",
|
|
|
|
" } bind def\n",
|
|
|
|
/* Utility procedure for colorimage operator.
|
|
|
|
* This procedure takes two procedures off the
|
|
|
|
* stack and merges them into a single procedure
|
|
|
|
*/
|
|
|
|
" /mergeprocs { % def",
|
|
|
|
" dup length",
|
|
|
|
" 3 -1 roll dup length dup 5 1 roll",
|
|
|
|
" 3 -1 roll add array cvx dup",
|
|
|
|
" 3 -1 roll 0 exch putinterval",
|
|
|
|
" dup 4 2 roll putinterval",
|
|
|
|
" } bind def\n",
|
|
|
|
" /colorimage { % def",
|
|
|
|
/* remove 'false 3' operands */
|
|
|
|
" pop pop",
|
|
|
|
" {colortogray} mergeprocs",
|
|
|
|
" image",
|
|
|
|
" } bind def",
|
|
|
|
/* end of 'false' case */
|
|
|
|
" } ifelse"
|
|
|
|
};
|
|
|
|
|
|
|
|
PSconst_out(txt);
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* PScolormap - write colormap
|
|
|
|
*
|
|
|
|
* spits out code for the colormap of the following image
|
|
|
|
* if !color, it spits out a mono-ized graymap
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PScolormap(int color,
|
|
|
|
int nc,
|
|
|
|
int *rmap,
|
|
|
|
int *gmap,
|
|
|
|
int *bmap)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* define the colormap */
|
|
|
|
PSprintf("/cmap %d string def\n\n\n", nc * ((color) ? 3 : 1));
|
|
|
|
|
|
|
|
/* load up the colormap */
|
|
|
|
PSprintf("currentfile cmap readhexstring\n");
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
for (i=0; i<nc; i++)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
if (color)
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf("%02x%02x%02x ", rmap[i]>>8,
|
|
|
|
gmap[i]>>8, bmap[i]>>8);
|
2013-03-09 18:59:42 -06:00
|
|
|
else
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf("%02x ", MONO(rmap[i], gmap[i], bmap[i]));
|
|
|
|
if ((i%10) == 9)
|
|
|
|
PSprintf("\n");
|
|
|
|
}
|
|
|
|
PSprintf("\n");
|
|
|
|
PSprintf("pop pop\n"); /* lose return values from readhexstring */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSrle_cmapimage - define rlecmapimage operator
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
static void
|
2013-03-09 18:59:42 -06:00
|
|
|
PSrle_cmapimage(int color)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
|
|
|
|
static char *txt[] = {
|
|
|
|
|
|
|
|
/* rlecmapimage expects to have 'w h bits matrix' on stack */
|
|
|
|
"/rlecmapimage {",
|
|
|
|
" /buffer 1 string def",
|
|
|
|
" /rgbval 3 string def",
|
|
|
|
" /block 384 string def",
|
|
|
|
" { currentfile buffer readhexstring pop",
|
|
|
|
" /bcount exch 0 get store",
|
|
|
|
" bcount 128 ge",
|
|
|
|
" { ",
|
|
|
|
" 0 1 bcount 128 sub",
|
|
|
|
" { currentfile buffer readhexstring pop pop"
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *txt_color[] = {
|
|
|
|
" /rgbval cmap buffer 0 get 3 mul 3 getinterval store",
|
|
|
|
" block exch 3 mul rgbval putinterval",
|
|
|
|
" } for",
|
|
|
|
" block 0 bcount 127 sub 3 mul getinterval",
|
|
|
|
" }",
|
|
|
|
" { ",
|
|
|
|
" currentfile buffer readhexstring pop pop",
|
|
|
|
" /rgbval cmap buffer 0 get 3 mul 3 getinterval store",
|
|
|
|
" 0 1 bcount { block exch 3 mul rgbval putinterval } for",
|
|
|
|
" block 0 bcount 1 add 3 mul getinterval",
|
|
|
|
" } ifelse",
|
|
|
|
" }",
|
|
|
|
" false 3 colorimage",
|
|
|
|
"} bind def"
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *txt_gray[] = {
|
|
|
|
" /rgbval cmap buffer 0 get 1 getinterval store",
|
|
|
|
" block exch rgbval putinterval",
|
|
|
|
" } for",
|
|
|
|
" block 0 bcount 127 sub getinterval",
|
|
|
|
" }",
|
|
|
|
" { ",
|
|
|
|
" currentfile buffer readhexstring pop pop",
|
|
|
|
" /rgbval cmap buffer 0 get 1 getinterval store",
|
|
|
|
" 0 1 bcount { block exch rgbval putinterval } for",
|
|
|
|
" block 0 bcount 1 add getinterval",
|
|
|
|
" } ifelse",
|
|
|
|
" }",
|
|
|
|
" image",
|
|
|
|
"} bind def"
|
|
|
|
};
|
|
|
|
|
|
|
|
PSconst_out(txt);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (color)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSconst_out(txt_color);
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
|
|
|
else
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSconst_out(txt_gray);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSwrite_bw - write B&W image
|
|
|
|
*
|
|
|
|
* Write the given image array 'pic' (B/W stippled, 1 byte per pixel,
|
|
|
|
* 0=blk,1=wht) out as hexadecimal, max of 72 hex chars per line. If
|
|
|
|
* 'flipbw', then 0=white, 1=black. Returns '0' if everythings fine,
|
|
|
|
* 'EOF' if writing failed.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
PSwrite_bw(unsigned char *pic, int w, int h, int flipbw)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int err=0;
|
|
|
|
unsigned char outbyte, bitnum, bit;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
outbyte = bitnum = 0;
|
|
|
|
for (i=0; i<h && err != EOF; i++) {
|
|
|
|
for (j=0; j<w && err != EOF; j++) {
|
|
|
|
bit = *(pic++);
|
|
|
|
outbyte = (outbyte<<1) | ((bit)&0x01);
|
|
|
|
bitnum++;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
if (bitnum==8) {
|
|
|
|
if (flipbw)
|
|
|
|
outbyte = ~outbyte & 0xff;
|
|
|
|
err=PShex(outbyte, False);
|
|
|
|
outbyte = bitnum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bitnum) { /* few bits left over in this row */
|
|
|
|
outbyte <<= 8-bitnum;
|
|
|
|
if (flipbw)
|
|
|
|
outbyte = ~outbyte & 0xff;
|
|
|
|
err=PShex(outbyte, False);
|
|
|
|
outbyte = bitnum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err=PShex('\0', True); /* Flush the hex buffer if needed */
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PSimage - generate image Postscript code
|
|
|
|
*
|
|
|
|
* Draw the image, unless there was no image, in which case an empty grey
|
|
|
|
* rectangle is shown.
|
|
|
|
* If anchor is set, a black border is shown around the image.
|
|
|
|
* Positioning is not exactly that of Xmosaic's screen, but close enough.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
static void
|
2010-03-08 04:55:21 -06:00
|
|
|
PSimage(HTMLWidget hw, struct ele_rec *eptr, int fontfamily)
|
|
|
|
{
|
|
|
|
ImageInfo *img = eptr->pic_data;
|
|
|
|
unsigned char *imgp = img->image_data;
|
2013-03-09 18:59:42 -06:00
|
|
|
int anchor = (eptr->anchorHRef != NULL);
|
2010-03-08 04:55:21 -06:00
|
|
|
int ncolors = img->num_colors;
|
|
|
|
int i, j;
|
|
|
|
int w = img->width;
|
|
|
|
int h = img->height;
|
|
|
|
int slen, colorps, colortype, bits;
|
|
|
|
int err=0;
|
|
|
|
int extra = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* Isgray returns true if the nth color index is a gray value */
|
|
|
|
# define Isgray(i,n) (i->reds[n]==i->greens[n] && i->reds[n]==i->blues[n])
|
|
|
|
/* Is_bg returns true if the nth color index is the screen background */
|
|
|
|
# define Is_bg(i,n) (i->reds[n]==bg_color.red && \
|
|
|
|
i->greens[n]==bg_color.green && i->blues[n]==bg_color.blue)
|
|
|
|
/* Is_fg returns true if the nth color index is the screen foreground */
|
|
|
|
# define Is_fg(i,n) (i->reds[n]==fg_color.red && \
|
|
|
|
i->greens[n]==fg_color.green && i->blues[n]==fg_color.blue)
|
|
|
|
|
|
|
|
|
|
|
|
PSmove_offset(eptr->y_offset);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (anchor)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* draw an outline by drawing a slightly larger black square
|
|
|
|
* below the actual image
|
|
|
|
*/
|
|
|
|
PSprintf("gsave currentpoint %d sub translate ", h);
|
|
|
|
PSprintf("0 -2 translate %d %d scale\n", w+4, h+4);
|
|
|
|
PSprintf("SQ fill\n");
|
|
|
|
PSprintf("grestore\n");
|
|
|
|
extra = 4;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
if (imgp == NULL)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* image was not available... do something instead
|
|
|
|
* draw an empty square for example
|
|
|
|
*/
|
|
|
|
PSprintf("gsave currentpoint %d sub translate", h);
|
|
|
|
if (anchor)
|
|
|
|
PSprintf(" 2 0 translate");
|
|
|
|
else
|
|
|
|
PSprintf(" 0 2 translate");
|
|
|
|
PSprintf(" %d %d scale\n", w, h);
|
|
|
|
PSprintf("0.9 setgray SQ fill\n");
|
|
|
|
PSprintf("grestore\n");
|
|
|
|
/* move currentpoint just right of image */
|
|
|
|
PSprintf("%d 0 R\n", w+extra);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/* this is a hack to see if the image is Black & White,
|
2010-03-08 04:55:21 -06:00
|
|
|
* Greyscale or 8 bit color
|
|
|
|
* assume it's bw if it has only one or two colors, both some grey's
|
|
|
|
* assume it's greyscale if all the colors (>2) are grey
|
|
|
|
* Images with only one color do occur too.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
if ( ( (ncolors == 2)
|
2010-03-08 04:55:21 -06:00
|
|
|
&& ( (Isgray(img,0) && Isgray(img,1))
|
2013-03-09 18:59:42 -06:00
|
|
|
|| (Is_bg(img,0) && Is_fg(img,1))
|
2010-03-08 04:55:21 -06:00
|
|
|
|| (Is_fg(img,0) && Is_bg(img,1)) ))
|
|
|
|
|| ( (ncolors == 1)
|
|
|
|
&& (Isgray(img,0)
|
2013-03-09 18:59:42 -06:00
|
|
|
|| Is_bg(img,0)
|
2010-03-08 04:55:21 -06:00
|
|
|
|| Is_fg(img,0))))
|
|
|
|
{
|
|
|
|
colortype = F_BWDITHER;
|
|
|
|
slen = (w+7)/8;
|
|
|
|
bits = 1;
|
|
|
|
colorps = 0;
|
|
|
|
} else {
|
|
|
|
colortype = F_GREYSCALE;
|
|
|
|
slen = w;
|
|
|
|
bits = 8;
|
|
|
|
colorps = 0;
|
|
|
|
for (i=0; i<ncolors; i++) {
|
|
|
|
if (!Isgray(img,i)) {
|
|
|
|
colortype = F_REDUCED;
|
|
|
|
slen = w*3;
|
|
|
|
bits = 8;
|
|
|
|
colorps = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* build a temporary dictionary */
|
|
|
|
PSprintf("20 dict begin\n\n");
|
|
|
|
|
|
|
|
/* define string to hold a scanline's worth of data */
|
|
|
|
PSprintf("/pix %d string def\n\n", slen);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* position and scaling */
|
|
|
|
PSprintf("gsave currentpoint %d sub translate", h);
|
|
|
|
if (anchor)
|
|
|
|
PSprintf(" 2 0 translate");
|
|
|
|
else
|
|
|
|
PSprintf(" 0 2 translate");
|
|
|
|
PSprintf(" %d %d scale\n", w, h);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
if (colortype == F_BWDITHER)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* 1-bit dither code uses 'image' */
|
|
|
|
int flipbw = 0;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* set if color#0 is 'white' */
|
|
|
|
if ((ncolors == 2 &&
|
|
|
|
MONO(img->reds[0], img->greens[0],img->blues[0]) >
|
|
|
|
MONO(img->reds[1], img->greens[1], img->blues[1])) ||
|
2013-03-09 18:59:42 -06:00
|
|
|
(ncolors == 1 &&
|
2010-03-08 04:55:21 -06:00
|
|
|
MONO(img->reds[0], img->greens[0],img->blues[0]) >
|
|
|
|
MONO(127, 127, 127) ))
|
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
flipbw=1;
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* dimensions of data */
|
|
|
|
PSprintf("%d %d %d\n", w, h, bits);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* mapping matrix */
|
|
|
|
PSprintf("[%d 0 0 %d 0 %d]\n\n", w, -h, h);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSprintf("{currentfile pix readhexstring pop}\n");
|
|
|
|
PSprintf("image\n");
|
|
|
|
|
|
|
|
/* write the actual image data */
|
|
|
|
err = PSwrite_bw(imgp, w, h, flipbw);
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* all other formats */
|
|
|
|
unsigned char *rleline = (unsigned char *) NULL;
|
|
|
|
int rlen;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* if we're using color, make sure 'colorimage' is defined */
|
|
|
|
if (colorps)
|
|
|
|
PScolor_image();
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PScolormap(colorps, ncolors, img->reds, img->greens, img->blues);
|
|
|
|
PSrle_cmapimage(colorps);
|
|
|
|
|
|
|
|
/* dimensions of data */
|
|
|
|
PSprintf("%d %d %d\n", w, h, bits);
|
|
|
|
/* mapping matrix */
|
|
|
|
PSprintf("[%d 0 0 %d 0 %d]\n", w, -h, h);
|
|
|
|
PSprintf("rlecmapimage\n");
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
rleline = (unsigned char *) malloc(w * 2);
|
2013-03-09 18:59:42 -06:00
|
|
|
if (!rleline)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
#ifndef DISABLE_TRACE
|
|
|
|
if (htmlwTrace) {
|
|
|
|
fprintf(stderr,"failed to malloc space for rleline\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
for (i=0; i<h && err != EOF; i++)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
rlen = PSrle_encode(imgp, rleline, w);
|
|
|
|
imgp += w;
|
|
|
|
for (j=0; j<rlen && err != EOF; j++)
|
|
|
|
err=PShex(rleline[j], False);
|
|
|
|
err=PShex('\0', True); /* Flush the hex buffer */
|
|
|
|
}
|
|
|
|
free(rleline);
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* stop using temporary dictionary */
|
|
|
|
PSprintf("end\n");
|
|
|
|
PSprintf("grestore\n");
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* move currentpoint just right of image */
|
2013-03-09 18:59:42 -06:00
|
|
|
PSprintf("%d 0 R\n", w + extra);
|
|
|
|
if (HTML_Print_Footers && has_footnote(eptr))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PSmove_offset(0);
|
|
|
|
PSfootnote(eptr->anchorHRef, 2.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* forget about the macro's */
|
|
|
|
# undef Isgray
|
|
|
|
# undef Is_fg
|
|
|
|
# undef Is_bg
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ParseTextToPSString - entry point for postscript output
|
|
|
|
*
|
|
|
|
* Parse all the formatted text elements from start to end
|
|
|
|
* into an ascii text string, and return it.
|
|
|
|
* Very like ParseTextToString() except the text is prettied up
|
|
|
|
* into Postscript to show headers and the like.
|
|
|
|
* space_width and lmargin tell us how many spaces
|
|
|
|
* to indent lines.
|
|
|
|
* Because this routine is only used to print whole documents,
|
|
|
|
* some parameters are not needed at all!
|
|
|
|
* Also it assumes that you are indeed printing the whole document, and
|
|
|
|
* not just a selected portion of it. It therefore can assume that
|
|
|
|
* only for the first page the initialization is needed, and only
|
|
|
|
* the last page has the trailers. You cannot use ParseTextToPSString()
|
|
|
|
* as you can use ParseTextToString() because of this initialization code.
|
|
|
|
*
|
|
|
|
* the fontfamily parameter is new
|
|
|
|
* The font is encoded as:
|
|
|
|
* 0: times (default for now)
|
|
|
|
* 1: helvetica
|
|
|
|
* 2: new century schoolbook
|
|
|
|
* 3: lucida
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
String ParseTextToPSString(HTMLWidget hw,
|
2010-03-08 04:55:21 -06:00
|
|
|
struct ele_rec *elist,
|
|
|
|
struct ele_rec *startp,
|
|
|
|
struct ele_rec *endp,
|
2013-03-09 18:59:42 -06:00
|
|
|
int start_pos,
|
2010-03-08 04:55:21 -06:00
|
|
|
int end_pos,
|
|
|
|
int space_width,
|
|
|
|
int lmargin,
|
|
|
|
int fontfamily,
|
|
|
|
char *url,
|
|
|
|
char *time_str)
|
|
|
|
{
|
|
|
|
int xpos, ypos, epos;
|
|
|
|
int height;
|
|
|
|
double pagewidth;
|
|
|
|
int line = -1;
|
|
|
|
struct ele_rec *eptr;
|
|
|
|
struct ele_rec *start;
|
|
|
|
struct ele_rec *end;
|
|
|
|
struct ele_rec *last;
|
|
|
|
struct ele_rec *tmpptr;
|
2013-03-09 18:59:42 -06:00
|
|
|
unsigned long fg_pixel, bg_pixel;
|
2010-03-08 04:55:21 -06:00
|
|
|
int footnotes_this_page = 0;
|
|
|
|
int footnotes_this_line;
|
|
|
|
int reserved_space;
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
if (startp == NULL)
|
|
|
|
return(NULL);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the foreground and background colors so we can check later
|
|
|
|
* for black&white documents
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
XtVaGetValues (hw->html.view,
|
2010-03-08 04:55:21 -06:00
|
|
|
#ifdef MOTIF
|
|
|
|
XtNforeground, &fg_pixel,
|
|
|
|
#endif
|
2013-03-09 18:59:42 -06:00
|
|
|
XtNbackground, &bg_pixel,
|
2010-03-08 04:55:21 -06:00
|
|
|
NULL);
|
|
|
|
#ifndef MOTIF
|
2013-03-09 18:59:42 -06:00
|
|
|
XtVaGetValues ((Widget)hw,
|
2010-03-08 04:55:21 -06:00
|
|
|
XtNforeground, &fg_pixel,
|
|
|
|
NULL);
|
2013-03-09 18:59:42 -06:00
|
|
|
#endif
|
2010-03-08 04:55:21 -06:00
|
|
|
fg_color.pixel = fg_pixel;
|
|
|
|
bg_color.pixel = bg_pixel;
|
|
|
|
XQueryColor(XtDisplay(hw->html.view),
|
|
|
|
(installed_colormap ?
|
|
|
|
installed_cmap :
|
|
|
|
DefaultColormap(XtDisplay(hw->html.view),
|
|
|
|
DefaultScreen(XtDisplay(hw->html.view)))),
|
|
|
|
&fg_color);
|
|
|
|
XQueryColor(XtDisplay(hw->html.view),
|
|
|
|
(installed_colormap ?
|
|
|
|
installed_cmap :
|
|
|
|
DefaultColormap(XtDisplay(hw->html.view),
|
|
|
|
DefaultScreen(XtDisplay(hw->html.view)))),
|
|
|
|
&bg_color);
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* this piece of code is needed if the user selects a portion
|
|
|
|
* of the document with the mouse.
|
|
|
|
* I think it will never be used, but I left it in anyway. F.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
if (SwapElements(startp, endp, start_pos, end_pos))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
start = endp;
|
|
|
|
end = startp;
|
|
|
|
epos = start_pos;
|
|
|
|
start_pos = end_pos;
|
|
|
|
end_pos = epos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
start = startp;
|
|
|
|
end = endp;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
/* Setup page size according to user preference. */
|
|
|
|
|
|
|
|
if (HTML_Print_Paper_Size_A4)
|
|
|
|
page_dimens = a4_page_dimens;
|
|
|
|
else
|
|
|
|
page_dimens = us_letter_page_dimens;
|
|
|
|
|
|
|
|
page_dimens.text_height = ( page_dimens.page_height
|
2013-03-09 18:59:42 -06:00
|
|
|
- page_dimens.top_margin
|
2010-03-08 04:55:21 -06:00
|
|
|
- page_dimens.bot_margin);
|
|
|
|
page_dimens.text_width = ( page_dimens.page_width
|
2013-03-09 18:59:42 -06:00
|
|
|
- page_dimens.left_margin
|
2010-03-08 04:55:21 -06:00
|
|
|
- page_dimens.right_margin);
|
|
|
|
|
|
|
|
/* Calculate the number of Postscript points per pixel of current
|
|
|
|
* screen, and the height of the page in pixels (used in figuring
|
|
|
|
* when we've hit the bottom of the page).
|
|
|
|
*/
|
|
|
|
Points_Pixel = 72.0 / GetDpi(hw);
|
|
|
|
#ifdef OLD
|
|
|
|
pagewidth = hw->html.doc_width;
|
|
|
|
#else /* gustaf fix */
|
|
|
|
pagewidth = hw->html.view_width;
|
|
|
|
#endif /* gustaf fix */
|
|
|
|
|
|
|
|
/* reduce the scaling if the width used for formatting is greater
|
|
|
|
* than 8 * 72 pixels (8 inch)
|
|
|
|
* In theory, this is not what you want for A4 paper (only 8.27 inch
|
|
|
|
* wide), but I guess that the hw->html.doc_width includes some
|
|
|
|
* left and right margins, so it seems to work in practice.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
if (pagewidth > page_dimens.text_width)
|
2010-03-08 04:55:21 -06:00
|
|
|
Points_Pixel = Points_Pixel * page_dimens.text_width / pagewidth;
|
2013-03-09 18:59:42 -06:00
|
|
|
Pixels_Page = (int) (page_dimens.text_height / Points_Pixel);
|
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSinit();
|
|
|
|
PSheader(hw->html.title, fontfamily, url, time_str);
|
|
|
|
PSnewpage();
|
|
|
|
|
|
|
|
last = start;
|
|
|
|
eptr = start;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
while ((eptr != NULL) && (eptr != end))
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* Skip the special internal text added for multi-page
|
|
|
|
* documents.
|
|
|
|
*/
|
2013-03-09 18:59:42 -06:00
|
|
|
if (eptr->internal == True)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
2013-03-09 18:59:42 -06:00
|
|
|
if (eptr->type == E_LINEFEED)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_page_offset += eptr->line_height;
|
|
|
|
}
|
|
|
|
eptr = eptr->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check if this is a newline */
|
2013-03-09 18:59:42 -06:00
|
|
|
if (line != eptr->line_number)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
/* calculate max height */
|
|
|
|
height = 0;
|
|
|
|
footnotes_this_line = 0;
|
|
|
|
line = eptr->line_number;
|
|
|
|
tmpptr = eptr;
|
2013-03-09 18:59:42 -06:00
|
|
|
while (tmpptr != NULL && tmpptr->line_number == line)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
if (tmpptr->line_height > height)
|
|
|
|
height = tmpptr->line_height;
|
|
|
|
tmpptr = tmpptr->next;
|
|
|
|
if (HTML_Print_Footers && has_footnote(tmpptr))
|
|
|
|
footnotes_this_line++;
|
|
|
|
}
|
|
|
|
ypos = eptr->y - PS_page_offset ;
|
|
|
|
xpos = eptr->x - lmargin;
|
|
|
|
if (xpos < 0)
|
|
|
|
xpos = 0;
|
|
|
|
|
|
|
|
/* check if line fits completly on page */
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
reserved_space = 0;
|
2013-03-09 18:59:42 -06:00
|
|
|
if (footnotes_this_page || footnotes_this_line)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
reserved_space = ( ( footnote_space
|
|
|
|
+ ( footnote_ptsize
|
2013-03-09 18:59:42 -06:00
|
|
|
* ( footnotes_this_page
|
2010-03-08 04:55:21 -06:00
|
|
|
+ footnotes_this_line)))
|
|
|
|
/ Points_Pixel);
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if (ypos + height + reserved_space > PS_start_y + Pixels_Page)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
PS_start_y = ypos;
|
|
|
|
PSshowpage();
|
|
|
|
PSnewpage();
|
|
|
|
footnotes_this_page = 0;
|
|
|
|
}
|
|
|
|
footnotes_this_page += footnotes_this_line;
|
|
|
|
PSmoveto( xpos, ypos);
|
|
|
|
}
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
|
|
|
|
switch (eptr->type)
|
2010-03-08 04:55:21 -06:00
|
|
|
{
|
|
|
|
case E_TEXT:
|
|
|
|
PStext(hw, eptr, fontfamily,
|
|
|
|
(String)((eptr == start) ? (eptr->edata + start_pos) : eptr->edata));
|
|
|
|
break;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
case E_BULLET:
|
2010-03-08 04:55:21 -06:00
|
|
|
PSbullet(hw, eptr, fontfamily);
|
|
|
|
break;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
case E_IMAGE:
|
2010-03-08 04:55:21 -06:00
|
|
|
PSimage(hw, eptr, fontfamily);
|
|
|
|
break;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
case E_LINEFEED:
|
2010-03-08 04:55:21 -06:00
|
|
|
break;
|
|
|
|
|
|
|
|
case E_HRULE:
|
|
|
|
PShrule(hw, eptr, fontfamily);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case E_TABLE:
|
|
|
|
PStable(hw, eptr, fontfamily);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case E_WIDGET:
|
|
|
|
PSwidget(hw, eptr, fontfamily);
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
last = eptr;
|
|
|
|
eptr = eptr->next;
|
|
|
|
}
|
2013-03-09 18:59:42 -06:00
|
|
|
|
2010-03-08 04:55:21 -06:00
|
|
|
PSshowpage();
|
|
|
|
PStrailer();
|
|
|
|
|
|
|
|
return (PS_string);
|
|
|
|
}
|
|
|
|
|