This is lj.c in view mode; [Download] [Up]
/* Project: lj2ps ** File: lj.c ** ** Author: Christopher Lishka ** Organization: Wisconsin State Laboratory of Hygiene ** Data Processing Dept. ** ** Copyright (C) 1990 by Christopher Lishka. ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 1, or (at your option) ** any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static char * ModuleID = "Module lj: v1.0, production"; /* Include files */ #include <stdio.h> #if defined (NeXT) #include <stdlib.h> #endif #include "lj.h" #include "ljcmds.h" #include "ljfonts.h" #include "scan.h" #include "lj2ps.h" /* External definitions */ /* Global variables */ /* Front panel variables */ int panel_copies; /* Front panel: Copies */ int panel_manual_feed; /* Front panel: Manual Feed */ int panel_font_source; /* Front panel: Font Source */ int panel_font_number; /* Front panel: Font Number */ int panel_orientation; /* Front panel: Font Source, Font Number */ int panel_form; /* Front panel: Form (i.e. lines/page) */ /* Postscript specific variables */ double ps_scale_x; /* PS: scale in x direction */ double ps_scale_y; /* PS: scale in y direction */ double ps_offset_x; /* PS: offset in x direction */ double ps_offset_y; /* PS: offset in y direction */ /* Job control */ int copies; /* Number of copies */ #if defined (NeXT) int allow_page_reversing = 1; #endif /* Page control */ int paper_source; /* Where the paper is coming from */ int orientation; /* Portrait/landscape (code) */ psize page_size; /* Type of paper being used (structure) */ double page_height; /* Height of physical page (inches) */ double page_width; /* Width of physical page (inches) */ double char_height; /* Char height (~= VMI) (inches) */ double char_width; /* Char width (~= HMI) (inches) */ double margin_top; /* Top margin (inches) */ int text_length; /* Text length (lines) */ double text_height; /* Text height (inches) */ double margin_left; /* Left margin (inches) */ double text_width; /* Text width (inches) */ int perf_skip; /* 1 if perforation skip is on */ int line_term; /* Current line termination mode */ /* Fonts */ ljfont font_p; /* Primary font */ ljfont font_s; /* Secondary font */ int underline; /* Underline mode */ /* Font management */ int font_ID; /* Current font ID */ int char_code; /* Current character code */ /* Raster graphics */ int resolution; /* Current graphics resolution */ int margin_graphics; /* Graphics left margin, in dots? */ /* Rectangular area fill */ int rect_size_h; /* Horizontal rectangle size */ int rect_size_v; /* Vertical rectangle size */ int fill_ID; /* Current area fill ID */ /* Macro */ int macro_ID; /* Current macro ID */ /* Troubleshooting commands */ int eol_wrap; /* End-of-line wrap on/off */ int display_funcs; /* Display functions on/off */ /* Implementation variables */ double current_x; /* Current X position (inches) */ double current_y; /* Current Y position (inches) */ int current_line; /* Current line being printed (lines) */ int current_font; /* Primary or secondary (code) */ int empty_line; /* Ture if line is empty (boolean) */ int empty_text; /* True if text is empty (boolean) */ int empty_page; /* True if page is empty (boolean) */ double compress_width; /* Compression in x axis (%) */ double compress_height; /* Compression in y axis (%) */ double offset_width; /* Offset of x axis (inches) */ double offset_height; /* Offset of y axis (inches) */ /* Global function list */ extern void lj_factory_setup(); /* Reset to factory defaults */ extern void lj_startup(); /* Do before the virtual LJ is ready... */ extern void lj_shutdown(); /* Do after the virtual LJ is shutdown... */ extern void lj_page_begin(); /* Start a new page */ extern void lj_page_end(); /* End the current page */ /* macro lj_text_begin();*/ /* Start text */ /* macro lj_text_add(); */ /* Add text to buffer */ /* macro lj_text_end(); */ /* End text (i.e. flush the buffer) */ /* macro lj_cursor_move();*//* Move cursor to a new location */ /* macro lj_set_font(); */ /* Use a new font to print the text */ /* macro lj_undl_begin();*/ /* Start underlining */ /* macro lj_undl_flush();*/ /* Flush the current underline request */ /* macro lj_undl_end(); */ /* End underlining */ extern void lj_nl(); /* Print a newline */ extern void lj_reset(); /* Reset the printer to default state */ extern int lj_paper_size(); /* Get the dimensions of paper and envelopes */ /* Local constants */ /* Local structures and types */ /* Local variables */ /* Implementation variables */ static int new_page; /* Is the next page a new one? */ static int page_number; /* Which page we are currently printing */ /* Tables */ psize paper_size[] = { /* Sizes (in inches) for paper and envelopes */ { LJ_PS_EXECUTIVE, 7.2500, 10.5000, 57, /* Paper sizes */ 0.2000, 0.2000, 0.1667, 0.3333 }, { LJ_PS_LETTER, 8.5000, 11.0000, 60, 0.2000, 0.2000, 0.1667, 0.3333 }, { LJ_PS_LEGAL, 8.5000, 14.0000, 78, 0.2000, 0.2000, 0.1667, 0.3333 }, { LJ_PS_A4, 8.2677, 11.6929, 64, 0.2000, 0.1933, 0.1667, 0.3067 }, { LJ_PS_MONARCH, 3.8750, 7.5000, 39, /* Envelope sizes */ 0.2000, 0.2000, 0.1667, 0.3333 }, { LJ_PS_COMMERCIAL10, 4.1250, 9.5000, 51, 0.2000, 0.2000, 0.1667, 0.3333 }, { LJ_PS_INTERNATIONALDL, 4.3307, 8.6614, 46, 0.2000, 0.1933, 0.1667, 0.3067 }, { LJ_PS_INTERNATIONALC5, 6.3780, 9.0157, 48, 0.2000, 0.1933, 0.1667, 0.3067 }, { 0, 0.0000, 0.0000 } /* The end must be all 0's */ }; /* Local macro definitions */ /* Local function list */ /* Function bodies */ void lj_factory_setup() { panel_copies = 1; panel_manual_feed = LJ_PS_TRAY_1; panel_form = 60; panel_orientation = LJ_OR_PORTRAIT; panel_font_source = LJ_FS_INTERNAL; panel_font_number = 0; ps_scale_x = 1.0; ps_scale_y = 1.0; ps_offset_x = 0.0; ps_offset_y = 0.0; } /* lj_factory_setup() */ void lj_startup(ofile) FILE *ofile; { /* Set the default laserjet variables by executing a reset (ljcmd_E) */ lj_reset(ofile); /* ** The postscript prologue ** ** Postscript naming conventions used here: ** ** Note: X = uppercase letter; x = lowercase letter. ** ** X, XX, XXX: Functions ** ** x, xx, xxx: Global variables ** ** Xx, Xxx: Temporary variables */ /* First write out the comments */ fprintf(ofile, "%%!PS-Adobe-1.0\n"); /* The standard header */ fprintf(ofile, "%%%%Creator: %s %s (%s)\n", PROGRAM, VERSION, STATUS); /* Identify oneself! */ fprintf(ofile, "%%%%Pages: (atend)\n"); fprintf(ofile, "%%%%EndComments\n"); fprintf(ofile, "\n"); /* Next, write the prologue code */ /* Set the number of copies */ fprintf(ofile, "/#copies %d def\n", copies); /* Use letter size paper (8.5"x11") */ /* fputs("letter\n", ofile);*/ /* XXX */ #if !defined (NeXT) /* Set manual or automatic feed */ if( (paper_source == LJ_PS_MANUAL) || (paper_source == LJ_PS_MANUAL_ENVELOPE) ){ fprintf(ofile, "statusdict begin /manualfeed true def end\n"); } else{ fprintf(ofile, "statusdict begin /manualfeed false def end\n"); } #endif /* Define variables for the current font, font size, and font width */ fputs("\n", ofile); fprintf(ofile, "/cf /%s def\n", font_p.ps_name); fprintf(ofile, "/cs %.4f def\n", pt2in(font_p.point_size)); fprintf(ofile, "/cw %.4f def\n", font_p.width); /* Left margin */ fputs("\n", ofile); fprintf(ofile, "/ml %.4f def\n", margin_left); /* Variables for underlining */ fputs("\n", ofile); fputs("/ux 0.0 def\n", ofile); /* X coord of underline beginning */ fputs("/uy 0.0 def\n", ofile); /* Y coord of underline beginning */ /* <String> S -> % Show the string */ fputs("\n/S /show load def\n", ofile); /* <X> <Y> -> % Move to (<X>,<Y>) */ fputs("\n/M /moveto load def\n", ofile); /* <DeltaX> HRM -> % Move <DeltaX> horizontally (i.e. relative) */ fputs("\n\ /HRM {\n\ 0 rmoveto\n\ } bind def\n\ ", ofile); /* <Y> VM -> % Move to <Y> (i.e. vertical absolute) */ fputs("\n\ /VM {\n\ currentpoint pop exch moveto\n\ } bind def\n\ ", ofile); /* Set Right Margin -- uses clippath ** Note: 25 is used as an arbitrary size. The only requirement of this ** number is that it must be outside the page boundaries */ fputs("\n\ /RM {\n\ /Tr exch def\n\ currentpoint initclip\n\ newpath\n\ 0 0 moveto Tr 0 lineto Tr 25 lineto 0 25 lineto\n\ closepath clip\n\ moveto\n\ } bind def\n\ ", ofile); /* <typeface> <point-size> F -> ** Set the font, given typeface and point size. ** Note that the character-width is derived by having PostScript ** provide the width of the *space* character (which is likely ** the best character to use for a proportional font). */ fputs("\n\ /F {\n\ /Tp exch def /Tf exch def\n\ Tf findfont Tp scalefont setfont\n\ /cf Tf def /cs Tp def /cw ( ) stringwidth pop def\n\ } bind def\n\ ", ofile); /* <typeface> <width> <height> FS -> ** Set the font, given typeface, X scale factor, Y scale factor. ** Note that the character-width is derived by having PostScript ** provide the width of the *space* character (which is likely ** the best character to use for a proportional font). */ fputs("\n\ /FS {\n\ /Ty exch def /Tx exch def /Tf exch def\n\ Tf findfont [Tx 0 0 Ty 0 0] makefont setfont\n\ /cf Tf def /cs Ty def /cw ( ) stringwidth pop def\n\ } bind def\n\ ", ofile); /* US -> Start a new underline */ fputs("\n\ /US {\n\ currentpoint /uy exch def /ux exch def\n\ } bind def\n\ ", ofile); /* UE -> Finish (i.e. draw!) the current underline ** ** Note that this underlining does not yet work across separate lines, ** so US and UE must be called on the same line. Also, underlining does ** not work backwards, so only use it if going forwards with the ** underlines (yes, I know this is very limited, but tracking page motion ** is a bit hard with underlining). */ fputs("\n\ /UE {\n\ /Tcx currentpoint pop def\n\ gsave\n\ newpath\n\ cf findfont cs scalefont dup\n\ /FontMatrix get 0 get /Ts exch def /FontInfo get dup\n\ /UnderlinePosition get Ts mul /To exch def\n\ /UnderlineThickness get Ts mul /Tt exch def\n\ ux uy To add moveto Tcx uy To add lineto\n\ Tt setlinewidth stroke\n\ grestore\n\ } bind def\n\ ", ofile); /* TAB -> Tab over to the next tab stop ** For efficiency, this function gets the currentpoint, exch's to ** get the current-x to the top-of-stack, works magic on the ** current-x to figure out the position of the tab stop, exch's ** again to get the arguments in the right sequence for the moveto ** operator, and moves to the tab position. ** ** Note that (1.0 + LJ_ERROR) is added to the calculation. The 1.0 ** represents the movement to the next tab-stop. LJ_ERROR is needed ** insure that the value is within a certain error-margin in its proximity ** to the tab-stop when the "cvi" (i.e. drop the decimal portion) is ** performed. */ fprintf(ofile, "\n\ /TAB {\n\ currentpoint exch\n\ ml sub cw div %d div %f add cvi %d mul cw mul ml add\n\ exch moveto\n\ } bind def\n\ ", LJ_TAB_WIDTH, (1.0 + LJ_ERROR), LJ_TAB_WIDTH); /* Initialization of the position stack would go here, if it was ** implemented! */ /* Mark the end of the prolog */ fprintf(ofile, "\n%%%%EndProlog\n"); #if defined (NeXT) fprintf (ofile, "%%%%BeginSetup\n"); if (!allow_page_reversing) fprintf (ofile, "%%%%Feature: *PageOrder Special\n"); /* Set manual feed, if desired. */ if( (paper_source == LJ_PS_MANUAL) || (paper_source == LJ_PS_MANUAL_ENVELOPE) ) fprintf(ofile, "%%%%Feature: *ManualFeed True\n"); else fprintf (ofile, "%%%%Feature: *ManualFeed False\n"); fprintf (ofile, "%%%%EndSetup\n"); #endif /* Start the first page */ new_page = 1; page_number = 0; } /* lj_startup() */ void lj_shutdown(ofile) FILE *ofile; { #if !defined (NeXT) fprintf(ofile, "\nstatusdict begin /manualfeed false def end\n"); #endif fprintf(ofile, "%%%%Trailer\n"); fprintf(ofile, "%%%%Pages: %d\n", page_number); } /* lj_shutdown() */ void lj_page_begin(ofile) FILE *ofile; { /* Set starting position */ current_x = margin_left; current_y = page_height - margin_top - char_height; current_line = 1; /* Print the PostScript page header */ if( new_page ){ page_number++; #if defined (NeXT) /* ** To prevent page reversing, we don't output %%Page comments, at ** least until NeXT pays attention to %%PageOrder commands. */ if (allow_page_reversing) #endif fprintf(ofile, "\n%%%%Page: ? %d\n", page_number); } /* Save the current graphics state */ fputs("save\n", ofile); /* Note: the next three pieces of code must be in the following ** order to insure that everything works correctly: ** ** (1) Make inches the default measure ** (2) Rotate the the page to landscape, if necessary ** (3) Perform default offsets and page scaling */ /* Make inches the default measure. Note that this must be at the ** beginning of every *page* (rather than in the prologue) because ** the PostScript showpage function resets the graphics state. */ fprintf(ofile, "72 72 scale\n"); /* Rotate the page to the proper orientation */ if( orientation == LJ_OR_LANDSCAPE ){ fprintf(ofile, "90 rotate 0 %.4f translate\n", -page_size.width); } /* Make sure everything fits in the printable region */ fprintf(ofile, "%.4f %.4f translate %.4f %.4f scale\n", offset_width, offset_height, compress_width, compress_height); /* Make sure that a current point exists */ fputs("0 0 moveto\n", ofile); /* Set the initial font */ if( current_font == LJ_FT_PRIMARY ) lj_set_font(ofile, font_p); else lj_set_font(ofile, font_s); /* Set the left margin */ fprintf(ofile, "/ml %.4f def ", margin_left); /* Set the right margin */ fprintf(ofile, " %.4f RM ", margin_left + text_width); /* Default position */ fprintf(ofile, "%.4f %.4f M\n", current_x, current_y); empty_page = 1; lj_undl_mark(ofile); lj_text_begin(); } /* lj_page_begin() */ void lj_page_end(ofile) FILE *ofile; { lj_text_end(ofile); lj_undl_flush(ofile); fputs("\nrestore ", ofile); if( empty_page ){ /* Clear the page without using erasepage! */ fputs("gsave newpath clippath 1 setgray fill grestore\n", ofile); new_page = 0; /* Still the same physical page */ } else{ fputs("showpage\n", ofile); /* Print the page */ new_page = 1; /* A new physical page is started */ } } /* lj_page_end() */ void lj_nl(ofile) FILE *ofile; { lj_text_end(ofile); lj_undl_flush(ofile); current_x = margin_left; current_y -= char_height; fprintf(ofile, "%% NL\n%.4f %.4f M ", current_x, current_y); empty_line = 1; lj_undl_mark(ofile); lj_text_begin(); } /* lj_nl() */ void lj_reset(ofile) FILE *ofile; { /* ***** JOB CONTROL ************************************************** */ copies = panel_copies; /* Number of copies, from the "front panel" */ /* ***** FONTS ******************************************************** ** ** Note: fonts must come before page control because the HMI (i.e. ** char_width) is determined from the font. */ /* Reset the primary font */ if( lj_find_font(panel_font_source, panel_font_number, &font_p) == 1 ){ fatal_error("could not find specified font", ""); } /* Reset the secondary font */ if( lj_find_font(panel_font_source, panel_font_number, &font_p) == 1 ){ fatal_error("could not find specified font", ""); } /* Underline, should be off */ underline = LJ_UL_OFF; /* ***** PAGE CONTROL ************************************************ */ /* Paper source, from the "front panel" */ paper_source = panel_manual_feed; /* Page orientation, from the "front panel" */ orientation = panel_orientation; /* Determine the physical page size */ page_size.code = LJ_PS_LETTER; /* Letter size, by default */ if( lj_paper_size(&page_size) ){ internal_error("illegal page size", ""); } /* Page width and height */ if( orientation == LJ_OR_PORTRAIT ){ page_width = page_size.width; page_height = page_size.height; } else{ page_width = page_size.height; page_height = page_size.width; } /* Top margin, text height (inches), and text length (lines). ** Char width and height are set here as well due to the ** inter-dependencies. */ margin_top = 0.5; /* Top and bottom margins are 1/2" */ text_height = page_height - margin_top - 0.5; /* 0.5 is for bottom margin */ char_height = text_height / panel_form; char_width = font_p.width; /* inches per character */ text_length = text_height / char_height; /* Left margin + text_width (= page width - right margin) */ margin_left = 0.0; /* Initially, the right margin is not set. To simulate this, the ** text_width is set to be wider than any reasonable page width. */ text_width = 99.00; /* Perforation skip */ perf_skip = 1; /* Line termination: start with normal */ line_term = LJ_LT_NORM; /* ***** FONT MANAGEMENT ********************************************** */ /* Current font ID, for soft fonts */ font_ID = 0; /* Current character code, for soft fonts */ char_code = 0; /* ***** RASTER GRAPHICS ********************************************** */ /* Graphics resolution, start at 300 dpi */ resolution = 75; /* Graphics margin, start at 0 */ margin_graphics = 0; /* ***** RECTANGULAR AREA FILL **************************************** */ /* ID for filling areas (one ID used for both patterns and gray scales) */ fill_ID = LJ_FI_RULE; /* *Black* greyscale! */ /* Horizontal and vertical graphics area sizes */ rect_size_h = 0; rect_size_v = 0; /* ***** MACRO ******************************************************** */ /* Current macro ID */ macro_ID = 0; /* ***** TROUBLESHOOTING COMMANDS ************************************* */ /* End-of-line wrap: should be off */ eol_wrap = 0; /* Display functions should be off */ display_funcs = 0; /* ***** IMPLEMENTATION VARIABLES ************************************* */ current_x = margin_left; current_y = page_height - margin_top - char_height; current_line = 1; current_font = LJ_FT_PRIMARY; empty_line = 1; empty_text = 1; empty_page = 1; compress_width = ps_scale_x * LJ_DEFAULT_SCALE_X; compress_height = ps_scale_y * LJ_DEFAULT_SCALE_Y; offset_width = ps_offset_x + LJ_DEFAULT_OFFSET_X; offset_height = ps_offset_y + LJ_DEFAULT_OFFSET_Y; } /* lj_reset() */ /* lj_paper_size() looks up the dimensions of the paper or envelope ** passed in the code field of the argument. If the code is legal, then ** the width and height fields are filled and a 0 is returned. If the ** code does not exist, then the width and height fields are undefined and ** a 1 is returned. */ int lj_paper_size(page_size) psize *page_size; { int found; int counter; found = 0; for( counter = 0; !found && !(paper_size[counter].code == 0); counter++ ){ if( page_size->code == paper_size[counter].code ){ found = 1; page_size->width = paper_size[counter].width; page_size->height = paper_size[counter].height; } /* if(...) */ } /* for(...) */ return( !found ); } /* lj_paper_size() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.