diff options
Diffstat (limited to 'unix/gdev')
61 files changed, 6132 insertions, 0 deletions
diff --git a/unix/gdev/README b/unix/gdev/README new file mode 100644 index 00000000..235194cb --- /dev/null +++ b/unix/gdev/README @@ -0,0 +1,126 @@ +ZFIOGD -- FIO device driver for binary graphics devices. + Note: this code is part of library LIBSYS. + +The purpose of this driver is to provide a low level i/o interface to the +interactive binary graphics devices supported on a particular system. This +includes devices such as image displays and bit mapped vector graphics devices +(e.g., the Versatec plotters). The ZFIOGD driver is not intended for graphics +devices with a text interface, e.g., the Tektronix compatible graphics +terminals. A third interface, i.e., the ZFIOPL driver, is used for devices +accessed via the NCAR system plot package. + +By using a ZFIO level driver to talk to the binary graphics devices we can +isolate the system dependencies of the interface to a small amount of code. +We gain the ability to access the device over the network, since the kernel +server can be used once the i/o interface to the device is part of the kernel. + +The ZFIOGD driver is implemented in LIBSYS rather than LIBOS since the +interface code, while system dependent, is generally written at least partially +in SPP to access header files shared with the GIO graphics kernel for the +device, as well as to gain access to the LIBSYS library functions for ease +of coding. ZFIOGD is used only by the graphics kernels hence is not needed +to bootstrap the system; it is added to LIBSYS after the system is up and +running. + +The code is made as follows: + + [1] In a bootstrap, the commands in the mkpkg.csh file are executed by + the root mkpkg.csh file in host$. + + [2] In a sysgen, the mkpkg file in this directory is called by an entry + in sys$mkpkg to to update the libsys.a library. + + +ARCHITECTURE + + The single FIO device driver ZFIOGD is used to access all binary graphics +devices. This simplifies the KI and VOS interfaces and maximally isolates +knowledge of the devices supported on a particular system. New devices can +be added to ZFIOGD without any changes to the kernel interface or the VOS. +When a device is opened via the ZFIOGD driver the name of the device is +specified as follows: + + node!device:hostdevname +e.g., + lyra!iis,/dev/iis + vela!iis,iia0 + +where + device identifies the bottom level driver to be used + + hostdevname is the host system name for the particular + device to be accessed (there may be + multiple copies of a device on a single + system) + +The task of ZOPNGD is to look up device name in an internal table and call +the appropriate lower level device open procedure to physically open the +device. If the device resides on a remote node the kernel interface will +have have spawned a remote kernel server which will call ZOPNGD on the host +which actually owns the device. + + + ZFIOGD + + + iism7X deanza peritek versatec (etc.) + + +The ZFIOGD interface is a data driven interface, i.e., all control and status +readback functions are performed by ZARDGD and ZAWRGD calls to read and write +binary packets of data. This is ideal for a device such as the IIS which is +also data driven, but is less convenient for devices which have a control +type interface (in a control type interface, a subroutine is called to do +something to the device, rather than writing to the device). Even when the +device is control driven at the host system level, a data driven interface is +desirable to isolate the system dependence of the OS device driver, as well +as to provide network access. + + +PROTOCOLS + + When building a ZFIOGD sub-driver for a control driven device, it is +suggested that a control packet be defined for the device which is capable +of encoding all control functions. The high level code (GIO graphics device +driver) will encode control functions in this packet (which should have a +machine independent external representation), and send it along via ZAWRGD +to the sub-kernel, which will decode the packet and poke the host system device +driver as necessary to perform the indicated function. + +There is no predefined protocol for encoding control packets for binary +graphics devices. Conceivably such an interface could be defined, but our +goal with the ZFIOGD interface is to isolate the host system dependence of +the interface and provide network access capabilities; we are NOT trying to +address the problems of device independence in this interface. That is the +function of the GIO device driver, which should be machine independent and +portable, but addresses the problems of providing a device independent +interface. + +A control packet and communications protocol should therefore be defined +separately for each device. One possibility is to use the OFFSET argument +in the ZAWRGD call as a function code, rather than placing the function code +in a generic packet header. This is possible since the OFFSET argument is not +used for streaming devices. The only disadvantage to using the OFFSET field +in this way is that doing so would prevent use of FIO to buffer i/o to the +device, since FIO always sets OFFSET to zero when calling ZAWRGD for a +streaming device. The alternative is the generic packet approach, wherein +each i/o or control operation is preceded by a packet defining the operation +to be performed (this can simplify the interface, since a single set of +subroutines can be used to encode/transmit and receive/decode packet headers). +Yet another possibilty is to combine the two approaches, using a generic +packet header for most operations, but a special "offset" or function code +for special operations such as master clear or device reset (as well as to +reset the communications protocol). + +See the send/receive procedures in the KI (kernel interface) for an example +of how to encode packets in a machine independent form for transmission over +the network. + + +ADDING NEW DEVICES + + To add a new device to ZFIOGD, create a subdirectory with the name of the +device and implement the six driver subroutines therein. Add an entry to the +mkpkg to compile the new subdirectory. Add a new entry to the device table +and to each switch-case statement in zfiogd.x. Relink all affected graphics +executables, and relink the kernel server executable. diff --git a/unix/gdev/iism70/README b/unix/gdev/iism70/README new file mode 100644 index 00000000..8023068b --- /dev/null +++ b/unix/gdev/iism70/README @@ -0,0 +1,18 @@ +UNIX IRAF/FIO device driver for the IIS Model 70 +(will probably also work for the model 75). 11/85 dct +---------------------------------------------------------------------- + +This directory contains the IRAF/FIO driver subroutines for the IIS Model 70 +image display on UNIX. On a UNIX system the ZIFOBF (binary file) driver is +used to access the display, hence the subroutines herein merely map the calls +into the corresponding BF procedures. + + +Driver Procedures: + + zopm70 -- open + allocate + zclm70 -- close + deallocate + zrdm70 -- asynchronous binary read + zwrm70 -- asynchronous binary write + zwtm70 -- wait for i/o completion, return status + zstm70 -- get device status diff --git a/unix/gdev/iism70/m70.h b/unix/gdev/iism70/m70.h new file mode 100644 index 00000000..6a1a7d28 --- /dev/null +++ b/unix/gdev/iism70/m70.h @@ -0,0 +1,27 @@ +# Definitions for the VMS/IIS device driver. + +define IIS_READ 1 # read function code +define IIS_WRITE 0 # write function code +define IIS_INACTIVE -1 # no i/o in progress + +define EFN EFN2 # EFN to use for i/o +define EFN1W 0 # efn #1, wait for completion +define EFN2 1 # efn #2, no wait for completion +define EFN3 2 # efn #3, no wait for completion + +# Function control block structure for IIS. The first part of the structure +# is filled in by VMS at open time; all we need to know is the offset of the +# device name. We use the latter part of the buffer + +define LEN_FCB 30 +define FCB_U_NAME (P2S($1)+16+($2)-1) +define FCB_STATUS Memi[$1+20] # channel status (r, w, err) +define FCB_NBYTES Memi[$1+21] # nbytes last transfer +define FCB_EFN Memi[$1+22] # event flag used for transfer + +# IIS device status words. + +define IIS_FILSIZE (512 * 512 * SZB_CHAR) +define IIS_BLKSIZE 1024 +define IIS_OPTBUFSIZE (512 * SZB_CHAR) +define IIS_MAXBUFSIZE 32768 diff --git a/unix/gdev/iism70/mkpkg b/unix/gdev/iism70/mkpkg new file mode 100644 index 00000000..57b920c5 --- /dev/null +++ b/unix/gdev/iism70/mkpkg @@ -0,0 +1,15 @@ +# Make the UNIX version of the IIS driver. + +$checkout libsys.a lib$ +$update libsys.a +$checkin libsys.a lib$ +$exit + +libsys.a: + zclm70.x + zopm70.x + zrdm70.x + zstm70.x m70.h <fio.h> <mach.h> + zwrm70.x + zwtm70.x + ; diff --git a/unix/gdev/iism70/zclm70.x b/unix/gdev/iism70/zclm70.x new file mode 100644 index 00000000..719bc727 --- /dev/null +++ b/unix/gdev/iism70/zclm70.x @@ -0,0 +1,12 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# ZCLM70 -- Close and deallocate the IIS. + +procedure zclm70 (chan, status) + +int chan +int status + +begin + call zclsbf (chan, status) +end diff --git a/unix/gdev/iism70/zopm70.x b/unix/gdev/iism70/zopm70.x new file mode 100644 index 00000000..5c49d506 --- /dev/null +++ b/unix/gdev/iism70/zopm70.x @@ -0,0 +1,14 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# ZOPM70 -- Open the IIS for binary file i/o. The device will be automatically +# allocated if necessary. + +procedure zopm70 (device, mode, chan) + +char device[ARB] # packed UNIX device name +int mode # access mode +int chan # receives device channel + +begin + call zopnbf (device, mode, chan) +end diff --git a/unix/gdev/iism70/zrdm70.x b/unix/gdev/iism70/zrdm70.x new file mode 100644 index 00000000..f3ef3f2a --- /dev/null +++ b/unix/gdev/iism70/zrdm70.x @@ -0,0 +1,14 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# ZRDM70 -- Initiate an asynchronous read from the IIS. + +procedure zrdm70 (chan, buf, nbytes, offset) + +int chan # FCB pointer for device +char buf[ARB] # output buffer +int nbytes # number of bytes to read +long offset # not used for this device + +begin + call zardbf (chan, buf, nbytes, offset) +end diff --git a/unix/gdev/iism70/zstm70.x b/unix/gdev/iism70/zstm70.x new file mode 100644 index 00000000..2b790dfa --- /dev/null +++ b/unix/gdev/iism70/zstm70.x @@ -0,0 +1,28 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <fio.h> +include "m70.h" + +# ZSTM70 -- Return device status for the IIS. + +procedure zstm70 (chan, what, lvalue) + +int chan # FCB pointer for device +int what # status parameter +long lvalue + +begin + switch (what) { + case FSTT_FILSIZE: + lvalue = IIS_FILSIZE + case FSTT_BLKSIZE: + lvalue = IIS_BLKSIZE + case FSTT_OPTBUFSIZE: + lvalue = IIS_OPTBUFSIZE + case FSTT_MAXBUFSIZE: + lvalue = IIS_MAXBUFSIZE + default: + lvalue = ERR + } +end diff --git a/unix/gdev/iism70/zwrm70.x b/unix/gdev/iism70/zwrm70.x new file mode 100644 index 00000000..10545f99 --- /dev/null +++ b/unix/gdev/iism70/zwrm70.x @@ -0,0 +1,14 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# ZWRM70 -- Initiate an asynchronous write to the IIS. + +procedure zwrm70 (chan, buf, nbytes, offset) + +int chan # FCB pointer for device +char buf[ARB] # input buffer +int nbytes # number of bytes to write +long offset # not used for this device + +begin + call zawrbf (chan, buf, nbytes, offset) +end diff --git a/unix/gdev/iism70/zwtm70.x b/unix/gdev/iism70/zwtm70.x new file mode 100644 index 00000000..b2523c31 --- /dev/null +++ b/unix/gdev/iism70/zwtm70.x @@ -0,0 +1,13 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# ZWTM70 -- Wait for i/o completion and return the number of bytes read or +# written or ERR. Repetitive calls return the same value. + +procedure zwtm70 (chan, status) + +int chan # FCB pointer for device +int status # nbytes transferred or ERR + +begin + call zawtbf (chan, status) +end diff --git a/unix/gdev/iism75/README b/unix/gdev/iism75/README new file mode 100644 index 00000000..60433d4d --- /dev/null +++ b/unix/gdev/iism75/README @@ -0,0 +1,24 @@ +UNIX IRAF/FIO device driver for the IIS Model 75 +2 Feb 1896 Dct.; ported to UNIX from VMS 10 Mar 1987 SRo. +---------------------------------------------------------------------- + +This directory contains the IRAF/FIO driver subroutines for the IIS Model 75 +image display. This directory is self contained. + +The model 75 interface is implemented as a transformation on the data stream +for the model 70. The high level code thinks that it is talking to a model +70; we translate the headers as necessary for the model 75 before passing +them on to the device. This approach does not provide full access to the +capabilities of the model 75, however the existing high level code is all +written for the model 70 and we are not at present interested in the advanced +features of either display. + + +Driver Procedures: + + zopm75 -- open + allocate + zclm75 -- close + deallocate + zrdm75 -- asynchronous binary read + zwrm75 -- asynchronous binary write + zwtm75 -- wait for i/o completion, return status + zstm75 -- get device status diff --git a/unix/gdev/iism75/iis.h b/unix/gdev/iism75/iis.h new file mode 100644 index 00000000..515c0def --- /dev/null +++ b/unix/gdev/iism75/iis.h @@ -0,0 +1,106 @@ +# IIS.H -- Hardware definitions for the IIS models 70 and 75. + +# Define header +define LEN_IISHDR 8 # Length of IIS header + +define XFERID $1[1] # transfer id +define THINGCT $1[2] # thing count +define SUBUNIT $1[3] # subuint select +define CHECKSUM $1[4] # check sum +define XREG $1[5] # x register +define YREG $1[6] # y register +define ZREG $1[7] # z register +define TREG $1[8] # t register + +# Transfer ID definitions +define BYTEORDER 20B +define PMA 40B +define ACCELERATE 100B +define REPEAT 200B +define IREAD 100000B +define IWRITE 000000B +define PACKED 40000B +define BYPASSIFM 20000B +define PAGEMODE 10000B +define ADDWRITE 4000B +define ACCUM 2000B +define BLOCKXFER 1000B +define VRETRACE 400B + +define M70_BYTE 10000B +define M70_MUX32 200B + +# Subunits +define REFRESH 1 +define LUT 2 +define OFM 3 +define IFM 4 +define FEEDBACK 5 +define SCROLLZOOM 6 +define VIDEOM 7 +define SUMPROC 8 +define GRAPHICS 9 +define CURSOR 10 +define ALU 11 + +define M70_SCROLL 6 +define M70_ZOOM 12 + +# Command definitions +define COMMAND 100000B +define ERASE 100000B # Erase + +define SCROLL 1B +define ZOOM 10000B +define WRAP 1000B + +define M70_ADVXONTC 100000B # Advance x on thing count +define M70_ADVXONYOV 40000B # Advance x on y overflow +define M70_ADVYONXOV 100000B # Advance y on x overflow +define M70_ADVYONTC 40000B # Advance y on thing count + +define M75_ADVXONTC 400B # Advance x on thing count +define M75_ADVXONYOV 200B # Advance x on y overflow +define M75_ADVYONXOV 2000B # Advance y on x overflow +define M75_ADVYONTC 4000B # Advance y on thing count + +# 4 - Button Trackball +define PUSH 40000B +define BUTTONA 400B +define BUTTONB 1000B +define BUTTONC 2000B +define BUTTOND 4000B + +# Display channels +define CHAN1 1B +define CHAN2 2B +define CHAN3 4B +define CHAN4 10B +define GRCHAN 100000B + +define LEN_IISFRAMES 4 +define IISFRAMES CHAN1, CHAN2, CHAN3, CHAN4 + +# Colors +define BLUE 1B +define GREEN 2B +define RED 4B +define MONO 7B + +# Bit plane selections +define BITPL0 1B +define BITPL1 2B +define BITPL2 4B +define BITPL3 10B +define BITPL4 20B +define BITPL5 40B +define BITPL6 100B +define BITPL7 200B +define ALLBITPL 377B + +# IIS Sizes +define MCXSCALE 64 # Metacode x scale +define MCYSCALE 64 # Metacode y scale +define IIS_XDIM 512 +define IIS_YDIM 512 +define SZB_IISHDR 16 # Size of IIS header in bytes diff --git a/unix/gdev/iism75/m75.h b/unix/gdev/iism75/m75.h new file mode 100644 index 00000000..832aa423 --- /dev/null +++ b/unix/gdev/iism75/m75.h @@ -0,0 +1,28 @@ +# Definitions for the Model 75 UNIX/IIS device driver. + +define IIS_READ 1 # read function code +define IIS_WRITE 0 # write function code +define IIS_INACTIVE 2 # no i/o in progress + +# Function control block structure containing only our own internal variables. + +define LEN_FCB 20 +define FCB_CHAN Memi[($1)] # os channel +define FCB_STATUS Mems[P2S(($1)+1)] # channel status (r, w, err) +define FCB_NBYTES Mems[P2S(($1)+2)] # nbytes last transfer +define FCB_STATE Mems[P2S(($1)+3)] # instruction processing state +define FCB_IISHDR Mems[P2S(($1)+4)] # m70 header of current instr. + # (extra space) + +# Instruction processing states + +define READY 0 # ready for new instruction +define DATA_READ 1 # read data to complete instruction +define DATA_WRITE 2 # write data to complete instruction + +# IIS device status words. + +define IIS_FILSIZE (512 * 512 * SZB_CHAR) +define IIS_BLKSIZE 1024 +define IIS_OPTBUFSIZE (512 * SZB_CHAR) +define IIS_MAXBUFSIZE 16384 diff --git a/unix/gdev/iism75/m75put.x b/unix/gdev/iism75/m75put.x new file mode 100644 index 00000000..01ca6511 --- /dev/null +++ b/unix/gdev/iism75/m75put.x @@ -0,0 +1,160 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" +include "iis.h" + +# M75PUT -- Translate an M70 instruction+data into an M75 instruction+data and +# output it to the display device. We are called after both the instruction +# header and the data (if any) have been received. The M70 header has been +# saved in the the channel descriptor and the data, if any, is in BUF. + +procedure m75put (fcb, buf, nbytes_buf, offset) + +pointer fcb # pointer to channel descriptor +short buf[ARB] # data array +int nbytes_buf # nbytes of data in buffer +long offset # not used + +int ifcb +bool use_altbuf +short altbuf[128] +short m70[LEN_IISHDR] +short m75[LEN_IISHDR] +int nbytes, status, sum, i +int xferid, subunit, xreg, yreg +int and(), or(), not() + +begin + ifcb = fcb + use_altbuf = false + + # Retrieve the M70 header from the channel descriptor. + call amovs (FCB_IISHDR(fcb), m70, LEN_IISHDR) + + xferid = XFERID(m70) + subunit = SUBUNIT(m70) + xreg = XREG(m70) + yreg = YREG(m70) + + if (THINGCT(m70) == 0) + nbytes = 0 + else + nbytes = nbytes_buf + + # Start with a copy of the header for the M75, but turn off those bits + # in the transfer id which the M70 knows nothing about and hence could + # not have set. + + call amovs (m70, m75, LEN_IISHDR) + XFERID(m75) = and (xferid, + not (BYTEORDER+PMA+ACCELERATE+REPEAT+PAGEMODE)) + + # Translate the remaining fields of the header as necessary for each + # subunit. + + switch (and (subunit, 77B)) { + case REFRESH: + if (and (xreg, M70_ADVXONTC) != 0) + subunit = or (subunit, M75_ADVXONTC) + if (and (xreg, M70_ADVXONYOV) != 0) + subunit = or (subunit, M75_ADVXONYOV) + if (and (yreg, M70_ADVYONTC) != 0) + subunit = or (subunit, M75_ADVYONTC) + if (and (yreg, M70_ADVYONXOV) != 0) + subunit = or (subunit, M75_ADVYONXOV) + + SUBUNIT(m75) = subunit + XREG(m75) = and (xreg, IIS_XDIM-1) + YREG(m75) = and (yreg, IIS_YDIM-1) + + case LUT: + XREG(m75) = and (xreg, 1777B) + YREG(m75) = 0 + + case OFM: + XREG(m75) = and (xreg, 1777B) + YREG(m75) = 0 + + # The M70 feeds a 10 bit output DAC while the M75 DAC is 8 bits. + do i = 1, nbytes_buf / (SZB_CHAR * SZ_SHORT) + buf[i] = buf[i] / 4 + + case FEEDBACK: + subunit = COMMAND + FEEDBACK + SUBUNIT(m75) = subunit + XREG(m75) = 0 + YREG(m75) = 0 + + case GRAPHICS: + XREG(m75) = and (xreg, 777B) + + # In a command mode transfer, the status register value is passed + # as data for the M70, but in the T register for the M75. + + if (and (subunit, COMMAND) != 0) { + TREG(m75) = buf[1] + THINGCT(m75) = 0 + nbytes = 0 + } + + case CURSOR: + XREG(m75) = and (xreg, 7777B) + YREG(m75) = 0 + + case M70_SCROLL: + SUBUNIT(m75) = SCROLLZOOM + XREG(m75) = and (xreg, 3B) + YREG(m75) = 0 + ZREG(m75) = ALLBITPL + TREG(m75) = SCROLL + WRAP + + case M70_ZOOM: + SUBUNIT(m75) = SCROLLZOOM + THINGCT(m75) = 2 + XREG(m75) = and (xreg, 3B) + YREG(m75) = 0 + ZREG(m75) = ALLBITPL + TREG(m75) = ZOOM + SCROLL + WRAP + + # There are up to 3 words of data for the M70: zoom factor, + # x center, y center. For the M75 the zoom is specified + # separately for each axis in the high bits of the word which + # contains the axis center. For simplicity we require that + # all 3 words always be given. + + altbuf[1] = buf[1] * 10000B + buf[2] + altbuf[2] = buf[1] * 10000B + buf[3] + use_altbuf = true + nbytes = 2 * (SZ_SHORT * SZB_CHAR) + } + + # Compute the checksum for the new header. + + CHECKSUM(m75) = 1 + if (THINGCT(m75) > 0) + THINGCT(m75) = -THINGCT(m75) + + sum = 0 + do i = 1, LEN_IISHDR + sum = sum + m75[i] + + CHECKSUM(m75) = -sum + + # Output the header. + + call zzwrii (fcb, m75, SZB_IISHDR, offset) + call zwtm75 (ifcb, status) + if (status == ERR) { + FCB_STATUS(fcb) = ERR + return + } + + # Output the data block, if any. + + if (nbytes > 0) + if (use_altbuf) + call zzwrii (fcb, altbuf, nbytes, offset) + else + call zzwrii (fcb, buf, nbytes, offset) +end diff --git a/unix/gdev/iism75/mkpkg b/unix/gdev/iism75/mkpkg new file mode 100644 index 00000000..97387aec --- /dev/null +++ b/unix/gdev/iism75/mkpkg @@ -0,0 +1,18 @@ +# Mkpkg for the UNIX version of the IIS driver. + +$checkout libsys.a lib$ +$update libsys.a +$checkin libsys.a lib$ +$exit + +libsys.a: + m75put.x iis.h m75.h <mach.h> + zclm75.x m75.h <mach.h> + zopm75.x m75.h <mach.h> + zrdm75.x iis.h m75.h <mach.h> + zstm75.x m75.h <fio.h> <mach.h> + zwrm75.x iis.h m75.h <mach.h> + zwtm75.x m75.h <mach.h> + zzrdii.x m75.h <mach.h> + zzwrii.x m75.h <mach.h> + ; diff --git a/unix/gdev/iism75/zclm75.x b/unix/gdev/iism75/zclm75.x new file mode 100644 index 00000000..989358d9 --- /dev/null +++ b/unix/gdev/iism75/zclm75.x @@ -0,0 +1,19 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" + +# ZCLM75 -- Close and deallocate the IIS. + +procedure zclm75 (ifcb, status) + +int ifcb # pointer to channel descriptor passed as int +int status +pointer fcb + +begin + fcb = ifcb + call zclsbf (FCB_CHAN(fcb), status) + + call mfree (fcb, TY_STRUCT) +end diff --git a/unix/gdev/iism75/zopm75.x b/unix/gdev/iism75/zopm75.x new file mode 100644 index 00000000..33a9acf8 --- /dev/null +++ b/unix/gdev/iism75/zopm75.x @@ -0,0 +1,32 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" + +# ZOPM75 -- Open the IIS for binary file i/o. + +procedure zopm75 (device, mode, ifcb) + +char device[ARB] # packed UNIX device name +int mode # access mode +int ifcb # pointer to channel descriptor passed as int + +pointer fcb +int chan + +begin + call calloc (fcb, LEN_FCB, TY_STRUCT) + ifcb = fcb + + FCB_STATUS(fcb) = IIS_INACTIVE + FCB_NBYTES(fcb) = 0 + FCB_STATE(fcb) = READY + + call zopnbf (device, mode, chan) + + if (chan < 0) { + call mfree (fcb, TY_STRUCT) + ifcb = ERR + } else + FCB_CHAN(fcb) = chan +end diff --git a/unix/gdev/iism75/zrdm75.x b/unix/gdev/iism75/zrdm75.x new file mode 100644 index 00000000..9cc2498d --- /dev/null +++ b/unix/gdev/iism75/zrdm75.x @@ -0,0 +1,163 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" +include "iis.h" + +# ZRDM75 -- Initiate an asynchronous read of data from the IIS. Note that +# the zwrm75 procedure is called to write the header for data reads, as well +# as writes. Hence we should be called only after the header has been saved +# in the channel descriptor by ZWRM75, leaving the channel in state DATA_READ. +# Our task is to translate and output the header, read the M75 data block, and +# return the data block to the user after performing any transformations +# necessary to make it look like M70fdata. + +procedure zrdm75 (ifcb, buf, nbytes_buf, offset) + +int ifcb # pointer to channel descriptor passed as int +short buf[ARB] # data array +int nbytes_buf # nbytes of data in buffer +long offset # not used + +pointer fcb +short m70[LEN_IISHDR] +short m75[LEN_IISHDR] +int nbytes, status, sum, i +int xferid, subunit, xreg, yreg +int and(), or(), not() + +begin + fcb = ifcb + nbytes = nbytes_buf + + if (FCB_STATE(fcb) != DATA_READ) { + FCB_STATUS(fcb) = ERR + return + } + + # Retrieve the M70 header from the channel descriptor. + call amovs (FCB_IISHDR(fcb), m70, LEN_IISHDR) + + xferid = XFERID(m70) + subunit = SUBUNIT(m70) + xreg = XREG(m70) + yreg = YREG(m70) + + # Start with a copy of the header for the M75, but turn off those bits + # in the transfer id which the M70 knows nothing about and hence could + # not have set. + + call amovs (m70, m75, LEN_IISHDR) + XFERID(m75) = and (xferid, + not (BYTEORDER+PMA+ACCELERATE+REPEAT+PAGEMODE)) + + # Translate the remaining fields of the header as necessary for each + # subunit. + + switch (and (subunit, 77B)) { + case REFRESH: + if (and (xreg, M70_ADVXONTC) != 0) + subunit = or (subunit, M75_ADVXONTC) + if (and (xreg, M70_ADVXONYOV) != 0) + subunit = or (subunit, M75_ADVXONYOV) + if (and (yreg, M70_ADVYONTC) != 0) + subunit = or (subunit, M75_ADVYONTC) + if (and (yreg, M70_ADVYONXOV) != 0) + subunit = or (subunit, M75_ADVYONXOV) + + SUBUNIT(m75) = subunit + XREG(m75) = and (xreg, IIS_XDIM-1) + YREG(m75) = and (yreg, IIS_YDIM-1) + + case LUT: + XREG(m75) = and (xreg, 1777B) + YREG(m75) = 0 + + case OFM: + XREG(m75) = and (xreg, 1777B) + YREG(m75) = 0 + + # The M70 OFM lookup table is 10 bits deep, whereas the M75 table + # is only 8 bits deep, so scale the 8 bit M75 values up to 10 bits. + + do i = 1, nbytes_buf / (SZB_CHAR * SZ_SHORT) + buf[i] = buf[i] * 4 + + case FEEDBACK: + subunit = COMMAND + FEEDBACK + SUBUNIT(m75) = subunit + XREG(m75) = 0 + YREG(m75) = 0 + + case GRAPHICS: + XREG(m75) = and (xreg, 777B) + TREG(m75) = 0 # ?? + + case CURSOR: + XREG(m75) = and (xreg, 7777B) + YREG(m75) = 0 + + case M70_SCROLL: + SUBUNIT(m75) = SCROLLZOOM + XREG(m75) = and (xreg, 3B) + YREG(m75) = 0 + ZREG(m75) = ALLBITPL + TREG(m75) = SCROLL + WRAP + + case M70_ZOOM: + SUBUNIT(m75) = SCROLLZOOM + THINGCT(m75) = 2 + nbytes = 2 * (SZ_SHORT * SZB_CHAR) + XREG(m75) = and (xreg, 3B) + YREG(m75) = 0 + ZREG(m75) = ALLBITPL + TREG(m75) = ZOOM + } + + # Compute the checksum for the new header. + + CHECKSUM(m75) = 1 + if (THINGCT(m75) > 0) + THINGCT(m75) = -THINGCT(m75) + + sum = 0 + do i = 1, LEN_IISHDR + sum = sum + m75[i] + + CHECKSUM(m75) = -sum + + # Output the header. + + call zzwrii (fcb, m75, SZB_IISHDR, offset) + call zwtm75 (ifcb, status) + if (status == ERR) { + FCB_STATUS(fcb) = ERR + return + } + + # Read the data block. + + if (nbytes > 0) { + call zzrdii (fcb, buf, nbytes, offset) + call zwtm75 (ifcb, status) + if (status <= 0) { + FCB_STATUS(fcb) = ERR + return + } + } + + # Perform any transformations on the data just read necessary to + # convert it into M70 format. If the number of bytes read is + # different than that expected by the M70, be sure to set the + # expected count in the channel descriptor for the next ZWTM75. + + if (and (subunit, 77B) == ZOOM) { + FCB_NBYTES(fcb) = 3 * (SZ_SHORT * SZB_CHAR) + FCB_STATUS(fcb) = IIS_INACTIVE + buf[3] = mod (int(buf[2]), 10000B) + buf[2] = mod (int(buf[1]), 10000B) + buf[1] = buf[1] / 10000B + } + + FCB_STATE(fcb) = READY +end diff --git a/unix/gdev/iism75/zstm75.x b/unix/gdev/iism75/zstm75.x new file mode 100644 index 00000000..b1e9923c --- /dev/null +++ b/unix/gdev/iism75/zstm75.x @@ -0,0 +1,28 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <fio.h> +include "m75.h" + +# ZSTM75 -- Return device status for the IIS. + +procedure zstm75 (ifcb, what, lvalue) + +int ifcb # pointer to channel descriptor passed as int +int what # status parameter +long lvalue + +begin + switch (what) { + case FSTT_FILSIZE: + lvalue = IIS_FILSIZE + case FSTT_BLKSIZE: + lvalue = IIS_BLKSIZE + case FSTT_OPTBUFSIZE: + lvalue = IIS_OPTBUFSIZE + case FSTT_MAXBUFSIZE: + lvalue = IIS_MAXBUFSIZE + default: + lvalue = ERR + } +end diff --git a/unix/gdev/iism75/zwrm75.x b/unix/gdev/iism75/zwrm75.x new file mode 100644 index 00000000..38bb0f3c --- /dev/null +++ b/unix/gdev/iism75/zwrm75.x @@ -0,0 +1,76 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" +include "iis.h" + +# ZWRM75 -- Initiate an asynchronous write to the IIS. We are called to +# output the header of all instructions sent to the IIS. There are 3 types +# of instructions; those which consist only of a header write, those which +# consist of a header write followed by a data write, and those which +# consist of a header write followed by a data read. Translation of an M70 +# instruction into an M75 instruction may involve moving information between +# the header and data block, hence we must save the headers of the read and +# write instructions until the data has been read or written. The STATE +# variable in the channel descriptor is used to keep track of the instruction +# processing state. + +procedure zwrm75 (ifcb, buf, nbytes, offset) + +int ifcb # pointer to channel descriptor passed as int +char buf[ARB] # input buffer +int nbytes # number of bytes to write +long offset # not used for this device + +pointer fcb +int xferid, and() + +begin + fcb = ifcb + + if (FCB_STATE(fcb) == READY) { + # Start a new instruction. + + if (nbytes != SZB_IISHDR) { + FCB_STATUS(fcb) = ERR + return + } + + # Save the M70 header in the descriptor. + call amovs (buf, FCB_IISHDR(fcb), LEN_IISHDR) + xferid = XFERID(buf) + + # Determine the state for the new instruction. + + if (THINGCT(buf) == 0) + FCB_STATE(fcb) = READY + else if (and (xferid, IREAD) != 0) + FCB_STATE(fcb) = DATA_READ + else + FCB_STATE(fcb) = DATA_WRITE + + # If the new state is READY, no data read or write is needed, + # so just translate and output the header. + + if (FCB_STATE(fcb) == READY) + call m75put (fcb, buf, nbytes, offset) + else { + # Set up a channel status as if we had just written the new + # header, so that the next ZWTM75 will not return an error. + + FCB_STATUS(fcb) = IIS_INACTIVE + FCB_NBYTES(fcb) = SZB_IISHDR + } + + } else if (FCB_STATE(fcb) == DATA_WRITE) { + # This is the second zwrm75 call for a hdr+data output + # instruction. + + call m75put (fcb, buf, nbytes, offset) + FCB_STATE(fcb) = READY + + } else { + # ZRDM75 should have been called, set error on the channel. + FCB_STATUS(fcb) = ERR + } +end diff --git a/unix/gdev/iism75/zwtm75.x b/unix/gdev/iism75/zwtm75.x new file mode 100644 index 00000000..491b0f50 --- /dev/null +++ b/unix/gdev/iism75/zwtm75.x @@ -0,0 +1,29 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" + +# ZWTM75 -- Wait for i/o completion and return the number of bytes read or +# written or ERR. Repetitive calls return the same value. + +procedure zwtm75 (ifcb, status) + +int ifcb # pointer to channel descriptor passed as int +int status # nbytes transferred or ERR + +pointer fcb + +begin + fcb = ifcb + + switch (FCB_STATUS(fcb)) { + case ERR: + status = ERR + case IIS_INACTIVE: + status = FCB_NBYTES(fcb) + + default: + call zawtbf (FCB_CHAN(fcb), status) + FCB_STATUS(fcb) = IIS_INACTIVE + } +end diff --git a/unix/gdev/iism75/zzrdii.x b/unix/gdev/iism75/zzrdii.x new file mode 100644 index 00000000..f72058c3 --- /dev/null +++ b/unix/gdev/iism75/zzrdii.x @@ -0,0 +1,17 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" + +# ZZRDII -- Initiate an asynchronous read from the IIS. + +procedure zzrdii (fcb, buf, nbytes, offset) + +pointer fcb # pointer to channel descriptor +char buf[ARB] # output buffer +int nbytes # number of bytes to read +long offset # not used for this device + +begin + call zardbf (FCB_CHAN(fcb), buf, nbytes, offset) +end diff --git a/unix/gdev/iism75/zzwrii.x b/unix/gdev/iism75/zzwrii.x new file mode 100644 index 00000000..8515cc64 --- /dev/null +++ b/unix/gdev/iism75/zzwrii.x @@ -0,0 +1,17 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include "m75.h" + +# ZZWRII -- Initiate an asynchronous write to the IIS. + +procedure zzwrii (fcb, buf, nbytes, offset) + +pointer fcb # pointer to channel descriptor +char buf[ARB] # input buffer +int nbytes # number of bytes to write +long offset # not used for this device + +begin + call zawrbf (FCB_CHAN(fcb), buf, nbytes, offset) +end diff --git a/unix/gdev/m70vms/README b/unix/gdev/m70vms/README new file mode 100644 index 00000000..23a06824 --- /dev/null +++ b/unix/gdev/m70vms/README @@ -0,0 +1,68 @@ +VMS IRAF/FIO device driver for the IIS Model 70 +(will probably also work for the model 75). 11/85 dct +---------------------------------------------------------------------- + +This directory contains the IRAF/FIO driver subroutines for the IIS Model 70 +image display on VMS. This directory is self contained; no external code is +required other than the VMS/IIS device driver itself. The code should be +portable to any VMS system. + + +Driver Procedures: + + zopm70 -- open + allocate + zclm70 -- close + deallocate + zrdm70 -- asynchronous binary read + zwrm70 -- asynchronous binary write + zwtm70 -- wait for i/o completion, return status + zstm70 -- get device status + + +On a UNIX system the ordinary binary file driver (ZFIOBF) may be used for these +functions. This might work on VMS too, but the IRAF/VMS binary file driver is +complicated and uses RMS, so I did not bother to try. This driver uses a +modified version local KPNO IIS library, which I suppose came originally from +IIS corp. The interface procedures are written in VMS Fortran and make direct +calls to the VMS system services. The original library has been modified to +convert all the names to the prefix "m70", and to remove all Fortran i/o. + + +VMS/IIS Interface Procedures: + + m70get (fcb, error) # open+allocate+mclear + m70rel (fcb) # close+deallocate + m70opn (fcb, error) # open + m70cls (fcb) # close + m70mcl (fcb, error) # master clear + + m70io (fcb, data, count, read, opcd, iosb, error) + m70wt (fcb, bfnum, bfcnt, iosb, error) + m70wti (fcb, func, time, button, x, y) + + +M70IO: I/O between M70 and a VAX. + + fcb function communications block. + data input/output buffer. + count number of words to read/write. + read 0 -> write, 1 -> read. + opcd :: 0 -> qio with efn = 1 and wait for completion + 1 -> qio with efn = 2 + 2 -> qio with efn = 3 + iosb I/O status quadword + error :: -1 => display not available + 0 => success + 1 => time/out + 2 => invalid or non-responding device + 1000 > machine dependent error code + + +M70WT: Wait for i/o. + + fcb function communication block. + bfnum used to determine event flag to wait for + bfcnt number of words in buffer. should be -1 indicating + i/o pending. reset to zero when i/o completed. + iosb i/o status block + error 0 success, -1 not acquired, 1 timeout, + 2 invalid device, 1000+n system dep. error diff --git a/unix/gdev/m70vms/fcbu.inc b/unix/gdev/m70vms/fcbu.inc new file mode 100644 index 00000000..54f23244 --- /dev/null +++ b/unix/gdev/m70vms/fcbu.inc @@ -0,0 +1,6 @@ +c +c vax offsets for display.for and termio.for +c + parameter fcb_u_spool = 21 + parameter fcb_u_m70_chan = 19 + parameter fcb_u_m70_name = 17 diff --git a/unix/gdev/m70vms/m70.h b/unix/gdev/m70vms/m70.h new file mode 100644 index 00000000..16b4c938 --- /dev/null +++ b/unix/gdev/m70vms/m70.h @@ -0,0 +1,30 @@ +# Definitions for the VMS/IIS device driver. + +define IIS_READ 1 # read function code +define IIS_WRITE 0 # write function code +define IIS_INACTIVE 2 # no i/o in progress + +define EFN EFN2 # EFN to use for i/o +define EFN1W 0 # efn #1, wait for completion +define EFN2 1 # efn #2, no wait for completion +define EFN3 2 # efn #3, no wait for completion + +# Function control block structure for IIS. The first part of the structure +# is filled in by VMS at open time; all we need to know is the offset of the +# device name. We use the latter part of the buffer for our own internal +# variables. + +define LEN_FCB 28 +define FCB_U_NAME Mems[($1)+16+($2)-1] +define FCB_IOSB Mems[($1)+20+($2)-1] +define FCB_KCHAN Mems[($1)+24] # NULL if on local node, else remote +define FCB_STATUS Mems[($1)+25] # channel status (r, w, err) +define FCB_NBYTES Mems[($1)+26] # nbytes last transfer +define FCB_EFN Mems[($1)+27] # event flag used for transfer + +# IIS device status words. + +define IIS_FILSIZE (512 * 512 * SZB_CHAR) +define IIS_BLKSIZE 1024 +define IIS_OPTBUFSIZE (512 * SZB_CHAR) +define IIS_MAXBUFSIZE 32768 diff --git a/unix/gdev/m70vms/m70cls.f b/unix/gdev/m70vms/m70cls.f new file mode 100644 index 00000000..9eb2fcd3 --- /dev/null +++ b/unix/gdev/m70vms/m70cls.f @@ -0,0 +1,26 @@ + subroutine m70cls (fcb) +c +c Routine to close model 70 display +c + integer fcb(*) + include 'fcbu.inc' +c + integer*4 sys$dassgn, chan, junk + integer*2 chan2(2) + equivalence (chan, chan2) +c +c call wtexec (fcb) +c + chan2(1) = fcb(fcb_u_m70_chan) + chan2(2) = fcb(fcb_u_m70_chan+1) +c +c if (chan.ne.0) call lib$signal (%val(sys$dassgn (%val(chan)))) + if (chan.ne.0) then + junk = sys$dassgn (%val(chan)) + endif +c + fcb(fcb_u_m70_chan) = 0 + fcb(fcb_u_m70_chan+1) = 0 +c + return + end diff --git a/unix/gdev/m70vms/m70get.f b/unix/gdev/m70vms/m70get.f new file mode 100644 index 00000000..c9d0b1c2 --- /dev/null +++ b/unix/gdev/m70vms/m70get.f @@ -0,0 +1,43 @@ + subroutine m70get (fcb, error) +c +c Routine to get (allocate) the model 70 +c +c arguments: +c +c fcb function communications block +c +c error -2 => device already allocated +c -1 => m70 not acquired +c 0 => success +c 1 => timeout +c 2 => invalid device or powerfail +c >=1000 machine dependent error number +c + integer fcb(*), error +c + include 'fcbu.inc' + external ss$_normal, ss$_devalloc + integer*4 len,status, sys$alloc + integer*2 nam2(2), stat + byte nam(4) + character name*4, result*8 + equivalence (nam2, nam), (name, nam), (status, stat) +c + nam2(1) = fcb(fcb_u_m70_name) + nam2(2) = fcb(fcb_u_m70_name+1) +c + status = sys$alloc (name, len, result,) + if (status.ne.%loc(ss$_normal)) then + if (status .eq. %loc(ss$_devalloc)) then + error = -2 + else + error = 1000 + stat + endif + else + call m70opn (fcb, error) + if (error .ne. 0) return + call m70mcl (fcb, error) + endif +c + return + end diff --git a/unix/gdev/m70vms/m70io.f b/unix/gdev/m70vms/m70io.f new file mode 100644 index 00000000..cbe0418e --- /dev/null +++ b/unix/gdev/m70vms/m70io.f @@ -0,0 +1,75 @@ + subroutine m70io (fcb, data, count, read, opcd, iosb, error) +c +c Routine does io between M70 and a VAX +c +c Parameters: +c +c fcb function communications block. +c +c data input/output buffer. +c +c count number of words to read/write. +c +c read 0 -> write, 1 -> read. +c +c opcd 0 -> qio with efn = 1 and wait for completion +c 1 -> qio with efn = 2 +c 2 -> qio with efn = 3 +c +c iosb I/O status quadword +c +c error -1 => display not available +c 0 => success +c 1 => time/out +c 2 => invalid or non-responding device +c 1000 > machine dependent error code +c + integer fcb(*), data(1), count, read, opcd, error + integer*4 iosb(2) +c + include 'fcbu.inc' + external io$_writevblk, io$_readvblk, ss$_timeout, ss$_powerfail + integer*4 chan, sys$qio, sys$waitfr, func, status, l_iosb(2) + integer*2 chan2(2), stat(2) + equivalence (chan, chan2), (status, stat(1)) +c + chan2(1) = fcb(fcb_u_m70_chan) + chan2(2) = fcb(fcb_u_m70_chan+1) +c + if (read.eq.1) then + func = %loc(io$_readvblk) + else + func = %loc(io$_writevblk) + endif +c + if (opcd.eq.0) then + status = sys$qio (%val(opcd+1), %val(chan), %val(func), + 1 l_iosb,,, data, %val(2*count),,,,) + if (status) then + status = sys$waitfr (%val(1)) + if (l_iosb(1)) then + error = 0 + else + stat(1) = lib$match_cond + 1 (iosb, ss$_timeout, ss$_powerfail) + if (stat(1) .eq. 0) then + error = 1000 + iosb(1) + else + error = stat(1) + endif + endif + else + error = 1000 + stat(1) + endif + else + status = sys$qio (%val(opcd+1), %val(chan), %val(func), + 1 iosb,,, data, %val(2*count),,,,) + if (status) then + error = 0 + else + error = 1000 + stat(1) + endif + endif +c + return + end diff --git a/unix/gdev/m70vms/m70mcl.f b/unix/gdev/m70vms/m70mcl.f new file mode 100644 index 00000000..c9fb5c98 --- /dev/null +++ b/unix/gdev/m70vms/m70mcl.f @@ -0,0 +1,35 @@ + subroutine m70mcl (fcb, error) +c +c master clear model 70 +c + integer fcb(*), error +c + include 'fcbu.inc' + external io$_rewind, ss$_normal + integer*4 status, iosb(2), chan, sys$qiow + integer*2 chan2(2), iostat, stat + equivalence (chan, chan2), (iosb, iostat) + equivalence (status, stat) + external ss$_timeout, ss$_powerfail +c + chan2(1) = fcb(fcb_u_m70_chan) + chan2(2) = fcb(fcb_u_m70_chan+1) +c + status = sys$qiow (, %val(chan), io$_rewind, iosb,,,,,,,,) + if (status) then + if (iosb(1)) then + error = 0 + else + status = lib$match_cond (iosb, ss$_timeout, ss$_powerfail) + if (status .eq. 0) then + error = 1000 + iostat + else + error = status + endif + endif + else + error = 1000 + stat + endif +c + return + end diff --git a/unix/gdev/m70vms/m70opn.f b/unix/gdev/m70vms/m70opn.f new file mode 100644 index 00000000..4bb91b3a --- /dev/null +++ b/unix/gdev/m70vms/m70opn.f @@ -0,0 +1,41 @@ + subroutine m70opn (FCB, error) +C +c Routine to open model 70 +c +c Error is returned as: +c -1 = display open +c 0 = OK +c 1 = timeout +c 2 = invalid or non-responding device +c >= 1000 : machine dependent error number +c + integer fcb(*), error + include 'fcbu.inc' +C + integer*4 sys$assign, chan, status + integer*2 chan2(2), name2(2), stat(2) + byte name1(4) + character*4 m70 + equivalence (chan, chan2), (status, stat(1)) + equivalence (name1, name2), (name1, m70) +C + name2(1) = fcb(fcb_u_m70_name) + name2(2) = fcb(fcb_u_m70_name+1) + chan2(1) = fcb(fcb_u_m70_chan) + chan2(2) = fcb(fcb_u_m70_chan+1) +c + if (chan.eq.0) then + status = sys$assign ('_'//m70//':', chan,,) + if (status) then + fcb(fcb_u_m70_chan) = chan2(1) + fcb(fcb_u_m70_chan+1) = chan2(2) + error = 0 + else + error = 1000 + stat(1) + endif + else + error = -1 + endif +c + return + end diff --git a/unix/gdev/m70vms/m70rel.f b/unix/gdev/m70vms/m70rel.f new file mode 100644 index 00000000..7b686d10 --- /dev/null +++ b/unix/gdev/m70vms/m70rel.f @@ -0,0 +1,19 @@ + subroutine m70rel (fcb) +c +c routine to release(DEALLOCATE) the model 70 +c + integer fcb(*) +c + include 'fcbu.inc' + integer*2 dev2(2) + byte dev(4) + character*4 m70 + equivalence (dev2,dev), (m70,dev) +c + call m70cls (fcb) + dev2(1) = fcb(fcb_u_m70_name) + dev2(2) = fcb(fcb_u_m70_name+1) + call sys$dalloc ('_'//m70//':',) +c + return + end diff --git a/unix/gdev/m70vms/m70wt.f b/unix/gdev/m70vms/m70wt.f new file mode 100644 index 00000000..715a1c68 --- /dev/null +++ b/unix/gdev/m70vms/m70wt.f @@ -0,0 +1,44 @@ + subroutine m70wt (fcb, bfnum, bfcnt, iosb, error) +c +c routine to wait for completion of buffer write on pdp-11's +c +c fcb function communication block. +c bfnum used to determine event flag to wait for +c bfcnt number of words in buffer. should be -1 indicating +c i/o pending. reset to zero when i/o completed. +c iosb i/o status block +c error 0 success, -1 not acquired, 1 timeout, +c 2 invalid device, 1000+n system dep. error +c + integer fcb(*) + integer bfnum, bfcnt, error + integer*4 iosb(2), status + integer*2 stat(2) +c + integer*4 sys$waitfr + equivalence (status, stat(1)) + external ss$_timeout, ss$_powerfail +c +c is this wait required? +c + error = 0 + if (bfcnt .ge. 0) return +c + status = sys$waitfr (%val(bfnum+1)) + if (status) then + bfcnt = 0 + if (.not. iosb(1)) then + stat(1) = lib$match_cond + 1 (iosb, ss$_timeout, ss$_powerfail) + if (stat(1) .eq. 0) then + error = 1000 + iosb(1) + else + error = stat(1) + endif + endif + else + error = 1000 + stat(1) + endif +c + return + end diff --git a/unix/gdev/m70vms/m70wti.f b/unix/gdev/m70vms/m70wti.f new file mode 100644 index 00000000..0aabd1fd --- /dev/null +++ b/unix/gdev/m70vms/m70wti.f @@ -0,0 +1,46 @@ + subroutine m70wti (fcb, func, time, button, x, y) +c +c This routine waits for the appropriate interupt from the +c Unibus M70 interface card, then returns button and cursor +c information. +c +c +c parameter descriptions: +c +c fcb is a system info. array. +c +c func is interpreted: +c 0 ==> wait for button push. +c 1 ==> wait for cursor move. +c 2 ==> wait for button push or cursor move. +c + integer fcb(*), func, time, button, x, y +c + include 'fcbu.inc' + external io$_rewindoff + integer*4 sys$qiow, mask, chan, iosb(2) + integer*2 chan2(2) + equivalence (chan, chan2) +c + chan2(1) = fcb(fcb_u_m70_chan) ! get M70 channel + chan2(2) = fcb(fcb_u_m70_chan+1) +c + if (func.eq.0) then + mask = '0400'x ! wait for button + elseif (func.eq.1) then + mask = '0800'x ! wait for trackball + elseif (func.eq.2) then + mask = '0C00'x ! wait for button or trackball + else + mask = '0C00'x + endif +c + status = sys$qiow (, %val(chan), io$_rewindoff, + 1 iosb,,,%val(mask),,,,,) +c +c Get button word and X-Y position of cursor +c + call rbutn (fcb, button, x, y) +c + return + end diff --git a/unix/gdev/m70vms/mkpkg b/unix/gdev/m70vms/mkpkg new file mode 100644 index 00000000..976cc1e4 --- /dev/null +++ b/unix/gdev/m70vms/mkpkg @@ -0,0 +1,29 @@ +# Makelib for the VMS version of the IIS driver. + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + @(i2) + zclm70.x m70.h <mach.h> <knet.h> + zopm70.x m70.h <mach.h> <knet.h> + zrdm70.x m70.h <mach.h> <knet.h> + zstm70.x m70.h <mach.h> <fio.h> + zwrm70.x m70.h <mach.h> <knet.h> + zwtm70.x m70.h <mach.h> <knet.h> + ; + +i2: # Compile the VMS/Fortran IIS i/o routines with the VMS /NOI4 option. + $set XFLAGS = "-c -O -i2" + + m70cls.f fcbu.inc + m70get.f fcbu.inc + m70io.f fcbu.inc + m70mcl.f fcbu.inc + m70opn.f fcbu.inc + m70rel.f fcbu.inc + m70wt.f + m70wti.f fcbu.inc + ; diff --git a/unix/gdev/m70vms/zclm70.x b/unix/gdev/m70vms/zclm70.x new file mode 100644 index 00000000..a7ebb8f7 --- /dev/null +++ b/unix/gdev/m70vms/zclm70.x @@ -0,0 +1,24 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <knet.h> +include "m70.h" + +# ZCLM70 -- Close and deallocate the IIS. + +procedure zclm70 (chan, status) + +int chan # FCB pointer for device +int status +pointer fcb + +begin + fcb = chan + if (FCB_KCHAN(fcb) == NULL) { + call zwtm70 (chan, status) + call m70rel (Mems[fcb]) + } else + call zclsbf (FCB_KCHAN(fcb), status) + + call mfree (fcb, TY_SHORT) +end diff --git a/unix/gdev/m70vms/zopm70.x b/unix/gdev/m70vms/zopm70.x new file mode 100644 index 00000000..f338dbe7 --- /dev/null +++ b/unix/gdev/m70vms/zopm70.x @@ -0,0 +1,59 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <knet.h> +include "m70.h" + +# ZOPM70 -- Open the IIS for binary file i/o. The device will be automatically +# allocated if necessary. + +procedure zopm70 (device, mode, chan) + +char device[ARB] # packed VMS device name +int mode # access mode +int chan # receives device channel + +pointer fcb +int kchan +char upkdev[SZ_FNAME] +int ki_connect() + +short ier +% character m70*4 +% integer*2 namw(2) +% equivalence (m70, namw) + +begin + call calloc (fcb, LEN_FCB, TY_SHORT) + + # Use the binary file driver if the device resides on a remote node. + # This precludes remote access to a VMS hosted IIS at present. + + if (ki_connect (device) != NULL) { + call zopnbf (device, mode, kchan) + if (kchan != ERR) + FCB_KCHAN(fcb) = kchan + } else { + # Load string descriptor for device name into FCB. + call strupk (device, upkdev, SZ_FNAME) +% call f77pak (upkdev, m70, 4) + + FCB_U_NAME(fcb,1) = namw[1] + FCB_U_NAME(fcb,2) = namw[2] + FCB_KCHAN(fcb) = NULL + FCB_STATUS(fcb) = IIS_INACTIVE + FCB_NBYTES(fcb) = 0 + + # Allocate and open the device. + call m70get (Mems[fcb], ier) + kchan = ier + if (kchan != 0) + kchan = ERR + } + + if (kchan < 0) { + call mfree (fcb, TY_SHORT) + chan = ERR + } else + chan = fcb +end diff --git a/unix/gdev/m70vms/zrdm70.x b/unix/gdev/m70vms/zrdm70.x new file mode 100644 index 00000000..2bf726ab --- /dev/null +++ b/unix/gdev/m70vms/zrdm70.x @@ -0,0 +1,36 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <knet.h> +include "m70.h" + +# ZRDM70 -- Initiate an asynchronous read from the IIS. + +procedure zrdm70 (chan, buf, nbytes, offset) + +int chan # FCB pointer for device +char buf[ARB] # output buffer +int nbytes # number of bytes to read +long offset # not used for this device + +pointer fcb +short rwflag, opcd, nwords, ier +data rwflag /IIS_READ/, opcd /EFN/ + +begin + fcb = chan + if (FCB_KCHAN(fcb) == NULL) { + nwords = nbytes / (SZ_SHORT * SZB_CHAR) + call m70io (Mems[fcb], buf, nwords, rwflag, opcd, FCB_IOSB(fcb,1), + ier) + + FCB_NBYTES(fcb) = nbytes + FCB_EFN(fcb) = opcd + + if (ier != 0) + FCB_STATUS(fcb) = ERR + else + FCB_STATUS(fcb) = IIS_READ + } else + call zardbf (FCB_KCHAN(fcb), buf, nbytes, offset) +end diff --git a/unix/gdev/m70vms/zstm70.x b/unix/gdev/m70vms/zstm70.x new file mode 100644 index 00000000..2b790dfa --- /dev/null +++ b/unix/gdev/m70vms/zstm70.x @@ -0,0 +1,28 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <fio.h> +include "m70.h" + +# ZSTM70 -- Return device status for the IIS. + +procedure zstm70 (chan, what, lvalue) + +int chan # FCB pointer for device +int what # status parameter +long lvalue + +begin + switch (what) { + case FSTT_FILSIZE: + lvalue = IIS_FILSIZE + case FSTT_BLKSIZE: + lvalue = IIS_BLKSIZE + case FSTT_OPTBUFSIZE: + lvalue = IIS_OPTBUFSIZE + case FSTT_MAXBUFSIZE: + lvalue = IIS_MAXBUFSIZE + default: + lvalue = ERR + } +end diff --git a/unix/gdev/m70vms/zwrm70.x b/unix/gdev/m70vms/zwrm70.x new file mode 100644 index 00000000..7cc1ef8a --- /dev/null +++ b/unix/gdev/m70vms/zwrm70.x @@ -0,0 +1,36 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <knet.h> +include "m70.h" + +# ZWRM70 -- Initiate an asynchronous write to the IIS. + +procedure zwrm70 (chan, buf, nbytes, offset) + +int chan # FCB pointer for device +char buf[ARB] # input buffer +int nbytes # number of bytes to write +long offset # not used for this device + +pointer fcb +short rwflag, opcd, nwords, ier +data rwflag /IIS_WRITE/, opcd /EFN/ + +begin + fcb = chan + if (FCB_KCHAN(fcb) == NULL) { + nwords = nbytes / (SZ_SHORT * SZB_CHAR) + call m70io (Mems[fcb], buf, nwords, rwflag, opcd, FCB_IOSB(fcb,1), + ier) + + FCB_NBYTES(fcb) = nbytes + FCB_EFN(fcb) = opcd + + if (ier != 0) + FCB_STATUS(fcb) = ERR + else + FCB_STATUS(fcb) = IIS_WRITE + } else + call zawrbf (FCB_KCHAN(fcb), buf, nbytes, offset) +end diff --git a/unix/gdev/m70vms/zwtm70.x b/unix/gdev/m70vms/zwtm70.x new file mode 100644 index 00000000..69ab39da --- /dev/null +++ b/unix/gdev/m70vms/zwtm70.x @@ -0,0 +1,44 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <knet.h> +include "m70.h" + +# ZWTM70 -- Wait for i/o completion and return the number of bytes read or +# written or ERR. Repetitive calls return the same value. + +procedure zwtm70 (chan, status) + +int chan # FCB pointer for device +int status # nbytes transferred or ERR + +pointer fcb +short bfnum, bufcnt, ier + +begin + fcb = chan + + if (FCB_KCHAN(fcb) == NULL) { + switch (FCB_STATUS(fcb)) { + case ERR: + status = ERR + case IIS_INACTIVE: + status = FCB_NBYTES(fcb) + + default: + bfcnt = -1 # m70wt is a nop if we don't do this + bfnum = FCB_EFN(fcb) + + call m70wt (Mems[fcb], bfnum, bfcnt, FCB_IOSB(fcb,1), ier) + + if (ier != 0) + status = ERR + else + status = FCB_NBYTES(fcb) + + FCB_STATUS(fcb) = IIS_INACTIVE + } + + } else + call zawtbf (FCB_KCHAN(fcb), status) +end diff --git a/unix/gdev/mkpkg b/unix/gdev/mkpkg new file mode 100644 index 00000000..800c7e9c --- /dev/null +++ b/unix/gdev/mkpkg @@ -0,0 +1,12 @@ +# Make the ZFIOGD (binary graphics) device driver and install it in libsys. + +$checkout libsys.a lib$ +$update libsys.a +$checkin libsys.a lib$ +$exit + +libsys.a: + zfiogd.x <fio.h> <mach.h> + @iism70 + @iism75 + ; diff --git a/unix/gdev/mkpkg.sh b/unix/gdev/mkpkg.sh new file mode 100644 index 00000000..3984d71f --- /dev/null +++ b/unix/gdev/mkpkg.sh @@ -0,0 +1,3 @@ +# GDEV -- Host dependent graphics device drivers. + +(cd sgidev; sh -x mkpkg.sh) diff --git a/unix/gdev/sgidev/README b/unix/gdev/sgidev/README new file mode 100644 index 00000000..363b490f --- /dev/null +++ b/unix/gdev/sgidev/README @@ -0,0 +1,24 @@ +SGIDEV -- This directory contains the UNIX dependent sources for the metacode +or bitmap translation programs for all devices supported by the SGI graphics +kernel. See gio$sgikern or `help sgikern' for further information on SGI. + +To add a new SGI device: + + [1] Add source file for translator to this directory. + [2] Add references to mkpkg.csh and mkpkg. + [3] Run `mkpkg update' in this directory to install new translator. + + [4] Add entry to graphcap file, including DD command string + containing host command to dispose of the output. + + [5] Test new device interface. + +Alternatively, you might wish to install the source for the translator in +local somewhere, to avoid a merge operation when a new version of the VMS +host system interface is installed. + +Note that some example graphcap entries for SGI devices might require non- +standard tasks residing outside of IRAF, for example the `impress300' +command to ship Impress output from a UNIX node to a VMS node running +Eunice in order to execute the VMS IMPRINT command. These are considered +so unusual that support is not included in the standard system. diff --git a/unix/gdev/sgidev/README.gif b/unix/gdev/sgidev/README.gif new file mode 100644 index 00000000..85833d3f --- /dev/null +++ b/unix/gdev/sgidev/README.gif @@ -0,0 +1,438 @@ + +Announcement for adass.iraf.system: + + An SGI translator which converts IRAF graphics directly to GIF +images is now available from our anonymous ftp archive as + + ftp://iraf.noao.edu/pub/sgi2gif.c + ftp://iraf.noao.edu/pub/sgi2gif.readme + +The associated readme file describes how to install the translator and +configure a variety of graphcap entries for it. + SGI translators are used to convert IRAF graphics to some other +format, usually Postscript, for disposal to a printer or some other +hardcopy device. The SGI2GIF translator now allows users to generate +GIF images (suitable for web page presentation) directly from IRAF using +the familiar ":.snap" command or non-interactively. See the readme file +for a full discussion of the capabilities and configuration options, or +contact site support (iraf@noao.edu) with questions or problems. + +-------------------------------------------------------------------------------- + +README: + +1. Introduction +--------------- + + IRAF hardcopy graphics are generated by converting the graphics +metacode through the SGI (Simple Graphics Interface) kernel which +translates the numerous graphics commands to a minimal set of move/draw +instructions or a bitmap raster of the plot. In the case of +hardcopy/output graphics (i.e. the SGI kernel), the dev$graphcap file +defines parameters for this conversion which include the plot size, SGI +kernel options, and most especially a "device dispose" (DD) string which +specifies the SGI translator to be used and what to do with the resulting +translator output. The SGI kernel is not a full graphics kernel so +information such as line color and fill areas are lost, below we will +discuss how to retain this when producing a GIF images using other +translators and graphcap file trickery. + + For most printer devices the "sgi2uapl" Postscript translator is +used to convert the SGI kernel metacode from a series of move/draw +instructions to equivalent postscript commands, other translators are +available to convert to other printer languages. The SGI kernel can also +be used, with the proper graphcap entries, to generate a bitmap raster of +the plot which can be easily converted to various image formats. The SGI2GIF +translator takes advantage of this latter feature to produce GIF images +directly from the IRAF graphics metacode. + + The translator has options for specifying the image size, +foreground and background colors, GIF transparency, and can be used to +convert multiple input bitmap files or a single file containing multiple +graphics frames. It allows users to easily generate images suitable for +presentation on the web, either manually or automatically. + + +2. Installation +--------------- + + The SGI translator is distributed in source form and to be used +must be compiled and installed in the system hbin$ directory. To install +the new SGI translator follow these steps while logged in through the iraf +user account: + + [1] Download the translator from the IRAF anonymous FTP archive or + one of it's mirror sites using: + + % ftp iraf.noao.edu (140.252.1.1) + login: anonymous + password: [your email address] + ftp> cd /pub + ftp> mget sgi2gif.c + ftp> quit + + [2] Compile the source using + + % cc -o sgi2gif.e sgi2gif.c # compile the source + % mv sgi2gif.e $hbin # move to the $hbin + + "$hbin" is defined in the iraf environment to be something like + $iraf/unix/bin.<arch>, where <arch> would be 'ssol' for Solaris, + 'sparc' for SunOS and so on. + + [3] Optionally place the source in the directory $iraf/unix/gdev/sgidev. + + [4] Edit the dev$graphcap file and add the following default entries + for the device near the top of the file: + + g-gif|UNIX generic interface to multi-frame GIF file generator:\ + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ + rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: + + sgi_image_format|Generic raster file format specification:\ + :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + :xr#640:yr#480 :PX#640:PY#480 :XW#640:YW#480:\ + :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + + The 'g-gif' entry takes one or more graphics file input and converts + each input frame to a redirected file on output called 'sgigifXXX.gif' + where the 'XXX' is frame number. See below for details one + configuring other graphcap entries. + + +2. Translator Options +--------------------- + The SGI2GIF translator allows the following options: + + -w N Set the width of input bitmap and output image. The + argument must be derived from the graphcap value since + that is what the SGI kernel will use when generating the + bitmap, e.g. "-w $(PX)" instead of "-w 640". + + -h N Set the height of input bitmap and output image. The + argument must be derived from the graphcap value since + that is what the SGI kernel will use when generating the + bitmap, e.g. "-h $(PY)" instead of "-h 640". + + -i Invert the bitmap before conversion. By default the + graphics are drawn using the foreground color, this + option inverts the bitmap before conversion meaning the + graphics are drawn using the background color. + + -t Set background color as transparent. If enabled the + translator will produce a GIF89 format image with the + background color set as "transparent". When this image + is used with an HTML document the background color is + the HTML page color. + + -root Set the root rame for output file. If defined this + root name will be combined with the frame number and + a ".gif" extension to form the output name. If not + defined and only one input image is present the default + action is to send the output to STDOUT. + + -fg R G B Specify foreground color (default 'black'). Set the + foreground color as a triplet of RGB values in the + range 0-255. The -fg flag must have three arguments. + + -bg R G B Specify background color (default 'white'). Set the + foreground color as a triplet of RGB values in the + range 0-255. The -bg flag must have three arguments. + + +3. Configuring Alternate Graphcap Entries +----------------------------------------- + + Most of the work in a graphcap entry is done by the 'device +dispose' (i.e. "DD") string. This string is composed of three comma +delimited parts: a node/device name (which is normally ignored), a +temporary filename, and a host dispose command. To configure a new entry +it is only this last field that normally needs to be modified, perhaps in +conjunction with another graphcap parameter. As an example let's look at +the DD string used in the example graphcap above: + + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; rm $F.[1-8]; }&: + +where 'ugif' is the unused node/device name, 'tmp$sgk' is the temporary +filename, and the remainder is a host dispose command. The 'sgidispatch' +command is an iraf binary that launches the specified translator +('sgi2gif' here) with any required arguments. Note that everything within +the "!{...}&" curly braces is executed (as a background Bourne shell +command) so any string of valid unix command separate by a semicolon will +be executed. In this case the sgidispatch command launches the sgi2gif +translator with all of it's arguments, it then deletes the input metacode +file symbolized by the "$F". + You may notice that some arguments are specified as e.g. "-w +$(PX)". When the DD string is executed any macro values beginning with a +'$' such as '$(PX)' are replaced with values from the rest of the graphcap +entry. In this case '$(PX)' is replaced by the value contained in the +graphcap :PX (physical X size) field, the "$F.[1-8]" is expanded to +include the unique root filename along with any extension 1 thru 8 which may +be generated because of multiple plots in the input. In +most cases all you may need to change in the DD string itself is the +output file, or e.g. whether it gets piped to some other command. + + +3.1 Changing Image Size +----------------------- + + Changing the image size is simply a matter of changing the graphcap +parameters + + :xr#640:yr#480: sets X,Y device resolution + :PX#640:PY#480: sets X,Y physical size of bitmap + :XW#640:YW#480: sets X,Y width of plotting window + +These are defined in the 'sgi_image_format' entry given above. Graphics +are drawn using Normalized Device Coordinates ('NDC', values in the range +0.0 to 1.0) and will be scaled appropriately for any specified output +dimensions allowing users to configure graphcap entries for images which are +larger/smaller than the default, or have square or elongated aspect ratios. + +3.2 Preserving Color Information +-------------------------------- + + Colors such as those used for the axis labels and frame, and colors +used in the plot itself for different line/marker types cannot be preserved +by the SGI kernel directly. To do this you must use a full graphics kernel +such as the PSIKERN postscript kernel found in STSDAS. The V2.11 +distribution contains graphcap entries suitable for this kernel but assumes +you have STSDAS available. See the online help for more information about +this kernel. + Using the '-fg' and '-bg' flags will allow you to specify foreground +and background colors to be used for the plot as a whole. Note that these +flags require three arguments to specify the RGB color components. The '-t' +flag may be used to mark the background color as 'transparent' so only the +foreground color is shown when the image is used in an HTML document. + +3.3 Generating Other Image Formats +---------------------------------- + + GIF may be used as an intermediate format which can be converted to +something else as part of the graphcap DD string. For example, to use the +ImageMagick CONVERT task to produce a JPEG image the graphcap DD string +could be written as + + g-jpeg|UNIX generic interface to JPEG file generator:\ + :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + -bg 0 0 0 -fg 255 255 255 -root sgi $F | \ + convert sgi$$.gif sgi$$.jpg ; rm $F; }&: \ + :MF#1:NF:tc=sgi_image_format: + +The DD string first uses the SGI2GIF translator to produce a 'sgi.gif' +image, then calls the convert task (which is assumed to be in the user's +path) to convert this to JPEG as a separate step. The :MF field is +set to one meaning each frame will generate a new file. The '$$' used in +the filenames (e.g. 'sgi$$.gif') is the process id created for the shell +running the DD command meaning multiple filenames of the form 'sgi12345.gif' +will be created, each with a unique id number so the images aren't over- +written. In the past this form of DD string could be used with the standard +sgi2uapl postscript translator and a host task such as 'gs' to convert +postscript to some other format. + +4. Interfacing to Web CGI Scripts +---------------------------------- + + It would be impossible to give complete details about interfacing +IRAF programs to CGI scripts due to the variety of languages and tasks +that may be used. To begin lets look at how to execute a task from the +host level, which is essentially what we'll be doing from within a CGI +script. + In principle this can be done in one of two ways: Either invoke +the executable directly with the correct command line arguments, or run +the CL with the input redirected to execute the task. In the first case +you must know in which executable the task resides, core IRAF system tasks +(e.g. things in the PLOT and IMAGES packages) have their executables in +the main $iraf/bin.<arch> directory, NOAO package tasks have the +executables in the $iraf/noao/bin.<arch> directory. There is usually a +separate executable for each package and you can probably figure out which +one goes for each package otherwise just look at the package cl file to +find out, for example the PLOT package defines the task in the +$iraf/pkg/plot/plot.cl file, if you look in their you'll see that is +defines the tasks as (part of the file reads) + +task contour, + surface, hafton, velvect = "plot$x_ncar.e" + +which means that the CONTOUR, SURFACE, etc tasks are in the "x_ncar.e" +executable. + Once you find the correct binary, you need to create a file with +the task parameters: usually it's easiest to set the parameters and then +dump the parameter file with 'dpar', e.g. + + cl> dpar listpix > listpix.par + +It's likely that CGI scripts will need to set certain parameters itself so +thought must be given to how to edit this list of default parameters with +values given in the CGI script. + +To run the task you would then do something like: + + % $iraf/bin.sparc/x_images.e listpix @listpix.par + +In this case you must be careful that ALL of the task parameters are +defined, this is done by 'dpar' but empty string parameters will always +be prompted for. On a host command line simply respond to the parameter +prompts by hitting the return key, from with a CGI script these must +be supplied automatically in some way (e.g. via redirection). + In the second case you create a command file and input it to the +cl, for example + + % cl < cl.input >& some_logfile + +where cl.input contains CL commands such as + + wfits.scale=no # set a parameter wfits image*.imh + mta # call a task + logout # logout of the CL + +You must be careful about making sure you are in the right directory and +that parameters are given explicitly if they're like to change, but with +this approach you can call any iraf task. + +4.1 Graphics Tasks +------------------- + + Regardless of the method chosen, you need to be careful about +redirecting any required input or text/graphics output. Graphics output +can be redirected either by setting the "device" parameter to e.g. 'vdm' +to create a file called 'vdm' in the uparm directory, or using the '>G' CL +syntax as in + + cl> surface dev$pix >G surf.plot # redirect metacode to a file + cl> surface dev$pix dev="vdm" # save metacode to uparm dir + cl> surface dev$pix dev="stdplot" # to print it out + cl> gflush # flush graphics buffer + +Which of these approaches works best for depends depends on the tasks you +need and the method of execution chosen above. Note that the ">G" syntax +will only work for tasks executed within the CL, setting a device +parameter to something that creates a file will work with either method. + For non-interactive tasks like SURFACE or CONTOUR this file is +created automatically, interactive tasks however may need to create +metacode files explicitly or else the CGI script must take care to extract +only those plots of interest from the metacode file (e.g. with a separate +call to GKIEXTRACT). + Interactive tasks must also satisfy requests for cursor commands, +including the usual 'q' keystroke needed to exit the task. Since cursor +commands are in reality queries to the CL any binary run as a host task +will generate a cursor prompt on the standard output the same as for any +other parameter query. The response to a cursor query however is usually +of the form + x y wcs key strval + +where 'x' and 'y' are the cursor position, 'wcs' is the WCS of those coords +(usually not important), 'key' is the keystroke you would normally enter, +and if 'key' is a color the 'strval' is the remainder of that color command. +See section 3.7 of the "help cursors" help page for more details on alternate +graphics input. Note however, that your CGI script must know in advance the +order in which the prompts will occur to be able to satisfy them correctly, +e.g. any parameter prompts generated by empty string values should be met +with a newline, and cursor prompts with something as above. Since the tasks +will be very narrowly defined as to how they are run this usually isn't +difficult to set up. + +4.2 Example +----------- + + As an example let create a CGI script to execute the PCOL task +from a web interface. All that we need to do this is the PLOT package +binary to execute the task, a 'graphcap' file, and the SGIKERN binary in +order to convert our graphics metacode to a GIF format using the specified +graphcap entries and the newly installed SGI2GIF translator. In the +following we detail the steps involved in creating this script on a system +with IRAF installed, your application may vary somewhat. We use a +C-shell script here but the same principles apply to all scripting +languages, users should contact site support with questions. + +----------------------------------------------------------------------------- + +#!/bin/csh -f +# +# Sample CGI script demonstrating the using the PCOL graphics task to +# produce an 'sgigif.gif' file of the resulting plot which can be shown +# as an image of the output web page. The script does not show how to +# parse arguments or format the resulting HTML page. All that is required +# for IRAF execution is the binary for the task to be run, the SGIKERN +# binary, and a graphcap file to produce the GIF (given below). The CGI +# script can define the task parameters itself or use a predefined 'dpar' +# dump to set defaults as we do below. + +# The REMOTE_ADDR variable is defined in the environment of the CGI +# script automatically, we specify it here for demonstration purposes. +set REMOTE_ADDR = 140.252.30.95 + +# This would be defined as the graphcap file installed for the local web +# server. + +# The only graphcap entries needed to output graphics to a GIF file using +# the SGI translator is as follows: +# +# vdm|stdvdm|Virtual Device Metafile:\ +# :co#80:li#35:xr#1024:yr#1024:zr#256:ar#.77:ch#.0294:cw#.0125:\ +# :X1#0:X2#1023:Y1#0:Y2#1023: +# +# g-gif|UNIX generic interface to multi-frame GIF file generator:\ +# :DD=ugif,tmp$sgk,!{ /<path>/sgi2gif.e -w $(PX) -h $(PY) \ +# -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ +# rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: +# +# sgi_image_format|Generic raster file format specification:\ +# :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ +# :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ +# :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: +# +# Note that the path to the sgigif.e binary is specified explicitly, this +# must be replaced by the path to the actual binary. +# +# On the web server this file would normally be installed in the cgi-bin +# or some other directory, the cgi script itself needs to define this location +# with the following variable: + +set graphcap = /tmp/graphcap + +# A uparm directory needs to be defined for saving the VDM file. This is +# defined based on the REMOTE_ADDR so we can have multiple connections +# running at the same time without concurrency problems. + +set uparm = /tmp/uparm-$REMOTE_ADDR/ + +# Create the uparm directory we'll be using... +mkdir $uparm + +# Execute the graphics task desired. In this example we're running the PCOL +# task and assume we've saved the parameters to a 'pcol.dpar' file in the +# current directory. In practice the parameters can be specified using a +# dpar file in the cgi-bin dir or explicitly on the command line. To execute +# the task we call the binary directly, direct output to /dev/null and +# redirect input blank lines to respond to params that take no value. We +# must set the uparm and graphcap values set above to handle the graphics. +# The CGI script can insert values such as 'image' based on arguments, the +# defaults come from a predefined dpar file. + +/iraf/iraf/bin.ssun/x_plot.e >>& /dev/null << EOF +set uparm = $uparm +set graphcap = $graphcap +pcol @pcol.dpar pcol.device="vdm" + +EOF + +# At this point the GKI metacode is saved in the uparm$vdm file, where +# 'uparm' is set above and is created by the custom graphcap file we're +# using. To convert GKI metacode to the final GIF file we call the SGIKERN +# directly and specify the device as 'g-gif' which produces an 'sgigif.gif' +# file in the current directory. Graphcap entries can be created to name +# the file anything desired, that filename is then used as a URL for the +# web page returned. + +/iraf/iraf/bin.ssun/x_sgikern.e >>& /dev/null << EOF +set uparm = $uparm +set graphcap = $graphcap +sgikern input=uparm\$vdm device=g-gif generic=yes +EOF + +# Finally, clean up the temp files we've created. +/bin/rm -rf $uparm + diff --git a/unix/gdev/sgidev/mkpkg b/unix/gdev/sgidev/mkpkg new file mode 100644 index 00000000..e9dac3df --- /dev/null +++ b/unix/gdev/sgidev/mkpkg @@ -0,0 +1,9 @@ +# Make the SGI device host level translation programs [MACHDEP]. + +$call update +$exit + +update: + ! sh -x mkpkg.sh + ! mv $hlib/sgi*.e $hbin + ; diff --git a/unix/gdev/sgidev/mkpkg.sh b/unix/gdev/sgidev/mkpkg.sh new file mode 100644 index 00000000..85d6c83a --- /dev/null +++ b/unix/gdev/sgidev/mkpkg.sh @@ -0,0 +1,60 @@ +# Make the SGI translators and install them in hlib. + +$CC -c $HSI_CF sgiUtil.c + +$CC -c $HSI_CF sgidispatch.c +$CC $HSI_LF sgidispatch.o ../../hlib/libos.a $HSI_LIBS -o sgidispatch.e +mv -f sgidispatch.e ../../hlib +rm sgidispatch.o + +$CC -c $HSI_CF sgi2uimp.c +$CC $HSI_LF sgi2uimp.o sgiUtil.o $HSI_LIBS -o sgi2uimp.e +mv -f sgi2uimp.e ../../hlib +rm sgi2uimp.o + +$CC -c $HSI_CF sgi2uapl.c +$CC $HSI_LF sgi2uapl.o sgiUtil.o $HSI_LIBS -o sgi2uapl.e +mv -f sgi2uapl.e ../../hlib +rm sgi2uapl.o + +$CC -c $HSI_CF sgi2uqms.c +$CC $HSI_LF sgi2uqms.o sgiUtil.o $HSI_LIBS -o sgi2uqms.e +mv -f sgi2uqms.e ../../hlib +rm sgi2uqms.o + +$CC -c $HSI_CF sgi2uptx.c +$CC $HSI_LF sgi2uptx.o sgiUtil.o $HSI_LIBS -o sgi2uptx.e +mv -f sgi2uptx.e ../../hlib +rm sgi2uptx.o + +$CC -c $HSI_CF sgi2uhplj.c +$CC $HSI_LF sgi2uhplj.o sgiUtil.o $HSI_LIBS -o sgi2uhplj.e +mv -f sgi2uhplj.e ../../hlib +rm sgi2uhplj.o + +$CC -c $HSI_CF sgi2uhpgl.c +$CC $HSI_LF sgi2uhpgl.o sgiUtil.o $HSI_LIBS -o sgi2uhpgl.e +mv -f sgi2uhpgl.e ../../hlib +rm sgi2uhpgl.o + +$CC -c $HSI_CF sgi2ueps.c +$CC $HSI_LF sgi2ueps.o sgiUtil.o $HSI_LIBS -o sgi2ueps.e +mv -f sgi2ueps.e ../../hlib +rm sgi2ueps.o + +$CC -c $HSI_CF sgi2gif.c +$CC $HSI_LF sgi2gif.o sgiUtil.o $HSI_LIBS -o sgi2gif.e +mv -f sgi2gif.e ../../hlib +rm sgi2gif.o + +$CC -c $HSI_CF sgi2xbm.c +$CC $HSI_LF sgi2xbm.o sgiUtil.o $HSI_LIBS -o sgi2xbm.e +mv -f sgi2xbm.e ../../hlib +rm sgi2xbm.o + +$CC -c $HSI_CF sgi2svg.c +$CC $HSI_LF sgi2svg.o sgiUtil.o $HSI_LIBS -o sgi2svg.e +mv -f sgi2svg.e ../../hlib +rm sgi2svg.o + +rm sgiUtil.o diff --git a/unix/gdev/sgidev/sgi2gif.c b/unix/gdev/sgidev/sgi2gif.c new file mode 100644 index 00000000..e46d4d28 --- /dev/null +++ b/unix/gdev/sgidev/sgi2gif.c @@ -0,0 +1,731 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include "sgiUtil.h" + + +/* + * SGI2GIF.C -- Read an IRAF SGI bitmap file on standard input and convert + * to a GIF format image on standard outout. + * + * Usage: + * sgi2gif.e [-params] [ [sgi_bitmap] [sgi_bitmap] ... ] + * + * -w N width of input bitmap and output image + * -h N height of input bitmap and output image + * -i invert the bitmap values before conversion + * -t set background color as transparent + * -root set the root rame for output file (default stdout) + * -fg R G B specify foreground color + * -bg R G B specify background color + * + * The input file name and the switches may occur in any order. The + * foreground/background flags require three arguments giving the values + * of the RGB components of the color as a decimal number in the range 0-255. + * Enabling the transparency flag will cause a GIF 89 image to be written, + * otherwise the default will be a GIF 87 format image. The transparent + * color will always be the backgrund color. The bitmap may be inverted + * here using the -i flag. + * + * Sample graphcaps for this translator might look like: + * + * g-gif|UNIX generic interface to multi-frame GIF file generator:\ + * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2gif -w $(PX) -h $(PY) \ + * -bg 0 0 0 -fg 255 255 255 -root sgigif $F.[1-8] ; \ + * rm $F.[1-8]; }&:MF#8:NF:tc=sgi_image_format: + * + * sgi_image_format|Generic raster file format specification:\ + * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ + * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + * + * The 'g-gif' entry takes one or more graphics file input and converts + * each input frame to a redirected file on output called 'sgigifXXX.gif' + * where the 'XXX' is frame number. + * + * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and + * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i + * or -t flags must be specified in the graphcap DD string along with the + * -fg/bg flags and their arguments. + */ + + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define DEF_WIDTH 640 /* default image width */ +#define DEF_HEIGHT 480 /* default image height */ +#define DEF_BG 255 /* default background RGB */ +#define DEF_FG 0 /* default foreground RGB */ +#define MAX_INFILES 16 /* max number of input bitmaps */ +#define SZ_FNAME 64 /* size of a filename */ + +typedef int code_int; +typedef long int count_int; +typedef unsigned char byte; + +static byte *pixels; + +static int px = DEF_WIDTH; +static int py = DEF_HEIGHT; +static int nrows = DEF_HEIGHT; +static int ncols = DEF_WIDTH; +static int transparent = 0; +static int invert = 0; +static int red[] = { DEF_BG, DEF_FG } ; +static int green[] = { DEF_BG, DEF_FG } ; +static int blue[] = { DEF_BG, DEF_FG } ; +static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static char *s_root = "sgigif_"; + +static int GIFNextPixel(); +static void BumpPixel(), GIFEncode(), Putword(), compress(); +static void output(), cl_block(), cl_hash(), char_init(); +static void char_out(), flush_char(), unpack1to8(); + + + +/* MAIN -- Main entry point for the task. + */ +int +main (int argc, char *argv[]) +{ + FILE *fdi, *fdo; + char fname[SZ_FNAME]; + char *root = s_root; + byte *buffer, *ip; + int i, index, numin=0, len_buf; + int interlace, background, bpp; + + + /* Process the command line. + */ + for (i=1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp (argv[i], "-w") == 0) { + ncols = px = atoi (argv[++i]); + } else if (strcmp (argv[i], "-h") == 0) { + nrows = py = atoi (argv[++i]); + } else if (strcmp (argv[i], "-i") == 0) { + invert++; + } else if (strcmp (argv[i], "-root") == 0) { + root = argv[++i]; + } else if (strcmp (argv[i], "-t") == 0) { + transparent++; + } else if (strcmp (argv[i], "-bg") == 0) { + if (isdigit(argv[++i][0])) + red[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + green[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + blue[0] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + } else if (strcmp (argv[i], "-fg") == 0) { + if (isdigit(argv[++i][0])) + red[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + green[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + if (isdigit(argv[++i][0])) + blue[1] = atoi (argv[i]); + else + fprintf (stderr, + "sgi2gif: invalid -bg arg '%s'\n", argv[i]); + } else { + fprintf (stderr, "sgi2gif: unknown switch '%s'\n", argv[i]); + } + } else { + /* input sgi-bitmap file specification */ + if (numin < MAX_INFILES) + infile[numin++] = argv[i]; + } + } + + /* Allocate space for the images. */ + len_buf = px / NBITS_CHAR; + buffer = (byte *) malloc (len_buf); + ip = pixels = (byte *) malloc (px * (py + 1)); + + /* Loop over the input bitmaps, writing the converted output to + * either stdout or a filename. + */ + for (index = 0; index == 0 || index < numin; index++) { + + /* Open the input file. */ + fdi = (infile[index] ? fopen (infile[index], "r") : stdin); + + /* Open the output file. For multiple input files force each + * output to a new image, when reading from stdin or only one + * bitmap write to stdout if we didn't set the rootname. + */ + if (numin <= 1 && strcmp (root, s_root) == 0) { + fdo = stdout; + } else { + if (numin > 1) + sprintf (fname, "%s%d.gif", root, index); + else + sprintf (fname, "%s.gif", root); + fdo = fopen (fname, "w+"); + } + + /* Now unpack this bitmap to the output image as byte data. */ + ip = pixels; + while (fread (buffer, len_buf, 1, fdi)) { + /* If we're on a MSB ordered machine wordswap the bitmap so + * it's in the correct order for unpacking to be interpreted + * as an LSB-ordered image. + */ + if ( ! isSwapped ()) + bswap4 (buffer, buffer, len_buf); + + unpack1to8 ((ip+=px), buffer, px); + } + + /* All set, write it out. */ + GIFEncode (fdo, px, py, (interlace=0), (background=0), (bpp=1), + red, green, blue); + + fflush (fdi); + fflush (fdo); + if (fdi != stdin) + fclose (fdi); + if (fdo != stdout) + fclose (fdo); + } + + /* Clean up. */ + free (buffer); + free (pixels); + + return (0); +} + + +/* UNPACK1TO8 -- Unpack each bit in the bitmap to a byte on output. + */ + +static void +unpack1to8 (byte *dest, byte *src, int len) +{ + register int i, b; + byte c = 0; + + for (i = 0, b = 0; i < len; i++) { + if (b > 7) { + b = 0; + c = (invert ? ~(*src++) : (*src++) ); + } + *dest++ = (byte) ((c >> (b++)) & 1); + } +} + + +/* GIF Writing Procedures. + * + * Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A + * Lempel-Zim compression based on "compress". Original Copyright 1990, + * David Koblas, heavily modified since then.... + */ + +#define GIFBITS 12 + +static int Width, Height; +static int curx, cury; +static long CountDown; +static int Interlace; + + +/* GIFENCODE -- GIF Image compression interface. + */ + +static void +GIFEncode (fp, GWidth, GHeight, GInterlace, Background, Bpp, Red, Green, Blue) +FILE *fp; +int GWidth, GHeight; +int GInterlace; +int Background; +int Bpp; +int Red[], Green[], Blue[]; +{ + int B; + int RWidth, RHeight; + int LeftOfs, TopOfs; + int Resolution; + int ColorMapSize; + int InitCodeSize; + int i; + + Interlace = GInterlace; + + ColorMapSize = 1 << Bpp; + + RWidth = Width = GWidth; + RHeight = Height = GHeight; + LeftOfs = TopOfs = 0; + + Resolution = Bpp; + + /* Calculate number of bits we are expecting */ + CountDown = (long)Width * (long)Height; + + /* The initial code size */ + if (Bpp <= 1) + InitCodeSize = 2; + else + InitCodeSize = Bpp; + + /* Set up the current x and y position */ + curx = cury = 0; + + /* Write the Magic header */ + fwrite ((transparent ? "GIF89a" : "GIF87a"), 1, 6, fp); + + /* Write out the screen width and height */ + Putword (RWidth, fp); + Putword (RHeight, fp); + + /* Indicate that there is a global colour map */ + B = 0x80; /* Yes, there is a color map */ + + /* OR in the resolution */ + B |= (Resolution - 1) << 5; + + /* OR in the Bits per Pixel */ + B |= (Bpp - 1); + + /* Write it out */ + fputc (B, fp); + + /* Write out the Background colour */ + fputc (Background, fp); + + /* Byte of 0's (future expansion) */ + fputc (0, fp); + + /* Write out the Global Colour Map */ + for (i = 0; i < ColorMapSize; ++i) { + fputc (Red[i], fp); + fputc (Green[i], fp); + fputc (Blue[i], fp); + } + + /* If doing transparency, write the extension. */ + if (transparent) { + fputc (0x21, fp); /* graphics extension... */ + fputc (0xf9, fp); /* transparency... */ + fputc (0x4, fp); + fputc (0x1, fp); + fputc (0x0, fp); + fputc (0x0, fp); + fputc ((char) 0, fp); /* background color index */ + fputc (0x0, fp); + } + + /* Write an Image separator */ + fputc (',', fp); + + /* Write the Image header */ + Putword (LeftOfs, fp); + Putword (TopOfs, fp); + Putword (Width, fp); + Putword (Height, fp); + + /* Write out whether or not the image is interlaced */ + if (Interlace) + fputc (0x40, fp); + else + fputc (0x00, fp); + + /* Write out the initial code size */ + fputc (InitCodeSize, fp); + + /* Go and actually compress the data */ + compress (InitCodeSize + 1, fp); + + /* Write out a Zero-length packet (to end the series) */ + fputc (0, fp); + + /* Write the GIF file terminator */ + fputc (';', fp); +} + + +/* Bump the 'curx' and 'cury' to point to the next pixel + */ +static void +BumpPixel() +{ + /* Bump the current X position */ + ++curx; + + /* If at the end of a scan line, set curx back to the beginning. */ + if (curx == Width) { + curx = 0; + ++cury; + } +} + + +/* Return the next pixel from the image + */ +static int +GIFNextPixel () +{ + int r; + + if (CountDown == 0) + return EOF; + + --CountDown; + r = (int) pixels[ cury * ncols + curx ] ; + BumpPixel(); + return r; +} + + +/* Write out a word to the GIF file + */ +static void +Putword (w, fp) +int w; +FILE*fp; +{ + unsigned short val = w; + + fputc (val & 0xff, fp); + fputc ((val / 256) & 0xff, fp); +} + + +/* + * GIF Image compression - modified 'compress' + * + * Based on: compress.c - File compression ala IEEE Computer, June 1984. + * + * By Authors: Spencer W. Thomas, Jim McKie, Steve Davies, Ken Turkowski, + * James A. Woods, Joe Orost + * + * Lempel-Ziv compression based on 'compress'. GIF modifications by + * David Rowley (mgardi@watdcsu.waterloo.edu) + */ + +#define HSIZE 5003 /* 80% occupancy */ + +static int n_bits; /* number of bits/code */ +static int maxbits = GIFBITS; /* user settable max # bits/code */ +static code_int maxcode; /* maximum code, given n_bits */ + /* should NEVER generate this code */ +static code_int maxmaxcode = (code_int) 1 << GIFBITS; +#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) + +static count_int htab[HSIZE]; +static unsigned short codetab [HSIZE]; +#define HashTabOf(i) htab[i] +#define CodeTabOf(i) codetab[i] + +/* To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) CodeTabOf(i) +#define tab_suffixof(i) ((unsigned char *)(htab))[i] + +static code_int free_ent = 0; /* first unused entry */ +static code_int hsize = HSIZE; /* for dynamic table sizing */ + + +/* block compression parameters -- after all codes are used up, + * and compression rate changes, start over. + */ +static int clear_flg = 0; + +/* + * compress stdin to stdout + * + * Algorithm: use open addressing double hashing (no chaining) on the + * prefix code / next character combination. We do a variant of Knuth's + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + * secondary probe. Here, the modular division first probe is gives way + * to a faster exclusive-or manipulation. Also do block compression with + * an adaptive reset, whereby the code table is cleared when the compression + * ratio decreases, but after the table fills. The variable-length output + * codes are re-sized at this point, and a special CLEAR code is generated + * for the decompressor. Late addition: construct the table according to + * file size for noticeable speed improvement on small files. Please direct + * questions about this implementation to ames!jaw. + */ + +static FILE *g_outfile; +static int g_init_bits; +static int ClearCode; +static int EOFCode; +static int cur_bits = 0; + +static unsigned long cur_accum = 0; +static unsigned long masks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +static int a_count; /* Number of characters so far in this 'packet' */ +static char accum[256]; /* Define the storage for the packet accumulator */ + +static void +compress (init_bits, outfile) +int init_bits; +FILE *outfile; +{ + register long fcode; + register code_int i /* = 0 */; + register int c; + register code_int ent; + register code_int disp; + register code_int hsize_reg; + register int hshift; + + /* Set up the globals: g_init_bits - initial number of bits + * g_outfile - pointer to output file + */ + g_init_bits = init_bits; + g_outfile = outfile; + + /* Set up the necessary values */ + clear_flg = 0; + cur_accum = 0; + cur_bits = 0; + maxbits = GIFBITS; + maxcode = MAXCODE(n_bits = g_init_bits); + + ClearCode = (1 << (init_bits - 1)); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + char_init(); + for (i=0; i<HSIZE; i++) { + htab[i] = 0; + codetab[i] = 0; + } + + ent = GIFNextPixel (); + + hshift = 0; + for (fcode = (long) hsize; fcode < 65536L; fcode *= 2L) + ++hshift; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash ((count_int) hsize_reg); /* clear hash table */ + + output ((code_int)ClearCode); + + while ((c = GIFNextPixel ()) != EOF) { + + fcode = (long) (((long) c << maxbits) + ent); + i = (((code_int)c << hshift) ^ ent); /* xor hashing */ + + if (HashTabOf (i) == fcode) { + ent = CodeTabOf (i); + continue; + } else if ((long)HashTabOf (i) < 0) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if (i == 0) + disp = 1; +probe: + if ((i -= disp) < 0) + i += hsize_reg; + + if (HashTabOf (i) == fcode) { + ent = CodeTabOf (i); + continue; + } + if ((long)HashTabOf (i) > 0) + goto probe; +nomatch: + output ((code_int) ent); + ent = c; + if (free_ent < maxmaxcode) { /* } */ + CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } else + cl_block(); + } + + /* + * Put out the final code. + */ + output ((code_int)ent); + output ((code_int) EOFCode); +} + +/* + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a GIFBITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static void +output (code) +code_int code; +{ + cur_accum &= masks[ cur_bits ]; + + if (cur_bits > 0) + cur_accum |= ((long)code << cur_bits); + else + cur_accum = code; + + cur_bits += n_bits; + + while (cur_bits >= 8) { + char_out ((unsigned int)(cur_accum & 0xff)); + cur_accum >>= 8; + cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if (free_ent > maxcode || clear_flg) { + + if (clear_flg) { + maxcode = MAXCODE (n_bits = g_init_bits); + clear_flg = 0; + } else { + ++n_bits; + if (n_bits == maxbits) + maxcode = maxmaxcode; + else + maxcode = MAXCODE(n_bits); + } + } + + if (code == EOFCode) { + /* At EOF, write the rest of the buffer. */ + while (cur_bits > 0) { + char_out ((unsigned int)(cur_accum & 0xff)); + cur_accum >>= 8; + cur_bits -= 8; + } + flush_char(); + fflush (g_outfile); + if (ferror (g_outfile)) + perror ("error writing output file"); + } +} + +/* + * Clear out the hash table + */ +static void +cl_block () /* table clear for block compress */ +{ + + cl_hash ((count_int) hsize); + free_ent = ClearCode + 2; + clear_flg = 1; + + output ((code_int)ClearCode); +} + +static void +cl_hash(hsize) /* reset code table */ +register count_int hsize; +{ + + register count_int *htab_p = htab + hsize; + + register long i; + register long m1 = -1; + + i = hsize - 16; + do { /* might use Sys V memset(3) here */ + *(htab_p - 16) = m1; + *(htab_p - 15) = m1; + *(htab_p - 14) = m1; + *(htab_p - 13) = m1; + *(htab_p - 12) = m1; + *(htab_p - 11) = m1; + *(htab_p - 10) = m1; + *(htab_p - 9) = m1; + *(htab_p - 8) = m1; + *(htab_p - 7) = m1; + *(htab_p - 6) = m1; + *(htab_p - 5) = m1; + *(htab_p - 4) = m1; + *(htab_p - 3) = m1; + *(htab_p - 2) = m1; + *(htab_p - 1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + + for (i += 16; i > 0; --i) + *--htab_p = m1; +} + +/* Set up the 'byte output' routine + */ +static void +char_init() +{ + register int i; + + a_count = 0; + for (i=0; i<256; i++) + accum[i] = 0; +} + +/* Add a character to the end of the current packet, and if it is 254 + * characters, flush the packet to disk. + */ +static void +char_out (c) +int c; +{ + accum[ a_count++ ] = c; + if (a_count >= 254) + flush_char(); +} + +/* Flush the packet to disk, and reset the accumulator */ +static void +flush_char() +{ + if (a_count > 0) { + fputc (a_count, g_outfile); + fwrite (accum, 1, a_count, g_outfile); + a_count = 0; + } +} diff --git a/unix/gdev/sgidev/sgi2svg.c b/unix/gdev/sgidev/sgi2svg.c new file mode 100644 index 00000000..be25a704 --- /dev/null +++ b/unix/gdev/sgidev/sgi2svg.c @@ -0,0 +1,245 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* +** SGI2SVG.C -- Read IRAF SGI metacode from standard input, translate into +** Scalable Vector Graphics (SVG) format. +** +** Usage +** sgi2svg.e [-params] [sgi_metacode] [| lpr -Papple] +** +** -fg <N> FG color specified as RGB triplet (e.g. 'F00' is red) +** -bg <N> BG color specified as RGB triplet (e.g. '0F0' is green) +** -fill <N> fill color specified as RGB triplet (e.g. '00F' is blue) +** -w <N> width of plot, device pixels starting from l +** -h <N> height of plot, device pixels starting from b +** -p <N> pen width +** +** Option values must be separated from their flags by a space; the input +** file name and the switches may occur in any order. +** +** Sample Graphcap: +** +** g-svg|UNIX generic interface to SVG file generator:\ +** :DD=usvg,tmp$sgk,!{ sgidispatch sgi2svg -w $(PX) -h $(PY) \ +** -bg FFF -fg 000 -fill FFF $F > sgi$$.svg ; }&:PX#640:PY#480:\ +** :kf=bin$x_sgikern.e:tn=sgikern:tc=sgi_apl: +*/ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767. /* SGK units */ + + +/* Device opcodes and parameters. + */ +#define DEF_LEFT 0 /* origin in device pixels in x */ +#define DEF_BOTTOM 0 /* origin in device pixels in y */ +#define DEF_WIDTH 640 /* width in x (240d/i, 11" paper) */ +#define DEF_HEIGHT 480 /* height in y (240d/i, 8.5" paper)*/ +#define DEF_PENWIDTH 1 /* origin in device pixels in x */ + + +/* Commands to setup SVG environment. +*/ +static char *svg_prolog[] = { + "<?xml version=\"1.0\" standalone=\"no\"?>\n", + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", + " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", + NULL +}; + +/* Opcode instruction. +*/ +struct sgi_inst { + short opcode; + short x, y; +}; + + +int pen_width = DEF_PENWIDTH; /* initial line width */ +int width = DEF_WIDTH; /* margins */ +int height = DEF_HEIGHT; +char *bg = "#FFF"; /* BG/FG colors */ +char *fg = "#000"; +char *fill = "#FFF"; /* vector fill color */ + + +static void translate (FILE *in, FILE *out); + + + +/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device +** window parameters and name of input file. +*/ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile = "stdin", *argp; + int argno; + register char **lp; + + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'f': + if (argp[2] == 'g') + fg = argv[++argno]; + else + fill = argv[++argno]; + break; + case 'b': + bg = argv[++argno]; + break; + case 'w': width = atoi (argv[++argno]); break; + case 'h': height = atoi (argv[++argno]); break; + case 'p': pen_width = atoi (argv[++argno]); break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + + /* Open the input file. */ + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2svg): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + + /* Output the standard prolog. + */ + for (lp=svg_prolog; *lp; lp++) + fputs (*lp, stdout); + + fprintf (stdout,"<svg width=\"%dpx\" height=\"%dpx\" version=\"1.1\"\n", + width, height); + fprintf (stdout," xmlns=\"http://www.w3.org/2000/svg\">"); + fprintf (stdout, + "<g id=\"g0\" fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\">\n", + bg, fg); + fprintf (stdout, + "<rect x=\"1\" y=\"1\" width=\"%d\" height=\"%d\"\n", + width, height); + fprintf (stdout, + " fill=\"#%s\" stroke=\"#%s\" stroke-width=\"1\"/>\n", fill, bg); + + + + /* Process the metacode. + */ + translate (in, stdout); + + + /* Clean up. + */ + fprintf (stdout, "</g></svg>"); /* output the end of file */ + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device +** instructions and write to stdout. +*/ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, in_stroke=0, swap_bytes = isSwapped(); + int x, y, gnum=1; + + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fprintf (out, "\n"); + break; + + case SGK_MOVE: + x = (int) (((float)sgip->x / GKI_MAXNDC) * width); + y = (int) (((float)sgip->y / GKI_MAXNDC) * height); + y = height - y + 1; + if (in_stroke) /* end current stroke */ + fprintf (out, "\"/>"); + + /* Begin a new output stroke. + */ + fprintf (out, "<polyline points=\"%d,%d", x, y); + in_stroke = 1; + break; + + case SGK_DRAW: + x = (int) (((float)sgip->x / GKI_MAXNDC) * width); + y = (int) (((float)sgip->y / GKI_MAXNDC) * height); + y = height - y + 1; + fprintf (out, " %d,%d", x, y); + in_stroke = 1; + break; + + case SGK_SETLW: + /* Set pen width. + */ + pen_width = sgip->x + 1; + if (in_stroke) /* end current stroke */ + fprintf (out, "\"/></g>"); + fprintf (out, "<g id=\"g%d\" stroke-width=\"%d\">", + gnum++, pen_width); + in_stroke = 0; + break; + + default: + fprintf (stderr, "sgi2svg: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fprintf (out, " \"/></g>\n"); +} diff --git a/unix/gdev/sgidev/sgi2uapl.c b/unix/gdev/sgidev/sgi2uapl.c new file mode 100644 index 00000000..3c59d284 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uapl.c @@ -0,0 +1,545 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <pwd.h> + +#ifdef SOLARIS +#include <sys/systeminfo.h> +#endif + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UAPL.C -- Read IRAF SGI metacode from standard input, translate into + * Postscript for the Apple Laserwriter and write to standard output. + * + * Usage: + * + * sgi2uapl.e [-params] [sgi_metacode] [| lpr -Plw] + * + * -4 use 4 byte point encoding scheme (default is 7 byte) + * -t omit the timestamp/logo normally written to corner of plot + * -l N left edge; x plot origin in device pixels + * -b N bottom edge; y plot origin in device pixels + * -w N width of plot, device pixels starting from l + * -h N height of plot, device pixels starting from b + * -p O.S pen width `origin' and `slope' + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * Note that you can arrange for the Postscript output to be saved in a file + * as well as directed to the printer by calling the translator as + * + * sgi2uapl.e [params] | tee -a file | lpr -Plw + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define SGK_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in Apple Laserwriter pixels, at 300 dots/inch. Although bypassing + * the device-independence of Postscript, this achieves greater efficiency + * both in translator performance and in transmission rate to the plotter. + * The device y-origin is at the lower left corner of the page, but we take + * care of this with a Postscript coordinate transformation. Thus the maximum + * page `width' is 11*300 pixels, `height' is 8.5*300 pixels. + */ +#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */ +#define DEV_SETLW "setlinewidth\n" /* linewidth */ + +#define MAX_POINTS 512 /* maximum points on stack before a STROKE */ +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */ +#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ +#define XY_MOVE 0 +#define XY_DRAW 1 + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +/* Commands to setup Postscript environment. + */ +static char *ps_init[] = { + "%!PS-Adobe-2.0", + "/devppi 300 def", + "/userppi 72 def", + "/pagewidth 8.5 def", + "/devpixtouser { userppi mul devppi div } def", + "/pagetolandscape 90 def", + "/setcoords { pagewidth userppi mul 0 translate", + " pagetolandscape rotate 1 devpixtouser 1 devpixtouser scale } def", + "/setjoins { 1 setlinejoin 1 setlinecap } def", + "erasepage initgraphics setcoords setjoins", + NULL }; + +/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates + * encoded as a 4 byte sequence (7 bytes including the command name and spaces) + * following the command name. This is the fastest encoding, since it + * minimizes the Postscript interpreter execution time. + * + * bit 76543210 + * ------------------------------------------ + * 0 01XXXXXX hi 6 X bits + * 1 01XXXXXX li 6 X bits + * 2 01YYYYYY hi 6 Y bits + * 3 01YYYYYY lo 6 Y bits + */ +static char *ps_7byte[] = { + "/getpoint {", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " } def", + "/m { getpoint moveto } def", + "/d { getpoint lineto } def", + NULL }; + +/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors, + * encoded 4 bytes per point. This is the most space efficient encoding, + * but the runtime may be somewhat longer than for the 7byte encoding, + * due to the Postscript interpreter overhead. + * + * Optional Flag byte: + * > move instruction + * + draw instruction + * $ terminate plotting + * other ignored (e.g., whitespace) + * + * Point Encoding: + * bit 76543210 + * ------------------------------------------ + * 1 01XXXXXX hi 6 X bits + * 2 01XXXXXX lo 6 X bits + * 3 01YYYYYY hi 6 Y bits + * 4 01YYYYYY lo 6 Y bits + * + * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte + * is used as the terminator, to toggle the move/draw state, and to permit + * whitespace to be ignored. A high bit is set in each byte to ensure a + * printable character, as control codes would interfere with the operation of + * the Postscript interpreter. + */ +#define CH_MOVE '>' +#define CH_DRAW '+' +#define CH_EXITPLOT '$' + +static char *ps_4byte[] = { + "/plot { /movepen { moveto } def", + " { currentfile read not { exit } if", + " { dup 8#100 ge", + " { exit }", + " { dup 8#076 eq", + " { pop /movepen { moveto } def", + " currentfile read not { exit } if }", + " { dup 8#053 eq", + " { pop /movepen { lineto } def", + " currentfile read not { exit } if }", + " { dup 8#044 eq", + " { exit }", + " { pop currentfile read not { exit } if }", + " ifelse }", + " ifelse }", + " ifelse }", + " ifelse", + " } loop", + " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " movepen", + " } loop", + " } def", + NULL }; + +static int fourbyte = 0; +static int penmode = -1; +static int omit_logo = 0; +static int dev_left; +static int dev_bottom; +static int dev_width; +static int dev_height; +static int dev_penbase = DEF_PENBASE; +static int dev_penslope = DEF_PENSLOPE; +static int npts = 0; + + +static void translate (FILE *in, FILE *out); +static char *make_label (void); +static void textout (FILE *out, char *text[]); +static char *penencode (int val, char *code); +static void xy_flush (FILE *out); +static void xy_point (FILE *out, register int x, register int y, int flag); + + + +/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case '4': + fourbyte++; + break; + case 't': + omit_logo++; + break; + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + fprintf (stderr, "sgi2uapl: unknown switch '%s'\n", argp); + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uapl): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, x, y, curpoints = 0, swap_bytes; + float xscale, yscale; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) SGK_MAXNDC; + yscale = (float) dev_height / (float) SGK_MAXNDC; + + /* Output device initialization. */ + textout (out, ps_init); + + /* Define the Postscript plotting procedures. */ + if (fourbyte) + textout (out, ps_4byte); + else + textout (out, ps_7byte); + + /* Initialize pen width. */ + fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + xy_flush (out); + fprintf (out, DEV_FRAME); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_MOVE); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_DRAW); + + /* Limit number of points passed to Postscript between + * 'stroke' commands to draw the buffered points. + */ + curpoints = curpoints + 1; + if (curpoints > MAX_POINTS) { + xy_flush (out); + xy_point (out, x, y, XY_MOVE); + curpoints = 0; + } + break; + + case SGK_SETLW: { + /* Set pen width. + */ + int x = max (0, sgip->x - 1); + + xy_flush (out); + curpoints = 0; + fwrite (penencode ( + max (1, dev_penbase + x * dev_penslope), DEV_SETLW), + SZ_PENCMD, 1, out); + } + break; + + default: + fprintf (stderr, "sgi2uapl: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + xy_flush (out); + + /* Add the NOAO logo and timestamp at the bottom of the page and + * output the page. + */ + if (!omit_logo) { + fprintf (out, "/Times-Roman findfont 24 scalefont setfont\n"); + + /* fprintf (out, "[-1 0 0 -1 2350 3180] setmatrix\n"); */ + fprintf (out, "initmatrix\n"); + fprintf (out, "-1 72 mul 300 div 1 72 mul 300 div scale\n"); + fprintf (out, "-2409 88 translate\n"); + + fprintf (out, "%d %d moveto\n", 1600, 3150); + fprintf (out, "[1 0 0 -1 0 0] concat\n"); + fprintf (out, "(%s) show\n", make_label()); + } + + fprintf (out, "showpage\n"); +} + + +/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or + * 7 byte encoding scheme. + */ +static void +xy_point ( + FILE *out, /* output file */ + register int x, /* coords to move to */ + register int y, /* coords to move to */ + int flag /* move or draw? */ +) +{ + static char o[] = "m XXXX"; + register char *op = o; + register int n; + + if (fourbyte) { + if (npts == 0) { + fputs ("plot\n", out); + penmode = XY_MOVE; + } + + if (flag != penmode) + *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW; + + *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, op-o, 1, out); + if (!(++npts % 15)) + fputc ('\n', out); + + } else { + o[0] = (flag == XY_MOVE) ? 'm' : 'd'; + o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n); + o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, 6, 1, out); + if (!(++npts % 10)) + fputc ('\n', out); + else + fputc (' ', out); + } +} + + +/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the + * stroke command to Postscript to draw the buffered points. + */ +static void +xy_flush (FILE *out) +{ + if (npts > 0) { + if (fourbyte) + fputs ("$\n", out); + else if (npts % 10) + fputc ('\n', out); + fputs ("stroke\n", out); + npts = 0; + } +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + int val, /* device line width */ + char *code /* device set-linewidth command */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op, *ip; + + for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + obuf[SZ_PENVAL] = ' '; + for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; ) + *op++ = *ip++; + + return (obuf); +} + + +/* TEXTOUT -- Output lines of text to a file. + */ +static void +textout ( + FILE *out, /* output file */ + char *text[] /* array of lines of text */ +) +{ + register char **lp; + + for (lp=text; *lp; lp++) { + fputs (*lp, out); + fputc ('\n', out); + } +} + + +/* MAKE_LABEL -- Generate the label for the output printer page. + */ +static char * +make_label (void) +{ + static char buf[128]; + char hostname[32]; + char username[32]; + struct passwd *pw; + time_t clock; + +#ifdef SOLARIS + sysinfo (SI_HOSTNAME, hostname, 32); +#else + gethostname (hostname, 32); +#endif + + clock = time(0); + pw = getpwuid (getuid()); + strcpy (username, pw->pw_name); + endpwent(); + + sprintf (buf, "NOAO/IRAF %s@%s %s", + username, hostname, asctime(localtime(&clock))); + + return (buf); +} diff --git a/unix/gdev/sgidev/sgi2ueps.c b/unix/gdev/sgidev/sgi2ueps.c new file mode 100644 index 00000000..345eb702 --- /dev/null +++ b/unix/gdev/sgidev/sgi2ueps.c @@ -0,0 +1,530 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <ctype.h> +#include <time.h> +#include <pwd.h> +#include <string.h> +#include <stdlib.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UEPS.C -- Read IRAF SGI metacode from standard input, translate into + * Encapsulated Postscript and write to standard output. + * + * Usage: + * + * sgi2ueps.e [-params] [sgi_metacode] [| lpr -Plw] + * + * -4 use 4 byte point encoding scheme (default is 7 byte) + * -l N left edge; x plot origin in device pixels + * -b N bottom edge; y plot origin in device pixels + * -w N width of plot, device pixels starting from l + * -h N height of plot, device pixels starting from b + * -p O.S pen width `origin' and `slope' + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * Note that you can arrange for the Postscript output to be saved in a file + * as well as directed to the printer by calling the translator as + * + * sgi2ueps.e [params] | tee -a file | lpr -Plw + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define SGK_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in pixels at 300 dots/inch. Although bypassing the + * device-independence of Postscript, this achieves greater efficiency + * both in translator performance and in transmission rate to the plotter. + * The device y-origin is at the lower left corner of the page, but we take + * care of this with a Postscript coordinate transformation. Thus the maximum + * page `width' is 11*300 pixels, `height' is 8.5*300 pixels. + */ +#define DEV_FRAME "showpage setcoords setjoins\n" /* newframe */ +#define DEV_SETLW "setlinewidth\n" /* linewidth */ + +#define MAX_POINTS 512 /* maximum points on stack before a STROKE */ +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEV_UNITS 300 /* EPS translator units: N per inch */ +#define EPS_UNITS 72 /* PostScript units (points) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 16 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VCODE 7 /* no. of chars in MOVE or DRAW opcode */ +#define SZ_VECT 17 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ +#define XY_MOVE 0 +#define XY_DRAW 1 + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +/* Commands to setup Postscript environment. + */ +static char *ps_init[] = { + "/devppi 300 def", + "/userppi 72 def", + "/pagewidth 8.5 def", + "/devpixtouser { userppi mul devppi div } def", + "/setscale { 1 devpixtouser 1 devpixtouser scale } def", + "/pagetolandscape 90 def", + "/setcoords { pagewidth userppi mul 0 translate", + " pagetolandscape rotate setscale } def", + "/setjoins { 1 setlinejoin 1 setlinecap } def", + NULL }; + +static char *ps_endprolog[] = { + "%%EndProlog", + "%%Page: 1 1", + "gsave setscale setjoins", + NULL }; + +/* 7BYTE -- Postscript procedures to move or draw, with the X,Y coordinates + * encoded as a 4 byte sequence (7 bytes including the command name and spaces) + * following the command name. This is the fastest encoding, since it + * minimizes the Postscript interpreter execution time. + * + * bit 76543210 + * ------------------------------------------ + * 0 01XXXXXX hi 6 X bits + * 1 01XXXXXX li 6 X bits + * 2 01YYYYYY hi 6 Y bits + * 3 01YYYYYY lo 6 Y bits + */ +static char *ps_7byte[] = { + "/getpoint {", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " } def", + "/m { getpoint moveto } def", + "/d { getpoint lineto } def", + NULL }; + +/* 4BYTE -- Postscript procedure to draw an arbitrary series of vectors, + * encoded 4 bytes per point. This is the most space efficient encoding, + * but the runtime may be somewhat longer than for the 7byte encoding, + * due to the Postscript interpreter overhead. + * + * Optional Flag byte: + * > move instruction + * + draw instruction + * $ terminate plotting + * other ignored (e.g., whitespace) + * + * Point Encoding: + * bit 76543210 + * ------------------------------------------ + * 1 01XXXXXX hi 6 X bits + * 2 01XXXXXX lo 6 X bits + * 3 01YYYYYY hi 6 Y bits + * 4 01YYYYYY lo 6 Y bits + * + * Data points are encoded 12 bits (0-4095) per X,Y coordinate. The flag byte + * is used as the terminator, to toggle the move/draw state, and to permit + * whitespace to be ignored. A high bit is set in each byte to ensure a + * printable character, as control codes would interfere with the operation of + * the Postscript interpreter. + */ +#define CH_MOVE '>' +#define CH_DRAW '+' +#define CH_EXITPLOT '$' + +static char *ps_4byte[] = { + "/plot { /movepen { moveto } def", + " { currentfile read not { exit } if", + " { dup 8#100 ge", + " { exit }", + " { dup 8#076 eq", + " { pop /movepen { moveto } def", + " currentfile read not { exit } if }", + " { dup 8#053 eq", + " { pop /movepen { lineto } def", + " currentfile read not { exit } if }", + " { dup 8#044 eq", + " { exit }", + " { pop currentfile read not { exit } if }", + " ifelse }", + " ifelse }", + " ifelse }", + " ifelse", + " } loop", + " dup 8#044 eq { pop exit } { 8#77 and 6 bitshift } ifelse", + " currentfile read pop 8#77 and or", + " currentfile read pop 8#77 and 6 bitshift", + " currentfile read pop 8#77 and or", + " movepen", + " } loop", + " } def", + NULL }; + +static int npts = 0; +static int fourbyte = 0; +static int penmode = -1; +static int dev_left; +static int dev_bottom; +static int dev_width; +static int dev_height; +static int dev_penbase = DEF_PENBASE; +static int dev_penslope = DEF_PENSLOPE; +static char progname[SZ_LINE+1]; + +static void translate (FILE *in, FILE *out); +static void xy_point (FILE *out, register int x, register int y, int flag); +static void xy_flush (FILE *out); +static char *penencode (int val, char *code); +static void textout (FILE *out, char *text[]); +static void eps_comments (FILE *out); + + + +/* MAIN -- Main entry point for SGI2UAPL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + strcpy (progname, argv[0]); + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case '4': + fourbyte++; + break; + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + fprintf (stderr, "sgi2ueps: unknown switch '%s'\n", argp); + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2ueps): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, x, y, curpoints = 0, swap_bytes; + float xscale, yscale; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) SGK_MAXNDC; + yscale = (float) dev_height / (float) SGK_MAXNDC; + + /* Output device initialization. */ + eps_comments (out); + textout (out, ps_init); + + /* Define the Postscript plotting procedures. */ + if (fourbyte) + textout (out, ps_4byte); + else + textout (out, ps_7byte); + + textout (out, ps_endprolog); + + /* Initialize pen width. */ + fwrite (penencode (dev_penbase, DEV_SETLW), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + xy_flush (out); + fprintf (out, DEV_FRAME); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_MOVE); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + xy_point (out, x, y, XY_DRAW); + + /* Limit number of points passed to Postscript between + * 'stroke' commands to draw the buffered points. + */ + curpoints = curpoints + 1; + if (curpoints > MAX_POINTS) { + xy_flush (out); + xy_point (out, x, y, XY_MOVE); + curpoints = 0; + } + break; + + case SGK_SETLW: { + /* Set pen width. + */ + int x = max (0, sgip->x - 1); + + xy_flush (out); + curpoints = 0; + fwrite (penencode ( + max (1, dev_penbase + x * dev_penslope), DEV_SETLW), + SZ_PENCMD, 1, out); + } + break; + + default: + fprintf (stderr, "sgi2ueps: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + xy_flush (out); + + fprintf (out, "grestore showpage\n"); +} + + +/* XY_POINT -- Output a move or draw instruction, using either the 4 byte or + * 7 byte encoding scheme. + */ +static void +xy_point ( + FILE *out, /* output file */ + register int x, /* coords to move to */ + register int y, /* coords to move to */ + int flag /* move or draw? */ +) +{ + static char o[] = "m XXXX"; + register char *op = o; + register int n; + + if (fourbyte) { + if (npts == 0) { + fputs ("plot\n", out); + penmode = XY_MOVE; + } + + if (flag != penmode) + *op++ = ((penmode = flag) == XY_MOVE) ? CH_MOVE : CH_DRAW; + + *op++ = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (x & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + *op++ = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, op-o, 1, out); + if (!(++npts % 15)) + fputc ('\n', out); + + } else { + o[0] = (flag == XY_MOVE) ? 'm' : 'd'; + o[2] = ((n = ((x >> 6) & 077)) == 077) ? n : (0100 | n); + o[3] = ((n = (x & 077)) == 077) ? n : (0100 | n); + o[4] = ((n = ((y >> 6) & 077)) == 077) ? n : (0100 | n); + o[5] = ((n = (y & 077)) == 077) ? n : (0100 | n); + + fwrite (o, 6, 1, out); + if (!(++npts % 10)) + fputc ('\n', out); + else + fputc (' ', out); + } +} + + +/* XY_FLUSH -- Terminate the current drawing sequence, if any, and issue the + * stroke command to Postscript to draw the buffered points. + */ +static void +xy_flush (FILE *out) +{ + if (npts > 0) { + if (fourbyte) + fputs ("$\n", out); + else if (npts % 10) + fputc ('\n', out); + fputs ("stroke\n", out); + npts = 0; + } +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + int val, /* device line width */ + char *code /* device set-linewidth command */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op, *ip; + + for (op = &obuf[SZ_PENVAL-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + obuf[SZ_PENVAL] = ' '; + for (op = &obuf[SZ_PENVAL+1], ip = code, n = SZ_PENCMD; --n >= 0; ) + *op++ = *ip++; + + return (obuf); +} + + +/* TEXTOUT -- Output lines of text to a file. + */ +static void +textout ( + FILE *out, /* output file */ + char *text[] /* array of lines of text */ +) +{ + register char **lp; + + for (lp=text; *lp; lp++) { + fputs (*lp, out); + fputc ('\n', out); + } +} + + +/* EPS_COMMENTS -- Set identifying comments for EPS conformance. + */ +static void +eps_comments (FILE *out) +{ + time_t clock; + int llx, lly, urx, ury; + + clock = time(0); + + fprintf (out, "%%!PS-Adobe-3.0 EPSF-3.0\n"); + fprintf (out, "%%%%Title: IRAF SGI plot\n"); + fprintf (out, "%%%%Creator: %s\n", progname); + fprintf (out, "%%%%CreationDate: %s", asctime(localtime(&clock))); + + /* Compute bounding box in PostScript coordinates. */ + llx = ((float) dev_left / (float) DEV_UNITS) * (float) EPS_UNITS; + lly = ((float) dev_bottom / (float) DEV_UNITS) * (float) EPS_UNITS; + urx = ((float) (dev_left + dev_width) / (float) DEV_UNITS) + * (float) EPS_UNITS; + ury = ((float) (dev_bottom + dev_height) / (float) DEV_UNITS) + * (float) EPS_UNITS; + + fprintf (out, "%%%%BoundingBox: %d %d %d %d\n", llx, lly, urx, ury); + fprintf (out, "%%%%Pages: 1\n"); + fprintf (out, "%%%%EndComments\n"); +} diff --git a/unix/gdev/sgidev/sgi2uhpgl.c b/unix/gdev/sgidev/sgi2uhpgl.c new file mode 100644 index 00000000..2e952446 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uhpgl.c @@ -0,0 +1,160 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UHPGL.C -- Read IRAF SGI metacode from standard input, translate into + * HP graphics language call for HP 7550A plotter + * + * Usage + * sgi2uhpgl.e [sgi_metacode] [| lpr -Papple] + * + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. + */ +#define DEV_INIT "IN;DF;SP1;" /* initialize */ +#define DEV_END "SP0;PG:" /* terminate */ +#define DEV_FRAME "PG;" /* newframe */ +#define DEV_MOVE "PU" /* move */ +#define DEV_DRAW "PD" /* draw */ +#define PRES 1016 /* plotter resolution per inch */ +#define XLEN_INCHES 10.0 /* width of plot (x) in inches */ +#define YLEN_INCHES 8.0 /* height of plot (y) in inches */ +#define XSCALE PRES * XLEN_INCHES / GKI_MAXNDC +#define YSCALE PRES * YLEN_INCHES / GKI_MAXNDC + + +#define SZ_COORD 4 /* no. of chars in device coordinate */ + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +static void translate (FILE *in, FILE *out); + + +/* MAIN -- Main entry point for SGI2UHPGL. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + + + infile = "stdin"; + + /* Process the command line. + */ + infile = argv[1]; + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uhpp): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + int n, swap_bytes; + float x, y; + + + swap_bytes = isSwapped(); + + /* Output device initialization. + */ + fprintf (out, "%s\n", DEV_INIT); + + /* Initialize pen width. Not implemented. + */ + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fprintf (out, "%s\n", DEV_FRAME); + break; + + case SGK_MOVE: + x = sgip->x * XSCALE; + y = sgip->y * YSCALE; + fprintf (out, + "%s%06.0f%s%06.0f%s\n", DEV_MOVE, x, ",", y, ";"); + break; + + case SGK_DRAW: + x = sgip->x * XSCALE; + y = sgip->y * YSCALE; + fprintf (out, + "%s%06.0f%s%06.0f%s\n", DEV_DRAW, x, ",", y, ";"); + break; + + case SGK_SETLW: + /* Set pen width. + */ + break; + default: + fprintf (stderr, "sgi2uhpp: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); + fprintf (out, "\n"); +} diff --git a/unix/gdev/sgidev/sgi2uhplj.c b/unix/gdev/sgidev/sgi2uhplj.c new file mode 100644 index 00000000..7c8956ce --- /dev/null +++ b/unix/gdev/sgidev/sgi2uhplj.c @@ -0,0 +1,223 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UHPLJ.C -- Read IRAF SGI rasterfile from standard input, translate into + * the Hewlett Packard Printer Command Language (HP Laserjet Series) and + * write to standard output. + * + * Warning + * The output of this is for 150 dpi. At this resolution it will take + * some 200 seconds to plot an simple "prow". + * + * Usage + * sgi2uhplj.e [-params] [sgi_] [| lpr -Phpraw] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + */ + +#define OSOK 0 /* normal successful completion */ +#define NBITS_CHAR 8 /* number of bits in a char */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in HP pixels, at 150 dots/inch. The HP plots in portrait mode + * by default so RO must be set in GRAPHCAP. Thus the maximum page `width' is + * 11*150pixels, `height' is 8.5*150 pixels. + */ + +#define DEV_INIT "\033*t150R\033*r1A" /* Enter graph. */ +#define DEV_END "\033*rB\014" /* Exit graph. */ +#define DEV_VECT "\033*p%03dX\033*p%03dY"/* x,y cursor posn in dots */ +#define DEV_RAST "\033*b%03dW" /* transfer raster graphics */ + +#define DEF_LEFT 15 /* origin in device pixels in x */ +#define DEF_WIDTH 1216 /* width in x (150d/i, 8.5" paper) */ +#define DEF_BOTTOM 30 /* origin in device pixels in y */ +#define DEF_HEIGHT 1590 /* height in y (150d/i, 11" paper) */ + +#define SZ_VECT 14 /* total chars in cursor position command */ +#define SZ_RAST 7 /* total chars in transfer graphics command */ + +/* graphcap entry for uhplj and sgi_hplaserjet. one problem with current + * entry is that graph comes out slightly to the right of center on the page + * The printer used, "hpraw", is site dependent. + * + * uhplj|UNIX generic interface to Hewlett-Packard LaserJet II:\ + * :BF:WS:XO#0:YO#0:LO#2:LS#2:\ + * :DD=plnode!hpii,tmp$sgk,!{ sgidispatch sgi2uhpii $F \ + * -l$(XO) -b$(YO) -w$(PX) -h$(PY) $F | lpr -Phpraw; rm $F; }&:\ + * :tc=sgi_hplaserjet: + * + * sgi_hplaserjet|Hewlett Packard LaserJet Plus at 150 dpi:\ + * :kf=bin$x_sgikern.e:tn=sgikern:cw#.0125:ch#.0294:\ + * :ar#1.325:xs#.2032:ys#.2692:xr#1200:yr#1590:\ + * :XO#8:YO#0:XW#1200:YW#1590:PX#1216:PY#1590:LO#1:LS#0:\ + * :BI:MF#8:RO:NB#8: + */ + +int dev_left; +int dev_bottom; +int dev_width; +int dev_height; + +static void translate (FILE *in, FILE *out); +static char *xyencode (int x, int y); + + +/* MAIN -- Main entry point for SGI2UHPII. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + default: + break; + } + + } else { + /* Input sgi-raster file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uhpii): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the rasterfile. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI Raster File format into Hewlett Packard + * Raster graphics instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n1, swap_bytes; + int n, nlines, length, len_buf; + register unsigned char *bp1, *buffer1; + char buf_rast [SZ_RAST]; + + + swap_bytes = isSwapped (); + + len_buf = dev_width / NBITS_CHAR; + buffer1 = (unsigned char *)malloc (len_buf); + + /* Output device initialization. + */ + fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out); + fwrite (DEV_INIT, strlen(DEV_INIT), 1, out); + + /* Process the raster file + */ + nlines = dev_height; + while ((n = fread (buffer1, len_buf, 1, in)) > 0) { + + if (swap_bytes) + bswap2 (buffer1, buffer1, len_buf); + + /* Keep track of number of lines left on the page. + */ + if (!(nlines--)) { + nlines += dev_height; + fwrite (DEV_END, strlen (DEV_END), 1, out); + fwrite (xyencode (dev_left, dev_bottom), SZ_VECT, 1, out); + fwrite (DEV_INIT, strlen (DEV_INIT), 1, out); + } + + /* Search for trailing null bytes to trim them off. + */ + length = len_buf; + for (bp1 = buffer1+length; length && *(--bp1) == 0; length--) + ; + + n1 = length; + if (n1 == 0) { + n1 = 1; + *buffer1 = 0; + } + + /* Now copy out this line and prefix it with the control codes. + */ + sprintf (buf_rast, DEV_RAST, n1); + fwrite (buf_rast, SZ_RAST, 1, out); + fwrite (buffer1, n1, 1, out); + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); +} + + +/* XYENCODE -- Encode x, y into a character string formatted for the device. + */ +static char * +xyencode (int x, int y) +{ + static char obuf [SZ_VECT]; + + memset (obuf, 0, SZ_VECT); + sprintf (obuf, DEV_VECT, x, y); + return (obuf); +} diff --git a/unix/gdev/sgidev/sgi2uimp.c b/unix/gdev/sgidev/sgi2uimp.c new file mode 100644 index 00000000..a8f566ed --- /dev/null +++ b/unix/gdev/sgidev/sgi2uimp.c @@ -0,0 +1,341 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UIMP.C -- Read IRAF SGI metacode from standard input, translate into + * the Impress language and write to standard output. + * + * Usage + * sgi2uimp.e [-params] [sgi_metacode] [| lpr -v -Pimagen] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * -p O.S pen width `origin' and `slope' def DEF_PENBASE + * .DEF_PENSLOPE + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + * The windowing parameters are specified explicitly rather than using the + * plotter resolution and paper size due to differences in exactly where + * each different Imagen begins and ends plotting within the paper window. + * + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters + * (DEF_), given in device pixels for a 240 dot/inch Imagen with 8 1/2" x 11" + * paper, should be modified to fit the local plotter. + */ +#define DEF_LEFT 85 /* origin in device pixels in x */ +#define DEF_WIDTH 2490 /* width in x (240d/i, 11" paper) */ +#define DEF_BOTTOM 50 /* origin in device pixels in y */ +#define DEF_HEIGHT 1905 /* height in y (240d/i, 8.5" paper)*/ +#define DEF_PENBASE 2 /* base pen width */ +#define DEF_PENSLOPE 2 /* pen slope (b.s=3.2 ==> 3,5,7,9) */ +#define SZ_PENPARAM 5 /* max chars in penwidth parameter */ +#define BLACK_LINE 15 /* draw solid line */ +#define CREATE_PATH 230 /* set up set of vertices */ +#define DRAW_PATH 234 /* draw that set of vertices */ +#define END_DOCUMENT 255 /* end of document */ +#define END_PAGE 219 /* formfeed */ +#define HV_VALUE 125 /* 0 11 11 101 (orig, axes, orient)*/ +#define SET_ABS_H 135 /* move absolute in h */ +#define SET_ABS_V 137 /* move absolute in v */ +#define SET_HV_SYSTEM 205 /* establish coordinate system */ +#define SET_PEN 232 /* set pen width */ +#define SZ_HEAD 3 /* # header opcode bytes in obuf */ +#define SZ_TAIL 2 /* # trailing opcode bytes in obuf */ +#define COUNT_OFFSET 1 /* byte offset to npoints in obuf */ + +/* Output macros -- watch out for SZ_OBUF; some Imagens have a limited amount + * of memory for the DRAW buffer: + */ +#define SZ_OBUF (1024) +#define DECL_OBUF register char *op; char *np; char obuf[SZ_OBUF+1]; +#define o_clear (op=obuf) +#define o_flush(o) fwrite(obuf,op-obuf,1,o) +#define putbyte(v) (*op++ = (v)) +#define putword(v) ((*op++ = (v)/256), (*op++ = (v)%256)) +#define setcount(b,v) ((np = obuf+b), (*np++ = (v)/256), (*np = (v)%256)) +#define npoints ((op-obuf - SZ_HEAD)/4) +#define obuf_full ((op-obuf + SZ_TAIL) >= SZ_OBUF) + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +int imp_left; +int imp_bottom; +int imp_width; +int imp_height; +int imp_penbase = DEF_PENBASE; +int imp_penslope = DEF_PENSLOPE; + +static void translate (FILE *in, FILE *out); + + +/* MAIN -- Main entry point for SGI2UIMP. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENPARAM]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + imp_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + imp_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + imp_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + imp_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", imp_penbase, + imp_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &imp_penbase, + &imp_penslope); + if (np == 1) { + imp_penslope = imp_penbase; + } else if (np < 1) { + imp_penbase = DEF_PENBASE; + imp_penslope = DEF_PENSLOPE; + } + + break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uimp): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into the device + * language and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n, x, y, swap_bytes; + float xscale, yscale; + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + DECL_OBUF; + + swap_bytes = isSwapped(); + + xscale = (float) imp_width / (float) GKI_MAXNDC; + yscale = (float) imp_height / (float) GKI_MAXNDC; + + /* Output device header instructions. + */ + fprintf (out, "@Document(%s, %s, %s, %s, %s, %s)", + "language impress", "pagecollation on", "jamresistance on", + "name \"IRAF SGI plot\"", "prerasterization on", "jobheader off"); + + /* Output page orientation and coordinate system initialization. + */ + putc (SET_HV_SYSTEM, out); + putc (HV_VALUE, out); + + /* Initialize pen width. + */ + putc (SET_PEN, out); + putc (1 * imp_penbase, out); + + o_clear; + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + o_clear; + putbyte (END_PAGE); + putbyte (SET_ABS_H); + putword (0); + putbyte (SET_ABS_V); + putword (0); + o_flush (out); + break; + + case SGK_MOVE: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + x = imp_left + sgip->x * xscale; + y = imp_bottom + sgip->y * yscale; + + /* Initialize output buffer for start of draw instruction. + */ + o_clear; + putbyte (CREATE_PATH); + putword (1); + putword (x); putword (y); + + break; + + case SGK_DRAW: + x = imp_left + sgip->x * xscale; + y = imp_bottom + sgip->y * yscale; + putword (x); putword (y); + + /* If we are about to exceed output buffer, flush and re- + * initialize starting with current point. + */ + if (obuf_full) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + + /* Reinitialize DRAW buffer. + */ + o_clear; + putbyte (CREATE_PATH); + putword (1); + putword (x); putword (y); + } + + break; + + case SGK_SETLW: + /* Terminate and output any DRAW buffer contents. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + o_clear; + } + + /* Set pen width. + */ + putc (SET_PEN, out); + putc ((imp_penbase + ((sgip->x) - 1) * imp_penslope), out); + break; + + default: + fprintf (stderr, "sgi2uimp: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Flush any remaining buffered points. + */ + if (npoints > 1) { + setcount (COUNT_OFFSET, npoints); + putbyte (DRAW_PATH); + putbyte (BLACK_LINE); + o_flush (out); + } + + /* Signal end of page and end of document. + */ + putc (END_PAGE, out); + putc (END_DOCUMENT, out); +} diff --git a/unix/gdev/sgidev/sgi2uptx.c b/unix/gdev/sgidev/sgi2uptx.c new file mode 100644 index 00000000..6c44f334 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uptx.c @@ -0,0 +1,61 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define MASK 64 /* printronix raster flag */ +#define START_LINE "\005" /* start of raster line control code */ +#define END_LINE "\012" /* end of raster line control code */ +#define START_PAGE "\014" /* form feed */ + +/* PRINTRONIX translator from the SGI bitmap file to the STDOUT */ + +int +main (int argc, char *argv[]) +{ + + FILE *fpi; + char *buffer; + int n, len_buf, nlines; + int index; /* goes through all 8 files */ + int px, py; + + px = atoi (argv[1]); + py = atoi (argv[2]); + len_buf = px/NBITS_CHAR; + buffer = (char *) malloc (len_buf); + + for (index=3; index<argc; index++) { + + if (index != 3) fwrite (START_PAGE, 1, 1, stdout); + fpi = fopen (argv[index], "r"); + nlines = py; + + while (fread (buffer, len_buf, 1, fpi)) { + + /* Keep track of number of lines left on the page. */ + if (!(nlines--)) { + nlines += py; + fwrite (START_PAGE, 1, 1, stdout); + } + + /* Turn on the raster flag on every data byte */ + for (n = 0; n < len_buf; n++) buffer[n] |= MASK; + + /* Now copy out this line and bracket it with the control codes. */ + fwrite (START_LINE, 1, 1, stdout); + fwrite (buffer, len_buf, 1, stdout); + fwrite (END_LINE, 1, 1, stdout); + + } + + fclose (fpi); + + } + + return (0); +} diff --git a/unix/gdev/sgidev/sgi2uqms.c b/unix/gdev/sgidev/sgi2uqms.c new file mode 100644 index 00000000..e91d7e38 --- /dev/null +++ b/unix/gdev/sgidev/sgi2uqms.c @@ -0,0 +1,296 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#include <iraf.h> + +#include "sgiUtil.h" + + +/* + * SGI2UQMS.C -- Read IRAF SGI metacode from standard input, translate into + * the QMS Vector Graphics Mode (Talaris Lasergrafix, QUIC Command Mode) and + * write to standard output. + * + * Usage + * sgi2uqms.e [-params] [sgi_metacode] [| lpr -Pqms] + * + * -l N left edge; x plot origin in device pixels def DEF_LEFT + * -b N bottom edge; y plot origin in device pixels def DEF_BOTTOM + * -w N width of plot, device pixels starting from l def DEF_WIDTH + * -h N height of plot, device pixels starting from b def DEF_HEIGHT + * -p O.S pen width `origin' and `slope' def DEF_PENBASE + * .DEF_PENSLOPE + * + * Numeric values may be appended directly to their flags or separated by a + * space; the input file name and the switches may occur in any order. + */ + +#define OSOK 0 /* normal successful completion */ +#define LEN_MCBUF 1024 /* number of SGK instrs in buffer */ +#define SGK_FRAME 1 /* new frame instruction */ +#define SGK_MOVE 2 /* move pen */ +#define SGK_DRAW 3 /* draw pen */ +#define SGK_SETLW 4 /* set line width */ +#define GKI_MAXNDC 32767 /* SGK units */ + +/* Device opcodes and parameters. The default edge and width parameters (DEF_) + * are given in QMS pixels, at 300 dots/inch. The QMS y-origin is at the + * top of the page, so in GRAPHCAP, YF must be set, and Landscape Orientation + * used in the QMS. Thus the maximum page `width' is 11*300 pixels, `height' + * is 8.5*300 pixels. + */ +#define DEV_INIT "\012^PY^-\012^ISYNTAX00010^IOL^F^IGV" /* Enter graph.*/ +#define DEV_END "^IGE^ISYNTAX00000^IOP^O\012^PN^-\012" /* Exit graph. */ +#define DEV_FRAME "^," /* QMS Vector Graphics Mode form feed instr */ +#define DEV_MOVE "^U" /* QMS (VGM) pen-up instruction */ +#define DEV_DRAW "^D" /* QMS (VGM) pen-down instruction */ +#define DEV_SETLW "^PW" /* QMS (VGM) Set Line Width (follow w/ nn) */ + +#define DEF_LEFT 30 /* origin in device pixels in x */ +#define DEF_WIDTH 3180 /* width in x (300d/i, 11" paper) */ +#define DEF_BOTTOM 60 /* origin in device pixels in y */ +#define DEF_HEIGHT 2415 /* height in y (300d/i, 8.5" paper) */ +#define DEF_PENBASE 3 /* base pen width (LW 1->2) */ +#define DEF_PENSLOPE 4 /* pen width slope (LW 2->4, 3->6 etc.) */ +#define SZ_PENCMD 5 /* total no. of chars in penwidth instruction */ +#define SZ_PENVAL 2 /* no. of chars in penwidth value */ +#define SZ_VECT 11 /* total no. chars in a MOVE or DRAW inst. */ +#define SZ_COORD 4 /* no. of chars in device coordinate */ + +struct sgi_inst { + short opcode; + short x; + short y; +}; + +int dev_left; +int dev_bottom; +int dev_width; +int dev_height; +int dev_penbase = DEF_PENBASE; +int dev_penslope = DEF_PENSLOPE; + +static void translate (FILE *in, FILE *out); +static char *xyencode (int opcode, int x, int y); +static char *penencode (char *opcode, int val); + + + +/* MAIN -- Main entry point for SGI2UQMS. Optional arguments are device + * window parameters and name of input file. + */ +int +main (int argc, char *argv[]) +{ + FILE *in; + char *infile; + char *argp; + int argno; + int np; + char penparam[SZ_PENCMD]; + + + infile = "stdin"; + + /* Process the command line. + */ + for (argno=1; (argp = argv[argno]) != NULL; argno++) { + if (argp[0] == '-') { + /* A window-control or pen width switch. + */ + switch (argp[1]) { + case 'l': + dev_left = get_iarg (argp[2], argv, argno, DEF_LEFT); + break; + case 'b': + dev_bottom = get_iarg (argp[2], argv, argno, DEF_BOTTOM); + break; + case 'w': + dev_width = get_iarg (argp[2], argv, argno, DEF_WIDTH); + break; + case 'h': + dev_height = get_iarg (argp[2], argv, argno, DEF_HEIGHT); + break; + case 'p': + if (argp[2] == (char) 0) + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%s';", + argp); + fprintf (stderr, " reset to %d.%d\n", dev_penbase, + dev_penslope); + } else + strcpy (penparam, argv[++argno]); + else + strcpy (penparam, argv[argno]+2); + + np = sscanf (penparam, "%d . %d", &dev_penbase, + &dev_penslope); + if (np == 1) { + dev_penslope = dev_penbase; + } else if (np < 1) { + dev_penbase = DEF_PENBASE; + dev_penslope = DEF_PENSLOPE; + } + + break; + default: + break; + } + + } else { + /* Input sgi-metacode file specification. + */ + infile = argp; + } + } + + if (strcmp (infile, "stdin") == 0) + in = stdin; + else + in = fopen (infile, "r"); + + if (in == NULL) { + fprintf (stderr, "Fatal error (sgi2uqms): Cannot open `%s'\n", + infile); + fflush (stderr); + exit (OSOK+1); + } + + /* Process the metacode. + */ + translate (in, stdout); + + if (in != stdin) + fclose (in); + + return (0); +} + + +/* TRANSLATE -- Interpret input SGI metacode instructions into device + * instructions and write to stdout. + */ +static void +translate (FILE *in, FILE *out) +{ + int n, x, y, swap_bytes; + float xscale, yscale; + register struct sgi_inst *sgip; + struct sgi_inst inbuf[LEN_MCBUF], *buftop; + + + swap_bytes = isSwapped(); + + xscale = (float) dev_width / (float) GKI_MAXNDC; + yscale = (float) dev_height / (float) GKI_MAXNDC; + + /* Output device initialization. + */ + fwrite (DEV_INIT, strlen(DEV_INIT), 1, out); + + /* Initialize pen width. + */ + fwrite (penencode (DEV_SETLW, dev_penbase), SZ_PENCMD, 1, out); + + /* Process the metacode: + */ + while ((n = fread ((char *)inbuf, sizeof(*sgip), LEN_MCBUF, in)) > 0) { + + if (swap_bytes) + bswap2 ((unsigned char *)inbuf, (unsigned char *)inbuf, + sizeof(*sgip) * n); + + buftop = inbuf + n; + + for (sgip = inbuf; sgip < buftop; sgip++) { + switch (sgip->opcode) { + case SGK_FRAME: + fwrite (DEV_FRAME, strlen(DEV_FRAME), 1, out); + break; + + case SGK_MOVE: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + fwrite (xyencode ('U', x, y), SZ_VECT, 1, out); + break; + + case SGK_DRAW: + x = dev_left + sgip->x * xscale; + y = dev_bottom + sgip->y * yscale; + fwrite (xyencode ('D', x, y), SZ_VECT, 1, out); + break; + + case SGK_SETLW: + /* Set pen width. + */ + fwrite (penencode (DEV_SETLW, dev_penbase + + ((sgip->x) - 1) * dev_penslope), SZ_PENCMD, 1, out); + break; + + default: + fprintf (stderr, "sgi2uqms: unrecognized sgi opcode %d\n", + sgip->opcode); + break; + } + } + } + + /* Terminate plotting and exit. + */ + fwrite (DEV_END, strlen(DEV_END), 1, out); +} + + +/* XYENCODE -- Encode x, y into a character string formatted for the device. + */ +static char * +xyencode ( + int opcode, /* draw or move */ + int x, /* must be positive */ + int y /* must be positive */ +) +{ + static char obuf[] = "^X0000:0000"; + register int digit, n; + register char *op; + int i; + + obuf[1] = opcode; + i = SZ_VECT - 1 - SZ_COORD - 1; + for (op = &obuf[i], digit = SZ_COORD, n=x; --digit >= 0; n = n / 10) + *op-- = n % 10 + '0'; + i = SZ_VECT - 1; + for (op = &obuf[i], digit = SZ_COORD, n=y; --digit >= 0; n = n / 10) + *op-- = n % 10 + '0'; + + return (obuf); +} + + +/* PENENCODE -- Encode base, slope into a character string formatted for the + * device set-pen command. + */ +static char * +penencode ( + char *opcode, /* device set-linewidth command */ + int val /* device line width */ +) +{ + static char obuf[SZ_PENCMD+1]; + register int digit, n; + register char *op; + + strcpy (obuf, opcode); + for (op = &obuf[SZ_PENCMD-1], digit = SZ_PENVAL, n=val; --digit >= 0; + n = n / 10) + *op-- = n % 10 + '0'; + + return (obuf); +} diff --git a/unix/gdev/sgidev/sgi2xbm.c b/unix/gdev/sgidev/sgi2xbm.c new file mode 100644 index 00000000..6d4c230a --- /dev/null +++ b/unix/gdev/sgidev/sgi2xbm.c @@ -0,0 +1,135 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "sgiUtil.h" + + +/* SGI2XBM.C -- Read an IRAF SGI bitmap file on standard input and convert + * to a GIF format image on standard outout. + * + * Usage: + * sgi2xbm.e [-w N] [-h NY] [-i] [ [sgi_bitmap] [sgi_bitmap] ... ] + * + * -w N width of input bitmap and output image + * -h N height of input bitmap and output image + * -i invert the bitmap values before conversion + * + * The input file name and the switches may occur in any order. The bitmap + * may be inverted here using the -i flag. + * + * Sample graphcaps for this translator might look like: + * + * g-xbm|UNIX generic interface to multi-frame XBM file generator:\ + * :DD=ugif,tmp$sgk,!{ sgidispatch sgi2xbm -w $(PX) -h $(PY) \ + * $F.[1-8] > sgixbm$$; rm $F.[1-8]; }&:\ + * :MF#8:NF:tc=sgi_image_format: + * + * sgi_image_format|Generic raster file format specification:\ + * :kf=bin$x_sgikern.e:tn=sgikern:ar#.75:\ + * :xr#640:yr#480:PX#640:PY#480:XW#640:YW#480:\ + * :BI:MF#1:YF:NB#8:LO#1:LS#0:XO#0:YO#0: + * + * All bitmaps will be dumped to the file 'sgixbmXXX' in the local directory + * where XXX is a pid. + * + * To change the image size the graphcap :xr, :PX, :XW (X-dimension) and + * :yr, :PY, :XY (Y-dimension) fields all need to be changed. The -i + * flag must be specified in the graphcap DD string. + * + */ + +#define NBITS_CHAR 8 /* number of bits in a char */ +#define DEF_WIDTH 640 /* default image width */ +#define DEF_HEIGHT 480 /* default image height */ +#define MAX_INFILES 16 /* max number of input bitmaps */ +#define SZ_FNAME 64 /* size of a filename */ + +typedef unsigned char byte; + +static int px = DEF_WIDTH; +static int py = DEF_HEIGHT; +static int invert = 0; +static char *infile[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +int +main (int argc, char *argv[]) +{ + FILE *fd; + byte *buffer; + int i, n, len_buf, numin = 0, cnt = 0; + int index; /* goes through all files */ + + + /* Process the command line. + */ + for (i=1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcmp (argv[i], "-w") == 0) + px = atoi (argv[++i]); + else if (strcmp (argv[i], "-h") == 0) + py = atoi (argv[++i]); + else if (strcmp (argv[i], "-i") == 0) + invert++; + } else { + /* input sgi-bitmap file specification */ + if (numin < MAX_INFILES) + infile[numin++] = argv[i]; + } + + } + + /* Allocate some space for the working buffer. */ + len_buf = px / NBITS_CHAR; + buffer = (byte *) malloc (len_buf); + + /* Loop over the input bitmaps, writing the converted output to + * the stdout. + */ + for (index = 0; index == 0 || index < numin; index++) { + + /* Open the input file. */ + fd = (infile[index] ? fopen (infile[index], "r") : stdin); + + if (index > 0) printf ("\n"); + + printf ("#define xbm%03d_width %d\n", index, px); + printf ("#define xbm%03d_height %d\n", index, py); + printf ("static char xbm%03d_bits[] = {\n ", index); + + n = 0; + cnt = 0; + while (fread (buffer, len_buf, 1, fd)) { + /* If we're on a MSB ordered machine wordswap the bitmap so + * it's in the correct order for unpacking to be interpreted + * as an LSB-ordered image. + */ + if (!isSwapped ()) + bswap4 (buffer, buffer, len_buf); + + /* Write out the pixels. */ + for (i=0; i < len_buf; i++, cnt++) { + printf ("0x%.2x", + (byte) (invert ? ~buffer[i]: buffer[i])), n += 4; + if (cnt < (len_buf * py - 1)) + printf (","), n++; + else + printf ("};\n"); + if (n > 70) + printf ("\n "), n=0; + } + } + + if (fd != stdin) + fclose (fd); + fflush (fd); + } + free (buffer); + + return (0); +} diff --git a/unix/gdev/sgidev/sgiUtil.c b/unix/gdev/sgidev/sgiUtil.c new file mode 100644 index 00000000..25214450 --- /dev/null +++ b/unix/gdev/sgidev/sgiUtil.c @@ -0,0 +1,132 @@ +/** + * SGIUTIL.C -- Shared utility procedures for the SGI translators. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#define import_spp +#define import_error +#include <iraf.h> + + +/** + * BSWAP2 -- Move bytes from array "a" to array "b", swapping successive + * pairs of bytes. The two arrays may be the same but may not be offset + * and overlapping. + */ +void +bswap2 ( + unsigned char *a, /* input array */ + unsigned char *b, /* output array */ + int nbytes /* number of bytes to swap */ +) +{ + register unsigned char *ip, *op, *otop; + register unsigned int temp; + + ip = a; + op = b; + otop = op + (nbytes & ~1); + + /* Swap successive pairs of bytes. + */ + while (op < otop) { + temp = *ip++; + *op++ = *ip++; + *op++ = temp; + } + + /* If there is an odd byte left, move it to the output array. + */ + if (nbytes & 1) + *op = *ip; +} + + +/* BSWAP4 - Move bytes from array "a" to array "b", swapping the four bytes + * in each successive 4 byte group, i.e., 12345678 becomes 43218765. + * The input and output arrays may be the same but may not partially overlap. +*/ +void +bswap4 ( + unsigned char *a, /* input array */ + unsigned char *b, /* output array */ + int nbytes /* number of bytes to swap */ +) +{ + register int n; + register unsigned char *ip, *op, *tp; + static unsigned char temp[4]; + + tp = temp; + ip = (unsigned char *)a; + op = (unsigned char *)b; + + /* Swap successive four byte groups. + */ + for (n = nbytes >> 2; --n >= 0; ) { + *tp++ = *ip++; + *tp++ = *ip++; + *tp++ = *ip++; + *tp++ = *ip++; + *op++ = *--tp; + *op++ = *--tp; + *op++ = *--tp; + *op++ = *--tp; + } + + /* If there are any odd bytes left, move them to the output array. + * Do not bother to swap as it is unclear how to swap a partial + * group, and really incorrect if the data is not modulus 4. + */ + for (n = nbytes & 03; --n >= 0; ) + *op++ = *ip++; +} + + +/** + * ISSWAPPED -- Test whether we are running on a byte-swapped machine. + */ +int +isSwapped (void) +{ + union { + short tswap; + char b[2]; + } test; + + test.tswap = 1; + return ((int) test.b[0]); +} + + +/** + * GET_IARG -- Get an integer argument, whether appended directly to flag + * or separated by a whitespace character; if error, report and assign + * default. + */ +int +get_iarg ( + char argp, + char **argv, + int argno, + int def_val +) +{ + int temp_val; + + if (argp == (char) 0) { + if (argv[argno+1] == NULL) { + fprintf (stderr, "missing arg to switch `%c';", argp); + fprintf (stderr, " reset to %d\n", def_val); + temp_val = def_val; + } else + temp_val = atoi (argv[++argno]); + } else + temp_val = atoi (argv[argno]+2); + + return (temp_val); +} diff --git a/unix/gdev/sgidev/sgiUtil.h b/unix/gdev/sgidev/sgiUtil.h new file mode 100644 index 00000000..9630a03e --- /dev/null +++ b/unix/gdev/sgidev/sgiUtil.h @@ -0,0 +1,10 @@ +/** + * SGIUTIL.H -- Declarations for the SGI utility routines. + */ + +void bswap2 (unsigned char *a, unsigned char *b, int nbytes); +void bswap4 (unsigned char *a, unsigned char *b, int nbytes); + +int isSwapped (void); + +int get_iarg (char argp, char **argv, int argno, int def_val); diff --git a/unix/gdev/sgidev/sgidispatch.c b/unix/gdev/sgidev/sgidispatch.c new file mode 100644 index 00000000..90201460 --- /dev/null +++ b/unix/gdev/sgidev/sgidispatch.c @@ -0,0 +1,70 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define import_spp +#define import_error +#define import_kernel +#define import_knames +#include <iraf.h> + + +/* + * SGIDISPATCH.C -- Determine pathname to the executable for the named SGI + * translator, and execute the translator. Pass all command line arguments + * to the child, which also inherits stdin, stdout, and stderr. + * + * Usage: sgidispatch translator [args] + */ + +#define DEF_HOST "unix" /* default host system */ +#define F_OK 0 /* access mode `file exists' */ +#ifndef X_OK +#define X_OK 1 /* access mode `executable' */ +#endif + +char *irafpath(); + + +/* MAIN -- Main entry point for SGIDISPATCH. + */ +int +main (int argc, char *argv[]) +{ + char tpath[SZ_PATHNAME+1]; + char translator[SZ_PATHNAME+1]; + int ip; + + /* Do nothing if called with no arguments. + */ + if (argc < 2) + exit (OSOK); + + /* Construct pathname to translator. + */ + strcpy (translator, argv[1]); + ip = strlen (translator); + if (strcmp (&translator[ip], ".e") != 0) + strcat (translator, ".e"); + sprintf (tpath, "%s", irafpath(translator)); + + if (access (tpath, X_OK) == ERR) { + fprintf (stderr, "Fatal (sgidispatch): unable to access SGI"); + fprintf (stderr, " translator `%s'\n", tpath); + fflush (stderr); + exit (OSOK+1); + } + + /* Set up i/o for translator and attempt to fork. + */ + argv[argc] = 0; + execv (tpath, &argv[1]); + fprintf (stderr, "Fatal (sgidispatch): unable to execv(%s, ...)\n", + tpath); + fflush (stderr); + exit (OSOK+1); +} diff --git a/unix/gdev/zfiogd.x b/unix/gdev/zfiogd.x new file mode 100644 index 00000000..a401f9ff --- /dev/null +++ b/unix/gdev/zfiogd.x @@ -0,0 +1,420 @@ +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +include <mach.h> +include <fio.h> + +# ZFIOGD -- FIO device driver for the interactive binary graphics devices. +# This code is host system dependent (at least in part) as well as node +# dependent, since the set of graphics devices available on a particular node +# can vary greatly. The devices for which driver subroutines are linked +# into this particular version of ZFIOGD are listed below. The individual +# driver subroutines must be named explicitly in the case statements in +# each generic driver subroutine. + +define DEVICES "|iism70|iism75|imtool|" +define DEF_OSDEV_1 "unix:/tmp/.IMT%d" +define DEF_OSDEV_2 "fifo:/dev/imt1i:/dev/imt1o" +define IMTDEV "IMTDEV" +define DELIMCH ',' + +define SZ_OSDEV 512 # device specification string +define MAXDEV 8 +define MAXBYTES 4000 # fifo transfer size, bytes +define MAXTRYS 50 # fifo timeout +define DELAY 10 # fifo i/o interval, msec + +define IISM70 1 # IIS Model 70 image display +define IISM75 2 # IIS Model 75 image display +define IMTOOL 3 # IMTOOL-type display server +define NDEVICES 3 + + +# ZOPNGD -- Open a binary graphics device. The format of the DEVINFO string +# is "devname:osdev" (the KI will have already taken care of any network +# node prefix by the time we are called). + +procedure zopngd (devinfo, mode, chan) + +char devinfo[ARB] #I PACKED device info string +int mode #I access mode +int chan #O receives assigned channel + +bool first_time +pointer devname, envname +pointer sp, info, imtdev, osdev, pkfname, ip, op +int nchars, dev, oschan, arg1, arg2, i +int strdic(), ctoi() +data first_time /true/ +define err_ 91 + +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + call smark (sp) + call salloc (info, SZ_OSDEV, TY_CHAR) + call salloc (osdev, SZ_OSDEV, TY_CHAR) + call salloc (imtdev, SZ_OSDEV, TY_CHAR) + call salloc (pkfname, SZ_OSDEV, TY_CHAR) + call salloc (devname, SZ_FNAME, TY_CHAR) + call salloc (envname, SZ_FNAME, TY_CHAR) + + if (first_time) { + do i = 1, MAXDEV + gd_dev[i] = NULL + first_time = false + } + + # Parse device specification. + # ----------------------------- + call strupk (devinfo, Memc[info], SZ_OSDEV) + + # Extract generic device name. + op = devname + for (ip=info; Memc[ip] != EOS && Memc[ip] != DELIMCH; ip=ip+1) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[op] = EOS + if (Memc[ip] == DELIMCH) + ip = ip + 1 + else + goto err_ + + # Look up the generic device name in the device table. + dev = strdic (Memc[devname], Memc[osdev], 0, DEVICES) + if (dev <= 0) + goto err_ + + # Get the OS device name. + op = osdev + for (; Memc[ip] != EOS && Memc[ip] != DELIMCH; ip=ip+1) { + Memc[op] = Memc[ip] + op = op + 1 + } + Memc[op] = EOS + if (Memc[ip] == DELIMCH) + ip = ip + 1 + + # Get any optional integer arguments. + if (ctoi (Memc, ip, arg1) <= 0) + arg1 = 0 + if (Memc[ip] == DELIMCH) + ip = ip + 1 + if (ctoi (Memc, ip, arg2) <= 0) + arg2 = 0 + + # Edit device specification as necessary. + # ------------------------------------------ + + # If the generic device is IMTOOL and we have an old style OS device + # name, convert it to the format required by the ND driver. If the + # OS device name is null supply the default value. If the user has + # "IMTDEV" defined in their host environment this overrides the value + # passed in the argument list. + + if (dev == IMTOOL) { + call strpak (IMTDEV, Memc[envname], SZ_FNAME) + call zgtenv (Memc[envname], Memc[imtdev], SZ_OSDEV, nchars) + + if (nchars > 0) { + # Environment override. + call strupk (Memc[imtdev], Memc[osdev], SZ_OSDEV) + + } else if (Memc[osdev] == '/') { + # Old style device name. Convert to the form "fifo:in:out". + call strcpy ("fifo:", Memc[imtdev], SZ_OSDEV) + call strcat (Memc[osdev], Memc[imtdev], SZ_OSDEV) + call strcat ("i:", Memc[imtdev], SZ_OSDEV) + call strcat (Memc[osdev], Memc[imtdev], SZ_OSDEV) + call strcat ("o", Memc[imtdev], SZ_OSDEV) + call strcpy (Memc[imtdev], Memc[osdev], SZ_OSDEV) + } + } + + # Allocate a slot in the GD device table for the device. We need this + # to vector to the correct sub-driver when an i/o function is called. + + for (chan=1; chan <= MAXDEV; chan=chan+1) + if (gd_dev[chan] == NULL) + break + if (chan > MAXDEV) + goto err_ + + # Try to physically open the device. [ADD NEW DEVICES HERE]. + switch (dev) { + case IISM70: + call strpak (Memc[osdev], Memc[pkfname], SZ_OSDEV) + call zopm70 (Memc[pkfname], mode, oschan) + case IISM75: + call strpak (Memc[osdev], Memc[pkfname], SZ_OSDEV) + call zopm75 (Memc[pkfname], mode, oschan) + + case IMTOOL: + if (Memc[osdev] == EOS) { + # Supply default value. + call strpak (DEF_OSDEV_1, Memc[pkfname], SZ_OSDEV) + call zopnnd (Memc[pkfname], mode, oschan) + if (oschan == ERR) { + call strpak (DEF_OSDEV_2, Memc[pkfname], SZ_OSDEV) + call zopnnd (Memc[pkfname], mode, oschan) + } + } else { + call strpak (Memc[osdev], Memc[pkfname], SZ_OSDEV) + call zopnnd (Memc[pkfname], mode, oschan) + } + + default: + oschan = ERR + } + + if (oschan == ERR) + goto err_ + + gd_dev[chan] = dev + gd_oschan[chan] = oschan + gd_status[chan] = OK + gd_arg1[chan] = arg1 + gd_arg2[chan] = arg2 + + call sfree (sp) + return +err_ + chan = ERR + call sfree (sp) +end + + +# ZCLSGD -- Close a binary graphics device. + +procedure zclsgd (chan, status) + +int chan #I channel assigned device +int status #O receives status of close + +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + # [ADD NEW DEVICES HERE]. + + if (chan < 1 || chan > MAXDEV) { + status = ERR + return + } + + switch (gd_dev[chan]) { + case IISM70: + call zclm70 (gd_oschan[chan], status) + case IISM75: + call zclm75 (gd_oschan[chan], status) + case IMTOOL: + call zclsnd (gd_oschan[chan], status) + default: + status = ERR + } + + gd_dev[chan] = NULL +end + + +# ZARDGD -- Read from a binary graphics device. + +procedure zardgd (chan, buf, maxbytes, offset) + +int chan # channel assigned device +char buf[ARB] # buffer to be filled +int maxbytes # max bytes to read +long offset # file offset (function code else zero) + +int nread, nleft, ntries, n, op +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + gd_status[chan] = OK + + # [ADD NEW DEVICES HERE]. + + switch (gd_dev[chan]) { + case IISM70: + call zrdm70 (gd_oschan[chan], buf, maxbytes, offset) + case IISM75: + call zrdm75 (gd_oschan[chan], buf, maxbytes, offset) + + case IMTOOL: + # Nothing special here, except that we can only move 4096 bytes at + # a time through the pipe to the display server. Some provision + # for timeout is necessary in the event that the sender dies during + # the transfer. + # + # [we don't need all this for the ND driver, but there is still + # a 4096 byte limit for fifo's, so leave this in for now.] + + nread = 0 + ntries = 0 + op = 1 + + for (nleft=maxbytes; nleft > 0; ) { + n = min (nleft, MAXBYTES) + call zardnd (gd_oschan[chan], buf[op], n, offset) + call zawtnd (gd_oschan[chan], n) + if (n < 0) { + nread = ERR + break + } + + nread = nread + n + op = op + n / SZB_CHAR + nleft = nleft - n + if (n == 0) + call zwmsec (DELAY) + + ntries = ntries + 1 + if (ntries > MAXTRYS) { + nread = ERR + break + } + } + + gd_status[chan] = nread + + default: + gd_status[chan] = ERR + } +end + + +# ZAWRGD -- Write to a binary graphics device. + +procedure zawrgd (chan, buf, nbytes, offset) + +int chan # channel assigned device +char buf[ARB] # buffer containing the data +int nbytes # nbytes to be written +long offset # file offset (function code else zero) + +int nwrote, nleft, ntries, n, ip +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + gd_status[chan] = OK + + # [ADD NEW DEVICES HERE]. + + switch (gd_dev[chan]) { + case IISM70: + call zwrm70 (gd_oschan[chan], buf, nbytes, offset) + case IISM75: + call zwrm75 (gd_oschan[chan], buf, nbytes, offset) + + case IMTOOL: + nwrote = 0 + ntries = 0 + ip = 1 + + for (nleft=nbytes; nleft > 0; ) { + n = min (nleft, MAXBYTES) + call zawrnd (gd_oschan[chan], buf[ip], n, offset) + call zawtnd (gd_oschan[chan], n) + if (n < 0) { + nwrote = ERR + break + } + + ip = ip + n / SZB_CHAR + nwrote = nwrote + n + nleft = nleft - n + if (n == 0) + call zwmsec (DELAY) + + ntries = ntries + 1 + if (ntries > MAXTRYS) { + nwrote = ERR + break + } + } + + gd_status[chan] = nwrote + + default: + gd_status[chan] = ERR + } +end + + +# ZAWTGD -- Wait for i/o to a binary graphics device. + +procedure zawtgd (chan, status) + +int chan # channel assigned device +int status # receives nbytes transferred or ERR + +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + if (gd_status[chan] == ERR) { + status = ERR + return + } + + # [ADD NEW DEVICES HERE]. + + switch (gd_dev[chan]) { + case IISM70: + call zwtm70 (gd_oschan[chan], status) + case IISM75: + call zwtm75 (gd_oschan[chan], status) + case IMTOOL: + status = gd_status[chan] + default: + status = ERR + } +end + + +# ZSTTGD -- Get the file status of a binary graphics device. + +procedure zsttgd (chan, what, lvalue) + +int chan # channel assigned device +int what # status parameter being queried +long lvalue # receives value of parameter + +int gd_dev[MAXDEV], gd_oschan[MAXDEV] +int gd_status[MAXDEV], gd_arg1[MAXDEV], gd_arg2[MAXDEV] +common /zgdcom/ gd_dev, gd_oschan, gd_status, gd_arg1, gd_arg2 + +begin + # [ADD NEW DEVICES HERE]. + + switch (gd_dev[chan]) { + case IISM70: + call zstm70 (gd_oschan[chan], what, lvalue) + case IISM75: + call zstm75 (gd_oschan[chan], what, lvalue) + + case IMTOOL: + switch (what) { + case FSTT_FILSIZE: + lvalue = gd_arg1[chan] * gd_arg2[chan] * SZB_CHAR + case FSTT_BLKSIZE: + lvalue = gd_arg1[chan] * SZB_CHAR + case FSTT_OPTBUFSIZE: + lvalue = gd_arg1[chan] * SZB_CHAR + case FSTT_MAXBUFSIZE: + lvalue = 32768 + default: + lvalue = ERR + } + default: + lvalue = ERR + } +end |