      PROGRAM CONVERT_TO_SIXEL
C
C Version: 	V1.2
C
C Functional Description:
C
C This program will convert a ReGIS graphics file (such as one produced
C by Datatrieve) and produce a SIXEL graphics file which is suitable for
C printing on an appropriate printer (LA50, LA100, LN03, etc.).  It was
C written mainly to get around the need for DECSlide to create SIXEL files
C since a.) DECSlide isn't cheap and b.) it cannot be used in batch mode
C to create the SIXEL files.
C
C Since the SIXEL conversion is a hardware function of a graphics terminal,
C the program requires the use of a REGIS terminal.  This device is defined
C by the logical DISPLAY$DEVICE.  For an interactive terminal, therefore,
C a definitions such as the following should be made.
C
C $ DEFINE DISPLAY$DEVICE TT:
C
C If there is no logical translation for DISPLAY$DEVICE, the program performs
C the above definition on the users behalf.
C
C In addition, DISPLAY$DEVICE should be set to REGIS; the program will abort
C if this characteristics is not set.
C
C The specified ReGIS file is opened and displayed on the screen of
C DISPLAY$DEVICE.  The required sequences are sent to this device which
C set graphics to host, enter regis, and initiate hardcopy output.
C
C The appropriate terminal characteristics are set and successive QIO's are
C issued to read the SIXEL data which is returned a byte at a time.  The
C end of the conversion process is signaled by receipt of the byte after
C the third <ESC> character is detected.  The SIXEL data is collected
C in a 255 character buffer which is written to disk when full.  The
C SIXEL file, therefore, can be accessed by a standard text editor if
C necessary.
C
C Input to this program comes via the command line interpreter.  Specifically,
C the RTL routines CLI$GET_VALUE and CLI$PRESENT are used.  The command
C line definition file SIXEL.CLD contains the necessary information to
C define a command called SIXEL.  The following command line should be
C placed in the system wide login command file:
C
C 	$ SET COMMAND <directory>SIXEL
C
C where <directory> is the path to the SIXEL.CLD file.  The following
C command syntax is used to activate the program:
C
C
C $ SIXEL/GRAPH_TYPE=<option>  regis-file-spec  sixel-file-spec
C	or
C $ SIXEL/GRAPH_TYPE=<option>/LOCAL/RESET  regis-file-spec
C
C where /GRAPH_TYPE, /RESET and /LOCAL are optional qualifiers.  Valid values
C for the /GRAPH_TYPE qualifier are EXPANDED, ROTATED, and COMPRESSED.  If the
C EXPANDED option is selected, the sixel output produced will be approximately
C 12x8 inches.  The ROTATED option will produce output approximately 8x12
C inches and rotated 90 degrees; this will fit on standard 8 1/2 x 11 paper
C such as that typically loaded into an LA50 printer.  Finally, the COMPRESSED
C option will produce a graph approximately 6x3 inches.
C
C If the /LOCAL qualifier is present, SIXEL output is directed to a printer
C attached to DISPLAY$DEVICE.  If this qualifier is specified no sixel-file-spec
C is allowed.
C
C If the /RESET qualifier is present, DISPLAY$DEVICE will be set to COMPRESSED
C mode before exiting otherwise it will be left in the mode specified by the
C /GRAPH_TYPE option. 
C
C
C CREATED 1986,	WARNER-LAMBERT COMPANY
C 	CONSUMER HEALTH PRODUCTS GROUP
C 	MILFORD CONN 06460
C
C Author:				Creation date:
C
C Donald E. Stern, Jr.	-	February 4, 1986
C
C
C Modification History:
C
C Ver.		Author		Date		Reason for change
C
C 1.2	    B. Z. Lederman	29-May-1987	For VT125s
C
C
C Execution Enviroment
C
C VAX/VMS V4.2 or greater
C
C Functions and Subroutines Called:
C
C GET_TERMINAL_CHARACTERISTICS 	- Internally developed routine to determine terminal characteristics
C SET_TERMINAL_CHARACTERISTICS	- Internally developed routine to set terminal characteristics
C SYS$QIOW			- Synchronous queued I/O system service
C SYS$ASSIGN			- System service to assign a channel number to a device
C CLI$PRESENT			- RTL CLI argument detector
C CLI$GET_VALUE			- RTL CLI argument fetcher
C LIB$SYS_TRNLOG		- RTL routine to translate logical namesd
C LIB$SET_LOGICAL		- RTL routine to create a logical name
C LIB$GETDVI			- RTL routine to get device information
C
C SYS$QIO Structures
C
      INTEGER*2   INPUT_CHAN		! I/O Channel
      INTEGER	  CODE,  		! Type of I/O operation
     1		  INPUT_BUFFER_SIZE,	! Input buffer size
     2		  INPUT_SIZE		! Size of input as read
      PARAMETER   (INPUT_BUFFER_SIZE = 1)
C
C Terminal Characteristics Buffer
C
      BYTE        CLASS,
     1            TYPE
      INTEGER*2   WIDTH
      INTEGER*4   BASIC,
     1            EXTENDED
      INTEGER*4   OLD_BASIC,	! Old basic terminal characteristics
     1            OLD_EXTENDED	! Old extended terminal characteristics
C
C I/O Operations Definitions
C
      INCLUDE '($IODEF)'
C
C Terminal I/O Operation Modifiers
C
      INCLUDE '($TTDEF)'
      INCLUDE '($TT2DEF)'
C
C System Service Definitions
C
      INCLUDE '($SSDEF)'
C
C Device Information Definitions
C
      INCLUDE '($DVIDEF)'
      INCLUDE '($DCDEF)'
C
C QIO Status Block
C
      STRUCTURE   / IOSTAT_BLOCK /
                  INTEGER*2   IOSTAT,		! Return Status
     1                        TERM_OFFSET,	! Location of Line terminator
     2                        TERMINATOR,	! Value of terminator
     3                        TERM_SIZE   	! Size of terminator
      END STRUCTURE
      RECORD  / IOSTAT_BLOCK / IOSB
C
C Subprograms
C
      INTEGER*4   SYS$ASSIGN,
     1            SYS$QIOW,
     2            CLI$PRESENT,
     3            CLI$GET_VALUE,
     4            LIB$SYS_TRNLOG,
     5            LIB$SET_LOGICAL,
     6            LIB$GETDVI
C
      INTEGER*4   STATUS              ! Return status
C
      INTEGER*4   DEVICE_CLASS        ! Device class returned by LIB$GETDVI
C	
      BYTE    ENTER_REGIS(4)          ! Escape sequence to enter ReGIS mode
      BYTE    EXIT_REGIS(2)           ! Escape sequence to exit ReGIS
      BYTE    LOCK_KEYBOARD(4)        ! Escape sequence to lock keyboard
      BYTE    UNLOCK_KEYBOARD(4)      ! Escape sequence to unlock keyboard
      BYTE    GRAPHICS_TO_HOST(5)     ! Escape sequence for graphics to host
      BYTE    GRAPHICS_TO_PRINTER(5)  ! Escape sequence for graphics to printer
      BYTE    EXPANDED_PRINT(6)       ! Escape sequence for double wide graphics
      BYTE    ROTATED_PRINT(6)        ! Escape sequence for rotated graphics
      BYTE    COMPRESSED_PRINT(6)     ! Escape sequence for compressed  print
C
      INTEGER*2   NR,                 ! Number of characters in REGIS_FILE
     1            NS,                 ! Number of characters in SIXEL_FILE
     2            NG,                 ! Number of characters in QUALIFIER
     3            NT                  ! Number of characters in TRANSLATION
C
      CHARACTER*2     EXIT_GRAPHICS   ! Same as EXIT_REGIS
      CHARACTER*10    GRAPH_TYPE      ! Command line qualifier
      CHARACTER*13    MAKE_HARDCOPY   ! ReGIS instruction to make graphics hardcopy
      CHARACTER*255   REGIS_FILE      ! ReGIS source file
      CHARACTER*255   SIXEL_FILE      ! SIXEL destination file
      CHARACTER*255   TRANSLATION     ! Logical name translation
      CHARACTER*256   BUFF            ! Buffer for ReGIS and SIXEL data
C
      LOGICAL         QUIT
C
      EQUIVALENCE (EXIT_REGIS(1), EXIT_GRAPHICS)	
C
      DATA ENTER_REGIS            / 27, 80, 49, 112 /         ! <ESC>P1p
      DATA EXIT_REGIS             / 27, 92 /                  ! <ESC>\
      DATA LOCK_KEYBOARD          / 27, 91, 50, 104 /         ! <ESC>[2h
      DATA UNLOCK_KEYBOARD        / 27, 91, 50, 108 /         ! <ESC>[2l
      DATA GRAPHICS_TO_HOST       / 27, 91, 63, 50, 105 /     ! <ESC>[?2i
      DATA GRAPHICS_TO_PRINTER    / 27, 91, 63, 48, 105 /     ! <ESC>[?0i
      DATA EXPANDED_PRINT         / 27, 91, 63, 52, 51, 104 / ! <ESC>[?43h
      DATA ROTATED_PRINT          / 27, 91, 63, 52, 55, 104 / ! <ESC>[?47h
      DATA COMPRESSED_PRINT       / 27, 91, 63, 52, 51, 108 / ! <ESC>[?43l
Cxx   DATA MAKE_HARDCOPY          / 'S(H(P[50,0]))' /
      DATA MAKE_HARDCOPY          / 'S(H)' /		! B. Z. Lederman VT125
C
C See if there is a logical translation for DISPLAY$DEVICE and, if not, 
C assign 'TT:' to it.
C
      STATUS = LIB$SYS_TRNLOG('DISPLAY$DEVICE', NT, TRANSLATION,,,)
      IF (STATUS .EQ. SS$_NOTRAN)
     1            STATUS = LIB$SET_LOGICAL('DISPLAY$DEVICE', 'TT:',,,)
      IF (.NOT. STATUS)
     1            STOP 'Error translating or defining DISPLAY$DEVICE'
C
C Make sure that DISPLAY$DEVICE is a terminal device
C
      CODE = DVI$_DEVCLASS
      STATUS = LIB$GETDVI(CODE,, 'DISPLAY$DEVICE', DEVICE_CLASS,,)
      IF (STATUS .EQ. SS$_NOSUCHDEV)
     1            STOP 'Error - DISPLAY$DEVICE is unknown'
      IF (.NOT. STATUS)   STOP 'Error getting device information'
      IF (DEVICE_CLASS .NE. DC$_TERM)
     1            STOP 'Error - DISPLAY$DEVICE is not a terminal'
C
C Assign a channel number to DISPLAY$DEVICE
C
C Get a Channel No. for  DISPLAY$DEVICE
C
      STATUS = SYS$ASSIGN('DISPLAY$DEVICE', INPUT_CHAN,,)
C
C Stop on Errors
C
      IF (.NOT. STATUS) STOP 'Error assigning channel to DISPLAY$DEVICE'
C
C Get the existing terminal characteristics and save them
C
      CALL GET_TERMINAL_CHARACTERISTICS (INPUT_CHAN, CLASS, 
     1            TYPE, WIDTH, BASIC, EXTENDED)
      OLD_BASIC    = BASIC
      OLD_EXTENDED = EXTENDED
C
C If the terminal does not support ReGIS stop with an error message
C
      IF ((EXTENDED .AND. TT2$M_REGIS) .EQ. 0)
     1            STOP ' DISPLAY$DEVICE must be set to support ReGIS'
C
C Use the command line interpreter facility to get inputs
C
	STATUS = CLI$GET_VALUE('REGIS_FILE', REGIS_FILE, NR)
      IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
      IF (CLI$PRESENT('SIXEL_FILE'))
     1            STATUS = CLI$GET_VALUE('SIXEL_FILE', SIXEL_FILE, NS)
      IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
      IF (CLI$PRESENT('GRAPH_TYPE'))
     1            STATUS = CLI$GET_VALUE('GRAPH_TYPE', GRAPH_TYPE, NG)
      IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS))
C
C Open the input file
C
      OPEN (UNIT = 1, NAME = REGIS_FILE(1:NR), ACCESS = 'SEQUENTIAL',
     1            STATUS = 'OLD', READONLY, FORM = 'FORMATTED',
     2            RECORDTYPE = 'VARIABLE', CARRIAGECONTROL = 'LIST',
     3            ERR = 1100)
C
C Associate LUN 7 with DISPLAY$DEVICE and allow for large records
C
      OPEN (UNIT = 7, NAME = 'DISPLAY$DEVICE', RECL = 1024,
     1            STATUS = 'OLD', ERR = 1200)
C
C Lock the keyboard to avoid extraneous input during conversion
C
      WRITE (7, 18) LOCK_KEYBOARD
18    FORMAT('$', 4A1)
C
C Read the ReGIS code and display the plot on the screen of LUN 7
C
20    READ (1, 25, END = 100, ERR = 1300) NC, BUFF(1:NC)
25    FORMAT (Q, A)
      WRITE (7, 27) BUFF(1:NC)
27    FORMAT('+', A)
      GOTO 20					!Loop on READ 'til EOF
C
100   CLOSE (UNIT = 1)				!Close the ReGIS file
C
C Open a new file to contain the SIXEL information
C
      OPEN (UNIT = 1, NAME = SIXEL_FILE(1:NS), ACCESS = 'SEQUENTIAL',
     1            STATUS = 'NEW', FORM = 'UNFORMATTED',
     2            RECORDTYPE = 'VARIABLE', CARRIAGECONTROL = 'LIST',
     3            ERR = 1400)
C
C Set the required terminal characteristics
C
      BASIC = BASIC .OR.
     1     TT$M_HOSTSYNC .OR. ! Host sync. (CTRL-S on typeahead full)
     2	   TT$M_NOBRDCST .OR. ! No broadcast messages
     3	   TT$M_NOECHO   .OR. ! No echo
     4	   TT$M_TTSYNC        ! Terminal/Host sync
      BASIC = IBCLR(BASIC, TT$V_WRAP)             ! No wrap
      BASIC = IBCLR(BASIC, TT$V_EIGHTBIT)         ! Use 7 bit codes
      EXTENDED = EXTENDED .OR. TT2$M_PASTHRU .OR. ! Pass all data
     1		TT2$M_XON                         ! Resume output on SET
C
      CALL SET_TERMINAL_CHARACTERISTICS (INPUT_CHAN, CLASS, 
     1            TYPE, WIDTH, BASIC, EXTENDED)
C
C Send the appropriate escape sequence to DISPLAY$DEVICE to set it up
C to print graphics
C
      IF (GRAPH_TYPE(1:NG) .EQ. 'EXPANDED') THEN
                  WRITE(7, 102)EXPANDED_PRINT
                  MAKE_HARDCOPY(7:7) = '0'
      ENDIF
      IF (GRAPH_TYPE(1:NG) .EQ. 'ROTATED') THEN
                  WRITE(7, 102)ROTATED_PRINT
                  MAKE_HARDCOPY(7:7) = '0'
      ENDIF
      IF (GRAPH_TYPE(1:NG) .EQ. 'COMPRESSED') WRITE(7, 102) COMPRESSED_PRINT
101   FORMAT('+', 2A1, 5A1, 4A1, A13, $)
102   FORMAT('+', 6A1, $)
103   FORMAT('+', 2A1, 4A1, A13, $)
104   FORMAT('+', 2A1, 4A1, $)
C
      IF (CLI$PRESENT('LOCAL'))THEN			!Hardcopy to attached printer
                  WRITE(7, 103) EXIT_REGIS, ENTER_REGIS, MAKE_HARDCOPY
                  WRITE(7, 104) EXIT_REGIS, UNLOCK_KEYBOARD
      ELSE
                  WRITE(7, 101) EXIT_REGIS, GRAPHICS_TO_HOST, 
     1                ENTER_REGIS, MAKE_HARDCOPY
C
                  N    = 1			! Position in BUFF
                  NESC = 0			! Number of <ESC>'s detected
                  QUIT = .FALSE.		! Quit code
                  CODE  = IO$_READVBLK	! I/O code - Read virtual block
C
200               STATUS = SYS$QIOW(, 
     1                %VAL(INPUT_CHAN), 		!DISPLAY$DEVICE
     2                %VAL(CODE), 			!Read virtual block
     3                IOSB, , , 			!I/O Status
     4                %REF(BUFF(N:N)), 		!Input Buffer
     5                %VAL(INPUT_BUFFER_SIZE), , , , )	!Buffer Size
C
		IF (.NOT. STATUS) GOTO 1000
		IF (.NOT. IOSB.IOSTAT) GOTO 1000
		IF (QUIT) GOTO 250

		IF(BUFF(N:N) .EQ. CHAR(27))NESC = NESC+1		!Check for <ESC>
		IF(NESC .EQ. 3)QUIT = .TRUE.			!Escape on the byte after the third <ESC>
	
		IF (N .EQ. 255) THEN
			WRITE(1)BUFF(1:255)
			N = 0
		ENDIF

		N = N+1
		GOTO 200

250		WRITE(1)BUFF(1:N)
		CLOSE(UNIT = 1)

		WRITE(7, 252)EXIT_GRAPHICS, UNLOCK_KEYBOARD, GRAPHICS_TO_PRINTER
252		FORMAT('+', A2, 4A1, 5A1)
	ENDIF

C Reset terminal characteristics
	CALL SET_TERMINAL_CHARACTERISTICS (INPUT_CHAN, CLASS, 
	1	TYPE, WIDTH, OLD_BASIC, OLD_EXTENDED)
	IF(CLI$PRESENT('RESET'))WRITE(7, 102)COMPRESSED_PRINT
	STOP

C The following lines process errors
1000	WRITE(7, 252)EXIT_GRAPHICS, UNLOCK_KEYBOARD, GRAPHICS_TO_PRINTER
	CALL SET_TERMINAL_CHARACTERISTICS (INPUT_CHAN, CLASS, 
	1	TYPE, WIDTH, OLD_BASIC, OLD_EXTENDED)
	STOP 'Error reading SIXEL'
1100	STOP 'Error opening ReGIS file'
1200	STOP 'Error opening LUN 7'
1300	STOP 'Error reading ReGIS data'
1400	STOP 'Error opening SIXEL file'
	END
