Date: Mon, 24 Nov 86 17:25:49 est From: David Krowitz Here are the source files for a print-server for an Apple Imagewriter dot matrix printer running on an Apollo workstation with an RS232 interface. See the file PRF.IMAGEWRITER.HLP for the particular capabilities of this print-server (including multiple fonts, bitmap graphics, etc). Documentation and compiling instructions are in the normal .DOC and .BLD files. The bundled files start below the dashed line. -- David Krowitz ----------------------------------------------------------------------- # To unbundle, sh this file echo imagewriter.config 1>&2 cat >imagewriter.config <<'End of imagewriter.config' PAGE_WIDTH 80 PAGE_LENGTH 66 PAGENO_COLUMN 72 FILE_BANNERS OFF DEVICE user1 SIO_LINE 2 SPEED 9600 TOP_MARGIN 0 BOTTOM_MARGIN 6 FORM_FEEDS 0 PLOT_MODE ON RESOLUTION 72 End of imagewriter.config echo prf.imagewriter.hlp 1>&2 cat >prf.imagewriter.hlp <<'End of prf.imagewriter.hlp' 9.04;prf (print_file), revision 9.04, 85/05/30 PRF (PRINT_FILE) -- Queue a file for printing. usage: PRF pathname... [-INTER] [-COP n] [-PR name] [-SITE entry_dir] [-USER name] [-SIG ALARM|OFF] [-BAN [ON|OFF]] [-CONFIG [pathname]|-NDB] [-TEXT|-PLOT|-TRANSPARENT] [-NPAG] [-MARGINS [ON|OFF]] [-TOP n] [-BOT n] [-RIGHT n] [-LEFT n] [-HEADERS [ON|OFF]] [-HEAD l-string/c-string/r-string] [-FOOT l-string/c-string/r-string] [-FTN [ON|OFF]] [-WRAP [ON|OFF]] [-PITCH n] [-POINT n] [-WEIGHT value] [-LQ [ON|OFF]] [-RES n] [-WHITE n] [-BW [ON|OFF]] [-MAGN {-1..16}] {CL} FORMAT PRF [pathname...] [options] PRF queues a file for printing. The file must be an ASCII stream (i.e., text) file, a graphics metafile (GMF), or a GPR bitmap object. After successfully queueing a file, PRF displays a message containing the full pathname of the file that you queued. You can execute PRF once for each file that you want to print (specifying all the necessary options every time), or you can enter PRF's interactive mode and hand files to the program continuously. See the examples below. Files queued by PRF are physically printed using PRSVR (PRINT_SERVER). When you invoke PRF, it first sets all options to their default states (as described below). Next, it looks for a PRF configuration file called ~USER_DATA/PRF.DB unless you have invoked PRF with the -NDB option (described below). If PRF locates a configuration file, it executes the options contained in the file to configure the current session. Finally, it proceeds to process any options on the command line or in the interactive session. A menu-based version of the PRF command is also available. Type HELP PRFD for more information. ARGUMENTS pathname (optional) Specify the file to be printed. Multiple pathnames and pathname wildcarding are permitted. Default if omitted: read standard input. OPTIONS The following options may appear on the Shell command line or in PRF interactive mode as noted below. In addition, you may place one or more options in a configuration file (see -CONFIG). In that case, create the file with one option per line without the prepended hyphens (-). See Example 3 below. If no options are specified, the file(s) are printed using ASCII carriage control, with pagination enabled, on the default printer (as established by PRSVR). ___ _________ _______ _____ __ ___ ____ _____ The following options apply to all file types. -INTER[ACTIVE] Enter interactive mode. -COP[IES] n Print multiple copies of the file, where 'n' is the requested number of copies. If -COP[IES] is specified, 'n' is required. If this option is omitted, one copy is printed by default. -PR[INTER] name Specify the printer 'name' for printing the file. This option is useful only if more than one printer is in use on the network, or if a printer has been assigned a nonstandard name with the "PRINTER_NAME" configuration directive in the PRSVR command. If you omit this option, PRF uses the default printer name, "P". Note that "P" is also the default printer name used by the PRINT_SERVER. -S[ITE] entry_dir Specify print queue (/SYS/PRINT) on alternate node by giving that node's entry directory name. This option allows you to maintain more than one printer queue directory. You may want to maintain separate queues for different organizations, or you may want two queues to provide redundancy in case of node failure. -USER[_NAME] name Specify user name that will appear on the banner page of the printed file. The alarm facility of PRF also uses this name to determine who should be notified when printing is complete (see -SIG below). This means that this name must be a valid login name (unless you don't care about sending an alarm). If this option is omitted, the current login name is used. -SIG[NAL] ALARM|OFF Request an alarm server signal when the file has finished printing. The default is OFF. -BAN[NER] [ON|OFF] Enable/disable banner page. The default is specified in the PRSVR configuration file. If neither ON nor OFF is specified, ON is assumed. -CONFIG[_FILE] [pathname] Specify a file containing further PRF options, one per line. Do not use prepended hyphens (-) with the option names in the configuration file. If 'pathname' is omitted, PRF will execute the configuration file ~USER_DATA/PRF.DB. -NDB Suppress processing of the configuration file. -TEXT Specify text mode for printing ASCII files. This is the default print mode. -PLOT Specify plot mode. Include this option to print bitmap files created by a graphics metafile (GMF) manager or GPR or the CPSCR (COPY_SCREEN) command. -TRANSPARENT Specify that when the file is printed, the records of the file are to be passed directly to the printer driver routine with no processing by the PRINT_SERVER. ___ _________ _______ _____ __ ____ _____ ____ The following options apply to text files only. -NPAG Disable the headers and margins generated by PRF. -MARGINS [ON|OFF] Enable/disable margins generated by PRF. The default is 'ON'. If neither ON nor OFF is specified, ON is assumed. -TOP n Specify page top margin, in inches. The default is a value specified in the PRSVR configuration file. -BOT[TOM] n Specify page bottom margin, in inches. The default is a value specified in the PRSVR configuration file. -RIGHT n Specify page right margin, in inches. The default is 0 inches. -LEFT n Specify page left margin, in inches. The default is 0 inches. -HEADERS [ON|OFF] Enable/disable page headers and footers generated by PRF. The default is specified in the PRSVR configuration file. If neither ON nor OFF is specified, ON is assumed. -HEAD[_STRING] l-string/c-string/r-string Specify contents of left, center, and right components of the page header generated by PRF. Components may be empty strings. The following special characters return the values indicated when they appear in the header strings. @ = escape character # = current page number with 1 leading and 1 trailing space % = current date ! = filename & = filename's last time,date modified * = insert a space in text string (literal spaces are not allowed) Example: -HEAD !/Page#/% will produce a header with the filename in the left component, the string "Page" followed by the current page number in the center component, and the current date in the right component. The default header is a string specified in the PRSVR configuration file. -FOOT[_STRING] l-string/c-string/r-string Specify contents of page footers. The format is the same as for -HEAD above. There is no default footer. -FTN [ON|OFF] Force use of FORTRAN carriage control. The -FTN option causes the PRINT_SERVER to use FORTRAN forms control even if the file does not have the FORTRAN carriage control flag. Use of this option will cause PRF to interpret the first character of each line as a FORTRAN carriage control character (and not print it). This can be unfortunate if the file has ASCII carriage control, so be careful. If neither ON nor OFF is specified, ON is assumed. The default state is OFF. -WRAP [ON|OFF] Enable/disable automatic line wrapping. When enabled, PRF will wrap any lines that exceed the right margin onto the next line. When disabled, PRF truncates lines that exceed the right margin. If neither ON nor OFF is specified, ON is assumed. ___ _________ _______ ___ ___ ___ ____ ________ __________ ________ ____ ___ The following options are for use with printers supporting variable font and _____ _____ pitch sizes. -PITCH n Set the pitch (characters/inch) at which you wish the document to be printed. The following pitch settings are available on the printers indicated. Printronix 10 Spinwriter 12 Imagen 8.5, 10, 12, 15, 17.1 GE 10, 12, 13.1, 16.7 Versatec 12 Imagewriter 5, 6, 7.5, 8.5, 9, 10, 12, 13.4, 15, 17 -POINT n Set the point size for the font to be used. This is a real number in units of a point which is 1/72 inch. -WEIGHT value Set the weight of the font to be used. This option is only valid for the GE printer type. Possible values are 'light', 'medium', and 'bold'. The default is 'medium'. If this option is used with the Imagewriter printer, the 'light' and 'medium' values result in a normal typeface and the 'bold' value causes the printer to print in its bold typeface. -LQ [ON|OFF] Specify that the document is to be printed in 'letter quality' (ON) as opposed to 'draft' (OFF) mode. This option is only valid for the GE printer type. If neither ON nor OFF is specified, ON is assumed. The default state is OFF. If this option is given with the Imagewriter printer, the printer will use its proportionally space pica font when 10 char/inch is specified and it will use its proportionally spaced elite font when 12 char/inch is specified. ___ _________ _______ _____ __ ____ _____ The following options apply to plot files. -RES[OLUTION] n Specify resolution of output plot in dots per inch. If you specify a resolution not available on the particular printer, the file is printed at the closest available resolution. The default resolution is specified in the PRSVR configuration file. -WHITE[_SPACE] n Specify amount of white space (in inches) to appear between multiple plots in one file. The default is three inches. -BW[_REV] [ON|OFF] Enable/disable black and white reversal for bitmaps. If neither ON nor OFF is specified, ON is assumed. The default state is OFF. -MAGN[IFICATION] n Specify bitmap magnification value. 'n' is an integer in the range -1 to 16. -1 selects auto-scaling to magnify the bitmap to fill the available page space. 0 selects 'one-to-one' scaling between the display and the printer for GMF bitmaps. (For GPR bitmaps, this translates to magnification 1.) 1-16 selects magnification by that amount. Portions of the magnified bitmap that exceed the printer page boundaries are clipped. The default is 0. For the Imagewriter printer, the default magnification (0) results in a one-to-one scaling between each pixel of the display and the printer for GMF bitmaps (same result as using a magnification value of 1). This will make the picture on the printer roughly the same size as the picture on the display. This command uses the command line parser, and so also accepts the standard command options listed in HELP CL. COMMANDS COMMANDS COMMANDS -INTER -INTER Once PRF has been invoked in interactive mode (see -INTER above), it accepts the following interactive commands at the "PRF> " prompt (in addition to the options already discussed). P[RINT] pathname P[RINT] pathname P[RINT] pathname Queue the specified file for printing. Q[UIT] Q[UIT] Q[UIT] Quit interactive mode and return to the Shell. SH[ELL] SH[ELL] SH[ELL] Create a shell command line. This command allows you to issue Shell commands without leaving PRF interactive mode. When you have finished entering Shell commands, type CTRL/Z. This will return you to PRF interactive mode. Your previous PRF option settings remain undisturbed by the intervening Shell commands. INIT[IALIZE] INIT[IALIZE] INIT[IALIZE] Reset PRF parameters to their default values. R[EAD] [printer] R[EAD] [printer] R[EAD] [printer] List entries in the queue for the specified printer at the current site (as specified by -S). If 'printer' is omitted, then the contents of the queue (determined by the current setting of -PR) are listed. WD [pathname] WD [pathname] WD [pathname] Execute the Shell command WD (WORKING_DIRECTORY) to set or display the working directory. GET option GET option GET option Display the value of the PRF option specified. Use this command to show the settings of the various PRF parameters. CAN[CEL] [queued_filename] CAN[CEL] [queued_filename] CAN[CEL] [queued_filename] Cancel printing of the specified file at the current site (as specified by -S). Note that you must specify the pathname which PRF assigns when the file is queued (which may differ from the name of your original file). Use the READ command to display the names of currently queued files. If the filename is omitted, the last file to be queued by this process is cancelled. This command is only effective for files which have not yet physically begun to print. EXAMPLES 1. $ prf mary -npag -ftn Queue "mary"; suppress "//NODE1/MY_DIR/MARY" queued for printing. pagination; force $ FORTRAN carriage 2. $ prf filex -s //tape "//NODE1/MY_DIR/TEST_FILE.PAS" queued for printing at site //TAPE. $ Queue "filex" to the printer queue on the node called //tape. 3. Configuration File: the following commands might appear in the default PRF configuration file ~USER_DATA/PRF.DB. PR ge SITE //rye FOOT %/my_file/& 4. Sample interactive session: $ PRF -INTER PRF> get pr pr = p PRF> -pr cx PRF> get pr pr = cx PRF> -pitch 20 PRF> print test_file.pas "//NODE1/MY_DIR/TEST_FILE.PAS" queued for printing. PRF> q $ 5. Running PRF from an icon: If you would like to run PRF interactively in a process devoted to it, you might place the following command in your ~USER_DATA/STARTUP_DM file: cp -i -c 'P' /com/prf -inter -n print_file This will create a PRF process and turn its window into an icon using the print icon character in (/SYS/DM/FONTS/ICONS). Issue the DM command ICON to change the icon window into its full-size format. RELATED TOPICS More information is available. Type: - HELP PRFD for information on the menu-based version of this command. - HELP PRINTER for general information about printers supported in a DOMAIN network. - HELP PRSVR for details about the Print Server. End of prf.imagewriter.hlp echo user1.imagewriter.bld 1>&2 cat >user1.imagewriter.bld <<'End of user1.imagewriter.bld' ######################################################################################### ### ### ### Command file for Compiling and Binding the Apple Imagewriter Print Server ### ### ### ######################################################################################### von pas user1.imagewriter.pas -cpu any -optall -opt bind -b prsvr.user1.imagewriter /com/prsvr user1.imagewriter.bin voff End of user1.imagewriter.bld echo user1.imagewriter.doc 1>&2 cat >user1.imagewriter.doc <<'End of user1.imagewriter.doc' ******************************************************************************* ***** ***** ***** USER1.IMAGEWRITER.DOC ***** ***** Version 8 ***** ***** ***** ***** Programming Notes for the Apple Imagewriter Print Server ***** ***** ***** ***** Copyright (c) 1986 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmosheric, and Planetary Sciences ***** ******************************************************************************* The Apple Imagewriter printer ----------------------------- The Apple Imagewriter printer is a low cost dot-matrix printer sold by Apple for use with their Apple II and Macintosh personal computers. We are currently sharing one of these printers between an Apple II c and an Apollo DN320. The printer has the capability to print full bitmap graphics printing at a density of 72 by 72 dots per inch - a little less than the resolution of the Apollo's display. The Imagewriter prints 8 lines of up to 576 columns on each pass of the print-head across the paper, and it will print text with the print-head moving in either direction - which speeds the printing process. Interfacing the Printer with the Apollo --------------------------------------- We have interfaced our Imagewriter printer to an Apollo DN320 using a 3-wire RS232-C null modem cable. The wiring of the cable is: pin 2 - pin 3, pin 3 - pin 2, and pin 7 - pin 7 (ie. cross the data receive and data transmit wires, and connect the signal ground wire). We are using the X-ON/X-OFF protocal to control the flow of data between the Apollo and the printer rather than using the DTR and CTS signals in the RS232-C cable. The SIO line characteristics necessary to run the printer using X-ON/X-OFF are set up in the routine USER1_INIT. It is also necessary to change some of the internal jumpers in the Apple printer in order to use the 3-wire cable. The jumpers that we change are located on a dip switch underneath the printer's front cover on the right hand side of the printer. See the Apple Imagewriter manual for a diagram of the location of the dip switch. The switches should be set to the X-ON/X-OFF position (see the manual for the correct position of the switches). Apple normally ship's the printer with the switches in the position for using DTR/CTS to control the flow of data between the printer and the computer. If you wish to share the printer between and Apple computer and the Apollo you will have to use the DTR/CTS flow control. To do this you will also have to connect the DTR and CTS lines in the printer cable, and you will have to edit the USER1_INIT routine to set up the SIO line to use the CTS_ENABLE option and not use the HOST_SYNCH and INPUT_SYNC option. Description of the Print Server Routines ---------------------------------------- The Imagewriter print server program consists of six main subroutines (procedures) which are compiled and then bound to the standard print server program (/COM/PRSVR) supplied by Apollo. The subroutines are: USER1_INIT, USER1_WRITE, USER1_FLUSH, USER1_CLOSE, USER1_SET_MODE, and USER1_RETURN_INFO. Section 6.5 of The DOMAIN System Administrator's Guide gives a general description of the standard print server supplied by Apollo and the steps needed to generate a print server for a printer other than those supported by Apollo. The arguments to the user-supplied subroutines and the format of the data passed to the subroutines are defined in the Apollo supplied insert files /SYS/INS/PRSVR.INS.PAS or /SYS/INS/PRSVR.INS.C which, while defining the options and data types doesn't really tell you what these various options are supposed to do. To get that information, you either have to call Apollo or you just have to play with the print server for awhile and see how it responds to your poking and prying. Unfortunately for those of you who program in Fortran, there is no insert file for that language - you just have to learn Pascal. The USER1_INIT subroutine is called once by the print server when it starts up. The subroutine is given the line number of the SIO line to which the printer is connected and the baud rate of that SIO line. Both of these numbers are read from the printer configuration file (IMAGEWRITER.CONFIG) by the print server at startup time. The USER1_INIT subroutine opens the specified SIO line for stream output and then sets the necessary SIO line characteristics. These include the use of X-ON/X-OFF by both the Apollo node and the printer (input_sync and host_sync), turning off the echoing of characters which the printer may send to the host (something which is never really done except for X-ON and X-OFF), disabling the quit character on the SIO line (so if the printer accidentally glitches it can't kill the print server process), and the parity, number of bits per character, and number of stop bits of the characters being transmitted. After defining the SIO line for the printer, USER1_INIT also initializes several strings of control characters for the printer, resets various page, line, and graphics buffer counters. Finally, USER1_INIT sends the printer-init command to the Imagewriter to make sure the printer is correctly initialized. Note that the printer-init command also sets the top-of-page to the current position of the paper, so the paper should be correctly position in the printer before starting the print server. The USER1_WRITE subroutine does most of the work of the print server. This subroutine is called from the print server to perform the actual output of the data to the Imagewriter printer. The subroutine is given a buffer of up to 2048 characters and a buffer length. In practice, I have never seen the buffer length exceed 256 bytes. The USER1_WRITE subroutine checks the current printer output mode and then outputs the contents of the buffer according to the mode. The mode is set by the print server calling the USER1_SET_MODE subroutine prior to the first call to USER1_WRITE for the current output file. There are three possible output modes: 'text', 'transparent', and 'plot'. If the current output mode is 'text' (ie. a PRF command with no switches), the print server keeps track of the current page and line counts and prints a page header and and page number at the top of each page. The print server calls USER1_WRITE one time for each line printed and simply inserts an extra call to USER1_WRITE at the top of each page to print the page header and page number. All that USER1_WRITE has to do in text mode is to dump the buffer to the printer, but we also check each buffer for form-feed characters and keep a page count and a line count so that we could do our own (possibly fancier) page headings if we wanted to do so. If the current output mode is 'transparent' (ie. a PRF -TRANSPARENT command), the print server sends the contents of the output file to the printer with no modifications. USER1_WRITE is called once for each line in the file (same as with 'text' mode), but no page headers are inserted into the output stream. In this output mode USER1_WRITE does nothing except to dump the buffer to the Imagewriter's output stream. If the current output mode is 'plot' (ie. a PRF -PLOT command), the print server checks that the output file is a GMF bitmap file, calls USER1_SET_MODE to set the size of the bitmap, and then calls USER1_WRITE once for each horizontal scan line in the bitmap. The print server will not attempt to print bitmap files unless the PLOT_MODE switch in the printer's configuration file (ie. IMAGEWRITER.CONFIG -- which is specified on the command line which started the print server) is set to ON. The print server will try to automatically scale the bitmap so that it is roughly the same size on the printed page as it is on the display screen of the Apollo. (I am assuming that the bitmap was created from a dump from the screen. Actually, the print server checks the bits-per-inch at which the bitmap was created and compares that against the bit-per-inch of the printer and then tries to scale the bitmap to the closest integer factor. The bits-per-inch of the printer is defined in the USER1_RETURN_INFO subroutine. I believe that you can define the bit-per-inch at which the bitmap is created through one of the GPR or GMR calls. I know that you can create bitmaps without displaying them on the screen.) Since the Imagewriter printer's resolution (72 bpi) is roughly the same as the Apollo's display screen, the print server will not do any scaling of the bitmap. The -MAGNIFICATION option of the PRF command can be used to control the scaling of the bitmap by the print server. The default value (0) will cause the print server to try to scale the bitmap to the same size that it was on the screen (this results in a two to one scaling on the printer). In this case, the print server will simply tell the USER1_SET_MODE routine that the bitmap is twice the size of the bitmap on the screen and it will scale the bitmap before passing the data to the USER1_WRITE routine for printing. Since the Imagewriter prints 8 horizontal scan line on each pass, the USER1_WRITE subroutine buffers up 8 complete scan lines, padding short lines with zeros, before dumping the buffer to the printer. Lines which are longer than the maximum printable by the Imagewriter (576 dots across the page) are truncated to the maximum length which can be printed. If the user has requested the bitmap to be inverted (ie. black and white reversed), then each byte of the scan line is inverted as it is buffered. The bits in each of the horizontal scan lines sent to USER1_WRITE by the print server are packed 8 to each byte, the high order bit of the byte being the leftmost bit on the scan line. Since the Imagewriter printer (along with most other dot matrix printers) wants to print one complete vertical column of bits at a time, it is necessary to repack the bits in the scan lines which have been buffered before they can be sent to the printer. USER1_WRITE calls the WRITE_PLOT_BUFFER routine to repack the bits and output the repacked buffer to the printer. The WRITE_PLOT_BUFFER subroutine also attempts to speed up the output process by stripping zero bytes off of the end of the buffer to avoid the expense of having to repack and transmit these bytes. The USER1_SET_MODE subroutine is called by the printer server prior to the output of each file being printed to set the proper printer output mode and to such things as the bitmap size (for plot mode files). The print server may also call USER1_SET_MODE after the end of an output file to reset the printer mode or to change the printer mode to 'text' so it can output a top-of-page command (ie. a form feed) after finishing the printing of a bitmap. Note that we can not use the Imagewriter's printer-init command to reset the printer's mode to the default text mode. This is because the printer-init command resets the printer's top-of-page to the current paper position, and the print server may call USER1_SET_MODE at any point on the page. The USER1_FLUSH subroutine is called once at the end of each file output by the print server and also in between changing printer output modes. This routine checks if the printer is 'plot' and also checks if there is a partially full buffer of bitmap data. If this is the case, USER1_FLUSH will call USER1_WRITE with a dummy output buffer to force the output of the final buffer of bitmap data. USER1_FLUSH then resets all of the page, line, and buffer counters used during the output of the file. The USER1_CLOSE subroutine is only called when the print server is stopping permanently (as opposed to waiting between files). All that it does is to close the printer's output stream. Changes Since Version 6 ----------------------- Version 6 of the Imagewriter USER1 routines is compatible with the AEGIS SR9.0 version of PRSVR. It should also be backwards compatible with the SR8.0 version of the print server. The buffer repacking algorithm for printing GMF bitmap files has been improved. The new algorithm is faster and it also correctly handles bitmaps which are wider than the page (the bitmap is truncated to the width of the page). The printing of GMF bitmap files is now done with unidirectional printing (left to right on all lines) in order to get vertical line segments to line up better. If the -LQ option of the PRF command (letter quality printing) is used the printer will now switch to printing with the proportionally spaced pica font (if the character pitch is 10 char/in) or the proportionally spaced elite font (if the character pitch is 12 char/in). If the -WEIGHT option of the PRF command is used with the 'bold' value, the file will be printed with the printer's boldface option in order to make the output darker. If the 'light' or 'medium' values are used with the -WEIGHT option then the file is printed with the normal typeface. The default value of the weight option is 'medium'. The -PITCH option of the PRF command can now be used to select printing in 5.0, 6.0, 7.5, 8.5, 9, 10, 12, 13.4, 15, or 17 characters per inch. The default character pitch is 10 characters per inch. The -MAGNIFICATION option of the PRF command can now be used to control the scaling of bitmaps printed on the Imagewriter. The default magnification value (0) causes the print server to try to make the bitmap the same size on the printer as it was on the screen of the Apollo. Since the Imagewriter's 72 dot per inch resolution is approximately the same as the Apollo's screen the print server will print the bitmap with a 1 to 1 scaling. Giving the PRF command a magnification value of 1 will cause the bitmap to be printed without any scaling on the printer, a value of 2 will cause the bitmap to be doubled in size, a value of 3 will cause the bitmap to be tripled in size, etc. The USER1_INIT routine now reports any errors which it encounters while attempting to set up the SIO line for the printer. Seperate error messages are generated for each SIO line parameter to aid in locating any problems with the SIO line. Changes Since Version 7 ----------------------- The -BW_REV option of the PRF command can now be used to invert a GMF bitmap before it is printed. Areas of the bitmap which are normally white will be printed as black and vice versa. The problem which caused 'glitches' in the printing of certain bitmap files has been fixed. On previous versions of the software, certain bitmap files would have lines which would be shifted over by a couple of dots in the middle of the line. This was caused by the SIO system inserting a extra character in the output after a line feed character was sent to the printer. This has been fixed by using the new SR9.0 SIO_$NO_NL option when setting up the SIO line characteristics. Files Needed to Build the Print Server -------------------------------------- The files which are provided for the Apple Imagewriter print server are: USER1.IMAGEWRITER.DOC - This file. USER1.IMAGEWRITER.DOC.INSTALL - Notes on how to install the print server. PRF.IMAGEWRITER.HLP - An edited version of the standard Apollo help file for the PRF command (/SYS/HELP/PRF.HLP) with notes included for the Imagewriter printer. USER1.IMAGEWRITER.PAS - The Pascal sources for the print server. USER1.INS.PAS - An edited version of the standard Apollo insert file, /SYS/INS/PRSVR.INS.PAS, which is used by USER1.IMAGEWRITER.PAS to define the data types and structures used by the print server. USER1.IMAGEWRITER.BLD - A shell script file for compiling the USER1 routines (and their subroutines) and binding them with the Apollo supplied print server. IMAGEWRITER.CONFIG - The configuration file for the Imagewriter printer to be given as an argument to the print server when it is started. PRSVR.USER1.IMAGEWRITER - A ready to run Imagewriter print server. Just in case you don't have a Pascal compiler. This is the file which is produced by USER1.BLD. You will also need the following standard Apollo-supplied files: /SYS/INS/BASE.INS.PAS - These are all standard insert files which /SYS/INS/SIO.INS.PAS are used by USER1.IMAGEWRITER.PAS. /SYS/INS/STREAMS.INS.PAS /SYS/INS/PGM.INS.PAS /COM/PRSVR - The standard Apollo print server which must be bound with the Imagewriter routines to produce a working print server. Used in USER1.BLD to produce PRSVR.USER1.IMAGEWRITER. Bugs, Questions, and Improvements --------------------------------- If you find a bugs in the print server, have questions on how to install or use it, or have a good idea for improving the program please feel free to contact me at the address below. David M. Krowitz MIT dept. of Earth, Atmospheric, and Planetary Sciences Room 54-527 Cambridge, MA 02139 (617) 253-6180 ARPA net mailing adress: DAVID@MIT-MC.ARPA or KROWITZ%MIT-MARIE@MIT-MC.ARPA End of user1.imagewriter.doc echo user1.imagewriter.doc.install 1>&2 cat >user1.imagewriter.doc.install <<'End of user1.imagewriter.doc.install' ******************************************************************************* ***** ***** ***** USER1.IMAGEWRITER.DOC.INSTALL ***** ***** Version 7 ***** ***** Installing the Apple Imagewriter Print Server ***** ***** ***** ***** Copyright (c) 1986 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmosheric, and Planetary Sciences ***** ******************************************************************************* Read the general installation and documentation notes in USER1.IMAGEWRITER.DOC if you have not already done so. Then use the shell script file USER1.IMAGEWRITER.BLD to compile the Apple Imagewriter device-driver routines and to bind them to the standard Apollo printer server located in /COM/PRSVR. This will create the Apple Imagewriter version of the print server (PRSVR.USER1.IMAGEWRITER) in your working directory. Then edit the print server configuration file (IMAGEWRITER.CONFIG) and make sure it contains the proper SIO line number and baud rate for your installation. Next copy the new print server (PRSVR.USER1.IMAGEWRITER) and the print server configuration file (IMAGEWRITER.CONFIG) to the system directory from which you normally run the print server on your system. /COM or /SYS/NODE_DATA are two common directories which we use. You can then run the print server using the command: /COM/PRSVR.USER1.IMAGEWRITER /COM/IMAGEWRITER.CONFIG (assuming the files are stored in /COM). This will run the server in the current window. The server will be stopped when you log out. If you want to run the print server automatically when the system is brought up, add the following command line to your installation's startup file in /SYS/NODE_DATA: ### ### To startup user-defined print server for the Apple Imagewriter printer ### CPS /COM/PRSVR.USER1.IMAGEWRITER -N PRINT_SERVER /COM/IMAGEWRITER.CONFIG (again, assuming the files are kept in /COM). This will run the print server automatically when the node is brought up and will give it the process a server status so that you can logout and leave the print server running for other users on the network. Apollo's standard print server (and the Imagewriter version) looks for files to be printed in the /SYS/PRINT directory of the node on which the print server is running. If you want files from other nodes on the network to be automatically printed on the Toshiba you should delete the /SYS/PRINT directories on those nodes and replace them with links to the /SYS/PRINT directory on the node running the print server. Otherwise, users can use the command: PRF -S //NODE_NAME to have the PRF command send the file to the node which has the printer attached to it. More information on the installation and use of print servers can be found in The Domain System Administrator's Guide, section 6.5 (Peripheral Servers). End of user1.imagewriter.doc.install echo user1.imagewriter.pas 1>&2 cat >user1.imagewriter.pas <<'End of user1.imagewriter.pas' {********************************************************************************* ***** ***** ***** USER1.IMAGEWRITER.PAS ***** ***** ***** ***** Serial Printer Driver for the Apple Imagewriter dot-matrix printer ***** ***** Version 8 ***** ***** David M. Krowitz February 10, 1986. ***** ***** ***** ***** Copyright (c) 1986 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmosheric, and Planetary Sciences ***** ********************************************************************************* } MODULE USER1_IMAGEWRITER; %NOLIST; %INSERT '/sys/ins/base.ins.pas'; %INSERT '/sys/ins/sio.ins.pas'; %INSERT '/sys/ins/streams.ins.pas'; %INSERT '/sys/ins/pgm.ins.pas'; %INSERT 'user1.ins.pas'; %LIST; CONST {Definitions of standard ascii control characters} nul = chr(0); {null character} bs = chr(8); {backspace (control-H)} tab = chr(9); {tab (control-I)} lf = chr(10); {line feed (control-J)} vt = chr(11); {vertical tab (control-K)} ff = chr(12); {form feed (control-L)} cr = chr(13); {carriage return (control-M)} ctrl_n = chr(14); {control-N} ctrl_o = chr(15); {control-O} sub = chr(26); {sub (control-Z)} esc = chr(27); {escape} rs = chr(30); {rs} {Define maximum bitmap size which can be printed} max_bitmap_size = 576; {maximum number of pixels across the page} max_buffer_size = 72; {maximum buffer size to hold bitmap (576/8)} TYPE str1_t = packed array[1..1] of char; str2_t = packed array[1..2] of char; str3_t = packed array[1..3] of char; str4_t = packed array[1..4] of char; str5_t = packed array[1..5] of char; str6_t = packed array[1..6] of char; str7_t = packed array[1..7] of char; str8_t = packed array[1..8] of char; str9_t = packed array[1..9] of char; bitmap_buffer_t = packed array[1..8,1..max_buffer_size] of char; print_buffer_t = packed array[1..max_bitmap_size] of char; VAR {Definitions of control sequences for the Apple Imagewriter printer} init_printer: str2_t; {initialize printer characteristics} image_data: str6_t; {start 8 pin by nnnn column bit map image transfer} text_vert_spacing: str2_t; {set vertical spacing to 1/6" for default text size} plot_vert_spacing: str4_t; {set vertical spacing to 16/144" for bitmap graphics} text_horiz_spacing: str2_t; {set horizontal spacing to 1/10" for default text size} plot_horiz_spacing: str2_t; {set horizontal spacing to 1/9" for 72 bpi bitmap graphics} uni_directional: str2_t; {set uni-directional printing mode for bitmap graphics} bi_directional: str2_t; {set bi-directional printing mode for text} start_boldface: str2_t; {start printing in boldface} stop_boldface: str2_t; {stop printing in boldface} start_double: str1_t; {start printing double width characters} stop_double: str1_t; {stop printing double width characters} font_extended: str2_t; {Use extended font (9 chars/in)} font_pica: str2_t; {Use pica font (10 chars/in)} font_elite: str2_t; {Use elite font (12 chars/in)} font_pica_p: str2_t; {Use pica proportional font (??? chars/in)} font_elite_p: str2_t; {Use elite proportional font (??? chars/in)} font_semicond: str2_t; {Use semi-condensed font (13.4 chars/in)} font_cond: str2_t; {Use condensed font (15 chars/in)} font_ultracond: str2_t; {Use ultra-condensed font (17 chars/in)} crlf: str2_t; {carriage-return, line-feed sequence} {Defintions of global variables} x_bitmap_size: pinteger; {x dimension of GMR bit map being printed} y_bitmap_size: pinteger; {y dimension of GMR bit map being printed} scale_factor: pinteger; {factor by which bitmap has been scaled up by top-level routines} bitmap_buffer: bitmap_buffer_t; {buffer of 8 lines of 576 bits to hold data for one pass of the Apple printer's print-head} bcount: pinteger; {count of number of buffers of GMR data} invert_image: boolean; {TRUE if user requested black/white reversed for bitmap} plot_flag: boolean; {TRUE if we have been printing a bitmap} trans_flag: boolean; {TRUE if we have been printing in transparent mode} printer_mode: pr_$data_format_t; {printer mode: text, transparent, or plot} server_ptr: server_db_ptr_t; {pointer to database set up by server} driver_ptr: driver_db_ptr_t; {pointer to database of Toshiba's abilities} stream_id: stream_$id_t; {stream id returned by STREAM_$OPEN} status: status_$t; {status returned by SIO and STREAM calls} seek_key: stream_$SK_t; {seek_key returned by STREAM calls} testmask: array[1..8] of integer; {Constants for testing bits in a byte} setmask: array[1..8] of integer; {Constants for setting bits in a byte} PROCEDURE USER1_INIT ( IN sio_line: integer; IN sio_speed: UNIV sio_$value_t ); VAR sioname: array[1..3] of str9_t; {names of SIO lines for STREAM_$OPEN call} i,j: pinteger; {counters} BEGIN {Open I/O stream and set SIO line characteristics} sioname[1] := '/dev/sio1'; sioname[2] := '/dev/sio2'; sioname[3] := '/dev/sio3'; stream_$open (sioname[sio_line],9,stream_$append,stream_$no_conc_write, stream_id,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not open output stream: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$speed,sio_speed,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$SPEED: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$no_nl,true,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$NO_NL on: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$nlc_delay,0,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$NLC_DELAY to 0: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$input_sync,true,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$INPUT_SYNC on: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$host_sync,true,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$HOST_SYNC on: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$no_echo,true,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$NO_ECHO on: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$cts_enable,false,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$CTS_ENABLE off: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$quit_enable,false,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$QUIT_ENABLE off: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$parity,sio_$no_parity,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$PARITY to none: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$bits_per_char,sio_$8bpc,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$BPC to 8 bits/char: ', sioname[sio_line],' ****'); PGM_$EXIT; END; sio_$control (stream_id,sio_$stop_bits,sio_$stop_1,status); IF (status.fail = TRUE) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$STOP to 1 stop bit: ', sioname[sio_line],' ****'); PGM_$EXIT; END; {Initialize strings of control characters for printer} init_printer[1] := esc; init_printer[2] := 'c'; image_data[1] := esc; image_data[2] := 'S'; image_data[3] := '0'; image_data[4] := '0'; image_data[5] := '0'; image_data[6] := '0'; plot_vert_spacing[1] := esc; plot_vert_spacing[2] := 'T'; plot_vert_spacing[3] := '1'; plot_vert_spacing[4] := '6'; text_vert_spacing[1] := esc; text_vert_spacing[2] := 'A'; plot_horiz_spacing[1] := esc; plot_horiz_spacing[2] := 'n'; text_horiz_spacing[1] := esc; text_horiz_spacing[2] := 'N'; uni_directional[1] := esc; uni_directional[2] := '>'; bi_directional[1] := esc; bi_directional[2] := '<'; start_boldface[1] := esc; start_boldface[2] := '!'; stop_boldface[1] := esc; stop_boldface[2] := '"'; start_double[1] := ctrl_n; stop_double[1] := ctrl_o; font_extended[1] := esc; font_extended[2] := 'n'; font_pica[1] := esc; font_pica[2] := 'N'; font_elite[1] := esc; font_elite[2] := 'E'; font_pica_p[1] := esc; font_pica_p[2] := 'p'; font_elite_p[1] := esc; font_elite_p[2] := 'P'; font_semicond[1] := esc; font_semicond[2] := 'e'; font_cond[1] := esc; font_cond[2] := 'q'; font_ultracond[1] := esc; font_ultracond[2] := 'Q'; crlf[1] := cr; crlf[2] := lf; {Initialize the graphics output variables} bcount := 0; {No scan lines of graphics output waiting to be printed} scale_factor := 1; {Doesn't seem to be used in SR9.0 so must init ourselves for SR8 compatibility} invert_image := FALSE; {Do normal bitmap printing (not b/w reversed)} plot_flag := FALSE; {Not printing a bitmap right now} trans_flag := FALSE; {Not printing in transparent mode, either} {Initialize bit testing and bit setting masks} testmask[1] := 16#80; testmask[2] := 16#40; testmask[3] := 16#20; testmask[4] := 16#10; testmask[5] := 16#08; testmask[6] := 16#04; testmask[7] := 16#02; testmask[8] := 16#01; setmask[1] := 16#01; setmask[2] := 16#02; setmask[3] := 16#04; setmask[4] := 16#08; setmask[5] := 16#10; setmask[6] := 16#20; setmask[7] := 16#40; setmask[8] := 16#80; {Initialize the printer settings} stream_$put_chr (stream_id,addr(init_printer),2,seek_key,status); printer_mode := pr_$text; END; {End of USER1_INIT} PROCEDURE USER1_WRITE ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); PROCEDURE USER1_WRITE_TEXT ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); BEGIN stream_$put_chr (stream_id,addr(buffer),buffer_length, seek_key,status); END; {End of USER1_WRITE_TEXT} PROCEDURE USER1_WRITE_TRANSPARENT ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); BEGIN stream_$put_chr (stream_id,addr(buffer),buffer_length, seek_key,status); END; {End of USER1_WRITE_TRANSPARENT} PROCEDURE WRITE_PLOT_BUFFER ( IN buffer: bitmap_buffer_t; IN bitmap_length: pinteger ); VAR print_buffer: print_buffer_t; {Toshiba output buffer} print_buffer2: print_buffer_t; {Toshiba output buffer} buffer_length: pinteger; {length of non-zero data in input buffer} data_length: pinteger; {length of non-zero data in print_buffer} i,j,k: pinteger; {index counters} ii,jj,iii,jjj: pinteger; {buffer subscript variables} bit_value: pinteger; {value of bit being swapped} temp1: pinteger; {holds bits being repacked} temp2: pinteger; {tests bytes to see if repacking needed} BEGIN {Find end of the non-zero data in the input buffer. Don't want to waste time by having to repack a lot of zero bytes at the end of a line.} buffer_length := (((bitmap_length-1) div 8) +1); k := 0; REPEAT FOR j := 1 TO 8 DO BEGIN IF buffer[j,buffer_length] <> chr(0) THEN k := 1; END; IF k = 0 THEN buffer_length := buffer_length-1; UNTIL (k <> 0) OR (buffer_length = 0); {If the print buffer is all zeroes, then just output a carriage-return line-feed sequence. Otherwise, repack and print the non-zero portion of the printer buffer.} IF buffer_length = 0 THEN BEGIN stream_$put_chr (stream_id,addr(crlf),2, seek_key,status); END ELSE BEGIN {Repack the bitmap from 8 horizontal rows of BUFFER_LENGTH*8 bits (8 bits per byte) into BUFFER_LENGTH*8 columns of 1 byte each (8 bits per byte).} FOR i := 1 TO buffer_length DO BEGIN ii := (i-1)*8; {Check if 6 byte high by 8 bit wide section of bitmap is all zeros. If so, then we don't need to repack the bits in this section, we just set the output buffer to the correct constants. If the area is all ones, we also do not have to repack the bitmap, we just set the output buffer to a different constant.} temp2 := 0; FOR k := 1 TO 8 DO BEGIN temp2 := temp2+ord(buffer[k,i]); END; IF (temp2 = 0) THEN BEGIN FOR iii := 1 TO 8 DO BEGIN {Section is all zeros - don't need to repack} print_buffer[ii+iii] := chr(0); END; END ELSE IF (temp2 <> 8*16#FF) THEN BEGIN FOR iii := 1 TO 8 DO BEGIN temp1 := 0; {Init the byte} FOR k := 1 TO 8 DO BEGIN {Repack eight bits into byte} bit_value := (ord(buffer[k,i])&testmask[iii]); IF bit_value <> 0 THEN BEGIN temp1 := temp1!setmask[k]; END; END; print_buffer[ii+iii] := chr(temp1); {Put byte in output buffer} END; END ELSE BEGIN FOR iii := 1 TO 8 DO BEGIN {Section is all ones - don't need to repack} print_buffer[ii+iii] := chr(16#FF); END; END; END; {Find end of the non-zero data in the printer buffer. Don't want to waste time by having to transmit a lot of zeroes at the end of a line.} IF buffer_length*8 < bitmap_length THEN BEGIN data_length := buffer_length*8; END ELSE BEGIN data_length := bitmap_length; END; k := 0; REPEAT IF print_buffer[data_length] <> chr(0) THEN k := 1; IF k = 0 THEN data_length := data_length-1; UNTIL (k <> 0) OR (data_length = 0); {Set up the bitmap image data transfer header and print the buffer.} image_data[3] := chr(ord('0')+((data_length mod 10000) div 1000)); image_data[4] := chr(ord('0')+((data_length mod 1000) div 100)); image_data[5] := chr(ord('0')+((data_length mod 100) div 10)); image_data[6] := chr(ord('0')+((data_length mod 10) div 1)); stream_$put_chr (stream_id,addr(image_data),6, seek_key,status); stream_$put_chr (stream_id,addr(print_buffer),data_length, seek_key,status); stream_$put_chr (stream_id,addr(crlf),2,seek_key,status); END; END; {End of WRITE_PLOT_BUFFER} PROCEDURE USER1_WRITE_PLOT ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); VAR i: integer; {counter} j: integer; {size of bitmap buffer in bytes} k: integer; {size of bitmap in pixels across the page} BEGIN {Check that BUFFER_LENGTH does not exceed the maximum buffer size and that X_BITMAP_SIZE*SCALE_FACTOR does not exceed the maximum printable bitmap size.} IF buffer_length <= max_buffer_size THEN j := buffer_length ELSE j := max_buffer_size; IF x_bitmap_size*scale_factor <= max_bitmap_size THEN k := x_bitmap_size*scale_factor ELSE k := max_bitmap_size; {Buffer up 8 lines by X_BITMAP_SIZE*SCALE_FACTOR columns of the bitmap and then dump them out to the printer. Pad short lines with zeros. Invert the buffer if the user requested black/white reversal for printing bitmap.} bcount := bcount+1; i:= 0; IF (invert_image = FALSE) THEN BEGIN WHILE i < j DO BEGIN i := i+1; bitmap_buffer[bcount,i] := buffer[i]; END; WHILE i < (((k-1) div 8)+1) DO BEGIN i := i+1; bitmap_buffer[bcount,i] := chr(0); END; END ELSE BEGIN WHILE i < j DO BEGIN i := i+1; bitmap_buffer[bcount,i] := chr(~ord(buffer[i])); END; WHILE i < (((k-1) div 8)+1) DO BEGIN i := i+1; bitmap_buffer[bcount,i] := chr(16#FF); END; END; IF bcount = 8 THEN BEGIN write_plot_buffer (bitmap_buffer,k); bcount := 0; END; END; {End of USER1_WRITE_PLOT} BEGIN {Beginning of actual USER1_WRITE code} {Determine printer mode and dispatch for output of buffer} CASE printer_mode OF pr_$text: user1_write_text (buffer,buffer_length); pr_$transparent: user1_write_transparent (buffer,buffer_length); pr_$plot: user1_write_plot (buffer,buffer_length); END; END; {End of USER1_WRITE} PROCEDURE USER1_SET_MODE ( IN mode: pr_$set_op_t; IN data: pr_$data_rec_t ); BEGIN CASE mode OF pr_$font_weight: IF (data.font_weight = pr_$bold) THEN stream_$put_chr (stream_id,addr(start_boldface),2,seek_key,status) ELSE stream_$put_chr (stream_id,addr(stop_boldface),2,seek_key,status); pr_$font_size: ; pr_$text_precision: ; pr_$data_format: BEGIN printer_mode := data.data_format; CASE printer_mode OF pr_$text: BEGIN stream_$put_chr (stream_id,addr(stop_double),1,seek_key,status); stream_$put_chr (stream_id,addr(text_vert_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(text_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(bi_directional),2,seek_key,status); END; pr_$transparent: BEGIN stream_$put_chr (stream_id,addr(stop_double),1,seek_key,status); stream_$put_chr (stream_id,addr(text_vert_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(text_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(bi_directional),2,seek_key,status); trans_flag := TRUE; END; pr_$plot: BEGIN stream_$put_chr (stream_id,addr(stop_double),1,seek_key,status); stream_$put_chr (stream_id,addr(plot_vert_spacing),4,seek_key,status); stream_$put_chr (stream_id,addr(plot_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(uni_directional),2,seek_key,status); plot_flag := TRUE; END; END; END; pr_$pitch: CASE ROUND(data.pitch*10.0) OF 50: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_pica),2,seek_key,status); END; 60: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_elite),2,seek_key,status); END; 75: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_cond),2,seek_key,status); END; 85: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_ultracond),2,seek_key,status); END; 90: stream_$put_chr (stream_id,addr(font_extended),2,seek_key,status); 100: stream_$put_chr (stream_id,addr(font_pica),2,seek_key,status); 120: stream_$put_chr (stream_id,addr(font_elite),2,seek_key,status); 134: stream_$put_chr (stream_id,addr(font_semicond),2,seek_key,status); 150: stream_$put_chr (stream_id,addr(font_cond),2,seek_key,status); 170: stream_$put_chr (stream_id,addr(font_ultracond),2,seek_key,status); END; pr_$x_dimension: x_bitmap_size := data.x_dimension; pr_$y_dimension: y_bitmap_size := data.y_dimension; pr_$rep_factor: scale_factor := data.rep_factor; pr_$config: ; pr_$copies: ; pr_$server_db: BEGIN server_ptr := data.server_db_ptr; printer_mode := server_ptr^.print_mode; IF (server_ptr^.weight = pr_$bold) THEN stream_$put_chr (stream_id,addr(start_boldface),2,seek_key,status) ELSE stream_$put_chr (stream_id,addr(stop_boldface),2,seek_key,status); IF server_ptr^.bw_rev = TRUE THEN invert_image := TRUE ELSE invert_image := FALSE; CASE printer_mode OF pr_$text: BEGIN stream_$put_chr (stream_id,addr(text_vert_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(text_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(bi_directional),2,seek_key,status); CASE ROUND(server_ptr^.cpi*10.0) OF 50: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_pica),2,seek_key,status); END; 60: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_elite),2,seek_key,status); END; 75: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_cond),2,seek_key,status); END; 85: BEGIN stream_$put_chr (stream_id,addr(start_double),1,seek_key,status); stream_$put_chr (stream_id,addr(font_ultracond),2,seek_key,status); END; 90: stream_$put_chr (stream_id,addr(font_extended),2,seek_key,status); 100: IF (server_ptr^.lq = FALSE) THEN stream_$put_chr (stream_id,addr(font_pica),2,seek_key,status) ELSE stream_$put_chr (stream_id,addr(font_pica_p),2,seek_key,status); 120: IF (server_ptr^.lq = FALSE) THEN stream_$put_chr (stream_id,addr(font_elite),2,seek_key,status) ELSE stream_$put_chr (stream_id,addr(font_elite_p),2,seek_key,status); 134: stream_$put_chr (stream_id,addr(font_semicond),2,seek_key,status); 150: stream_$put_chr (stream_id,addr(font_cond),2,seek_key,status); 170: stream_$put_chr (stream_id,addr(font_ultracond),2,seek_key,status); END; END; pr_$transparent: BEGIN stream_$put_chr (stream_id,addr(text_vert_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(text_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(bi_directional),2,seek_key,status); trans_flag := TRUE; END; pr_$plot: BEGIN x_bitmap_size := server_ptr^.bitmap_size.x; y_bitmap_size := server_ptr^.bitmap_size.y; stream_$put_chr (stream_id,addr(plot_vert_spacing),4,seek_key,status); stream_$put_chr (stream_id,addr(plot_horiz_spacing),2,seek_key,status); stream_$put_chr (stream_id,addr(uni_directional),2,seek_key,status); plot_flag := TRUE; END; END; END; END; END; {End of USER1_SET_MODE} PROCEDURE USER1_RETURN_INFO ( IN query: pr_$inq_op_t; OUT data: pr_$data_rec_t ); BEGIN CASE query OF pr_$bpi: BEGIN data.bpi.x := 72; data.bpi.y := 72; END; pr_$rep_ability: data.rep_ability := false; pr_$driver_db: BEGIN driver_ptr := data.driver_db_ptr; WITH driver_ptr^ DO BEGIN valid := TRUE; copies := FALSE; cpi[1] := 10.0; {Put pica font first so it will be default} cpi[2] := 5.0; {Put the double-width fonts next} cpi[3] := 6.0; cpi[4] := 7.5; cpi[5] := 8.5; cpi[5] := 9.0; {Put the normal width fonts next} cpi[7] := 12.0; cpi[8] := 13.4; {Put the compressed fonts next} cpi[9] := 15.0; cpi[10] := 17.0; lpi[1] := 6; resolution[1] := 72; res_min := 72; res_max := 72; color_format := none; bw_rev := TRUE; END; END; END; END; {End of USER1_RETURN_INFO} PROCEDURE USER1_FLUSH; VAR temp: pr_$data_format_t; {printer mode: text, transparent, or plot} dummy: pr_$buf_t; {dummy buffer} BEGIN {If printer is in plot mode then make sure that the last buffer of bitmap data is filled out to 8 lines and printed. Then reset all of the counters.} {If the printer mode is TRANSPARENT or PLOT, then we need to eject the page from the printer. Under SR8, the PRSVR would change the printer mode to TEXT and issue a form feed after the end of a PLOT or TRANSPARENT mode output. Under SR9, we have to do the page ejection ourselves.} IF (bcount <> 0) THEN BEGIN temp := printer_mode; printer_mode := pr_$plot; REPEAT user1_write(dummy,0); UNTIL bcount = 0; printer_mode := temp; END; IF (plot_flag = TRUE) OR (trans_flag = TRUE) THEN BEGIN stream_$put_chr (stream_id,addr(ff),1,seek_key,status); END; plot_flag := FALSE; trans_flag := FALSE; END; {End of USER1_FLUSH} PROCEDURE USER1_CLOSE; BEGIN stream_$close (stream_id,status); END; {End of USER1_CLOSE} {***** End of module USER1_IMAGEWRITER *****} End of user1.imagewriter.pas echo user1.ins.pas 1>&2 cat >user1.ins.pas <<'End of user1.ins.pas' { PRSVR.INS.PAS, us/com/print, gtr, 05/09/83 Print server routines and associated data types which are exported for user supplied device drivers. Changes: 03/30/85 jjm updated for sr9 release 04/09/84 jjm update to sr8 05/09/83 gtr original coding -------------------------------------------------------------------------- | THE FOLLOWING PROGRAMS ARE THE SOLE PROPERTY OF APOLLO COMPUTER INC. | | AND CONTAIN ITS PROPRIETARY AND CONFIDENTIAL INFORMATION. | -------------------------------------------------------------------------- } CONST pr_$bufsize = 2048 ; TYPE pr_$buf_t = ARRAY [1..pr_$bufsize] OF char ; pr_$t = (pr_$user1, pr_$user2, pr_$user3, pr_$user4) ; pr_$set_op_t = ( pr_$font_weight, pr_$font_size, pr_$text_precision, pr_$data_format, pr_$pitch, pr_$y_dimension, pr_$x_dimension, pr_$rep_factor, pr_$config, pr_$copies, pr_$server_db ); pr_$inq_op_t = ( pr_$bpi, pr_$rep_ability, pr_$driver_db ); pr_$font_weight_t = ( pr_$light, pr_$medium, pr_$bold ); pr_$text_precision_t = ( pr_$draft, pr_$letter_quality ); pr_$data_format_t = ( pr_$text, pr_$plot, pr_$transparent ); prsvr_color_format_t = (none, {not a color printer} pixel, {color map format} scan_line_rgb,{3 plane formats} scan_line_ymc, plane_rgb, plane_ymc ); {this tells the server how to send bitmap data} pr_$interface_t = ( pr_$serial, pr_$parallel, pr_$external, pr_$versatec, pr_$multibus); {This data base is set up by PRSVR based on PRF options specified by the user and information the driver passes to PRSVR via the driver database (driver_db_t). To use this database, set up a record in your driver of type server_db_t. The setmode call will pass a pointer to this database as it exists in PRSVR.} server_db_t = RECORD copies : binteger; print_mode : pr_$data_format_t; cpi : real; {characters per inch} lpi : real; {lines per inch} weight : pr_$font_weight_t; lq : boolean; resolution : pinteger; {set the printer to print at this resolution} magnification : integer; {set the printer to magnify a bitmap by this amount} bitmap_size : RECORD x : integer; {the number of bits PRSVR will send} y : integer; planes : integer; {bits per pixel} END; color : boolean; {this file should be printed in color} bw_rev : boolean; {set if user requests it and the printer can do it } END; server_db_ptr_t = ^server_db_t; {this points you to the PRSVR server_db} {Use this database to pass PRSVR information about the driver and printers capabilities. PRSVR will issue a return_info call at startup, requesting this information. When the operation type of this call = pr_$driver_db , pass the PRSVR program the pointer to your driver database} driver_db_t = RECORD {information about the printer that the driver supplies} valid : boolean; { set this to true } copies : boolean; {does the printer do multiple copies} cpi : ARRAY [1..10] OF real; {an array of character spacings} lpi : ARRAY [1..10] OF real; resolution : ARRAY [1..4] OF pinteger; { the printer plots at these resolutions} res_min : pinteger; {a range of resolutions from minimum ...} res_max : pinteger; {... to maximum} magnification : ARRAY [1..16] OF binteger; color_format : prsvr_color_format_t; {tell prsvr how to send color images} bw_rev : boolean; {set if the printer can bw reverse image} END; driver_db_ptr_t = ^driver_db_t; {this tells PRSVR where to find your driver database} pr_$data_rec_t = packed RECORD font_weight : pr_$font_weight_t ; font_size : real ; text_precision : pr_$text_precision_t ; bpi : RECORD x : integer ; y : integer ; END; data_format: pr_$data_format_t; pitch : real ; x_dimension : pinteger ; y_dimension : pinteger ; rep_factor : pinteger; rep_ability : boolean; copies : pinteger; interface: pr_$interface_t; server_db_ptr : server_db_ptr_t; driver_db_ptr : driver_db_ptr_t; END ; %eject ; End of user1.ins.pas