Date: Tue, 23 Jun 87 11:24:37 edt From: David Krowitz Subject: Latest version of HP 7550 plotter software for Apollos Here is the latest version of my HP 7550 plotter software for the Apollo workstations. It is contained in 3 packed files because of its size. Simply running it through /bin/sh to unpack the files. -- David Krowitz mit-erl!mit-kermit!krowitz@eddie.mit.edu mit-erl!mit-kermit!krowitz@mit-eddie.arpa krowitz@mit-mc.arpa (in order of decreasing preference) "//ernie/users/krowitz/address" 7/193 -------------------------------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # hp7475.config # user1.hp7475.bld # user1.hp7475.doc # user1.hp7475.doc.install # user1.hp7475.pas # user1.ins.pas # This archive created: Tue Jun 23 11:15:54 1987 export PATH; PATH=/bin:$PATH if test -f 'hp7475.config' then echo shar: will not over-write existing file "'hp7475.config'" else cat << \SHAR_EOF > 'hp7475.config' FILE_BANNERS OFF DEVICE user1 SIO_LINE 2 SPEED 9600 PLOT_MODE OFF PRINTER_NAME HP7475 SHAR_EOF chmod +x 'hp7475.config' fi # end of overwriting check if test -f 'user1.hp7475.bld' then echo shar: will not over-write existing file "'user1.hp7475.bld'" else cat << \SHAR_EOF > 'user1.hp7475.bld' #################################################################################### ### ### ### Command file for Compiling and Binding the HP7475 Print Server ### ### ### #################################################################################### von pas user1.hp7475.pas -opt 3 bind -b prsvr.user1.hp7475 /com/prsvr user1.hp7475.bin voff SHAR_EOF chmod +x 'user1.hp7475.bld' fi # end of overwriting check if test -f 'user1.hp7475.doc' then echo shar: will not over-write existing file "'user1.hp7475.doc'" else cat << \SHAR_EOF > 'user1.hp7475.doc' ******************************************************************************* ***** ***** ***** USER1.HP7475.DOC ***** ***** Version 4 ***** ***** ***** ***** Programming Notes for the Hewlitt Packard 7475 Print Server ***** ***** ***** ***** Copyright (c) 1987 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmospheric, and Planetary Sciences ***** ******************************************************************************* Interfacing the Plotter with the Apollo --------------------------------------- We have interfaced our HP 7475 plotter 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 wires). We are using the X-ON/X-OFF protocal to control the flow of data between the Apollo and the plotter rather than using the DTR and CTS signals in the RS232-C cable. The SIO line characteristics necessary to run the plotter using X-ON/X-OFF are set up in the routine USER1_INIT. The plotter server is setup to use 9600 baud (this is selected in the plotter's configuration file, HP7475.CONFIG), 8 bits per character, 1 stop bit, and no parity. The settings of the switches on the back of the plotter should be as follows: Switch Setting ------ ------- Parity S1 0 no parity checking Parity S2 0 " " " D/Y D direct connection to computer US/MET US US size paper A3/A4 A4 A-size default paper (set to A3 for B-size) B4 1 9600 baud, 1 stop bit B3 0 " " " " " B2 1 " " " " " B1 0 " " " " " Refer to the "HP 7475A Operation and Interconnection Manual" for more detailed information on how to use the plotter and how to set up the parameters listed above. Description of the Plot Server Routines --------------------------------------- The HP7475 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 5.7 of Administering Your DOMAIN System gives a general description of the standard print server supplied by Apollo and the steps needed to generate a print server for a printer (or plotter) 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 (plot) 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 plot server when it starts up. The subroutine is given the line number of the SIO line to which the plotter is connected and the baud rate of that SIO line. Both of these numbers are read from the plotter configuration file (HP.CONFIG) by the plot 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 plotter 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 plotter accidentally glitches it can't kill the plot 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 plotter, USER1_INIT also initializes several strings of control characters for the plotter, resets various output-mode and warning message flags. Finally, USER1_INIT sends the plotter-init command to the HP 7475 to make sure the plotter is correctly initialized. The USER1_WRITE subroutine does most of the work of the plot server. This subroutine is called from the plot server to perform the actual output of the data to the HP7475 plotter. 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 plotter output mode and then outputs the contents of the buffer according to the mode. The mode is set by the plot 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 outputs an error message warning that the plotter is unable to print text files and throws away the output buffer. The warning message is only printed once at the beginning of a new file being output in text-mode, not during each line of output. The warning message is also suppressed when the print server tries to send a form-feed character (to eject the current page) to the plotter in text-mode after finishing the output of a plot-mode or transparent-mode file. 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 HP7475'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 twice to set the vertical and horizontal sizes 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. HP7475.CONFIG -- which is specified on the command line which started the print server) is set to ON. If the PLOT_MODE switch is on, then USER1_WRITE will output an error message warning that the plotter is unable to print bitmap files and will throw away the output buffer. The warning message is only output once at the beginning of the file, not during each buffer of output. The USER1_SET_MODE subroutine is called by the plot server prior to the output of each file being printed to set the proper plotter output mode and to set such things as the bitmap size (for plot mode files). The plot server may also call USER1_SET_MODE after the end of an output file to reset the plotter mode or to change the plotter mode to 'text' so it can output a top-of-page command (ie. a form feed) after finishing the printing of a bitmap or text-mode file. The USER1_SET_MODE routine also checks the 'WEIGHT' option of the PRF command to determine which kind of paper the user wanted their output to be plotted on. If the pen carosel currently loaded in the plotter is not the type requested by the user then the plotter will request that the pens (and paper) be changed. The USER1_FLUSH subroutine is called once at the end of each file output by the plot server and also in between changing plotter output modes. This routine checks if the output mode is 'transparent' and if it is, USER1_FLUSH sends the plotter the DF and NR commands to reset the HP 7475 to its default status (clearing any special plotter modes which the output file may have set up) and to unload the current page and to wait for new piece of paper to be loaded by the user. The USER1_CLOSE subroutine is only called when the plot server is stopping permanently (as opposed to waiting between files). All that it does is to close the plotter's output stream. Version 1 --------- Initial version of the HP7475 plotter server which was derived from the HP7570 plotter server. Includes the ability to check which kind of pens the user wants to be used for their plot and to ask for pens to be changed if necessary. The command 'PRF -WEIGHT LIGHT' requests that the plot be made with transparency pens, 'PRF -WEIGHT MEDIUM' requests fiber-tipped paper pens, and 'PRF -WEIGHT BOLD' requests drafting (vellum) pens. The default value is 'MEDIUM' (paper pens). If the wrong pen carosel is loaded, the plotter will unload the current page and pop up a window on the node running the plotter server requesting that the pens be changed. Like the HP7570 plotter (and unlike the HP7550 plotter from which the HP7570 software is derived), the HP7475 plotter is unable to automatically detect which type of pen carosel is loaded in the plotter. The HP7475 plotter server simply remembers which type of pens were last loaded in the plotter and compares this against the pen type requested by the user. If they differ, then the plotter server will request the user to change the pens AND ASSUMES THAT THE USER GETS THE CORRECT PENS IN THE PLOTTER. Version 2 --------- Corrected problem in detecting when a page had been unloaded. The HP 7475A does not implement the 'NR' command and the status bits being polled have a slightly different usage on the HP 7475 than on the HP 7550 and HP 7570 plotters. Version 3 --------- Changed way the FLUSH_FLAG is set and cleared to make it consistant with the order in which the USER1 routines are called by the SR9.5 print server (this flag is used to suppress the output of the printer configuration info). Changed the USER1_SET_MODE routine so that it will not asked for the pens to be changed during the startup of the print server when the print server tries to output the configuration info. Version 4 --------- Changed the REQUEST_PENS routine to check the current font size before popping up the window to request that the pen carosel be changed. The message used to get chopped off on some display types because the default font size was different from that used on the DN330 nodes on which the code was developed. Files Needed to Build the Plot Server ------------------------------------- The files which are provided for the HP 7475A plot server are: USER1.HP7475.DOC - This file. USER1.HP7475.DOC.INSTALL - Notes on how to install the plot server. PRF.HP7475.HLP - An edited version of the standard Apollo help file for the PRF command (/SYS/HELP/PRF.HLP) with notes included for the HP7475 plotter. USER1.HP7475.PAS - The Pascal sources for the plot server. USER1.INS.PAS - An edited version of the standard Apollo insert file, /SYS/INS/PRSVR.INS.PAS, which is used by USER1.HP7475.PAS to define the data types and structures used by the plot server. USER1.HP7475.BLD - A shell script file for compiling the USER1 routines (and their subroutines) and binding them with the Apollo supplied print server. HP7475.CONFIG - The configuration file for the HP7475 to be given as an argument to the plot server when it is started. PRSVR.USER1.HP7475 - A ready to run HP7475 plot server. Just in case you don't have a Pascal compiler. This is the file which is produced by USER1.HP7475.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/CAL.INS.PAS are used by USER1.HP7475.PAS. /SYS/INS/SIO.INS.PAS /SYS/INS/STREAMS.INS.PAS /SYS/INS/PAD.INS.PAS /SYS/INS/PGM.INS.PAS /SYS/INS/TIME.INS.PAS /SYS/INS/TONE.INS.PAS /SYS/INS/VFMT.INS.PAS /COM/PRSVR - The standard Apollo print server which must be bound with the plotter routines to produce a working print server. Used in USER1.HP7475.BLD to produce PRSVR.USER1.HP7475. 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 network mailing address: mit-erl!mit-kermit!krowitz@eddie.mit.edu mit-erl!mit-kermit!krowitz@mit-eddie.arpa krowitz@mit-mc.arpa (in order of decreasing preference) SHAR_EOF chmod +x 'user1.hp7475.doc' fi # end of overwriting check if test -f 'user1.hp7475.doc.install' then echo shar: will not over-write existing file "'user1.hp7475.doc.install'" else cat << \SHAR_EOF > 'user1.hp7475.doc.install' ******************************************************************************* ***** ***** ***** USER1.HP7475.DOC.INSTALL ***** ***** Version 1 ***** ***** Installing the HP7475 Print Server ***** ***** ***** ***** Copyright (c) 1987 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmospheric, and Planetary Sciences ***** ******************************************************************************* Read the general installation and documentation notes in USER1.HP7475.DOC if you have not already done so. The use the shell script file USER1.HP7475.BLD to compile the Hewlitt Packard device-driver routines and to bind them to the standard Apollo printer server located in /COM/PRSVR. This will create the HP7475 version of the print server (PRSVR.USER1.HP7475) in you working directory. Then edit the print server configuration file (HP7475.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.HP7475) and the print server configuration file (HP7475.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.HP7475 /COM/HP7475.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 HP7475 plotter ### CPS /COM/PRSVR.USER1.HP7475 -N PLOTTER_SERVER /COM/HP7475.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 Hewlitt Packard version) looks for files to be plotted 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 plotted on the HP7475 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 -PR HP7475 -S //NODE_NAME -TRANSPARENT to have the PRF command send the file to the node which has the plotter attached to it. (Note that you must give the name of the plotter in the PRF command, whether it is for the local /SYS/PRINT directory or for one on another node, in order to distinguish it from other printers/plotters which may be using the same /SYS/PRINT directory. The plotter's name is specified in its configuration file, HP7475.CONFIG, which is read when the plotter server starts up.) More information on the installation and use of print servers can be found in 'Administering Your DOMAIN System', section 5.7. SHAR_EOF chmod +x 'user1.hp7475.doc.install' fi # end of overwriting check if test -f 'user1.hp7475.pas' then echo shar: will not over-write existing file "'user1.hp7475.pas'" else cat << \SHAR_EOF > 'user1.hp7475.pas' {***************************************************************************** ***** ***** ***** USER1.HP7475.PAS ***** ***** ***** ***** Serial Plotter Driver for the Hewlitt Packard 7475A pen plotter ***** ***** Version 4 ***** ***** David M. Krowitz June 5, 1987. ***** ***** ***** ***** Copyright (c) 1987 ***** ***** David M. Krowitz ***** ***** Massachusetts Institute of Technology ***** ***** Department of Earth, Atmospheric, and Planetary Sciences ***** ***************************************************************************** } MODULE USER1_HP7475; %NOLIST; %INSERT '/sys/ins/base.ins.pas'; %INSERT '/sys/ins/cal.ins.pas'; %INSERT '/sys/ins/sio.ins.pas'; %INSERT '/sys/ins/streams.ins.pas'; %INSERT '/sys/ins/pad.ins.pas'; %INSERT '/sys/ins/pgm.ins.pas'; %INSERT '/sys/ins/time.ins.pas'; %INSERT '/sys/ins/tone.ins.pas'; %INSERT '/sys/ins/vfmt.ins.pas'; %INSERT 'user1.ins.pas'; %LIST; CONST {Program version number - should be same as in file header above} version_number = 4; {Definitions of standard ascii control characters} nul = chr(0); {null character} etx = chr(3); {etx (control-C) 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)} sub = chr(26); {sub (control-Z)} esc = chr(27); {escape} rs = chr(30); {rs} 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; str10_t = packed array[1..10] of char; str11_t = packed array[1..11] of char; str12_t = packed array[1..12] of char; str13_t = packed array[1..13] of char; str14_t = packed array[1..14] of char; str15_t = packed array[1..15] of char; str16_t = packed array[1..16] of char; str17_t = packed array[1..17] of char; str128_t = packed array[1..128] of char; command_buffer_t = packed array[1..4096] of char; user1_$pen_t = (unknown, empty, paper_pen, roller_ball_pen, drafting_pen, transparency_pen); VAR {Definitions of control sequences for the HP7475 plotter} init_plotter: str3_t; {initialize plotter characteristics} reset_plotter: str9_t; {reset plotter after finishing a plot} set_handshake: str17_t; {set handshake mode to Xon-Xoff} set_no_echo: str12_t; {set no turnaroud delay, no echo terminate char} unload_page: str3_t; {eject current page without loading new one} store_pen: str3_t; {put pen back into carosel} inq_status: str3_t; {inquire plotter status to check if paper loaded} crlf: str2_t; {carriage-return, line-feed sequence} {Defintions of global variables} text_flag: boolean; {Flags text-mode output being ignored} transparent_flag: boolean; {Flags transparent-mode output in progress} bitmap_flag: boolean; {Flags GMF bitmap plot-mode output being ignored} output_done_flag: boolean; {Flags output of file completed (all output modes)} flush_flag: boolean; {True if USER1_FLUSH routine called at least once} x_plot_size: pinteger; {x dimension of GMR vector file being plotted} y_plot_size: pinteger; {y dimension of GMR vector file being plotted} output_mode: pr_$data_format_t; {output mode: text, transparent, or bitmap plot} 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} pen_type_req: user1_$pen_t; {type of pens requested by user} pen_type_loaded: user1_$pen_t; {type of pens currently loaded in plotter} font_width: INTEGER16; {Width of current font in pixels} font_height: INTEGER16; {Height of font in pixels (including spacing between lines} font_name: PAD_$STRING_T; {Pathname of the font file} font_name_len: INTEGER16; {Length of the pathname} num_chars: pinteger; {Width of message requesting pen change to be popped up on screen} num_lines: pinteger; {Height of message requesting pen change to be popped up on screen} 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 {Identify ourselves.} WRITELN ('This is the HP7475-A Plotter Server - Version ',version_number:-1,'.'); WRITELN; {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.all <> STATUS_$OK) 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.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** USER1_INIT: Error - could not set SIO_$SPEED: ', sioname[sio_line],' ****'); PGM_$EXIT; END; SIO_$CONTROL (stream_id,sio_$nlc_delay,0,status); IF (status.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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.all <> STATUS_$OK) 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_plotter[1] := 'I'; init_plotter[2] := 'N'; init_plotter[3] := ';'; reset_plotter[1] := 'R'; reset_plotter[2] := 'O'; reset_plotter[3] := ';'; reset_plotter[4] := 'I'; reset_plotter[5] := 'P'; reset_plotter[6] := ';'; reset_plotter[7] := 'D'; reset_plotter[8] := 'F'; reset_plotter[9] := ';'; set_handshake[1] := esc; set_handshake[2] := '.'; set_handshake[3] := 'I'; set_handshake[4] := '8'; set_handshake[5] := '0'; set_handshake[6] := ';'; set_handshake[7] := ';'; set_handshake[8] := '1'; set_handshake[9] := '7'; set_handshake[10] := ':'; set_handshake[11] := esc; set_handshake[12] := '.'; set_handshake[13] := 'N'; set_handshake[14] := ';'; set_handshake[15] := '1'; set_handshake[16] := '9'; set_handshake[17] := ':'; set_no_echo[1] := esc; set_no_echo[2] := '.'; set_no_echo[3] := 'M'; set_no_echo[4] := '0'; set_no_echo[5] := ';'; set_no_echo[6] := '0'; set_no_echo[7] := ';'; set_no_echo[8] := '0'; set_no_echo[9] := ';'; set_no_echo[10] := '1'; set_no_echo[11] := '3'; set_no_echo[12] := ':'; unload_page[1] := 'N'; unload_page[2] := 'R'; unload_page[3] := ';'; store_pen[1] := 'S'; store_pen[2] := 'P'; store_pen[3] := ';'; inq_status[1] := esc; inq_status[2] := '.'; inq_status[3] := 'O'; crlf[1] := cr; crlf[2] := lf; {Initialize output-mode flags} text_flag := false; transparent_flag := false; bitmap_flag := false; output_done_flag := true; flush_flag := false; {Initialize the printer settings} STREAM_$PUT_CHR (stream_id,ADDR(init_plotter),3,seek_key,status); STREAM_$PUT_CHR (stream_id,ADDR(set_handshake),17,seek_key,status); STREAM_$PUT_CHR (stream_id,ADDR(set_no_echo),12,seek_key,status); STREAM_$PUT_CHR (stream_id,ADDR(store_pen),3,seek_key,status); output_mode := pr_$transparent; pen_type_loaded := unknown; 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 {If USER1_FLUSH has not been called at least once after the end of some text-mode output then ignore the output -- it is the printer configuration info which is printed when PRSVR starts up. It is not legal plotter output, but we don't want to print an error message for it since it is not an error on the part of the user -- PRSVR always prints its configuration on startup.} IF flush_flag = TRUE THEN BEGIN IF (text_flag = FALSE) AND (output_done_flag = TRUE) THEN BEGIN WRITELN ('Text mode output not possible on plotter - file discarded'); END; END; text_flag := TRUE; output_done_flag := FALSE; END; {End of USER1_WRITE_TEXT} PROCEDURE USER1_WRITE_TRANSPARENT ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); BEGIN IF (transparent_flag = FALSE) THEN BEGIN WRITELN ('Sending TRANSPARENT mode output to plotter'); END; STREAM_$PUT_CHR (stream_id,ADDR(buffer),buffer_length,seek_key,status); transparent_flag := TRUE; output_done_flag := FALSE; END; {End of USER1_WRITE_TRANSPARENT} PROCEDURE USER1_WRITE_PLOT ( IN buffer: UNIV pr_$buf_t; IN buffer_length: pinteger ); BEGIN IF (bitmap_flag = FALSE) AND (output_done_flag = TRUE) THEN BEGIN WRITELN ('GMF bitmap mode output not possible on plotter - file discarded'); END; bitmap_flag := TRUE; output_done_flag := FALSE; END; {End of USER1_WRITE_PLOT} BEGIN {Beginning of actual USER1_WRITE code} {Determine printer mode and dispatch for output of buffer} CASE output_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 WAIT_LOAD_PAGE; VAR i,j: pinteger; {counters} count: pinteger; {number of fields decoded by VFMT_$RS} sleep: TIME_$CLOCK_T; {number of seconds to sleep before re-checking status} BEGIN {Wait until the plotter has a sheet of paper loaded. Check the plotter's status until the 'not ready' state is reset by the user loading a new sheet of paper into the plotter. Bits 4 and 5 of the status word are the view-state and not-ready-state status bits. When they are both 0 the plotter is ready to go.} REPEAT CAL_$SEC_TO_CLOCK (5,sleep); TIME_$WAIT (TIME_$RELATIVE,sleep,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** WAIT_LOAD_PAGE: Error - sleep call failed ****'); PGM_$EXIT; END; STREAM_$PUT_CHR (stream_id,ADDR(inq_status),3,seek_key,status); VFMT_$RS2 (stream_id,'%EUWD%$',count,status,i,0); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** WAIT_LOAD_PAGE: Error - could not read plotter status ****'); PGM_$EXIT; END; UNTIL (i&(32!16) = 0); END; {End of WAIT_LOAD_PAGE} PROCEDURE WAIT_UNLOAD_PAGE; VAR i,j: pinteger; {counters} count: pinteger; {number of fields decoded by VFMT_$RS} sleep: TIME_$CLOCK_T; {number of seconds to sleep before re-checking status} BEGIN {Wait until the plotter has unloaded the current page.} REPEAT CAL_$SEC_TO_CLOCK (1,sleep); TIME_$WAIT (TIME_$RELATIVE,sleep,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** WAIT_UNLOAD_PAGE: Error - sleep call failed ****'); PGM_$EXIT; END; STREAM_$PUT_CHR (stream_id,ADDR(inq_status),3,seek_key,status); VFMT_$RS2 (stream_id,'%EUWD%$',count,status,i,0); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** WAIT_UNLOAD_PAGE: Error - could not read plotter status ****'); PGM_$EXIT; END; UNTIL (i = 40); END; {End of WAIT_UNLOAD_PAGE} FUNCTION INQ_PAGE_LOADED: BOOLEAN; VAR i,j: pinteger; {counters} count: pinteger; {number of fields decoded by VFMT_$RS} sleep: TIME_$CLOCK_T; {number of seconds to sleep before re-checking status} BEGIN {Check the plotter's status a see if the plotter has a page currently loaded.} STREAM_$PUT_CHR (stream_id,ADDR(inq_status),3,seek_key,status); VFMT_$RS2 (stream_id,'%EUWD%$',count,status,i,0); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('**** INQ_PAGE_LOADED: Error - could not read plotter status ****'); PGM_$EXIT; END; IF (i&(32!16) = 0) THEN BEGIN INQ_PAGE_LOADED := TRUE END ELSE BEGIN INQ_PAGE_LOADED := FALSE END; END; {End of INQ_PAGE_LOADED} PROCEDURE REQUEST_PENS ( IN pen_type_needed: user1_$pen_t ); VAR i,j: pinteger; {counters} pen_type_loaded: user1_$pen_t; {kind of pens currently loaded in plotter} sleep: TIME_$CLOCK_T; {number of seconds to sleep before re-checking pen type} pad_stream_id: STREAM_$ID_T; {Stream ID number of transcript pad} pad_seek_key: STREAM_$SK_T; {Stream's seek-key} pad_lines: INTEGER16; {Number of lines in the message window} pad_window: PAD_$WINDOW_DESC_T; {Position and size of the message window} beep_time: TIME_$CLOCK_T; {Length of time to beep at user} BEGIN {Request the desired pens to be loaded by the user. Pop up a windown on the node running the plotter server to request the new pens to be loaded. Then unload the current page so that the user will be sure to load the correct paper as well as the correct pens.} {Pop up a window on the node running the plotter server and request the pens to be changed.} pad_window.top := 0; pad_window.left := 0; pad_window.height := 100; pad_window.width := 400; PAD_$CREATE_WINDOW ('',0,PAD_$TRANSCRIPT,1,pad_window,pad_stream_id,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('***** REQUEST_PENS: Error - PAD_$CREATE_WINDOW call failed *****'); PGM_$EXIT; END; {Write out the message.} num_chars := 47; num_lines := 5; STREAM_$PUT_REC (pad_stream_id,ADDR('***********************************************'),num_chars,pad_seek_key,status); STREAM_$PUT_REC (pad_stream_id,ADDR(crlf),2,pad_seek_key,status); STREAM_$PUT_REC (pad_stream_id,ADDR(crlf),2,pad_seek_key,status); CASE pen_type_needed OF transparency_pen: STREAM_$PUT_REC (pad_stream_id,ADDR('Please load transparency pens in HP7550 plotter'),num_chars,pad_seek_key,status); paper_pen: STREAM_$PUT_REC (pad_stream_id,ADDR(' Please load paper pens in HP7550 plotter '),num_chars,pad_seek_key,status); drafting_pen: STREAM_$PUT_REC (pad_stream_id,ADDR(' Please load drafting pens in HP7550 plotter '),num_chars,pad_seek_key,status); END; STREAM_$PUT_REC (pad_stream_id,ADDR(crlf),2,pad_seek_key,status); STREAM_$PUT_REC (pad_stream_id,ADDR(crlf),2,pad_seek_key,status); STREAM_$PUT_REC (pad_stream_id,ADDR('***********************************************'),num_chars,pad_seek_key,status); STREAM_$PUT_REC (pad_stream_id,ADDR(crlf),2,pad_seek_key,status); {Resize window to fit the message.} PAD_$INQ_FONT (pad_stream_id,font_width,font_height,font_name,256,font_name_len,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('***** REQUEST_PENS: Error - PAD_$INQ_FONT call failed *****'); PGM_$EXIT; END; pad_window.width := (num_chars+2)*font_width; pad_window.height := (num_lines+2)*font_height; PAD_$SET_FULL_WINDOW (pad_stream_id,1,pad_window,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('***** REQUEST_PENS: Error - PAD_$SET_FULL call failed *****'); PGM_$EXIT; END; {Uload the page if necessary and beep at the user to get their attention.} beep_time.high16 := 0; beep_time.low32 := 30000; TONE_$TIME (beep_time); IF (inq_page_loaded = TRUE) THEN BEGIN STREAM_$PUT_CHR (stream_id,ADDR(unload_page),3,seek_key,status); END; {Wait until the user loads a new sheet of paper. Since the HP7475 plotter is unable to detect which type of pen carosel is loaded in the plotter we just have to assume that the user changed the pens when they loaded the paper.} wait_load_page; {Close the window we popped up on the node running the plotter server. Window will close automatically when the pad-stream is closed.} PAD_$SET_AUTO_CLOSE (pad_stream_id,1,TRUE,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('***** REQUEST_PENS: Error - PAD_$SET_AUTO_CLOSE call failed *****'); PGM_$EXIT; END; STREAM_$DELETE (pad_stream_id,status); IF (status.all <> STATUS_$OK) THEN BEGIN WRITELN ('***** REQUEST_PENS: Error - PAD_$CLOSE call failed *****'); PGM_$EXIT; END; END; {End of REQUEST_PENS} PROCEDURE USER1_SET_MODE ( IN mode: pr_$set_op_t; IN data: pr_$data_rec_t ); {Start of main body of USER1_SET_MODE.} BEGIN CASE mode OF pr_$font_weight: BEGIN CASE data.font_weight OF pr_$light: pen_type_req := transparency_pen; pr_$medium: pen_type_req := paper_pen; pr_$bold: pen_type_req := drafting_pen; END; IF (pen_type_req <> pen_type_loaded) AND (flush_flag = TRUE) THEN BEGIN request_pens (pen_type_req); pen_type_loaded := pen_type_req; END; END; pr_$font_size: ; pr_$text_precision: ; pr_$data_format: output_mode := data.data_format; pr_$pitch: ; pr_$x_dimension: ; pr_$y_dimension: ; pr_$rep_factor: ; pr_$config: ; pr_$copies: ; pr_$server_db: WITH data.server_db_ptr^ DO BEGIN output_mode := print_mode; CASE weight OF pr_$light: pen_type_req := transparency_pen; pr_$medium: pen_type_req := paper_pen; pr_$bold: pen_type_req := drafting_pen; END; IF (pen_type_req <> pen_type_loaded) AND (flush_flag = TRUE) THEN BEGIN request_pens (pen_type_req); pen_type_loaded := pen_type_req; 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 := 1016; data.bpi.y := 1016; END; pr_$rep_ability: data.rep_ability := true; pr_$driver_db: WITH data.driver_db_ptr^ DO BEGIN valid := TRUE; copies := FALSE; color_format := none; bw_rev := FALSE; image_rotation := FALSE; END; END; END; {End of USER1_RETURN_INFO} PROCEDURE USER1_FLUSH; BEGIN {Reset output-mode flags, issue the command to unload the current page, and wait for the plotter to finish and unload the paper.} IF transparent_flag = true THEN BEGIN STREAM_$PUT_CHR (stream_id,ADDR(reset_plotter),9,seek_key,status); STREAM_$PUT_CHR (stream_id,ADDR(store_pen),3,seek_key,status); STREAM_$PUT_CHR (stream_id,ADDR(unload_page),3,seek_key,status); wait_unload_page; END; {We have just finished output of some file (or just finished discarding it) so we set flag to inhibit printing of error message when PRSVR tries to send a form-feed in text-mode to move printer (plotter) to a new piece of paper.} IF (text_flag = true) THEN BEGIN output_done_flag := true; END; {IF USER1_FLUSH has been called at least once after performing some text-mode output then transparent-mode output can be enabled (first time around the output is the PRSVR configuration info which is printed the program is started -- but the output is not HP-GL commands so we quietly throw it away). All output modes have been completed so we reset their flags.} IF (text_flag = TRUE) THEN BEGIN flush_flag := true; {enable transparent-mode output} END; text_flag := false; transparent_flag := false; bitmap_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_HP7475 *****} SHAR_EOF chmod +x 'user1.hp7475.pas' fi # end of overwriting check if test -f 'user1.ins.pas' then echo shar: will not over-write existing file "'user1.ins.pas'" else cat << \SHAR_EOF > 'user1.ins.pas' { PRSVR.INS.PAS, Print server routines and associated data types which are exported for user supplied device drivers. Changes: 11/04/86 jjm Added comments 10/13/86 jjm added prf_$orient and prf_$paper_t 08/18/86 jjm added server_db and driver_db sr9.5 info 03/30/85 jjm updated for sr9 release 04/09/84 jjm update to sr8 05/09/83 gtr original coding } 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); prf_$paper_t = ( prf_$cut_sheet, prf_$fan_fold, prf_$roll, prf_$transparency, prf_$null ); prf_$orient_t = ( prf_$landscape, prf_$portrait ); (* This data structure is set up by PRSVR based on PRF options specified by the user and information the driver passes to PRSVR via the return_info call. When the setmode call operation type = pr_$server_db , dereference the server_db_ptr_t in pr_$data_rec_t to obtain the current parameters for this job. Use these values to format and control how the data is output to the print device. Ignore any other operation types (except interface) passed by the set mode call. They exist only for backwards compatability. *) 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 } color_map : UNIV_PTR; {pointer to the gpr bitmap color map} page_layout : prf_$orient_t; page_reversal : boolean; collate_copies : boolean; paper : RECORD page_size : RECORD w : REAL; l : REAL; END; style : prf_$paper_t; END; END; server_db_ptr_t = ^server_db_t; {this points you to the PRSVR server_db} (* Use this data structure 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 , deference driver_db_ptr_t in pr_$data_rec_t to pass PRSVR this information. Ignore any other operations passed by the return info call. They exist only for backwards compatability. *) 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} paper : RECORD page_size : RECORD w : REAL; l : REAL; END; style : prf_$paper_t; margins : RECORD {unprintable regions of paper} l,r,t,b : real; END; END; image_rotation : boolean; {the controller can rotate a bitmap} END; driver_db_ptr_t = ^driver_db_t; {a pointer to the PRSVR driver_db_t} 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 ; {Called once when the print server starts. Open I/O channels in this call} PROCEDURE user2_init ( IN sio_line: integer; IN sio_speed: integer ) ; EXTERN ; PROCEDURE user3_init ( IN sio_line: integer; IN sio_speed: integer ) ; EXTERN ; PROCEDURE user4_init ( IN sio_line: integer; IN sio_speed: integer ) ; EXTERN ; {Called at program startup. Use only the driver_db operation} PROCEDURE user2_return_info ( IN operation : pr_$inq_op_t; OUT datum : pr_$data_rec_t ); EXTERN ; PROCEDURE user3_return_info ( IN operation : pr_$inq_op_t; OUT datum : pr_$data_rec_t ); EXTERN ; PROCEDURE user4_return_info ( IN operation : pr_$inq_op_t; OUT datum : pr_$data_rec_t ); EXTERN ; {Called once at startup to set the interface} {Called at the beggining of each job. Use only the server_db operation to set job parameters} PROCEDURE user2_set_mode ( IN operation : pr_$set_op_t; IN datum : pr_$data_rec_t ); EXTERN ; PROCEDURE user3_set_mode ( IN operation : pr_$set_op_t; IN datum : pr_$data_rec_t ); EXTERN ; PROCEDURE user4_set_mode ( IN operation : pr_$set_op_t; IN datum : pr_$data_rec_t ); EXTERN ; {called multiple times for each job. This is the data to format and print} PROCEDURE user2_write ( IN str: UNIV pr_$buf_t ; IN strlen: pinteger ) ; EXTERN ; PROCEDURE user3_write ( IN str: UNIV pr_$buf_t ; IN strlen: pinteger ) ; EXTERN ; PROCEDURE user4_write ( IN str: UNIV pr_$buf_t ; IN strlen: pinteger ) ; EXTERN ; {Called at the end of each job. Reset job specific paramters to default values} PROCEDURE user2_flush ; EXTERN ; PROCEDURE user3_flush ; EXTERN ; PROCEDURE user4_flush ; EXTERN ; {Called when the print server terminates. Terminate any current jobs and close I/O channels} PROCEDURE user2_close ; EXTERN ; PROCEDURE user3_close ; EXTERN ; PROCEDURE user4_close ; EXTERN ; %eject ; SHAR_EOF chmod +x 'user1.ins.pas' fi # end of overwriting check # End of shell archive exit 0