aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/tv/iis/ids
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/images/tv/iis/ids')
-rw-r--r--pkg/images/tv/iis/ids/doc/Imdis.hlp793
-rw-r--r--pkg/images/tv/iis/ids/doc/Note.misc8
-rw-r--r--pkg/images/tv/iis/ids/doc/Note.pixel106
-rw-r--r--pkg/images/tv/iis/ids/doc/file.doc90
-rw-r--r--pkg/images/tv/iis/ids/doc/iis.doc172
-rw-r--r--pkg/images/tv/iis/ids/font.com207
-rw-r--r--pkg/images/tv/iis/ids/font.h29
-rw-r--r--pkg/images/tv/iis/ids/idscancel.x19
-rw-r--r--pkg/images/tv/iis/ids/idschars.x20
-rw-r--r--pkg/images/tv/iis/ids/idsclear.x16
-rw-r--r--pkg/images/tv/iis/ids/idsclose.x19
-rw-r--r--pkg/images/tv/iis/ids/idsclosews.x15
-rw-r--r--pkg/images/tv/iis/ids/idscround.x61
-rw-r--r--pkg/images/tv/iis/ids/idsdrawch.x67
-rw-r--r--pkg/images/tv/iis/ids/idsescape.x115
-rw-r--r--pkg/images/tv/iis/ids/idsfa.x16
-rw-r--r--pkg/images/tv/iis/ids/idsfaset.x18
-rw-r--r--pkg/images/tv/iis/ids/idsflush.x18
-rw-r--r--pkg/images/tv/iis/ids/idsfont.x40
-rw-r--r--pkg/images/tv/iis/ids/idsgcell.x170
-rw-r--r--pkg/images/tv/iis/ids/idsgcur.x33
-rw-r--r--pkg/images/tv/iis/ids/idsinit.x172
-rw-r--r--pkg/images/tv/iis/ids/idsline.x30
-rw-r--r--pkg/images/tv/iis/ids/idslutfill.x36
-rw-r--r--pkg/images/tv/iis/ids/idsopen.x58
-rw-r--r--pkg/images/tv/iis/ids/idsopenws.x120
-rw-r--r--pkg/images/tv/iis/ids/idspcell.x178
-rw-r--r--pkg/images/tv/iis/ids/idspl.x61
-rw-r--r--pkg/images/tv/iis/ids/idsplset.x21
-rw-r--r--pkg/images/tv/iis/ids/idspm.x56
-rw-r--r--pkg/images/tv/iis/ids/idspmset.x19
-rw-r--r--pkg/images/tv/iis/ids/idspoint.x65
-rw-r--r--pkg/images/tv/iis/ids/idsreset.x56
-rw-r--r--pkg/images/tv/iis/ids/idsrestore.x84
-rw-r--r--pkg/images/tv/iis/ids/idssave.x82
-rw-r--r--pkg/images/tv/iis/ids/idsscur.x12
-rw-r--r--pkg/images/tv/iis/ids/idsstream.x16
-rw-r--r--pkg/images/tv/iis/ids/idstx.x428
-rw-r--r--pkg/images/tv/iis/ids/idstxset.x30
-rw-r--r--pkg/images/tv/iis/ids/idsvector.x122
-rw-r--r--pkg/images/tv/iis/ids/mkpkg43
-rw-r--r--pkg/images/tv/iis/ids/testcode/README2
-rw-r--r--pkg/images/tv/iis/ids/testcode/box.x83
-rw-r--r--pkg/images/tv/iis/ids/testcode/boxin.x98
-rw-r--r--pkg/images/tv/iis/ids/testcode/crin.x130
-rw-r--r--pkg/images/tv/iis/ids/testcode/grey.x90
-rw-r--r--pkg/images/tv/iis/ids/testcode/grin.x98
-rw-r--r--pkg/images/tv/iis/ids/testcode/scr.x130
-rw-r--r--pkg/images/tv/iis/ids/testcode/scrin.x130
-rw-r--r--pkg/images/tv/iis/ids/testcode/sn.x192
-rw-r--r--pkg/images/tv/iis/ids/testcode/t_giis.x67
-rw-r--r--pkg/images/tv/iis/ids/testcode/zm.x64
-rw-r--r--pkg/images/tv/iis/ids/testcode/zmin.x84
-rw-r--r--pkg/images/tv/iis/ids/testcode/zztest.x81
54 files changed, 4970 insertions, 0 deletions
diff --git a/pkg/images/tv/iis/ids/doc/Imdis.hlp b/pkg/images/tv/iis/ids/doc/Imdis.hlp
new file mode 100644
index 00000000..0ddd46e5
--- /dev/null
+++ b/pkg/images/tv/iis/ids/doc/Imdis.hlp
@@ -0,0 +1,793 @@
+.help imdis Dec84 "Image Display I/O"
+.ce
+\fBImage display I/O Design\fR
+.ce
+Richard Wolff
+.ce
+May 1985
+.sp 1
+.nh
+Introduction
+
+ The image display i/o interface uses the features of the GIO interface
+to provide for the reading and writing of images and for the control of
+the various subunits of a typical image display device. The cell array
+calls of GIO are used for the image data, while the text and polyline
+functions handle the text and line generation. Cursor reads are also
+done with standard GIO calls. However, all the other display functions
+are implemented through a series of GIO escape sequences, which are
+described in this document.
+.sp
+.nh
+Escape sequences
+
+ Each sequence is described here, giving first a line with the count
+of the number of words in the escape "instruction", followed by the data.
+Since most of the data items might be more rationally considered arrays,
+they are so indicated here. This means that in most cases, the number of
+words in the escape instruction cannot be determined until run-time; an
+indication of this is the use of "sizeof(arrays)" to indicate the number
+of words in all the pseudo arrays.
+.sp
+Escape 10 -- reset
+.ls
+.tp 5
+1 hard/medium/soft
+.ls
+.nf
+hard Clear image and graphics planes
+medium reset all (lookup) tables to linear
+soft reset scroll, zoom, cursor, alu, etc.
+.fi
+.le
+.le
+.sp
+This sequence is used to preform various reset commands. These are not
+done at GKOPENWS time because the user will not necessarily want to
+upset the existing display when the image kernel is started up.
+.sp
+Escape 11 -- set image plane
+.ls
+.tp 4
+sizeof(arrays) IFA IBPL
+.ls
+.nf
+IFA(i) image frame array
+IBPL(i) image bit plane array
+.fi
+.le
+.le
+.sp
+This sequence is essentially a header to the getcell/putcell calls. It
+identifies both the frame(s) and bit plane(s) to be read or written. IFA
+is an array of (short) integers, each of which specifies a plane (using
+one indexing), the last element of the array being the integer IDS_EOD
+to flag the End Of Data. IDS_EOD is a defined to be (-2). IBPL represents
+the bit planes that are to be read or written for all the frames in IFA.
+The data is IBPL is terminated with IDS_EOD. If the first element of IFA (or
+IBPL) is IDS_EOD, all image frames (all bit planes) are involved in the I/O.
+All "array" data are expected to be terminated with IDS_EOD, and the general
+convention is maintained that IDS_EOD with no preceding data implies all
+"frames", "colors", or whatever.
+.sp
+Escape 12 -- set graphics plane
+.ls
+.tp 4
+sizeof(arrays) GFA GBPL
+.ls
+.nf
+GFA(i) graphics frame array
+GBPL(i) graphics bit plane array
+.fi
+.le
+.le
+.sp
+This sequence is identical to escape 11, but refers to graphics planes
+instead of image planes. Generally, each graphics bit plane will refer to
+a particular color, or perhaps, to a particular image plane. But there is
+no enforced correspondence between graphics planes and image planes or colors.
+The GFA specifies a set of graphics planes, and is probably unnecessary as the
+bitplane array carries adequate information. Including it, however, retains
+symmetry with escape 11. Thus, GFA cannot be omitted, for otherwise the
+kernel would not know where GBPL started, but is set to IDS_EOD, and the
+kernel can then find and ignore it.
+.sp
+Escape 13 -- display image
+.ls
+.tp 6
+1+sizeof(arrays) ON/OFF IFA ICOLOR IQUAD
+.ls
+.nf
+ON/OFF turn frame on or off
+IFA(i) image frame array
+ICOLOR(i) image color array
+IQUAD(i) image quadrant array (for split screen mode)
+.fi
+.le
+.le
+.sp
+The specified image planes are all to be displayed in all the colors given
+by ICOLOR. If ICOLOR(1) is IDS_EOD, a full color display is implied.
+The quadrant value specifies which quadrant the frames are
+to appear in--this is needed only when the split screen mode is in effect;
+otherwise, IQUAD[1] = IDS_EOD.
+.sp
+Escape 14 -- display graphics
+.ls
+.tp 6
+1+sizeof(arrays) ON/OFF GBPL GCOLOR GQUAD
+.ls
+.nf
+ON/OFF turn referenced planes on or off
+GBPL(i) graphics bit plane array
+GCOLOR(i) graphics color array
+GQUAD(i) graphics quadrant array (for split screen mode)
+.fi
+.le
+.le
+.sp
+This sequence is identical to escape 13, except for the substitution of
+a bitplane array for frames, since graphics are usually treated bit by bit.
+[With the IIS systems, for instance, this call requires manipulation of
+the color-graphics lookup table.]
+.sp
+Escape 15 -- save device state
+.ls
+.tp 5
+1+sizeof(arrays) FD IFA GFA
+.ls
+.nf
+FD file descriptor for save file
+IFA(i) image frame array
+GFA(i) graphics frame array
+.fi
+.le
+.le
+.sp
+Saves the specified image frames and graphics planes and all the device
+dependent status information in the file referenced by FD. Not implemented
+in the Kernel (yet).
+.sp
+Escape 16 -- restore device state
+.ls
+.tp 5
+1+sizeof(arrays) FD IFA GFA
+.ls
+.nf
+FD file descriptor for restore file
+IFA(i) image frame array
+GFA(i) graphics frame array
+.fi
+.le
+.le
+.sp
+Restores the specified image frames and graphics planes and all the device
+dependent status information from the file referenced by FD. Not implemented
+in the Kernel (yet).
+.sp
+Escape 17 -- control
+.ls
+.tp 9
+4+sizeof(arrays) REG RW N FRAME COLOR OFFSET DATA
+.ls
+.nf
+REG(i) control register or function
+RW(i) read or write (write is 0, read 1, wait/read is 2)
+N(i) Number of data values
+FRAME(i) frame array
+COLOR(i) color array
+OFFSET(i) offset or other datum
+DATA(Ni) array of data
+.fi
+.le
+.le
+.sp
+Escape 18 is a very general sequence for writing any device
+control register. Such "registers" include such generally available
+capabilities as look-up tables, as well as specifics, such as min/max
+registers. The upper level code may have to consult an "imagecap"
+file to determine what it can request.
+
+FRAME, OFFSET, and COLOR, may not be needed for a particular operation,
+but these arrays cannot be omitted; rather, use a one element array with
+the value IDS_EOD. Should additional information be needed for an operation,
+it can be transmitted in DATA.
+.sp
+.nh
+Examples
+
+.sp
+To clear all frames, one would issue the following sequence
+.ls
+.tp 4
+.nf
+GKI_ESCAPE 11 IFA[1] = IDS_EOD IBPL[1] = IDS_EOD
+GKI_CLEARWS
+GKI_ESCAPE 12 IFA[1] = IDS_EOD IBPL[1] = IDS_EOD
+GKI_CLEARWS
+.fi
+.le
+.sp
+To write an image to frame 2 ( IIS internal frame number 1 )
+.ls
+.tp 2
+.nf
+GKI_ESCAPE 11 IFA[1] = 2 IFA[2] = IDS_EOD IBPL[1] = IDS_EOD
+GKI_PCELL data
+.fi
+.le
+.sp
+To activate frame 1 in red and green
+.ls
+.tp 2
+.nf
+GKI_ESCAPE 13 IFA[1] = 1 IFA[2] = IDS_EOD ICOLOR[1] = IDS_RED
+ ICOLOR[2] = IDS_GREEN ICOLOR[3] = IDS_EOD
+ IQUAD[1] = IDS_EOD
+.fi
+.le
+.sp
+.bp
+.nh
+Defines
+
+This section presents the value and intended use of each of the various
+defined constants. This list is likely to expand.
+
+.nf
+define IDS_EOD (-2) # flag for end of data
+
+define IDS_RESET 10 # escape 10
+define IDS_R_HARD 0 # hard reset
+define IDS_R_MEDIUM 1 # medium
+define IDS_R_SOFT 2
+define IDS_R_SNAPDONE 3 # end snap
+
+define IDS_SET_IP 11 # escape 11
+define IDS_SET_GP 12 # escape 12
+define IDS_DISPLAY_I 13 # escape 13
+define IDS_DISPLAY_G 14 # escape 14
+define IDS_SAVE 15 # escape 15
+define IDS_RESTORE 16 # escape 16
+
+# max sizes
+
+define IDS_MAXIMPL 16 # maximum number of image planes
+define IDS_MAXGRPL 16 # maximum number of graphics planes
+define IDS_MAXBITPL 16 # maximum bit planes per frame
+define IDS_MAXGCOLOR 8 # maximum number of colors (graphics)
+define IDS_MAXDATA 8192 # maximum data structure in display
+
+define IDS_RED 1
+define IDS_GREEN 2
+define IDS_BLUE 3
+define IDS_YELLOW 4
+define IDS_RDBL 5
+define IDS_GRBL 6
+define IDS_WHITE 7
+define IDS_BLACK 8
+
+define IDS_QUAD_UR 1 # upper right quad.: split screen mode
+define IDS_QUAD_UL 2
+define IDS_QUAD_LL 3
+define IDS_QUAD_LR 4
+
+define IDS_CONTROL 17 # escape 17
+define IDS_CTRL_LEN 6
+define IDS_CTRL_REG 1 # what to control
+define IDS_CTRL_RW 2 # read/write field in control instr.
+define IDS_CTRL_N 3 # count of DATA items
+define IDS_CTRL_FRAME 4 # pertinent frame(s)
+define IDS_CTRL_COLOR 5 # and color
+define IDS_CTRL_OFFSET 6 # generalized "register"
+define IDS_CTRL_DATA 7 # data array
+
+define IDS_WRITE 0 # write command
+define IDS_READ 1 # read command
+define IDS_READ_WT 2 # wait for action, then read
+define IDS_OFF 1 # turn whatever off
+define IDS_ON 2
+define IDS_CBLINK 3 # cursor blink
+define IDS_CSHAPE 4 # cursor shape
+
+define IDS_CSTEADY 1 # cursor blink - steady (no blink)
+define IDS_CFAST 2 # cursor blink - fast
+define IDS_CMEDIUM 3 # cursor blink - medium
+define IDS_CSLOW 4 # cursor blink - slow
+
+define IDS_FRAME_LUT 1 # look-up table for image frame
+define IDS_GR_MAP 2 # graphics color map...lookup table per
+ # se makes little sense for bit plane
+define IDS_INPUT_LUT 3 # global input lut
+define IDS_OUTPUT_LUT 4 # final lut
+define IDS_SPLIT 5 # split screen coordinates
+define IDS_SCROLL 6 # scroll coordinates
+define IDS_ZOOM 7 # zoom magnification
+define IDS_OUT_OFFSET 8 # output bias
+define IDS_MIN 9 # data minimum
+define IDS_MAX 10 # data maximum
+define IDS_RANGE 11 # output range select
+define IDS_HISTOGRAM 12 # output data histogram
+define IDS_ALU_FCN 13 # arithmetic feedback function
+define IDS_FEEDBACK 14 # feedback control
+define IDS_SLAVE 15 # auxiliary host or slave processor
+
+define IDS_CURSOR 20 # cursor control - on/off/blink/shape
+define IDS_TBALL 21 # trackball control - on/off
+define IDS_DIGITIZER 22 # digitizer control - on/off
+
+define IDS_BLINK 23 # for blink request
+define IDS_SNAP 24 # snap function
+define IDS_MATCH 25 # match lookup tables
+
+# snap codes ... just reuse color codes from above.
+define IDS_SNAP_RED IDS_RED # snap the blue image
+define IDS_SNAP_GREEN IDS_GREEN # green
+define IDS_SNAP_BLUE IDS_BLUE # blue
+define IDS_SNAP_RGB IDS_BLACK # rgb image --- do all three
+define IDS_SNAP_MONO IDS_WHITE # do just one
+
+# cursor parameters
+
+define IDS_CSET 128 # number of cursors per "group"
+
+define IDS_CSPECIAL 4097 # special "cursors"
+ # must be > (IDS_CSET * number of cursor groups)
+define IDS_CRAW IDS_CSPECIAL # raw cursor read
+define IDS_BUT_RD 4098 # "cursor number" for read buttons cmd
+define IDS_BUT_WT 4099 # wait for button press, then read
+define IDS_CRAW2 4100 # a second "raw" cursor
+.fi
+.nh
+Explanation
+
+ Most of the control functions of an image display do not fit within
+the standard GIO protocols, which is why the escape function is provided.
+However, image displays exhibit a wide range of functionality, and some
+balance must be achieved between code portability/device independence and
+use of (possibly peculiar) capabilities of a particular device. The control
+functions (such as IDS_FRAME_LUT, IDS_CURSOR, IDS_SLAVE) "selected" here
+are, for the most part, general functions, but the code was written with
+the IIS Model 70 at hand (and in mind), and some "defines" reflect this.
+
+ The model of the display is a device with some number of image frames,
+each of which has associated with it an INPUT look-up table, used for
+scaling or bit selection as data is written into the image frame;
+a FRAME look-up table for each of the three primary colors, used to
+alter the video stream from the image frame; combining logic that sums the
+output of the various FRAME tables, forming three data streams, one for
+each color; an OUTPUT look-up table that forms a final transformation
+on each color prior to the data being converted to analog form; and
+possibly, bias (OUT_OFFSET) and RANGE scaling applied somewhere in the
+data stream (most likely near the OUTPUT look-up tables).
+
+ Each image plane can be SCROLLed and ZOOMed independently (though
+of course, not all devices can do this), and there may be SPLIT screen
+capability, with the possibility of displaying parts of four images
+simultaneously.
+
+ Hooks have been provided in case there is a ALU or FEEDBACK hardware,
+or there is a SLAVE processor, but use of these functions is likely to
+be quite device dependent. The IIS can return to the user the MINimum
+and MAXimum of a color data stream, and can also run a histogram on
+selected areas of the display: There are "defines" pointing to these
+functions, but their use is not yet specified and there is not yet
+a clean way, within the GIO protocols, for reading back such data.
+
+ Three functions that not so hardware oriented have "defines":
+BLINK, MATCH and SNAP. The first is used if the hardware supports
+blink. MATCH allows the kernel code to copy look-up tables---something
+the upper level code could do were there a well defined mechanism for
+reading non-image data back. SNAP is used to set-up the kernel so that
+a subsequent set of get_cellarray calls can be used to return a data
+stream that represents the digital data arriving at the
+digital-to-analog converters: the kernel mimics the hardware and so
+provides a digital snapshot of the image display screen.
+
+ Images are loaded by a series of put_cellarray calls, preceded
+by one IDS_SET_IP escape to configure the kernel to write the put_cell
+data into the correct image planes (and optionally, specific bit planes).
+The graphics planes are written to in the same manner, except that
+IDS_SET_GP is used. It is not guaranteed that the SET_IP and SET_GP
+are independent, and so the appropriate one should be given before
+each put_cell sequence. Put_cells can be done for any arbitrary
+rectangular array; they are turned into a series of writes to a
+sequence of image rows by the GIO interface code.
+
+ Calls to put_cell require the mapping of pixel coordinates
+to NDC, which is made more complex than one might first
+guess by the fact that the cell array operations are specified
+by *inclusive* end points...See the write-up in "Note.pixel".
+
+ Images planes are erased by the standard GIO gclear call, which
+must be preceded by a SET_IP (or SET_GP for graphics). This is
+perceived as reasonably consistent with the image loading as erasure
+is loading with zeros, but presumably can be done far more efficiently
+in most devices than with a series of put_cell calls.
+
+ Images planes are turned on and off with IDS_DISPLAY_I, and graphics
+planes with IDS_DISPLAY_G. Color and quadrant information must be
+supplied as mentioned in the descriptions for escapes 13 and 14.
+
+ The look-up tables are specified to the lower level code by giving
+the end points of the line segments which describe the table function.
+The end points are specified in NDC. This makes for a
+simple, and device independent, upper level code. However, there is no
+obvious (to the writer at least) code to invert the process, and return
+end points for the simplest line segments that would describe a given
+look-up table. (Moreover, there is no mechanism to return such information
+to the upper level.) Therefore, the kernel code is asymmetric, in that
+writes to the tables are fed data in the form of end points, but reads from
+the tables (needed for the kernel implementation of SNAP) return the
+requested number data values as obtained from the hardware.
+
+ The control sequence for the ZOOM function requires, in addition to
+the usual frame/color information, a zoom power followed by the GKI
+coordinates of the pixel to be placed at the screen center. Likewise,
+the SCROLL and SPLIT screen functions require GKI center coordinates.
+
+ The OFFSET and RANGE sequences provide for bias and scaling of the
+image data. Where they take effect is not specified. Offset requires
+a signed number to be added to the referenced data; range is specified
+by a small integer which selects the "range" of the data.
+
+ Control of hardware cursors, trackballs, etc is provided: CURSOR
+can be used to select cursor shape, blink rate, etc. Devices such as
+(trackball) buttons are interrogated as if they are cursors, with a
+cursor number that is greater than to IDS_CSPECIAL. The "key" value
+returned by a "read" call to devices such as the trackball buttons will
+be zero if no button was pressed or some positive number to represent
+the activated device. Any "read" may be instructed to return
+immediately (IDS_READ) or wait for some action (IDS_READ_WT); for
+buttons, there are special IDS_BUT_RD/IDS_BUT_WT.
+
+ Cursors are read and written through the standard GIO interface.
+The cursor number ranges from 1 up through IDS_CSPECIAL-1. Each
+frame has a set of set of cursors associated with it: frame n has
+cursors numbered n, IDS_CSET+n, 2*IDS_CSET+n, etc. Currently,
+IDS_CSPECIAL is 4097, and IDS_CSET is 128, so there can be 128
+different frames, each with 32 cursors. The coordinates associated
+with a given cursor, and hence frame, are NDC for the pixel on which
+the cursor is positioned. If a frame is not being displayed, a cursor
+read for that frame will return NDC for the pixel that would appear at
+the current cursor position if the frame were enabled. Note that the
+NDC used in the cursor_set and cursor_read calls are relative to
+the image planes in the display device; the fact the image data may
+have come from a much larger user "world" is not, and can not be,
+of any concern to the kernel code.
+
+ Cursor 0 is special, and is not associated with a particular frame;
+rather, the kernel is allowed to choose which frame to associate with
+each cursor zero read or write. The IIS code picks the lowest numbered
+frame that is on (being displayed). With split screen activated, a
+frame can be "on" and not be seen; for cursor zero, what matters is
+whether the frame video is active, not whether the split position
+happens to be hiding the frame. The "key" value returned by the cursor
+read routine is the frame number selected by the kernel. Cursor
+IDS_CSPECIAL is also unusual, since it refers to the screen coordinates
+and returns NDC for the screen. It is referred in the code as IDS_CRAW
+(a "raw" cursor) and is needed for positioning the cursor at specific
+points of the screen.
+
+ The MATCH function requires that the frame and color information
+of the control escape sequence point to the reference table; the
+tables to be changed are given in the "data" part with the (IDS_EOD
+terminated) frame sequence preceding the color information. The RW
+field specifies which type of look-up table is to be changed.
+.sp
+.nh
+Interface Routines
+
+ The routines listed here are those used to implement the video
+control package, and are found in the file "cvutil.x".
+Arguments relating to image frames, image colors, display quadrants,
+offset, range, and look-up table data are short integer arrays,
+terminated by IDS_EOD. Cursor position (x and y) are NDC (hence, real).
+All other arguments are integers.
+
+.ls cvclearg (frame, color)
+Clears (erases) the given color (or colors) in the graphics frame given
+by the argument "frame". For the IIS display, the "frame" argument
+is not relevant, there being only one set of graphics frames.
+.le
+.ls cvcleari (frames)
+Clears (erases) all bits in the given image display frames.
+.le
+.ls cv_rdbut
+Reads the buttons on whatever device the kernel code associates with
+this call, and returns an integer representing the button most recently
+pressed. If none pressed, returns zero.
+.le
+.ls cv_wtbut
+Same as cv_rdbut, but if no button pressed, waits until one is. This
+routine will, therefore, always return a non-zero (positive) integer.
+.le
+.ls cv_rcur (cnum, x, y)
+Reads the cursor "cnum" returning the NDC coordinates in x and y. The
+mapping of cursor number to frame is described in the preceding
+section: for cursors with numbers below IDS_CSET (128), the cursor
+refers to the frame (cnum equal 5 means frame 5).
+.le
+.ls cv_scur (cnum, x, y)
+Sets the cursor to the NDC given by x and y for the frame referenced by
+cnum.
+.le
+.ls cv_scraw (x, y)
+Sets the "raw cursor" to position (x,y).
+.le
+.ls cv_rcraw (x, y)
+Reads the "raw cursor" position in (screen) NDC.
+.le
+.ls cvcur (cmd)
+Turns the cursor on (cmd is IDS_ON) or off (IDS_OFF).
+.le
+.ls cvdisplay (instruction, device, frame, color, quad)
+Turns on ("instruction" equals IDS_ON) image plane ("device" equals
+IDS_DISPLAY_I) frame (or frames) in specified colors and quadrants.
+Turn them off if "instruction" equals IDS_OFF. Manipulates graphics
+planes instead if "device" equals IDS_DISPLAY_G.
+.le
+.ls cvmatch (type, refframe, refcolor, frames, color)
+Copies the reference frame and reference color into the given frames
+and color. For the IIS, "type" is either IDS_FRAME_LUT, referring to the
+look-up tables associated with each frame, or IDS_OUTPUT_LUT, referring
+to the global Output Function Memory tables.
+.le
+.ls cvoffset (color, data)
+Sets the offset constants for the specified colors to values given in
+"data"; if there are more colors given than corresponding data items,
+the kernel will reuse the last data item as often as necessary.
+.le
+.ls cvpan (frames, x, y)
+Moves the given frames so that the NDC position (x,y) is at the center
+of the display.
+.le
+.ls cvrange (color, range)
+Scales the output for the given colors; if there are more colors given
+than corresponding range items, the kernel will reuse the last data item
+as often as necessary. Range is a small number which specifies which
+range the data is to be "put" in. For the IIS, there are only 4 useful
+values (1,2,4, and 8); the kernel will map the requested value to the
+next smallest legitimate one.
+.le
+.ls cvreset (code)
+Resets the part of the display referenced by "code". For the IIS, a code
+of IDS_R_HARD refers to (erasing) the image and graphics planes, IDS_R_MEDIUM
+resets the various look-up tables, and IDS_R_SOFT resets the various registers
+(such as zoom, scroll, range, split screen, and so forth).
+.le
+.ls cvsnap (filename, snap_color)
+Creates an IRAF image file, named "filename", which represents the image
+display video output for the specified color (IDS_SNAP_RED, IDS_SNAP_MONO,
+etc). "filename" is a "char" array. The image is of the full display,
+though, since the data is obtained from the kernel line by line via
+get_cellarray calls, partial snapshots can be implemented easily.
+.le
+.ls cvsplit (x,y)
+Sets the split screen point at NDC position (x,y).
+.le
+.ls cvtext (x, y, text, size)
+Writes the given text at NDC position (x,y) in the specified size.
+Currently, font and text direction are set to NORMAL.
+.le
+.ls cvwhich (frame)
+Tells which frames are on. In the current implementation, this relies
+on reading cursor 0: in this special case, the cursor variable passed
+to ggcur() is changed by the kernel to reflect which frame it selected
+(or ERR if no frame is active).
+.le
+.ls cvwlut (device, frames, color, data, n)
+Writes the look-up tables associated with "frames" and "color". "device"
+is IDS_FRAME_LUT or IDS_OUTPUT_LUT. The data to be written is given as
+a series of line segments, and hence is described as a series of GKI
+(x,y) pairs representing the line end points. For connected lines,
+the first pair gives the first line segment starting coordinates, and all
+following pairs the endpoints. The variable "n" gives the number of
+values in "data"; there is no terminating IDS_EOD.
+.le
+.ls cvzoom (frames, power, x, y)
+Zooms, to the given power, the specified frames with each frame
+centered, after the zoom, at the given NDC position.
+.le
+
+ The following two support routines are included in the interface
+package.
+.ls cv_move (in, out)
+Copies the short array "in" into the short array "out", up to and
+including a trailing IDS_EOD. This procedure returns the number of
+items copied.
+.le
+.ls cv_iset (frames)
+Implements the image display escape sequence, with the bitplane
+argument to that escape sequence set to "all".
+.le
+.ls cv_gset (colors)
+Implements the graphics display escape sequence, with the image
+argument to that escape sequence set to "all".
+.le
+.sp
+.nh
+Example
+
+ The following code is used to pan (scroll) the image in response
+to a changing cursor position. It is assumed that the "frame" array
+consists of a list of frames to be panned together, terminated, as
+is almost everything in this code, by IDS_EOD.
+.nf
+
+# Pan subroutine
+
+procedure pansub (frames)
+
+short frames[ARB] # frames to pan
+
+int button
+int cnum, cv_rdbut()
+real x,y, xc, yc
+real oldx, oldy
+
+begin
+ button = cv_rdbut() # clear buttons by reading them
+ call eprintf ("Press any button when done\n")
+
+ # Where is cursor now?
+ # cv_rcraw uses the "RAW CURSOR" which reads and writes in
+ # screen (NDC) coordinates instead of image NDC.
+
+ call cv_rcraw (xc,yc)
+
+ # Pixel to NDC transformation is discussed in the file
+ # "Note.pixel"
+
+ x = x_screen_center_in_NDC
+ y = y_screen_center_in_NDC
+
+ call cv_scraw (x, y) # put cursor at screen center
+
+ # Select a cursor---at least one per frame (conceptually at least)
+
+ cnum = frames[1]
+
+ # If cnum == IDS_EOD, the calling code did not select a frame. So,
+ # if cnum is 0, the kernel will select an active frame as the
+ # one to use when mapping NDC cursor positions to screen
+ # coordinates.
+
+ if (cnum == IDS_EOD)
+ cnum = 0
+
+ # Determine NDC at screen center (where cursor was moved to)
+ # for frame of interest
+ call cv_rcur (cnum, x, y)
+
+ # Restore cursor to original position
+ call cv_scraw (xc, yc)
+
+ repeat {
+ oldx = xc
+ oldy = yc
+ repeat {
+ call cv_rcraw (xc, yc)
+ button = cv_rdbut()
+ } until ( (xc != oldx) || (yc != oldy) || (button > 0))
+ # Determine change and reflect it about current screen
+ # center so image moves in direction cursor moves.
+ x = x - (xc - oldx)
+ y = y - (yc - oldy)
+ # If x or y are <0 or > 1.0, add or subtract 1.0
+ "adjust x,y"
+ call cvpan (frames, x, y)
+ } until (button > 0)
+end
+.fi
+ [The call to cvpan may in fact need to be a series of calls, with
+the array "frames" specifying one frame at a time, and (x,y) being the
+new cursor position for that particular frame, so that differently panned
+frames retain their relative offsets.]
+ The cursor and button routines are given here.
+.nf
+
+# CV_RDBUT -- read button on trackball (or whatever)
+# if none pressed, will get zero back
+
+int procedure cv_rdbut()
+
+int oldcnum
+real x, y
+int button
+int gstati
+
+include "cv.com"
+
+begin
+ oldcnum = gstati (cv_gp, G_CURSOR)
+ call gseti (cv_gp, G_CURSOR, IDS_BUT_RD)
+ call ggcur (cv_gp, x, y, button)
+ call gseti (cv_gp, G_CURSOR, oldcnum)
+ return(button)
+end
+
+# CV_RCUR -- read cursor. The cursor read/set routines do not restore
+# the cursor number...this to avoid numerous stati/seti calls that
+# usually are not needed.
+
+procedure cv_rcur (cnum, x, y)
+
+int cnum
+real x,y
+int junk
+
+include "cv.com"
+
+begin
+ call gseti (cv_gp, G_CURSOR, cnum)
+ call ggcur (cv_gp, x, y, junk)
+end
+
+# CV_SCUR -- set cursor
+
+procedure cv_scur (cnum, x, y)
+
+int cnum
+real x,y
+
+include "cv.com"
+
+begin
+ call gseti (cv_gp, G_CURSOR, cnum)
+ call gscur (cv_gp, x, y)
+end
+
+# CV_SCRAW -- set raw cursor
+
+procedure cv_scraw (x, y)
+
+real x,y
+
+begin
+ call cv_scur (IDS_CRAW, x, y)
+end
+.fi
+
+ The routine cv_move copies its first argument to the second up through
+the required IDS_EOD termination, returning the number of items copied.
+"cv_stack" is a pointer to a pre-allocated stack area that is used to
+build the data array passed to the GIO escape function.
+
+.nf
+# cvpan -- move the image(s) around
+
+procedure cvpan (frames, x, y)
+
+short frames[ARB]
+real x,y # position in NDC
+int count, cv_move()
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_SCROLL # Control Unit
+ Mems[cv_stack+1] = IDS_WRITE # Read/Write
+
+ # Three is the number of data items (two coordinates) plus the
+ # terminating IDS_EOD. In many escape sequences, this number
+ # must be determined from the data rather than known in advance.
+
+ Mems[cv_stack+2] = 3
+
+ # Move the frame data, which is of "unknown" length
+
+ count = cv_move (frames, Mems[cv_stack+3])
+
+ # Color is unimportant here, but the color data must exist. The
+ # simplest solution is to use IDS_EOD by itself.
+
+ Mems[cv_stack+3+count] = IDS_EOD # default to all colors
+ Mems[cv_stack+4+count] = 1 # (unused) offset
+ Mems[cv_stack+5+count] = x * GKI_MAXNDC
+ Mems[cv_stack+6+count] = y * GKI_MAXNDC
+ Mems[cv_stack+7+count] = IDS_EOD # for all frames
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+8)
+end
+.fi
+.endhelp
diff --git a/pkg/images/tv/iis/ids/doc/Note.misc b/pkg/images/tv/iis/ids/doc/Note.misc
new file mode 100644
index 00000000..4b3a22de
--- /dev/null
+++ b/pkg/images/tv/iis/ids/doc/Note.misc
@@ -0,0 +1,8 @@
+To implement a full device save/restore, we need:
+zdev_restore(fd)
+zdev_save(fd)
+zim_save(fd,ipl)
+zgr_save(fd,gpl)
+zim_restore(fd,ipl)
+zgr_restore(fd,gpl)
+...zgr are just entry points into zim_{save,restore}(fd,pl)
diff --git a/pkg/images/tv/iis/ids/doc/Note.pixel b/pkg/images/tv/iis/ids/doc/Note.pixel
new file mode 100644
index 00000000..91c0338f
--- /dev/null
+++ b/pkg/images/tv/iis/ids/doc/Note.pixel
@@ -0,0 +1,106 @@
+ Herein is described how pixel coordinates should be encoded into
+GKI metacode units and how this data is then converted back to pixel numbers
+by the "lower level" code. For concreteness, the discussion is based on
+a 512 x 512 display, where the pixels are numbered from 1 to 512 (one-based)
+or 0 to 511 ( zero based). Only the X axis is discussed, the Y axis
+being treated identically.
+ GKI metacode ranges from 0 through 32767, for a total of 32768
+values. In NDC coordinates, the range is from 0.0 through 1.0.
+These coordinates are show in the diagram following.
+.sp
+.nf
+last GKI coordinate of pixel
+ 63 127 191 255 319 32703 32767(!)
+pixel | | | | | | |
+extent-- |<-->||<-->||<-->||<-->||<-->|| ... |<-->||<--->|
+ | | | | | | |
+the |-----|-----|-----|-----|-----| ... |-----|-----|
+pixels | | | | | | ... | | |
+ |-----|-----|-----|-----|-----| ... |-----|-----|
+num- (1-b) 1 2 3 4 5 511 512
+bers (0-b) 0 1 2 3 4 510 511
+ | | | | | | ... | | |
+GKI 0 64 128 192 256 320 32640 32704 32767(!)
+ | | | | | | ... | | |
+NDC 0.0 1/512 2/512 3/512 4/512 5/512 511/512 1.0
+.fi
+.sp
+ The pixels are not points, but rather, in GKI/NDC space, have
+"physical" extent. In NDC coordinates, the pixel boundaries are
+easily calculated as (left boundary = zero-based pixel number / 512)
+and (right boundary = 1-based pixel number / 512). In GKI coordinates,
+each pixel spans 64 GKI units, with the left boundary given by
+"zero-based pixel number times 64". The right boundary is then the
+left boundary plus 64 and then actually references the next pixel.
+That is, the left boundary is included in the pixel, while the right
+boundary is not.
+(Pixel 0 goes from 0 through 63, pixel one from 64 through 127, etc.)
+This works for all pixels except the last one, which would have a
+right boundary of 32768; in this special case, the right boundary
+is defined to be 32767. As will be seen later on, this should cause
+no difficulties.
+ Explicit reference to a particular pixel should, in GKI
+coordinates, refer to the pixel's left (or for Y, lower) edge. Thus,
+pixel 7 (one-based system) is, in GKI, 6*64 or 384.
+ Cell arrays are denoted by their lower-left and upper-right
+corners, with the understanding that all pixels WITHIN this rectangle
+are to be read/written. Thus, an array that covers (one-based)
+(4,10) to (18, 29) implies that, in X, pixels 4 through 17 are referenced.
+Therefore, the GKI coordinate range is from 3*64 up to 17*64, where
+3*64 is the GKI coordinate for the left edge of pixel 4 and 17*64 is
+the GKI coordinate for the right edge of pixel 17. (Remember, the
+right edge of pixel 512 is 32767, not 32768.)
+ The (real) NDC coordinate that is then passed to the interface code
+is determined by dividing the GKI coordinate by 32767. The interface
+code will, ultimately, multiply by 32767 to give the GKI coordinates
+passed to the lower level.
+ The lower level code translates the GKI coordinate values into
+zero-based pixel numbers by multiplying by 512/32768 ( not 32767).
+The (real) pixel numbers so determined are then truncated, and become
+the ones to scroll to, zoom to, or put the cursor on. Therefore,
+when refering to single pixels for such operations, use the left
+boundary of the pixel as the desired GKI/NDC coordinate.
+ Pixel computation for cell arrays is somewhat more complicated.
+The right boundary of a cell array can be the left boundary for
+an adjacent cell array; if the simple truncation scheme were used, that
+coordinate would be included in both cell array operations, which is not
+acceptable (especially for hard copy devices where the resultant overplotting
+would be, at best, objectionable). This problem gives rise to the following
+algorithm. Left (and lower) positions are rounded up to the next pixel
+boundary if the fractional position is greater than or equal 0.5. Right
+(and upper) positions are rounded down to the next pixel boundary if the
+fractional position is less than 0.5; since a fractional pixel value of 0.0
+is less than 0.5, the right/upper pixel will be decreased even if it is
+already on a boundary. The truncated values are then used as the
+INCLUSIVE range of pixels to read or write. (If the positions lie
+within the same pixel, that pixel becomes the X (or Y) range. If the
+positions are in adjacent pixels, the right pixel operation is
+not done if the left pixel moves into the same pixel as the right one.)
+ With this algorithm, the right edge of the display (NDC=1.0,
+GKI=32767) becomes position 511.98, which is not rounded down as the
+fractional part is >= 0.5, and, which, when truncated, turns into 511
+which is what is desired as the (last) included pixel in the range.
+
+ For zoomed (image) displays, fractional pixel coordinates are
+possible in the sense that, for a zoom of 4, pixels 16.0, 16.25,
+16.50, and 16.75, all refer to the same datum. When setting the cursor,
+the lower level code must distinguish all these cases, which have GKI
+values (from a one-based coordinate system) 960, 976, 992, and 1008.
+The lower level code will return these fractional pixel values when reading
+the cursor, but the integral value is the real reference to the data
+point. However, calls to the getcell and putcell routines should use
+16 (aka 960) or the cell array rounding will interfere with what is
+wanted. This does restrict getcell calls from starting/ending in the middle
+of a zoomed (replicated) pixel, but makes the behavior of getcell
+the same as putcell, which cannot write into the middle of a zoomed pixel.
+
+ In summary, users should reference individual pixels by
+specifying their left (or lower) boundaries in GKI/NDC. For cursor
+reference on zoomed displays, fractional (in the sense outlined above)
+pixels may be referenced. Right (or upper) boundaries are used only
+for cell arrays, and except for the very right-most, are determined by
+the user in an operation similar to that for the left boundaries. GKI
+coordinates that are a little too large (not more than 31 units for a
+512 resolution device) will be rounded/truncated to the desired
+coordinate. For cell array operations only, ones a little too small
+will still address the correct pixel.
diff --git a/pkg/images/tv/iis/ids/doc/file.doc b/pkg/images/tv/iis/ids/doc/file.doc
new file mode 100644
index 00000000..504a8330
--- /dev/null
+++ b/pkg/images/tv/iis/ids/doc/file.doc
@@ -0,0 +1,90 @@
+Some notes on the fio system.
+ Binary files.
+ open the binary file with
+ fio_fd = fopnbf(dev_name, mode, zopn_dev, zard_dev, zawr_dev,
+ zawt_dev, zstt_dev, zcl_dev)
+ where dev_name is a char string, terminated with EOS,
+ mode is READ_ONLY, READ_WRITE, WRITE_ONLY, NEW_FILE, APPEND,
+ TEMP_FILE, NEW_COPY
+ and the z routines are for open, read, write, wait, get status,
+ and close ( see system interface reference manual).
+
+ The fio_fd that is returned is then used in calls to read, write, and flush.
+ They have the form write(fio_fd, buffer, #_of_chars)
+ read (fio_fd, buffer, #_of_chars)
+ flush(fio_fd)
+ seek (fio_fd, loffset)
+ long = note (fio_fd)
+ The output data will be buffered in a buffer of CHAR size as set by
+ a kernel call to zstt(). This can be overridden by
+ fsetl(fio_fd, F_BUFSIZE, buffer_size_in_char)
+ Partially filled buffers can be forced out by "flush".
+ Input data is buffered up before being made available to the
+ user; if an i/o call is needed to fill the buffer and it returns with
+ an inadequate number of data items, then the read returns with fewer
+ than requested itmes.
+ The file system can be made to use an external (local) buffer by
+ fseti(fio_fd, F_BUFPTR, new_buffer)
+ For general image i/o, it is desirable to set the ASYNC parameter to YES
+ fseti(fio_fd, F_ASYNC, YES)
+ If the device has a specific block size, this can be set by
+ fseti(fio_fd, F_BLKSIZE, value);
+ the file system will use this value for checking validity of block offsets
+ in reads and writes. If the value is zero, the device is considered a
+ "streaming" device, and no checks are done.
+
+(from Doug)
+The device block size parameter is set at open time by all call to ZSTT__.
+FIO is permissive and allows one to set almost anything with FSET, but some
+of the parameters are best considered read only. This is documented at the
+parameter level in <fset.h>.
+
+Image displays are NOT streaming devices, they are random access, block
+structured devices. If you wish to defeat block alignment checking then
+ZSTT__ may return a block size of 1 char. Note that not all image displays
+are addressable at the pixel level. Even those that are are may be most
+efficiently accessed using line at a time i/o (block size equals 1 line).
+
+If the block size is set to 1 FIO will still access the device in chunks
+the size of the FIO buffer. The file area is partitioned up into a series
+of "pages" the size of the FIO buffer and FIO will fault these pages in and
+out when doing i/o. The only advantages of a block size of 1 are that the
+FIO buffers may be any size (not much of an advantage), and more significantly,
+AREAD and AWRITE calls may be used to randomly access the device. The latter
+are asynchronous and are not buffered, and are the lowest level of i/o
+provided by FIO.
+
+ The form for the z routines is
+ zopn_dev(dev_name, mode, channel)
+ zard_dev(channel, buffer, length, offset)
+ zawr_dev(channel, buffer, length, offset)
+ zawt_dev(channel, bytes_read/written)
+ zstt_dev(channel, what, lvalue)
+ zcl_dev (channel, status)
+
+ where channel is some number to be used however the z routines want, but
+ in the simplest case and under UNIX, would be the file descriptor of the
+ open file as determined by zopn_dev, or, in case of error, is ERR.
+ length and offset are in BYTES. zstt_dev() will be handled locally.
+
+Bytes, yes, but the file offsets are one-indexed. See the System Interface
+reference manual.
+
+ Each of the z*_dev routines above, with the exception of zstt_dev, will
+ ultimately result in a call to one of the system z routines for binary
+ files: zopnbf, zardbf, zawrbf, zawtbf, zclsbf. These routines take
+ the same arguments as the z*_dev routines, with the exception that
+ unix_fd is to be substituted for channel. "unix_fd" is the actual
+ file descriptor that results from the "real" open of the device by
+ zopnbf. It does not need to be visible above the z*_dev routines.
+
+The FIO z-routines for a device do not necessarily resolve into calls to the
+ZFIOBF driver. It is desirable to structure things this way if we can since
+it reduces the size of the kernel, but if necessary the z-routines can be
+system dependent. Since the IIS is data driven and is interfaced in UNIX
+as a file we were able to use the existing ZFIOBF driver, resulting in a
+very clean interface. New devices should also be interfaced this way if
+possible. For various reasons a data stream interface is almost always
+preferable to a control interface (like Sebok's Peritek driver). I would
+seriously consider adding a layer on a control driven device driver to make
+it appear to be data driven, if the driver itself could not be modified.
diff --git a/pkg/images/tv/iis/ids/doc/iis.doc b/pkg/images/tv/iis/ids/doc/iis.doc
new file mode 100644
index 00000000..450de91a
--- /dev/null
+++ b/pkg/images/tv/iis/ids/doc/iis.doc
@@ -0,0 +1,172 @@
+.TL
+The IIS Image Display
+.AU
+Richard Wolff
+.br
+Central Computer Services
+National Optical Astronomy Observatories
+Tucson, Arizona
+.DA
+.PP
+The International Imaging Systems (IIS) Model 70f is a reasonably
+flexible image display with some more advanced capabilities than the IPPS,
+(and, sad to say, some less advanced ones as well). This note describes
+the hardware so that the user can use the device to best advantage.
+The Model 75, which is in use at CTIO, is more elaborate still, but its
+fundamental properties are the same as the 70f boxes in use at NOAO.
+.PP
+The image display has four image planes (frames, memories), each of which
+can hold a 512 x 512 8 bit image. (The hardware can support 12 such planes,
+but only four are installed in the NOAO units.) These planes are loaded
+directly from the host computer; while there is hardware to support a
+13-bit input/8-bit output mapping during load, this is not currently used
+at NOAO. The frames are numbered 1 through 4 and there is nothing to
+distinguish one from another. More than one image plane may be displayed
+at one time; this may create a rather messy screen image, but, of course,
+the hardware doesn't care.
+.PP
+The image is generated by hardware that
+addresses each pixel in turn, and sends the data at that location to the
+video display. Panning (scrolling/roaming) is accomplished simply by
+starting the address generation somewhere other than at the normal starting
+place.
+Each plane has its own starting address, which just means that each
+plane can be panned independently. In contrast, on the model 70,
+all planes zoom together. Zooming is done by pixel replication:
+The master address generator
+"stutters", duplicating an address 2, 4, or 8 times before moving on to
+the next pixel (and duplicating each line 2, 4, or 8 times--an additional
+complication, but a necessary one, which is of interest only to hardware types).
+The master address is then added to the per-image start address
+and the resulting address streams are used to generate
+the per-image data streams, which are added together to form the final image.
+The net result of this is an image on the screen, with user control of the
+placement of each image plane, and with one overall "magnification" factor.
+.PP
+If more than one image is active, the pixel values for a given screen
+position are \fBadded\fR together. Thus, with four image planes, each of
+which has pixels that can range in value from 0 through 255, the output
+image can have pixel values that range from 0 through 3060. Unfortunately,
+the output hardware can handle only values from 0 through 1023. But,
+fortunately, hardware has been included to allow the use to offset and
+scale the data back to the allowed output range. We will look at that
+in more detail later.
+.PP
+The hardware that determines which frames are to be displayed consists
+of "gates" that enable or disable the frame output to the image screen.
+These "gates" are controlled by various data bits in the hardware.
+Conceptually, given the description in the previous paragraphs, one can
+imagine one bit (on or off) for each image frame, and it is these
+bits that the \fBdi\fR command turns on and off. However, there are
+complications, one of which is the split screen mode. Split screen
+hardware allows the user to specify a point, anywhere on the screen,
+where the screen will be divided into (generally, unequally sized) quadrants.
+The display control bits specify not only which images will be active,
+but in which of the four quadrants they will be active.
+There are four control bits per image plane, and so, any image can
+be displayed in any number of quadrants (including none, which means the
+image is "off").
+.PP
+If one imagines the split screen point in the middle of the screen, then
+four quadrants are visible, number 1 being the upper right, number 4 the bottom
+right, etc. As the split screen point is moved to the upper left, quadrant
+four increases in size and the other three decrease. When the split point
+reaches the top left corner (\fIIRAF\fR coordinate (1,512)), only quadrant
+four is left. Due to a hardware decision, this is the normal, non-split,
+screen configuration, the one you get when you type the \fBs o\fR command.
+It would make more sense to set the non-split position so the screen was
+filled with quadrant one, but the hardware won't allow it. So, be
+warned, if you have a split screen display,
+and then reset the split point to the "unsplit" point,
+what you see will be only what you had displayed in quadrant 4.
+.PP
+The model 70f is a color display, not monochrome, and this adds more
+complexity. What happens is that the data from each enabled image plane
+is replicated and sent to three \fIcolor pipelines\fR,
+one for the \fIred\fR gun of the monitor, one for the \fIgreen\fR,
+and one for the \fIblue\fR. If the pipeline data streams are
+the same, we get a black and white image. If they differ, the
+final screen image is colored. Since there are really three data streams
+leaving each image plane, it should not be surprising that there are
+display control bits for each color, as well as each quadrant, of each
+image. Thus (and finally) there are 12 control bits, three colors in each
+of four quadrants, for each image plane. One can set up a display with
+different images in different quadrants, and each colored differently!
+Of course, the coloration is somewhat primative as the choices are limited
+to red on or off, green on or off, both red and green on (yellow), blue on
+or off, etc. More control comes with look-up tables.
+.PP
+The data from the combined image planes is added together in the pipelines.
+There are offset and range registers for each pipeline which allow you to
+bias and scale the data. Offset allows you to add or subtract a 13 bit
+number (+-4095) and range scales the data by a factor of 1,2,4, or 8.
+These are of interest mostly when more than one image is combined; in this
+case, the resulting stream of data should be adjusted so that it
+has its most interesting data in the range 0 through 1023.
+.PP
+Why 1023? The reason is that after offset and range have taken their
+toll, the data is "passed through" a 10 bit in/10 bit out look-up table.
+Look-up tables are digital functions in which each input datum is used
+as an index into a table and the resultant value that is thus "looked-up"
+replaces the datum in the data stream. The look-up tables here
+are known as the \fIoutput\fR
+tables (or, as IIS would have it, the "Output Function Memories").
+There is one for
+each of the three pipelines, and each accepts an input value of 10 bits,
+which limits the data stream to 0 through 1023,
+If the image data in the three pipelines are the same, and the output
+tables are too, then a black and white image results. If, however, the
+pipelines are identical but the tables are different, a colored image
+results. Since this image is not a true color image,
+but simply results from manipulating the three identical color
+pipelines in differing ways, the result is called a pseudo-color image.
+.PP
+The simplest look-up table is a linear function, whose input values run
+from 0 through 1023 and whose output values do the same. The trouble
+with such a linear output table is that the usual case is a single image
+being displayed, in which case the pipeline data is never more than 255.
+With the unit slope table, the maximum output would be 255, which is
+one-quarter of full intensity. A better table in this case would be one of
+slope 4, so 255 would map to 1023 (maximum output). This is what the
+default is, and above 255 input, all values are mapped to 1023. If,
+however, two images are being displayed, then data values may be larger
+than 255 (at overlap points), and as these all map to 1023, only full white
+results. The range/offset registers may be of use here, or a different
+output table should be used.
+.PP
+The output of the "output" tables is combined with the graphics and cursor
+data and sent to the display screen. The graphics planes are one bit
+deep; there are seven of them, and together with the cursor, they form
+an "image" 8 bits deep. In this sense, the graphics planes are just
+like image data, and in particular, they pan and zoom just as the
+image planes do. Of course, the cursor is different. The graphics
+planes are sent through a look-up table of their own, which determines
+what happens when one graphics plane crosses/overlaps others and/or the
+cursor. The resultant data replaces the pipeline data. The graphics
+data can be added to the pipeline data instead of replacing it, but this
+feature is not available in \fIcv\fR at this time. The cursor is really
+a writable 46x64 bit array; thus, its shape can be changed, a feature
+that may be made available to users. Note that there is no quadrant/split
+screen control for the graphics planes.
+.PP
+The final complication, at least as far as the current software is
+concerned, is that each image plane has its own set of three look-up
+tables, one for each color. Thus, there are 4x3 frame look-up tables
+and three output tables. The image tables affect only the data from
+the associated image plane. It is the output of these tables that
+forms the input to the three color pipelines. Each table is an 8 bit in/9
+bit out table, with the output being treated as a signed number (255 to
+-256). (Combining 12 9 bit numbers (a full model 70f) can produce a 13 bit
+number, which is why the offset hardware accepts 13 bit numbers.) In
+the \fIcv\fR software, only positive numbers are used as output from
+the tables. Typically, the image tables are loaded with linear
+functions of varying slope and intercept.
+.PP
+With the two sets of tables, image and output, it is possible to create
+all sorts of interesting pseudo-color images. One possibility is to
+place the appropriate three mappings in the output tables so as to create
+the color (for instance, red can be used only for pixels with large
+values, blue for low values, green for middling ones). Then the image
+tables can be set to adjust the contrast/stretch of the each image
+individually, producing, one assumes, useful and/or delightful
+pseudo-color images.
diff --git a/pkg/images/tv/iis/ids/font.com b/pkg/images/tv/iis/ids/font.com
new file mode 100644
index 00000000..ec1b0ec9
--- /dev/null
+++ b/pkg/images/tv/iis/ids/font.com
@@ -0,0 +1,207 @@
+# CHRTAB -- Table of strokes for the printable ASCII characters. Each character
+# is encoded as a series of strokes. Each stroke is expressed by a single
+# integer containing the following bitfields:
+#
+# 2 1
+# 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1
+# | | | | | | |
+# | | | +---------+ +---------+
+# | | | | |
+# | | | X Y
+# | | |
+# | | +-- pen up/down
+# | +---- begin paint (not used at present)
+# +------ end paint (not used at present)
+#
+#------------------------------------------------------------------------------
+
+# Define the database.
+
+short chridx[96] # character index in chrtab
+short chrtab[800] # stroke data to draw the characters
+
+# Index into CHRTAB of each printable character (starting with SP).
+
+data (chridx(i), i=01,05) / 1, 3, 12, 21, 30/
+data (chridx(i), i=06,10) / 45, 66, 79, 85, 92/
+data (chridx(i), i=11,15) / 99, 106, 111, 118, 121/
+data (chridx(i), i=16,20) / 128, 131, 141, 145, 154/
+data (chridx(i), i=21,25) / 168, 177, 187, 199, 203/
+data (chridx(i), i=26,30) / 221, 233, 246, 259, 263/
+data (chridx(i), i=31,35) / 268, 272, 287, 307, 314/
+data (chridx(i), i=36,40) / 327, 336, 344, 352, 359/
+data (chridx(i), i=41,45) / 371, 378, 385, 391, 398/
+data (chridx(i), i=46,50) / 402, 408, 413, 425, 433/
+data (chridx(i), i=51,55) / 445, 455, 468, 473, 480/
+data (chridx(i), i=56,60) / 484, 490, 495, 501, 506/
+data (chridx(i), i=61,65) / 511, 514, 519, 523, 526/
+data (chridx(i), i=66,70) / 529, 543, 554, 563, 574/
+data (chridx(i), i=71,75) / 585, 593, 607, 615, 625/
+data (chridx(i), i=76,80) / 638, 645, 650, 663, 671/
+data (chridx(i), i=81,85) / 681, 692, 703, 710, 723/
+data (chridx(i), i=86,90) / 731, 739, 743, 749, 754/
+data (chridx(i), i=91,95) / 759, 764, 776, 781, 793/
+data (chridx(i), i=96,96) / 801/
+
+# Stroke data.
+
+data (chrtab(i), i=001,005) / 36, 1764, 675, 29328, 585/
+data (chrtab(i), i=006,010) / 21063, 21191, 21193, 21065, 29383/
+data (chrtab(i), i=011,015) / 1764, 355, 29023, 351, 29027/
+data (chrtab(i), i=016,020) / 931, 29599, 927, 29603, 1764/
+data (chrtab(i), i=021,025) / 603, 29066, 842, 29723, 1302/
+data (chrtab(i), i=026,030) / 28886, 143, 29839, 1764, 611/
+data (chrtab(i), i=031,035) / 29256, 78, 20810, 21322, 21581/
+data (chrtab(i), i=036,040) / 21586, 21334, 20822, 20569, 20573/
+data (chrtab(i), i=041,045) / 20833, 21345, 29789, 1764, 419/
+data (chrtab(i), i=046,050) / 20707, 20577, 20574, 20700, 20892/
+data (chrtab(i), i=051,055) / 21022, 21025, 20899, 1187, 28744/
+data (chrtab(i), i=056,060) / 717, 21194, 21320, 21512, 21642/
+data (chrtab(i), i=061,065) / 21645, 21519, 21327, 21197, 1764/
+data (chrtab(i), i=066,070) / 1160, 20700, 20704, 20835, 21027/
+data (chrtab(i), i=071,075) / 21152, 21149, 20561, 20556, 20744/
+data (chrtab(i), i=076,080) / 21192, 29841, 1764, 611, 21023/
+data (chrtab(i), i=081,085) / 21087, 21155, 21091, 1764, 739/
+data (chrtab(i), i=086,090) / 21087, 21018, 21009, 21068, 29384/
+data (chrtab(i), i=091,095) / 1764, 547, 21151, 21210, 21201/
+data (chrtab(i), i=096,100) / 21132, 29192, 1764, 93, 29774/
+data (chrtab(i), i=101,105) / 608, 29259, 78, 29789, 1764/
+data (chrtab(i), i=106,110) / 604, 29260, 84, 29780, 1764/
+data (chrtab(i), i=111,115) / 516, 21062, 21065, 21001, 21000/
+data (chrtab(i), i=116,120) / 21064, 1764, 84, 29780, 1764/
+data (chrtab(i), i=121,125) / 585, 21063, 21191, 21193, 21065/
+data (chrtab(i), i=126,130) / 21191, 1764, 72, 29859, 1764/
+data (chrtab(i), i=131,135) / 419, 20573, 20558, 20872, 21320/
+data (chrtab(i), i=136,140) / 21646, 21661, 21347, 20899, 1764/
+data (chrtab(i), i=141,145) / 221, 21155, 29320, 1764, 95/
+data (chrtab(i), i=146,150) / 20835, 21411, 21663, 21655, 20556/
+data (chrtab(i), i=151,155) / 20552, 29832, 1764, 95, 20899/
+data (chrtab(i), i=156,160) / 21347, 21663, 21658, 21334, 29270/
+data (chrtab(i), i=161,165) / 854, 5266, 21644, 21320, 20872/
+data (chrtab(i), i=166,170) / 28749, 1764, 904, 21411, 21283/
+data (chrtab(i), i=171,175) / 20561, 20559, 21391, 911, 13455/
+data (chrtab(i), i=176,180) / 1764, 136, 21320, 21645, 21652/
+data (chrtab(i), i=181,185) / 21337, 20889, 20565, 20579, 29859/
+data (chrtab(i), i=186,190) / 1764, 83, 20888, 21336, 21651/
+data (chrtab(i), i=191,195) / 21645, 21320, 20872, 20557, 20563/
+data (chrtab(i), i=196,200) / 20635, 29347, 1764, 99, 21667/
+data (chrtab(i), i=201,205) / 29064, 1764, 355, 20575, 20570/
+data (chrtab(i), i=206,210) / 20822, 20562, 20556, 20808, 21384/
+data (chrtab(i), i=211,215) / 21644, 21650, 21398, 20822, 918/
+data (chrtab(i), i=216,220) / 5274, 21663, 21411, 20835, 1764/
+data (chrtab(i), i=221,225) / 648, 21584, 21656, 21662, 21347/
+data (chrtab(i), i=226,230) / 20899, 20574, 20568, 20883, 21331/
+data (chrtab(i), i=231,235) / 21656, 1764, 602, 21210, 21207/
+data (chrtab(i), i=236,240) / 21079, 21082, 21207, 592, 21069/
+data (chrtab(i), i=241,245) / 21197, 21200, 21072, 21197, 1764/
+data (chrtab(i), i=246,250) / 602, 21146, 21143, 21079, 21082/
+data (chrtab(i), i=251,255) / 21143, 585, 21132, 21136, 21072/
+data (chrtab(i), i=256,260) / 21071, 21135, 1764, 988, 20628/
+data (chrtab(i), i=261,265) / 29644, 1764, 1112, 28824, 144/
+data (chrtab(i), i=266,270) / 29776, 1764, 156, 21460, 28812/
+data (chrtab(i), i=271,275) / 1764, 221, 20704, 20899, 21218/
+data (chrtab(i), i=276,280) / 21471, 21466, 21011, 21007, 521/
+data (chrtab(i), i=281,285) / 20999, 21127, 21129, 21001, 21127/
+data (chrtab(i), i=286,290) / 1764, 908, 20812, 20560, 20571/
+data (chrtab(i), i=291,295) / 20831, 21407, 21659, 21651, 21521/
+data (chrtab(i), i=296,300) / 21393, 21331, 21335, 21210, 21018/
+data (chrtab(i), i=301,305) / 20887, 20883, 21009, 21201, 21331/
+data (chrtab(i), i=306,310) / 1764, 72, 20963, 21219, 29768/
+data (chrtab(i), i=311,315) / 210, 5074, 1764, 99, 21411/
+data (chrtab(i), i=316,320) / 21663, 21658, 21398, 20566, 918/
+data (chrtab(i), i=321,325) / 5266, 21644, 21384, 20552, 20579/
+data (chrtab(i), i=326,330) / 1764, 1165, 21320, 20872, 20557/
+data (chrtab(i), i=331,335) / 20574, 20899, 21347, 29854, 1764/
+data (chrtab(i), i=336,340) / 99, 21347, 21662, 21645, 21320/
+data (chrtab(i), i=341,345) / 20552, 20579, 1764, 99, 20552/
+data (chrtab(i), i=346,350) / 29832, 86, 13078, 99, 29859/
+data (chrtab(i), i=351,355) / 1764, 99, 20552, 86, 13078/
+data (chrtab(i), i=356,360) / 99, 29859, 1764, 722, 21650/
+data (chrtab(i), i=361,365) / 29832, 1165, 4936, 20872, 20557/
+data (chrtab(i), i=366,370) / 20574, 20899, 21347, 29854, 1764/
+data (chrtab(i), i=371,375) / 99, 28744, 85, 5269, 1160/
+data (chrtab(i), i=376,380) / 29859, 1764, 291, 29603, 611/
+data (chrtab(i), i=381,385) / 4680, 328, 29576, 1764, 77/
+data (chrtab(i), i=386,390) / 20872, 21256, 21581, 29795, 1764/
+data (chrtab(i), i=391,395) / 99, 28744, 1160, 20887, 82/
+data (chrtab(i), i=396,400) / 13475, 1764, 99, 20552, 29832/
+data (chrtab(i), i=401,405) / 1764, 72, 20579, 21077, 21603/
+data (chrtab(i), i=406,410) / 29768, 1764, 72, 20579, 21640/
+data (chrtab(i), i=411,415) / 29859, 1764, 94, 20899, 21347/
+data (chrtab(i), i=416,420) / 21662, 21645, 21320, 20872, 20557/
+data (chrtab(i), i=421,425) / 20574, 862, 29859, 1764, 72/
+data (chrtab(i), i=426,430) / 20579, 21411, 21663, 21656, 21396/
+data (chrtab(i), i=431,435) / 20564, 1764, 94, 20557, 20872/
+data (chrtab(i), i=436,440) / 21320, 21645, 21662, 21347, 20899/
+data (chrtab(i), i=441,445) / 20574, 536, 29828, 1764, 72/
+data (chrtab(i), i=446,450) / 20579, 21411, 21663, 21657, 21398/
+data (chrtab(i), i=451,455) / 20566, 918, 13448, 1764, 76/
+data (chrtab(i), i=456,460) / 20808, 21384, 21644, 21649, 21397/
+data (chrtab(i), i=461,465) / 20822, 20570, 20575, 20835, 21411/
+data (chrtab(i), i=466,470) / 29855, 1764, 648, 21155, 99/
+data (chrtab(i), i=471,475) / 29923, 1764, 99, 20557, 20872/
+data (chrtab(i), i=476,480) / 21320, 21645, 29859, 1764, 99/
+data (chrtab(i), i=481,485) / 21064, 29795, 1764, 99, 20808/
+data (chrtab(i), i=486,490) / 21141, 21448, 29923, 1764, 99/
+data (chrtab(i), i=491,495) / 29832, 72, 29859, 1764, 99/
+data (chrtab(i), i=496,500) / 21079, 29256, 599, 13411, 1764/
+data (chrtab(i), i=501,505) / 99, 21667, 20552, 29832, 1764/
+data (chrtab(i), i=506,510) / 805, 20965, 20935, 29447, 1764/
+data (chrtab(i), i=511,515) / 99, 29832, 1764, 421, 21221/
+data (chrtab(i), i=516,520) / 21191, 29063, 1764, 288, 21091/
+data (chrtab(i), i=521,525) / 29600, 1764, 3, 29891, 1764/
+data (chrtab(i), i=526,530) / 547, 29341, 1764, 279, 21207/
+data (chrtab(i), i=531,535) / 21396, 21387, 21127, 20807, 20555/
+data (chrtab(i), i=536,540) / 20558, 20753, 21201, 21391, 907/
+data (chrtab(i), i=541,545) / 13447, 1764, 99, 28744, 76/
+data (chrtab(i), i=546,550) / 4424, 21256, 21516, 21523, 21271/
+data (chrtab(i), i=551,555) / 20823, 20563, 1764, 981, 21271/
+data (chrtab(i), i=556,560) / 20823, 20563, 20556, 20808, 21256/
+data (chrtab(i), i=561,565) / 29642, 1764, 1043, 4887, 20823/
+data (chrtab(i), i=566,570) / 20563, 20556, 20808, 21256, 21516/
+data (chrtab(i), i=571,575) / 1032, 29731, 1764, 80, 5136/
+data (chrtab(i), i=576,580) / 21523, 21271, 20823, 20563, 20556/
+data (chrtab(i), i=581,585) / 20808, 21256, 29707, 1764, 215/
+data (chrtab(i), i=586,590) / 29591, 456, 20958, 21153, 21409/
+data (chrtab(i), i=591,595) / 29727, 1764, 67, 20800, 21248/
+data (chrtab(i), i=596,600) / 21508, 29719, 1043, 21271, 20823/
+data (chrtab(i), i=601,605) / 20563, 20556, 20808, 21256, 21516/
+data (chrtab(i), i=606,610) / 1764, 99, 28744, 83, 4439/
+data (chrtab(i), i=611,615) / 21271, 21523, 29704, 1764, 541/
+data (chrtab(i), i=616,620) / 21019, 21147, 21149, 21021, 21147/
+data (chrtab(i), i=621,625) / 533, 21077, 29256, 1764, 541/
+data (chrtab(i), i=626,630) / 21019, 21147, 21149, 21021, 21147/
+data (chrtab(i), i=631,635) / 533, 21077, 21058, 20928, 20736/
+data (chrtab(i), i=636,640) / 28802, 1764, 99, 28744, 84/
+data (chrtab(i), i=641,645) / 29530, 342, 13320, 1764, 483/
+data (chrtab(i), i=646,650) / 21089, 21066, 29384, 1764, 87/
+data (chrtab(i), i=651,655) / 28744, 584, 21076, 84, 4375/
+data (chrtab(i), i=656,660) / 20951, 21076, 21207, 21399, 21588/
+data (chrtab(i), i=661,665) / 29768, 1764, 87, 28744, 83/
+data (chrtab(i), i=666,670) / 20823, 21271, 21523, 29704, 1764/
+data (chrtab(i), i=671,675) / 83, 20556, 20808, 21256, 21516/
+data (chrtab(i), i=676,680) / 21523, 21271, 20823, 20563, 1764/
+data (chrtab(i), i=681,685) / 87, 28736, 83, 20823, 21271/
+data (chrtab(i), i=686,690) / 21523, 21516, 21256, 20808, 20556/
+data (chrtab(i), i=691,695) / 1764, 1047, 29696, 1036, 21256/
+data (chrtab(i), i=696,700) / 20808, 20556, 20563, 20823, 21271/
+data (chrtab(i), i=701,705) / 21523, 1764, 87, 28744, 83/
+data (chrtab(i), i=706,710) / 20823, 21271, 29716, 1764, 74/
+data (chrtab(i), i=711,715) / 20808, 21256, 21514, 21518, 21264/
+data (chrtab(i), i=716,720) / 20816, 20562, 20565, 20823, 21271/
+data (chrtab(i), i=721,725) / 21461, 1764, 279, 29591, 970/
+data (chrtab(i), i=726,730) / 21320, 21128, 21002, 21025, 1764/
+data (chrtab(i), i=731,735) / 87, 20556, 20808, 21256, 21516/
+data (chrtab(i), i=736,740) / 1032, 29719, 1764, 151, 21064/
+data (chrtab(i), i=741,745) / 29719, 1764, 87, 20808, 21077/
+data (chrtab(i), i=746,750) / 21320, 29783, 1764, 151, 29704/
+data (chrtab(i), i=751,755) / 136, 29719, 1764, 87, 21064/
+data (chrtab(i), i=756,760) / 320, 29783, 1764, 151, 21527/
+data (chrtab(i), i=761,765) / 20616, 29704, 1764, 805, 21157/
+data (chrtab(i), i=766,770) / 21026, 21017, 20951, 20822, 20949/
+data (chrtab(i), i=771,775) / 21011, 21001, 21127, 21255, 1764/
+data (chrtab(i), i=776,780) / 611, 29273, 594, 29256, 1764/
+data (chrtab(i), i=781,785) / 485, 21093, 21218, 21209, 21271/
+data (chrtab(i), i=786,790) / 21398, 21269, 21203, 21193, 21063/
+data (chrtab(i), i=791,795) / 29127, 1764, 83, 20758, 20950/
+data (chrtab(i), i=796,800) / 21265, 21457, 29844, 1764, 0/
diff --git a/pkg/images/tv/iis/ids/font.h b/pkg/images/tv/iis/ids/font.h
new file mode 100644
index 00000000..c33dc6ee
--- /dev/null
+++ b/pkg/images/tv/iis/ids/font.h
@@ -0,0 +1,29 @@
+# NCAR font definitions.
+
+define CHARACTER_START 32
+define CHARACTER_END 126
+define CHARACTER_HEIGHT 26
+define CHARACTER_WIDTH 17
+
+define FONT_LEFT 0
+define FONT_CENTER 9
+define FONT_RIGHT 27
+define FONT_TOP 36
+define FONT_CAP 34
+define FONT_HALF 23
+define FONT_BASE 9
+define FONT_BOTTOM 0
+define FONT_WIDTH 27
+define FONT_HEIGHT 36
+
+define COORD_X_START 7
+define COORD_Y_START 1
+define COORD_PEN_START 13
+define COORD_X_LEN 6
+define COORD_Y_LEN 6
+define COORD_PEN_LEN 1
+
+define PAINT_BEGIN_START 14
+define PAINT_END_START 15
+define PAINT_BEGIN_LEN 1
+define PAINT_END_LEN 1
diff --git a/pkg/images/tv/iis/ids/idscancel.x b/pkg/images/tv/iis/ids/idscancel.x
new file mode 100644
index 00000000..b03aac61
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idscancel.x
@@ -0,0 +1,19 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include "../lib/ids.h"
+
+# IDS_CANCEL -- Cancel any buffered output.
+
+procedure ids_cancel (dummy)
+
+int dummy # not used at present
+include "../lib/ids.com"
+
+begin
+ if (i_kt == NULL)
+ return
+
+ # Just cancel any output in the FIO stream
+ call fseti (i_out, F_CANCEL, OK)
+end
diff --git a/pkg/images/tv/iis/ids/idschars.x b/pkg/images/tv/iis/ids/idschars.x
new file mode 100644
index 00000000..4a53ad56
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idschars.x
@@ -0,0 +1,20 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDSCHARS -- Write characters in the current plane
+
+procedure idschars (xs, ys, data, length, size, orien)
+
+int xs, ys # starting coordinates, GKI
+char data[ARB] # the characters
+int length # how many
+int size # how big
+int orien # character orientation
+
+
+include "../lib/ids.com"
+
+begin
+ # Not implemented yet.
+end
diff --git a/pkg/images/tv/iis/ids/idsclear.x b/pkg/images/tv/iis/ids/idsclear.x
new file mode 100644
index 00000000..6b6488d4
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsclear.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_CLEAR -- Clear an image frame.
+
+procedure ids_clear (dummy)
+
+int dummy # not used at present
+include "../lib/ids.com"
+
+begin
+ if (i_kt == NULL)
+ return
+ call zclear(Mems[IDS_FRAME(i_kt)], Mems[IDS_BITPL(i_kt)], i_image)
+end
diff --git a/pkg/images/tv/iis/ids/idsclose.x b/pkg/images/tv/iis/ids/idsclose.x
new file mode 100644
index 00000000..d77ade09
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsclose.x
@@ -0,0 +1,19 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_CLOSE -- Close the image display kernel.
+# Free up storage.
+
+procedure ids_close()
+
+include "../lib/ids.com"
+
+begin
+ call close(i_out)
+ call mfree (IDS_FRAME(i_kt), TY_SHORT)
+ call mfree (IDS_BITPL(i_kt), TY_SHORT)
+ call mfree (IDS_SBUF(i_kt), TY_CHAR)
+ call mfree (i_kt, TY_STRUCT)
+ i_kt = NULL
+end
diff --git a/pkg/images/tv/iis/ids/idsclosews.x b/pkg/images/tv/iis/ids/idsclosews.x
new file mode 100644
index 00000000..40f7e40e
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsclosews.x
@@ -0,0 +1,15 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_CLOSEWS -- Close the named workstation.
+
+procedure ids_closews (devname, n)
+
+short devname[n] # device name (not used)
+int n # length of device name
+include "../lib/ids.com"
+
+begin
+ call ids_flush(0)
+end
diff --git a/pkg/images/tv/iis/ids/idscround.x b/pkg/images/tv/iis/ids/idscround.x
new file mode 100644
index 00000000..fc70a813
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idscround.x
@@ -0,0 +1,61 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+include <gki.h>
+
+# IDS_CROUND -- coordinate rounding. Since putcell and other similar
+# calls are defined to include both the lower-left corner and the upper-right
+# corners of the desired rectangle, it is necessary to "round" the
+# coordinates so that adjacent rectangles do not have overlapping edges.
+# This could have been done by agreeing that the top and right edges of the
+# rectangle are not part of it, but this was not done in the GKI definition.
+# Hence, here, we adopt the notion that if (for example) the upper y coordinate
+# is in the top half of a pixel, that pixel is included and if the lower y
+# coordinate is in the bottom half of a pixel, likewise, that pixel is included.
+# Otherwise, the pixels are excluded from putcell. The x coordinates are
+# treated similarly.
+# The code depends on the fact that lower is <= upper, that upper will be
+# at most GKI_MAXNDC, and that the device resolution will never be as much
+# as (GKI_MAXNDC+1)/2. The last requirement stems from the fact that if
+# the resolution were that high, each pixel would be 2 GKI units and
+# the "rounding" based on whether or not we are in the upper or lower half
+# of a pixel would probably fail due to rounding/truncation errors.
+
+procedure ids_cround(lower, upper, res)
+
+int lower, upper
+real res # device resolution
+
+real low, up
+real factor
+
+begin
+ factor = res/(GKI_MAXNDC+1)
+ low = real(lower) * factor
+ up = real(upper) * factor
+
+ # if boundaries result in same row, return
+ if ( int(low) == int(up) )
+ return
+
+ # if low is in upper half of device pixel, round up
+ if ( (low - int(low)) >= 0.5 ) {
+ low = int(low) + 1
+ # don't go to or beyond upper bound
+ if ( low < up ) {
+ # low already incremented;
+ # ... 0.2 just for "rounding protection"
+ lower = (low + 0.2)/factor
+ # if now reference same cell, return
+ if ( int(low) == int(up) )
+ return
+ }
+ }
+
+ # if "up" in bottom half of pixel, drop down one. Note that
+ # due to two "==" tests above, upper will not drop below lower.
+ # 0.2 means drop partway down into pixel below; calling code will
+ # truncate.
+ if ( (up - int(up)) < 0.5 )
+ upper = (real(int(up)) - 0.2)/factor
+end
diff --git a/pkg/images/tv/iis/ids/idsdrawch.x b/pkg/images/tv/iis/ids/idsdrawch.x
new file mode 100644
index 00000000..8372fac2
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsdrawch.x
@@ -0,0 +1,67 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <gki.h>
+include <gset.h>
+include "font.h"
+
+define ITALIC_TILT 0.30 # fraction of xsize to tilt italics at top
+
+
+# IDS_DRAWCHAR -- Draw a character of the given size and orientation at the
+# given position.
+
+procedure ids_drawchar (ch, x, y, xsize, ysize, orien, font)
+
+char ch # character to be drawn
+int x, y # lower left GKI coords of character
+int xsize, ysize # width, height of char in GKI units
+int orien # orientation of character (0 degrees normal)
+int font # desired character font
+
+real px, py, sx, sy, coso, sino, theta
+int stroke, tab1, tab2, i, pen
+int bitupk()
+include "font.com"
+
+begin
+ if (ch < CHARACTER_START || ch > CHARACTER_END)
+ i = '?' - CHARACTER_START + 1
+ else
+ i = ch - CHARACTER_START + 1
+
+ # Set the font.
+ call ids_font (font)
+
+ tab1 = chridx[i]
+ tab2 = chridx[i+1] - 1
+
+ theta = -DEGTORAD(orien)
+ coso = cos(theta)
+ sino = sin(theta)
+
+ do i = tab1, tab2 {
+ stroke = chrtab[i]
+ px = bitupk (stroke, COORD_X_START, COORD_X_LEN)
+ py = bitupk (stroke, COORD_Y_START, COORD_Y_LEN)
+ pen = bitupk (stroke, COORD_PEN_START, COORD_PEN_LEN)
+
+ # Scale size of character.
+ px = px / FONT_WIDTH * xsize
+ py = py / FONT_HEIGHT * ysize
+
+ # The italic font is implemented applying a tilt.
+ if (font == GT_ITALIC)
+ px = px + ((py / ysize) * xsize * ITALIC_TILT)
+
+ # Rotate and shift.
+ sx = x + px * coso + py * sino
+ sy = y - px * sino + py * coso
+
+ # Draw the line segment or move pen.
+ if (pen == 0)
+ call ids_point (short(sx), short(sy), false)
+ else
+ call ids_vector (short(sx), short(sy))
+ }
+end
diff --git a/pkg/images/tv/iis/ids/idsescape.x b/pkg/images/tv/iis/ids/idsescape.x
new file mode 100644
index 00000000..3c0c404f
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsescape.x
@@ -0,0 +1,115 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_ESCAPE -- Pass a device dependent instruction on to the kernel.
+# Most of the display control work is done here.
+
+procedure ids_escape (fn, instruction, nwords)
+
+int fn # function code
+short instruction[ARB] # instruction data words
+int nwords # length of instruction
+
+pointer p,q
+int ids_dcopy()
+short frames[IDS_MAXIMPL+2] # storage for frame data
+short color[IDS_MAXGCOLOR+1] # ditto for color
+short bitpl[IDS_MAXBITPL+1] # ditto for graphics bit plane
+short quad[5] # 4 quadrant information
+int count, count2, total
+int junk
+
+short gki[GKI_ESCAPE_LEN]
+data gki[1] /BOI/, gki[2] /GKI_ESCAPE/
+
+include "../lib/ids.com"
+
+begin
+ switch(fn) {
+
+ case IDS_RESET:
+ call ids_reset(instruction[1])
+
+ case IDS_SET_IP:
+ p = IDS_FRAME(i_kt)
+ count = ids_dcopy(instruction[1], Mems[p])
+ call ids_expand(Mems[p],i_maxframes, true)
+ q = IDS_BITPL(i_kt)
+ junk = ids_dcopy ( instruction[count+1], Mems[q])
+ call ids_expand(Mems[q],IDS_MAXBITPL, false)
+ i_image = true
+ call zsetup (Mems[p], Mems[q], i_image)
+
+ case IDS_SET_GP:
+ p = IDS_FRAME(i_kt)
+ count = ids_dcopy(instruction[1], Mems[p])
+ call ids_expand(Mems[p],i_maxgraph, false)
+ q = IDS_BITPL(i_kt)
+ junk = ids_dcopy ( instruction[count+1], Mems[q])
+ call ids_expand(Mems[q],IDS_MAXBITPL, false)
+ i_image = false
+ call zsetup (Mems[p], Mems[q], i_image)
+
+ case IDS_DISPLAY_I:
+ count = ids_dcopy(instruction[2], frames[1])
+ call ids_expand(frames[1], i_maxframes, true)
+ count2 = ids_dcopy (instruction[2+count], color[1])
+ call ids_expand(color[1], IDS_MAXGCOLOR, false)
+ total = count + count2
+ count = ids_dcopy(instruction[total+2], quad[1])
+ call ids_expand(quad[1], 4, false)
+ call zdisplay_i(instruction[1], frames[1], color, quad)
+
+ case IDS_DISPLAY_G:
+ count = ids_dcopy(instruction[2], bitpl[1])
+ call ids_expand(bitpl[1], i_maxgraph, false)
+ count2 = ids_dcopy (instruction[2+count], color[1])
+ call ids_expand(color[1], IDS_MAXGCOLOR, false)
+ total = count + count2
+ count = ids_dcopy(instruction[total+2], quad[1])
+ call ids_expand(quad[1], 4, false)
+ call zdisplay_g(instruction[1], bitpl, color, quad)
+
+ case IDS_SAVE:
+ call idssave(instruction[1], nwords)
+
+ case IDS_RESTORE:
+ call idsrestore(instruction[1], nwords)
+
+ case IDS_CONTROL:
+ count = ids_dcopy(instruction[IDS_CTRL_FRAME], frames[1])
+ call ids_expand(frames[1], i_maxframes, true)
+ count2 = ids_dcopy (instruction[IDS_CTRL_FRAME+count], color[1])
+ call ids_expand(color[1], IDS_MAXGCOLOR, false)
+ total = count + count2
+ call zcontrol(instruction[IDS_CTRL_REG],
+ instruction[IDS_CTRL_RW],
+ frames[1], color[1],
+ instruction[total+IDS_CTRL_FRAME],
+ instruction[IDS_CTRL_N],
+ instruction[total+IDS_CTRL_FRAME+1] )
+ # if a read, would like to return the information in gki format
+ # but no mechanism (yet?) for that
+ }
+end
+
+# IDS_DCOPY -- copy frame and bitplane information; return the number of
+# items copied, including the IDS_EOD (whose presence is required and assumed).
+
+int procedure ids_dcopy(from, to)
+
+short from[ARB] # from this storage
+short to[ARB] # to this area
+
+int i # count
+
+begin
+ i = 0
+ repeat {
+ i = i + 1
+ to[i] = from[i]
+ } until ( to[i] == IDS_EOD )
+ return (i)
+end
diff --git a/pkg/images/tv/iis/ids/idsfa.x b/pkg/images/tv/iis/ids/idsfa.x
new file mode 100644
index 00000000..b2d162c8
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsfa.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_FILLAREA -- Fill a closed area.
+
+procedure ids_fillarea (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+include "../lib/ids.com"
+
+begin
+ # Not implemented yet.
+ call ids_polyline (p, npts)
+end
diff --git a/pkg/images/tv/iis/ids/idsfaset.x b/pkg/images/tv/iis/ids/idsfaset.x
new file mode 100644
index 00000000..a8807766
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsfaset.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_FASET -- Set the fillarea attributes.
+
+procedure ids_faset (gki)
+
+short gki[ARB] # attribute structure
+pointer fa
+include "../lib/ids.com"
+
+begin
+ fa = IDS_FAAP(i_kt)
+ FA_STYLE(fa) = gki[GKI_FASET_FS]
+ FA_COLOR(fa) = gki[GKI_FASET_CI]
+end
diff --git a/pkg/images/tv/iis/ids/idsflush.x b/pkg/images/tv/iis/ids/idsflush.x
new file mode 100644
index 00000000..cd177d40
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsflush.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_FLUSH -- Flush output.
+
+procedure ids_flush (dummy)
+
+int dummy # not used at present
+include "../lib/ids.com"
+
+begin
+ if (i_kt == NULL)
+ return
+
+ # We flush the FIO stream.
+ call flush (i_out)
+end
diff --git a/pkg/images/tv/iis/ids/idsfont.x b/pkg/images/tv/iis/ids/idsfont.x
new file mode 100644
index 00000000..b3109f83
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsfont.x
@@ -0,0 +1,40 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "../lib/ids.h"
+
+# IDS_FONT -- Set the character font. The roman font is normal. Bold is
+# implemented by increasing the vector line width; care must be taken to
+# set IDS_WIDTH so that the other vector drawing procedures remember to
+# change the width back. The italic font is implemented in the character
+# generator by a geometric transformation.
+
+procedure ids_font (font)
+
+int font # code for font to be set
+int pk1, pk2, width
+include "../lib/ids.com"
+
+begin
+ pk1 = GKI_PACKREAL(1.0)
+ pk2 = GKI_PACKREAL(2.0)
+
+ width = IDS_WIDTH(i_kt)
+
+ if (font == GT_BOLD) {
+ if (width != pk2) {
+ # Name collision with ids_open !!
+ # call ids_optn (*"inten", *"high")
+ width = pk2
+ }
+ } else {
+ if (GKI_UNPACKREAL(width) > 1.5) {
+ # Name collision with ids_open !!
+ # call ids_optn (*"inten", *"low")
+ width = pk1
+ }
+ }
+
+ IDS_WIDTH(i_kt) = width
+end
diff --git a/pkg/images/tv/iis/ids/idsgcell.x b/pkg/images/tv/iis/ids/idsgcell.x
new file mode 100644
index 00000000..6ba8245f
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsgcell.x
@@ -0,0 +1,170 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include <gset.h>
+include "../lib/ids.h"
+
+# IDS_GETCELLARRAY -- Fetch a cell array, i.e., two dimensional array of pixels
+# (greylevels or colors).
+
+procedure ids_getcellarray (nc, nr, ax1,ay1, ax2,ay2)
+
+int nc, nr # number of pixels in X and Y
+int ax1, ay1 # lower left corner of input window
+int ax2, ay2 # upper right corner of input window
+
+int x1, y1, x2, y2
+int nx,ny # number of device pixels in x and y
+real px1, px2, py1, py2
+
+real skip_x, skip_y, sx, sy
+real blockx, blocky, bcy
+int i, j, startrow, element
+real xres, yres
+pointer sp, cell
+pointer mp # final data pointer to "array" m
+bool ca, use_orig, new_row
+
+include "../lib/ids.com"
+
+begin
+
+ # determine if can do real cell array.
+
+ ca = (IDS_CELLARRAY(i_kt) != 0)
+ if ( !ca )
+ return
+
+ skip_x = 1.0
+ skip_y = 1.0
+ blockx = 1.0
+ blocky = 1.0
+
+ xres = real(i_xres)
+ yres = real(i_yres)
+
+ # adjust pixels for edges
+ x1 = ax1
+ x2 = ax2
+ y1 = ay1
+ y2 = ay2
+ call ids_cround(x1,x2,xres)
+ call ids_cround(y1,y2,yres)
+
+ # find out how many real pixels we have to fetch
+
+ px1 = real(x1) * xres /(GKI_MAXNDC+1)
+ py1 = real(y1) * yres /(GKI_MAXNDC+1)
+ px2 = real(x2) * xres /(GKI_MAXNDC+1)
+ py2 = real(y2) * yres /(GKI_MAXNDC+1)
+
+ nx = int( px2 ) - int( px1 ) + 1
+ ny = int( py2 ) - int( py1 ) + 1
+
+ # if too many data points in input, set skip. If skip is close
+ # enough to one, set it to one.
+ # set block replication factors - will be > 1.0 if too few input points.
+ # cannot set to 1.0 if "close" enough, since, if > 1.0, we don't have
+ # enough points and so *some* have to be replicated.
+
+ if ( nx > nc ) {
+ skip_x = real(nx)/nc
+ if ( (skip_x - 1.0)*(nc-1) < 1.0 )
+ skip_x = 1.0
+ } else
+ blockx = real(nc)/nx
+
+ if ( ny > nr ) {
+ skip_y = real(ny)/nr
+ if ( (skip_y - 1.0)*(nr-1) < 1.0 )
+ skip_y = 1.0
+ } else
+ blocky = real(nr)/ny
+
+ # initialize counters
+
+ call smark(sp)
+
+ # allocate storage for output
+
+ call salloc (mp, nc*nr, TY_SHORT)
+ sy = 0
+ bcy = blocky
+ startrow = 1
+
+ # see if we can use original data ... no massaging
+ # also set the initial value of the new_row flag, which tells
+ # if we have to rebuild the row data
+ # note that if blockx > 1.0, skip_x must be 1.0, and vv
+
+ if ( (skip_x == 1.0) && (blockx == 1.0) ) {
+ use_orig = true
+ } else {
+ use_orig = false
+ # allocate storage for a row of pixels.
+ call salloc ( cell, nx, TY_SHORT)
+ }
+ new_row = true
+
+ # do it
+
+ for ( i = 1; i <= nr ; i = i + 1) {
+
+ # fetch the row data. The reading routine will figure out
+ # how to read from the various individual frames and bitplanes.
+
+ if ( new_row) {
+ if (!i_snap)
+ call zseek (i_out, int(px1), int(py1)+int(sy+0.5))
+ if ( use_orig )
+ # just copy it in
+ if (i_snap)
+ call do_snap (Mems[mp+startrow-1], nx, int(px1),
+ int(py1)+int(sy+0.5))
+ else
+ call read (i_out, Mems[mp+startrow-1], nx)
+ else
+ # into Mems for rework
+ if (i_snap)
+ call do_snap (Mems[cell], nx, int(px1),
+ int(py1)+int(sy+0.5))
+ else
+ call read (i_out, Mems[cell], nx)
+ }
+
+ # rework the row data
+
+ if ( !use_orig && new_row ) {
+ if ( skip_x == 1.0)
+ call ids_blockit(Mems[cell], Mems[mp+startrow-1], nc,
+ blockx)
+ else {
+ sx = 0
+ for ( j = 1; j <= nc; j = j + 1) {
+ element = int(sx+0.5)
+ Mems[mp+startrow-1+j-1] = Mems[cell + element]
+ sx = sx + skip_x
+ }
+ }
+ }
+ # if don't need new row of input data, duplicate the
+ # previous one by copying within the "m" array
+ if ( ! new_row )
+ call amovs (Mems[mp+startrow-1-nc], Mems[mp+startrow-1], nc)
+
+ #advance a row
+
+ startrow = startrow + nc
+ if ( bcy <= real(i) ) {
+ sy = sy + skip_y
+ bcy = bcy + blocky
+ new_row = true
+ } else {
+ new_row = false
+ }
+ }
+
+ call gki_retcellarray (i_in, Mems[mp], nr * nc)
+ call sfree(sp)
+end
diff --git a/pkg/images/tv/iis/ids/idsgcur.x b/pkg/images/tv/iis/ids/idsgcur.x
new file mode 100644
index 00000000..d3c0a1c6
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsgcur.x
@@ -0,0 +1,33 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_GETCURSOR -- Get the position of a cursor. This is the low level
+# cursor read procedure. Reading the image cursor is only possible when
+# the ids kernel is run interactively, i.e., when the kernel is linked
+# into the CL process, which owns the terminal. A raw binary read is required.
+# The cursor value is returned as a GKI structure on the stream "i_in",
+# i.e., it is sent back to the process which requested it.
+
+procedure ids_getcursor (cursor)
+
+int cursor
+
+int cur
+int x, y, key
+
+include "../lib/ids.com"
+
+begin
+ cur = cursor
+ if ( cur > IDS_CSPECIAL ) {
+ switch( cur ) {
+ case IDS_BUT_RD, IDS_BUT_WT:
+ call iisbutton( cur, x, y, key)
+ }
+ } else
+ call zcursor_read (cur, x, y, key)
+
+ call gki_retcursorvalue (i_in, x, y, key, cur)
+ call flush (i_in)
+end
diff --git a/pkg/images/tv/iis/ids/idsinit.x b/pkg/images/tv/iis/ids/idsinit.x
new file mode 100644
index 00000000..7ac925a3
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsinit.x
@@ -0,0 +1,172 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_INIT -- Initialize the ids data structures from the graphcap entry
+# for the device. Called once, at OPENWS time, with the TTY pointer already
+# set in the common.
+
+procedure ids_init (tty, devname)
+
+pointer tty # graphcap descriptor
+char devname[ARB] # device name
+
+pointer nextch
+int maxch, i
+real char_height, char_width, char_size
+
+bool ttygetb()
+real ttygetr()
+int ttygeti(), btoi(), gstrcpy()
+
+include "../lib/ids.com"
+
+begin
+ # Allocate the ids descriptor and the string buffer.
+ if ( i_kt == NULL) {
+ call calloc (i_kt, LEN_IDS, TY_STRUCT)
+ call malloc (IDS_SBUF(i_kt), SZ_SBUF, TY_CHAR)
+ call malloc (IDS_BITPL(i_kt), IDS_MAXBITPL+1, TY_SHORT)
+ } else {
+ call mfree (IDS_FRAME(i_kt), TY_SHORT)
+ }
+
+
+ # Init string buffer parameters. The first char of the string buffer
+ # is reserved as a null string, used for graphcap control strings
+ # omitted from the graphcap entry for the device.
+
+ IDS_SZSBUF(i_kt) = SZ_SBUF
+ IDS_NEXTCH(i_kt) = IDS_SBUF(i_kt) + 1
+ Memc[IDS_SBUF(i_kt)] = EOS
+
+ # get the device resolution from the graphcap entry.
+
+ i_xres = ttygeti (tty, "xr")
+ if (i_xres <= 0)
+ i_xres = 512
+ i_yres = ttygeti (tty, "yr")
+ if (i_yres <= 0)
+ i_yres = 512
+
+
+ # Initialize the character scaling parameters, required for text
+ # generation. The heights are given in NDC units in the graphcap
+ # file, which we convert to GKI units. Estimated values are
+ # supplied if the parameters are missing in the graphcap entry.
+
+ char_height = ttygetr (tty, "ch")
+ if (char_height < EPSILON)
+ char_height = 1.0 / 35.0
+ char_height = char_height * GKI_MAXNDC
+
+ char_width = ttygetr (tty, "cw")
+ if (char_width < EPSILON)
+ char_width = 1.0 / 80.0
+ char_width = char_width * GKI_MAXNDC
+
+ # If the device has a set of discreet character sizes, get the
+ # size of each by fetching the parameter "tN", where the N is
+ # a digit specifying the text size index. Compute the height and
+ # width of each size character from the "ch" and "cw" parameters
+ # and the relative scale of character size I.
+
+ IDS_NCHARSIZES(i_kt) = min (MAX_CHARSIZES, ttygeti (tty, "th"))
+ nextch = IDS_NEXTCH(i_kt)
+
+ if (IDS_NCHARSIZES(i_kt) <= 0) {
+ IDS_NCHARSIZES(i_kt) = 1
+ IDS_CHARSIZE(i_kt,1) = 1.0
+ IDS_CHARHEIGHT(i_kt,1) = char_height
+ IDS_CHARWIDTH(i_kt,1) = char_width
+ } else {
+ Memc[nextch+2] = EOS
+ for (i=1; i <= IDS_NCHARSIZES(i_kt); i=i+1) {
+ Memc[nextch] = 't'
+ Memc[nextch+1] = TO_DIGIT(i)
+ char_size = ttygetr (tty, Memc[nextch])
+ IDS_CHARSIZE(i_kt,i) = char_size
+ IDS_CHARHEIGHT(i_kt,i) = char_height * char_size
+ IDS_CHARWIDTH(i_kt,i) = char_width * char_size
+ }
+ }
+
+ # Initialize the output parameters. All boolean parameters are stored
+ # as integer flags. All string valued parameters are stored in the
+ # string buffer, saving a pointer to the string in the ids
+ # descriptor. If the capability does not exist the pointer is set to
+ # point to the null string at the beginning of the string buffer.
+
+ IDS_POLYLINE(i_kt) = btoi (ttygetb (tty, "pl"))
+ IDS_POLYMARKER(i_kt) = btoi (ttygetb (tty, "pm"))
+ IDS_FILLAREA(i_kt) = btoi (ttygetb (tty, "fa"))
+ IDS_FILLSTYLE(i_kt) = ttygeti (tty, "fs")
+ IDS_ROAM(i_kt) = btoi (ttygetb (tty, "ro"))
+ IDS_CANZM(i_kt) = btoi (ttygetb (tty, "zo"))
+ IDS_ZRES(i_kt) = ttygeti (tty, "zr")
+ IDS_CELLARRAY(i_kt) = btoi (ttygetb (tty, "ca"))
+ IDS_SELERASE(i_kt) = btoi (ttygetb (tty, "se"))
+
+ # how many image frames and graph (bit)planes do we get to play with?
+
+ i_maxframes = ttygeti(tty, "ip")
+ if ( i_maxframes < 1 )
+ i_maxframes = 1
+ i_maxgraph = ttygeti(tty, "gp")
+ i_maxframes = min(int(i_maxframes), IDS_MAXIMPL)
+ i_maxgraph = min(int(i_maxgraph), IDS_MAXGRPL)
+
+ # allocate space for the frame descriptors
+ # the "2" accounts for possible graphics channel ( see ids_expand.x)
+ # and the trailing IDS_EOD
+
+ call malloc (IDS_FRAME(i_kt), max(i_maxframes,i_maxgraph)+2, TY_SHORT)
+
+ # Initialize the input parameters: last cursor used.
+
+ IDS_LCURSOR(i_kt) = 1
+
+ # Save the device string in the descriptor.
+ nextch = IDS_NEXTCH(i_kt)
+ IDS_DEVNAME(i_kt) = nextch
+ maxch = IDS_SBUF(i_kt) + SZ_SBUF - nextch + 1
+ nextch = nextch + gstrcpy (devname, Memc[nextch], maxch) + 1
+ IDS_NEXTCH(i_kt) = nextch
+
+end
+
+
+# IDS_GSTRING -- Get a string value parameter from the graphcap table,
+# placing the string at the end of the string buffer. If the device does
+# not have the named capability return a pointer to the null string,
+# otherwise return a pointer to the string. Since pointers are used,
+# rather than indices, the string buffer is fixed in size. The additional
+# degree of indirection required with an index was not considered worthwhile
+# in this application since the graphcap entries are never very large.
+
+pointer procedure ids_gstring (cap)
+
+char cap[ARB] # device capability to be fetched
+pointer strp, nextch
+int maxch, nchars
+int ttygets()
+
+include "../lib/ids.com"
+
+begin
+ nextch = IDS_NEXTCH(i_kt)
+ maxch = IDS_SBUF(i_kt) + SZ_SBUF - nextch + 1
+
+ nchars = ttygets (i_tty, cap, Memc[nextch], maxch)
+ if (nchars > 0) {
+ strp = nextch
+ nextch = nextch + nchars + 1
+ } else
+ strp = IDS_SBUF(i_kt)
+
+ IDS_NEXTCH(i_kt) = nextch
+ return (strp)
+end
diff --git a/pkg/images/tv/iis/ids/idsline.x b/pkg/images/tv/iis/ids/idsline.x
new file mode 100644
index 00000000..ecc63d8c
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsline.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include "../lib/ids.h"
+
+# IDS_LINE set the line type option in the nspp world
+
+procedure ids_line(index)
+
+int index # index for line type switch statement
+
+int linetype
+
+include "../lib/ids.com"
+
+begin
+ switch (index) {
+ case GL_CLEAR:
+ linetype = 0
+ case GL_DASHED:
+ linetype = 0FF00X
+ case GL_DOTTED:
+ linetype = 08888X
+ case GL_DOTDASH:
+ linetype = 0F040X
+ default:
+ linetype = 0FFFFX # GL_SOLID and default
+ }
+ i_linemask = linetype
+end
diff --git a/pkg/images/tv/iis/ids/idslutfill.x b/pkg/images/tv/iis/ids/idslutfill.x
new file mode 100644
index 00000000..be42c774
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idslutfill.x
@@ -0,0 +1,36 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+
+# IDSLUTFILL -- Fill a lookup table from a set of line end points
+
+procedure idslfill (in, icount, out, lenlut, lutmin, lutmax)
+
+short in[ARB] # input: line end points
+int icount # number of input data items
+short out[ARB] # output: the lookup table
+int lenlut # lut size
+int lutmin,lutmax # inclusive range for lut values
+
+int i,j
+int xs, ys, xe, ye
+real slope
+
+begin
+ # xs and xe are zero based coordinates
+ xs = real(in[1]) * (lenlut - 1)/GKI_MAXNDC. + 0.5
+ ys = real(in[2]) * (lutmax - lutmin)/GKI_MAXNDC. + lutmin + 0.5
+ do i = 3, icount, 2 {
+ xe = real(in[i]) * (lenlut - 1)/GKI_MAXNDC. + 0.5
+ ye = real(in[i+1]) * (lutmax - lutmin)/GKI_MAXNDC. + lutmin + 0.5
+ if (xe != xs) {
+ slope = real(ye - ys) / (xe - xs)
+ do j = xs, xe {
+ out[j+1] = ys + (j - xs) * slope
+ }
+ }
+ xs = xe
+ ys = ye
+ }
+ out[1] = 0 # keep background at zero
+end
diff --git a/pkg/images/tv/iis/ids/idsopen.x b/pkg/images/tv/iis/ids/idsopen.x
new file mode 100644
index 00000000..cee1aebe
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsopen.x
@@ -0,0 +1,58 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_OPEN -- Install the image kernel as a kernel device driver.
+# The device table DD consists of an array of the entry point addresses for
+# the driver procedures. If a driver does not implement a particular
+# instruction the table entry for that procedure may be set to zero, causing
+# the interpreter to ignore the instruction.
+
+procedure ids_open (devname, dd)
+
+char devname[ARB] # nonnull for forced output to device
+int dd[ARB] # device table to be initialized
+
+int locpr()
+extern ids_openws(), ids_closews(), ids_clear(), ids_cancel()
+extern ids_flush(), ids_polyline(), ids_polymarker(), ids_text()
+extern ids_fillarea(), ids_putcellarray(), ids_plset()
+extern ids_pmset(), ids_txset(), ids_faset()
+extern ids_escape()
+extern ids_setcursor(), ids_getcursor(), ids_getcellarray()
+
+include "../lib/ids.com"
+
+begin
+ # Flag first pass. Save forced device name in common for OPENWS.
+
+ i_kt = NULL
+ call strcpy (devname, i_device, SZ_IDEVICE)
+
+ # Install the device driver.
+ dd[GKI_OPENWS] = locpr (ids_openws)
+ dd[GKI_CLOSEWS] = locpr (ids_closews)
+ dd[GKI_DEACTIVATEWS] = 0
+ dd[GKI_REACTIVATEWS] = 0
+ dd[GKI_MFTITLE] = 0
+ dd[GKI_CLEAR] = locpr (ids_clear)
+ dd[GKI_CANCEL] = locpr (ids_cancel)
+ dd[GKI_FLUSH] = locpr (ids_flush)
+ dd[GKI_POLYLINE] = locpr (ids_polyline)
+ dd[GKI_POLYMARKER] = locpr (ids_polymarker)
+ dd[GKI_TEXT] = locpr (ids_text)
+ dd[GKI_FILLAREA] = locpr (ids_fillarea)
+ dd[GKI_PUTCELLARRAY] = locpr (ids_putcellarray)
+ dd[GKI_SETCURSOR] = locpr (ids_setcursor)
+ dd[GKI_PLSET] = locpr (ids_plset)
+ dd[GKI_PMSET] = locpr (ids_pmset)
+ dd[GKI_TXSET] = locpr (ids_txset)
+ dd[GKI_FASET] = locpr (ids_faset)
+ dd[GKI_GETCURSOR] = locpr (ids_getcursor)
+ dd[GKI_GETCELLARRAY] = locpr (ids_getcellarray)
+ dd[GKI_ESCAPE] = locpr (ids_escape)
+ dd[GKI_SETWCS] = 0
+ dd[GKI_GETWCS] = 0
+ dd[GKI_UNKNOWN] = 0
+end
diff --git a/pkg/images/tv/iis/ids/idsopenws.x b/pkg/images/tv/iis/ids/idsopenws.x
new file mode 100644
index 00000000..bd25b260
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsopenws.x
@@ -0,0 +1,120 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include <gki.h>
+include <error.h>
+include "../lib/ids.h"
+
+# IDS_OPENWS -- Open the named workstation. Once a workstation has been
+# opened we leave it open until some other workstation is opened or the
+# kernel is closed. Opening a workstation involves initialization of the
+# kernel data structures. Initialization of the device itself is left to
+# an explicit reset command.
+
+procedure ids_openws (devname, n, mode)
+
+short devname[ARB] # device name
+int n # length of device name
+int mode # access mode
+
+long filesize
+bool need_open, same_dev
+pointer sp, buf, devinfo
+
+long fstatl()
+pointer ttygdes()
+bool streq(), ttygetb()
+int fopnbf(), ttygets()
+extern zopnim(), zardim(), zawrim(), zawtim(), zsttim(), zclsim()
+errchk ttygdes
+int oldmode
+data oldmode /-1/
+
+include "../lib/ids.com"
+
+begin
+ call smark (sp)
+ call salloc (buf, max (SZ_FNAME, n), TY_CHAR)
+ call salloc (devinfo, SZ_LINE, TY_CHAR)
+
+ # If a device was named when the kernel was opened then output will
+ # always be to that device (i_device) regardless of the device named
+ # in the OPENWS instruction. If no device was named (null string)
+ # then unpack the device name, passed as a short integer array.
+
+ if (i_device[1] == EOS) {
+ call achtsc (devname, Memc[buf], n)
+ Memc[buf+n] = EOS
+ } else
+ call strcpy (i_device, Memc[buf], SZ_FNAME)
+
+ # find out if first time, and if not, if same device as before
+ # note that if (i_kt == NULL), then same_dev is false.
+
+ same_dev = false
+ need_open = true
+ if ( i_kt != NULL ) {
+ same_dev = (streq(Memc[IDS_DEVNAME(i_kt)], Memc[buf]))
+ if ( !same_dev || ( oldmode != mode))
+ call close(i_out)
+ else
+ need_open = false
+ }
+ oldmode = mode
+
+ # Initialize the kernel data structures. Open graphcap descriptor
+ # for the named device, allocate and initialize descriptor and common.
+ # graphcap entry for device must exist.
+
+ if (need_open) {
+ if ((i_kt != NULL) && !same_dev)
+ call ttycdes (i_tty)
+ if (!same_dev) {
+ i_tty = ttygdes (Memc[buf])
+ if (ttygetb (i_tty, "LC"))
+ call error (1, "operation not supported on device")
+ }
+
+ if (ttygets (i_tty, "DD", Memc[devinfo], SZ_LINE) <= 0)
+ call strcpy (Memc[buf], Memc[devinfo], SZ_LINE)
+
+ # Open the output file. The device is connected to FIO as a
+ # binary file. mode must be READ_WRITE or WRITE_ONLY
+ # for image display!
+
+ iferr (i_out = fopnbf (Memc[devinfo], mode, zopnim, zardim,
+ zawrim, zawtim, zsttim, zclsim)) {
+
+ call ttycdes (i_tty)
+ call erract (EA_ERROR)
+ }
+ call fseti (i_out, F_ADVICE, SEQUENTIAL)
+
+ }
+
+ # Initialize data structures.
+ # Device specific initialization will be done in the zinit call
+ # from ids_init().
+
+ if (!same_dev) {
+ call ids_init (i_tty, Memc[buf])
+
+ # Now set the file size to allow mapping of all control registers
+ # as well as all image and graphics planes. The call to fstatl
+ # returns the size of an image plane (!!). zinit does whatever
+ # device work it needs to do, and uses its arguments to determine
+ # the total file size, which it returns.
+ # This feature need not be used (and is not for the IIS display).
+ #
+ # We also set the F_ASYNC parameter to YES.
+
+ i_frsize = fstatl(i_out, F_FILESIZE)
+ filesize = i_frsize
+ call zinit(i_maxframes, i_maxgraph, filesize)
+ call fseti(i_out, F_ASYNC, YES)
+
+ }
+
+ call sfree (sp)
+end
diff --git a/pkg/images/tv/iis/ids/idspcell.x b/pkg/images/tv/iis/ids/idspcell.x
new file mode 100644
index 00000000..d678b286
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idspcell.x
@@ -0,0 +1,178 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "../lib/ids.h"
+
+# number of grey scale symbols
+define NSYMBOL 11
+define TSIZE (1.0/2.0)
+
+# IDS_PUTCELLARRAY -- Draw a cell array, i.e., two dimensional array of pixels
+# (greylevels or colors).
+
+procedure ids_putcellarray (m, nc, nr, ax1,ay1, ax2,ay2)
+
+short m[ARB] # cell array
+int nc, nr # number of pixels in X and Y
+ # (number of columns[x], rows[y]
+int ax1, ay1 # lower left corner of output window
+int ax2, ay2 # upper right corner of output window
+
+int x1,y1,x2,y2
+real px1, py1, px2, py2
+int nx, ny
+real skip_x, skip_y, sx, sy
+real blockx, blocky, bcy
+int i, j, startrow, element
+real xres, yres
+pointer sp, cell
+bool ca, use_orig, new_row
+
+include "../lib/ids.com"
+
+begin
+ # determine if can do real cell array.
+
+ ca = (IDS_CELLARRAY(i_kt) != 0)
+ if ( !ca )
+ return
+
+ skip_x = 1.0
+ skip_y = 1.0
+ blockx = 1.0
+ blocky = 1.0
+
+ xres = real(i_xres)
+ yres = real(i_yres)
+
+ # adjust pixels for edges
+ x1 = ax1
+ x2 = ax2
+ y1 = ay1
+ y2 = ay2
+ call ids_cround(x1,x2,xres)
+ call ids_cround(y1,y2,yres)
+
+ # find out how many real pixels we have to fill
+
+ px1 = real(x1) * xres /(GKI_MAXNDC+1)
+ py1 = real(y1) * yres /(GKI_MAXNDC+1)
+ px2 = real(x2) * xres /(GKI_MAXNDC+1)
+ py2 = real(y2) * yres /(GKI_MAXNDC+1)
+
+ nx = int( px2 ) - int( px1 ) + 1
+ ny = int( py2 ) - int( py1 ) + 1
+
+ # if too many data points in input, set skip. If skip is close
+ # enough to one, set it to one.
+ # set block replication factors - will be > 1.0 if too few input points.
+ # cannot set to 1.0 if "close" enough, since, if > 1.0, we don't have
+ # enough points and so *some* have to be replicated.
+
+ if ( nc > nx ) {
+ skip_x = real(nc)/nx
+ if ( (skip_x - 1.0)*(nx-1) < 1.0 )
+ skip_x = 1.0
+ } else
+ blockx = real(nx)/nc
+
+ if ( nr > ny ) {
+ skip_y = real(nr)/ny
+ if ( (skip_y - 1.0)*(ny-1) < 1.0 )
+ skip_y = 1.0
+ } else
+ blocky = real(ny)/nr
+
+ # initialize counters
+
+ call smark(sp)
+ sy = skip_y
+ bcy = blocky
+ startrow = 1
+ element = startrow
+
+ # see if we can use original data ... no massaging
+ # also set the initial value of the new_row flag, which tells
+ # if we have to rebuild the row data
+ # note that if blockx > 1.0, skip_x must be 1.0, and vv
+
+ if ( (skip_x == 1.0) && (blockx == 1.0) ) {
+ use_orig = true
+ new_row = false
+ } else {
+ use_orig = false
+ new_row = true
+ # allocate storage for a row of pixels.
+ call salloc ( cell, nx, TY_SHORT)
+ }
+
+ # do it
+
+ for ( i = 1; i <= ny ; i = i + 1) {
+
+ # Build the row data.
+
+ if (!use_orig && new_row) {
+ if ( skip_x == 1.0)
+ call ids_blockit(m[element], Mems[cell], nx, blockx)
+ else {
+ sx = skip_x
+ for ( j = 1; j <= nx; j = j + 1) {
+ Mems[cell+j-1] = m[element]
+ element = startrow + int(sx+0.5)
+ sx = sx + skip_x
+ }
+ }
+ }
+
+ # Send the row data. The writing routine will figure out
+ # how to send to the various individual frames and bitplanes.
+
+ call zseek (i_out, int(px1), int(py1)+i-1)
+ if (use_orig)
+ call write (i_out, m[element], nx)
+ else
+ call write (i_out, Mems[cell], nx)
+
+ # Advance a row.
+
+ element = startrow
+ if ( bcy <= real(i) ) {
+ startrow = 1 + nc * int(sy+0.5)
+ element = startrow
+ sy = sy + skip_y
+ bcy = bcy + blocky
+ new_row = true
+ } else {
+ new_row = false
+ }
+ }
+
+ call sfree(sp)
+end
+
+
+# IDS_BLOCKIT -- block replication of data
+
+procedure ids_blockit( from, to, count, factor)
+
+short from[ARB] # input data
+short to[ARB] # output data
+int count # number of output pixels
+real factor # blocking factor
+
+int i, j
+real bc
+
+begin
+ bc = factor
+ j = 1
+ for ( i = 1; i <= count ; i = i + 1 ) {
+ to[i] = from[j]
+ if ( bc <= real(i) ) {
+ j = j + 1
+ bc = bc + factor
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/ids/idspl.x b/pkg/images/tv/iis/ids/idspl.x
new file mode 100644
index 00000000..77ac3bc3
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idspl.x
@@ -0,0 +1,61 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# nspp particulars
+# base width of line
+define BASELW 8
+
+# IDS_POLYLINE -- Draw a polyline. The polyline is defined by the array of
+# points P, consisting of successive (x,y) coordinate pairs. The first point
+# is not plotted but rather defines the start of the polyline. The remaining
+# points define line segments to be drawn.
+
+procedure ids_polyline (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+
+pointer pl
+int i, len_p
+int linewidth
+
+include "../lib/ids.com"
+
+begin
+ if ( npts <= 0)
+ return
+
+ len_p = npts * 2
+
+ # Update polyline attributes if necessary.
+
+ pl = IDS_PLAP(i_kt)
+
+ if (IDS_TYPE(i_kt) != PL_LTYPE(pl)) {
+ call ids_line(PL_LTYPE(pl))
+ IDS_TYPE(i_kt) = PL_LTYPE(pl)
+ }
+ if (IDS_WIDTH(i_kt) != PL_WIDTH(pl)) {
+ linewidth = int(real(BASELW) * GKI_UNPACKREAL(PL_WIDTH(pl)))
+ i_linewidth = max(1,linewidth)
+ IDS_WIDTH(i_kt) = PL_WIDTH(pl)
+ }
+ if (IDS_COLOR(i_kt) != PL_COLOR(pl)) {
+ i_linecolor = PL_COLOR(pl)
+ IDS_COLOR(i_kt) = PL_COLOR(pl)
+ }
+
+ # Move to the first point. point() will plot it, which is
+ # ok here, and vector may well plot it again.
+
+ call ids_point(p[1], p[2], true)
+
+ # Draw the polyline.
+
+ for (i=3; i <= len_p; i=i+2) {
+ call ids_vector ( p[i], p[i+1])
+
+ }
+end
diff --git a/pkg/images/tv/iis/ids/idsplset.x b/pkg/images/tv/iis/ids/idsplset.x
new file mode 100644
index 00000000..cf49ea1f
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsplset.x
@@ -0,0 +1,21 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_PLSET -- Set the polyline attributes. The polyline width parameter is
+# passed to the encoder as a packed floating point number, i.e., int(LWx100).
+
+procedure ids_plset (gki)
+
+short gki[ARB] # attribute structure
+pointer pl
+
+include "../lib/ids.com"
+
+begin
+ pl = IDS_PLAP(i_kt)
+ PL_LTYPE(pl) = gki[GKI_PLSET_LT]
+ PL_WIDTH(pl) = gki[GKI_PLSET_LW]
+ PL_COLOR(pl) = gki[GKI_PLSET_CI]
+end
diff --git a/pkg/images/tv/iis/ids/idspm.x b/pkg/images/tv/iis/ids/idspm.x
new file mode 100644
index 00000000..b165b7cc
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idspm.x
@@ -0,0 +1,56 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# nspp particulars
+# base width of line
+define BASELW 8
+
+# IDS_POLYMARKER -- Draw a polymarker. The polymarker is defined by the array
+# of points P, consisting of successive (x,y) coordinate pairs. The first point
+# is not plotted but rather defines the start of the polyline. The remaining
+# points define line segments to be drawn.
+
+procedure ids_polymarker (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+
+pointer pm
+int i, len_p
+int linewidth
+short x,y
+
+include "../lib/ids.com"
+
+begin
+ if ( npts <= 0)
+ return
+
+ len_p = npts * 2
+
+ # Update polymarker attributes if necessary.
+
+ pm = IDS_PMAP(i_kt)
+
+ if (IDS_TYPE(i_kt) != PM_LTYPE(pm)) {
+ call ids_line(PM_LTYPE(pm))
+ IDS_TYPE(i_kt) = PM_LTYPE(pm)
+ }
+ if (IDS_WIDTH(i_kt) != PM_WIDTH(pm)) {
+ linewidth = int(real(BASELW) * GKI_UNPACKREAL(PM_WIDTH(pm)))
+ i_linewidth = max(1,linewidth)
+ IDS_WIDTH(i_kt) = PM_WIDTH(pm)
+ }
+ if (IDS_COLOR(i_kt) != PM_COLOR(pm)) {
+ i_linecolor = PM_COLOR(pm)
+ IDS_COLOR(i_kt) = PM_COLOR(pm)
+ }
+
+ for (i=1; i <= len_p; i=i+2) {
+ x = p[i]
+ y = p[i+1]
+ call ids_point (real(x)/GKI_MAXNDC, real(y)/GKI_MAXNDC, true)
+ }
+end
diff --git a/pkg/images/tv/iis/ids/idspmset.x b/pkg/images/tv/iis/ids/idspmset.x
new file mode 100644
index 00000000..be46ede8
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idspmset.x
@@ -0,0 +1,19 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_PMSET -- Set the polymarker attributes.
+
+procedure ids_pmset (gki)
+
+short gki[ARB] # attribute structure
+pointer pm
+include "../lib/ids.com"
+
+begin
+ pm = IDS_PMAP(i_kt)
+ PM_LTYPE(pm) = gki[GKI_PMSET_MT]
+ PM_WIDTH(pm) = gki[GKI_PMSET_MW]
+ PM_COLOR(pm) = gki[GKI_PMSET_CI]
+end
diff --git a/pkg/images/tv/iis/ids/idspoint.x b/pkg/images/tv/iis/ids/idspoint.x
new file mode 100644
index 00000000..2addb635
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idspoint.x
@@ -0,0 +1,65 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <fset.h>
+include "../lib/ids.h"
+
+# IDS_POINT -- Plot a point in the current plane at given (GKI) coordinates.
+
+procedure ids_point (ax,ay,flag)
+
+short ax,ay # point coordinates, GKI
+bool flag # true if should plot point, false if just a
+ # pen move
+int xp, yp
+int bufsize
+int fstati()
+
+include "../lib/ids.com"
+
+begin
+ # convert to device coords, plot max value, then record in i_pt
+ xp = real(ax) * i_xres /(GKI_MAXNDC+1)
+ yp = real(ay) * i_yres /(GKI_MAXNDC+1)
+
+ # if flag is true, we plot the point. If false, we just want
+ # to record the points (a pen move), so skip the plot commands
+
+ if (flag) {
+ # set buffer to size one
+ bufsize = fstati (i_out, F_BUFSIZE)
+ call fseti (i_out, F_BUFSIZE, 1)
+
+ # plot it
+ call zseek (i_out, xp, yp)
+ call write(i_out, short(IDS_ZRES(i_kt)-1), 1)
+
+ # restore buffer
+ call fseti (i_out, F_BUFSIZE, bufsize)
+ }
+ i_pt_x = xp
+ i_pt_y = yp
+end
+
+
+# IDS_RPOINT - Plot a point in the current plane at given (device coord) offsets
+# from current point.
+
+procedure ids_rpoint (dx,dy)
+
+short dx,dy # DEVICE coordinate increments from cur. pos.
+
+int xp, yp
+
+include "../lib/ids.com"
+
+begin
+ xp = i_pt_x + dx
+ yp = i_pt_y + dy
+
+ call zseek (i_out, xp, yp)
+ call write(i_out, short(IDS_ZRES(i_kt)-1), 1)
+
+ i_pt_x = xp
+ i_pt_y = yp
+end
diff --git a/pkg/images/tv/iis/ids/idsreset.x b/pkg/images/tv/iis/ids/idsreset.x
new file mode 100644
index 00000000..627b3d4e
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsreset.x
@@ -0,0 +1,56 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "../lib/ids.h"
+
+# IDS_RESET -- Reset the state of the transform common, i.e., in response to
+# a clear or a cancel. Initialize all attribute packets to their default
+# values and set the current state of the device to undefined, forcing the
+# device state to be reset when the next output instruction is executed.
+# Clear the image, graphics, and luts only if reset is "hard" enough.
+
+procedure ids_reset(hardness)
+
+short hardness
+
+pointer pl, pm, fa, tx
+
+include "../lib/ids.com"
+
+begin
+ # Set pointers to attribute substructures.
+ pl = IDS_PLAP(i_kt)
+ pm = IDS_PMAP(i_kt)
+ fa = IDS_FAAP(i_kt)
+ tx = IDS_TXAP(i_kt)
+
+ # Initialize the attribute packets.
+ PL_LTYPE(pl) = 1
+ PL_WIDTH(pl) = GKI_PACKREAL(1.)
+ PL_COLOR(pl) = 1
+ PM_LTYPE(pm) = 1
+ PM_WIDTH(pm) = GKI_PACKREAL(1.)
+ PM_COLOR(pm) = 1
+ FA_STYLE(fa) = 1
+ FA_COLOR(fa) = 1
+ TX_UP(tx) = 90
+ TX_SIZE(tx) = GKI_PACKREAL(1.)
+ TX_PATH(tx) = GT_RIGHT
+ TX_HJUSTIFY(tx) = GT_LEFT
+ TX_VJUSTIFY(tx) = GT_BOTTOM
+ TX_FONT(tx) = GT_ROMAN
+ TX_COLOR(tx) = 1
+ TX_SPACING(tx) = 0.0
+
+ # Set the device attributes to undefined, forcing them to be reset
+ # when the next output instruction is executed.
+
+ IDS_TYPE(i_kt) = -1
+ IDS_WIDTH(i_kt) = -1
+ IDS_COLOR(i_kt) = -1
+ IDS_TXSIZE(i_kt) = -1
+ IDS_TXFONT(i_kt) = -1
+
+ call zreset(hardness)
+end
diff --git a/pkg/images/tv/iis/ids/idsrestore.x b/pkg/images/tv/iis/ids/idsrestore.x
new file mode 100644
index 00000000..246631c0
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsrestore.x
@@ -0,0 +1,84 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_RESTORE -- Restore the control state of the display, together with
+# zero to all of the image and graphics planes.
+
+procedure ids_restore (data, n)
+
+short data[ARB] # instruction data words
+short n # number of data words
+
+int fd # binary file output descriptor
+short i, j
+short frame[IDS_MAXIMPL+1] # frames to save
+short graph[IDS_MAXGRPL+1] # graph planes to save
+short buffer[IDS_MAXDATA] # for data storage
+
+include "../lib/ids.com"
+
+begin
+ # determine file descriptor to read (opened by upper end)
+ # ( assume upper end has retrieved whatever data it stored and
+ # leaves fd pointing at control information offset)
+ # then retrieve the frame data
+
+ fd = data[1]
+
+ # image data
+
+ call read(fd, i, SZ_SHORT)
+ call read(fd, buffer, i)
+ j = 0
+ i = 0
+ repeat {
+ i = i + 1
+ j = j + 1
+ frame[j] = buffer[i]
+ } until ( (buffer[i] == IDS_EOD) || ( j == i_maxframes) )
+ frame[i+1] = IDS_EOD
+
+ # graph data
+
+ call read(fd, i, SZ_SHORT)
+ call read(fd, buffer, i)
+ i = 0
+ j = 0
+ repeat {
+ i = i + 1
+ j = j + 1
+ graph[j] = buffer[i]
+ } until ( (buffer[i] == IDS_EOD) || ( j == i_maxgraph) )
+ graph[i+1] = IDS_EOD
+
+ # get all control information
+
+ call zdev_restore(fd)
+
+ # get image data
+
+ if ( frame[1] == IDS_EOD) {
+ for ( i = 1 ; i <= i_maxframes ; i = i + 1)
+ frame[i] = i
+ frame[i+1] = IDS_EOD
+ }
+ if ( frame[1] != 0 ) {
+ for ( i = 1 ; frame[i] != IDS_EOD ; i = i + 1)
+ call zim_restore (fd, frame[i])
+ }
+
+ # get graphics data
+
+ if ( graph[1] == IDS_EOD) {
+ for ( i = 1 ; i <= i_maxgraph ; i = i + 1)
+ graph[i] = i
+ graph[i+1] = IDS_EOD
+ }
+ if ( graph[1] != 0 ) {
+ for ( i = 1 ; graph[i] != IDS_EOD ; i = i + 1)
+ call zgr_restore (fd, graph[i])
+ }
+
+ # upper end to close file
+end
diff --git a/pkg/images/tv/iis/ids/idssave.x b/pkg/images/tv/iis/ids/idssave.x
new file mode 100644
index 00000000..a66ebc00
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idssave.x
@@ -0,0 +1,82 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_SAVE -- Save the control state of the display, together with
+# zero to all of the image and graphics planes.
+
+procedure ids_save (data, n)
+
+short data[ARB] # instruction data words
+short n # count of data words
+
+int fd # binary file output descriptor
+short i, j
+short frame[IDS_MAXIMPL+1] # frames to save
+short graph[IDS_MAXGRPL+1] # graph planes to save
+
+include "../lib/ids.com"
+
+begin
+ # do we need to check n ??
+
+ # determine file descriptor to write (opened by upper end)
+ # ( assume upper end has saved whatever data it wanted and
+ # leaves fd pointing at control information offset)
+ # then squirrel away the frame data
+
+ fd = data[1]
+
+ # image data
+
+ i = 1
+ j = 0
+ repeat {
+ i = i + 1
+ j = j + 1
+ frame[j] = data[i]
+ } until ( data[i] == IDS_EOD )
+ call write(fd, j, SZ_SHORT)
+ call write(fd, frame[1], j*SZ_SHORT)
+
+ # graph data
+
+ j = 0
+ repeat {
+ i = i + 1
+ j = j + 1
+ graph[j] = data[i]
+ } until ( data[i] == IDS_EOD )
+ call write(fd, j, SZ_SHORT)
+ call write(fd, graph[1], j*SZ_SHORT)
+
+ # get all control information
+
+ call zdev_save(fd)
+
+ # get image data
+
+ if ( frame[1] == IDS_EOD) {
+ for ( i = 1 ; i <= i_maxframes ; i = i + 1)
+ frame[i] = i
+ frame[i+1] = IDS_EOD
+ }
+ if ( frame[1] != 0 ) {
+ for ( i = 1 ; frame[i] != IDS_EOD ; i = i + 1)
+ call zim_save (fd, frame[i])
+ }
+
+ # get graphics data
+
+ if ( graph[1] == IDS_EOD) {
+ for ( i = 1 ; i <= i_maxgraph ; i = i + 1)
+ graph[i] = i
+ graph[i+1] = IDS_EOD
+ }
+ if ( graph[1] != 0 ) {
+ for ( i = 1 ; graph[i] != IDS_EOD ; i = i + 1)
+ call zgr_save (fd, graph[i])
+ }
+
+ # upper end to close file
+end
diff --git a/pkg/images/tv/iis/ids/idsscur.x b/pkg/images/tv/iis/ids/idsscur.x
new file mode 100644
index 00000000..7ec48c32
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsscur.x
@@ -0,0 +1,12 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# IDS_SETCURSOR -- Set the position of a cursor.
+
+procedure ids_setcursor (x, y, cursor)
+
+int x, y # new position of cursor
+int cursor # cursor to be set
+
+begin
+ call zcursor_set(cursor, x, y)
+end
diff --git a/pkg/images/tv/iis/ids/idsstream.x b/pkg/images/tv/iis/ids/idsstream.x
new file mode 100644
index 00000000..bb7360b4
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsstream.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IDS_GRSTREAM -- Set the FD of the graphics/image stream, to which
+# we return cell arrays and cursor values.
+
+procedure ids_grstream (stream)
+
+int stream
+
+include "../lib/ids.com"
+
+begin
+ i_in = stream
+end
diff --git a/pkg/images/tv/iis/ids/idstx.x b/pkg/images/tv/iis/ids/idstx.x
new file mode 100644
index 00000000..7209d00b
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idstx.x
@@ -0,0 +1,428 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <gset.h>
+include <gki.h>
+include "../lib/ids.h"
+
+define BASECS_X 12 # Base (size 1.0) char width in GKI coords.
+define BASECS_Y 12 # Base (size 1.0) char height in GKI coords.
+
+
+# IDS_TEXT -- Draw a text string. The string is drawn at the position (X,Y)
+# using the text attributes set by the last GKI_TXSET instruction. The text
+# string to be drawn may contain embedded set font escape sequences of the
+# form \fR (roman), \fG (greek), etc. We break the input text sequence up
+# into segments at font boundaries and draw these on the output device,
+# setting the text size, color, font, and position at the beginning of each
+# segment.
+
+procedure ids_text (xc, yc, text, n)
+
+int xc, yc # where to draw text string
+short text[ARB] # text string
+int n # number of characters
+
+real x, y, dx, dy, tsz
+int x1, x2, y1, y2, orien
+int x0, y0, ids_dx, ids_dy, ch, cw
+int xstart, ystart, newx, newy
+int totlen, polytext, font, seglen
+pointer sp, seg, ip, op, tx, first
+int stx_segment()
+
+include "../lib/ids.com"
+
+real i_dx, i_dy # scale GKI to window coords
+int i_x1, i_y1 # origin of device window
+int i_x2, i_y2 # upper right corner of device window
+data i_dx /1.0/, i_dy /1.0/
+data i_x1 /0/, i_y1 /0/, i_x2 /GKI_MAXNDC/, i_y2 / GKI_MAXNDC/
+
+begin
+ call smark (sp)
+ call salloc (seg, n + 2, TY_CHAR)
+
+ # Set pointer to the text attribute structure.
+ tx = IDS_TXAP(i_kt)
+
+ # Set the text size and color if not already set. Both should be
+ # invalidated when the screen is cleared. Text color should be
+ # invalidated whenever another color is set. The text size was
+ # set by ids_txset, and is just a scaling factor.
+
+ IDS_TXSIZE(i_kt) = TX_SIZE(tx)
+ # For display, have 32767 sizes, so just scale the the base sizes.
+ tsz = GKI_UNPACKREAL(TX_SIZE(tx)) # scale factor
+ ch = IDS_CHARHEIGHT(i_kt,1) * tsz
+ cw = IDS_CHARWIDTH(i_kt,1) * tsz
+
+ if (TX_COLOR(tx) != IDS_COLOR(i_kt)) {
+ # Should do something like call ids_color (TX_COLOR(tx))
+ # But that requires some association of color with hardware
+ # and what that should be is not clear.
+ IDS_COLOR(i_kt) = TX_COLOR(tx)
+ }
+
+ # Set the linetype to a solid line, and invalidate last setting.
+ call ids_linetype (GL_SOLID)
+ IDS_TYPE(i_kt) = -1
+
+ # Break the text string into segments at font boundaries and count
+ # the total number of printable characters.
+
+ totlen = stx_segment (text, n, Memc[seg], TX_FONT(tx))
+
+ # Compute the text drawing parameters, i.e., the coordinates of the
+ # first character to be drawn, the step between successive characters,
+ # and the polytext flag (GKI coords).
+
+ call stx_parameters (xc,yc, totlen, x0,y0, ids_dx,ids_dy, polytext,
+ orien)
+
+ # Draw the segments, setting the font at the beginning of each segment.
+ # The first segment is drawn at (X0,Y0). The separation between
+ # characters is DX,DY. A segment is drawn as a block if the polytext
+ # flag is set, otherwise each character is drawn individually.
+
+ x = x0 * i_dx + i_x1
+ y = y0 * i_dy + i_y1
+ dx = ids_dx * i_dx
+ dy = ids_dy * i_dy
+
+ for (ip=seg; Memc[ip] != EOS; ip=ip+1) {
+ # Process the font control character heading the next segment.
+ font = Memc[ip]
+ ip = ip + 1
+
+ # Draw the segment.
+ while (Memc[ip] != EOS) {
+ # Clip leading out of bounds characters.
+ for (; Memc[ip] != EOS; ip=ip+1) {
+ x1 = x; x2 = x1 + cw
+ y1 = y; y2 = y1 + ch
+
+ if (x1 >= i_x1 && x2 <= i_x2 && y1 >= i_y1 && y2 <= i_y2)
+ break
+ else {
+ x = x + dx
+ y = y + dy
+ }
+
+ if (polytext == NO) {
+ ip = ip + 1
+ break
+ }
+ }
+
+ # Coords of first char to be drawn.
+ xstart = x
+ ystart = y
+
+ # Move OP to first out of bounds char.
+ for (op=ip; Memc[op] != EOS; op=op+1) {
+ x1 = x; x2 = x1 + cw
+ y1 = y; y2 = y1 + ch
+
+ if (x1 <= i_x1 || x2 >= i_x2 || y1 <= i_y1 || y2 >= i_y2)
+ break
+ else {
+ x = x + dx
+ y = y + dy
+ }
+
+ if (polytext == NO) {
+ op = op + 1
+ break
+ }
+ }
+
+ # Count number of inbounds chars.
+ seglen = op - ip
+
+ # Leave OP pointing to the end of this segment.
+ if (polytext == NO)
+ op = ip + 1
+ else {
+ while (Memc[op] != EOS)
+ op = op + 1
+ }
+
+ # Compute X,Y of next segment.
+ newx = xstart + (dx * (op - ip))
+ newy = ystart + dy
+
+ # Quit if no inbounds chars.
+ if (seglen == 0) {
+ x = newx
+ y = newy
+ ip = op
+ next
+ }
+
+ # Output the inbounds chars.
+
+ first = ip
+ x = xstart
+ y = ystart
+
+ while (seglen > 0 && (polytext == YES || ip == first)) {
+ call ids_drawchar (Memc[ip], nint(x), nint(y), cw, ch,
+ orien, font)
+ ip = ip + 1
+ seglen = seglen - 1
+ x = x + dx
+ y = y + dy
+ }
+
+ x = newx
+ y = newy
+ ip = op
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# STX_SEGMENT -- Process the text string into segments, in the process
+# converting from type short to char. The only text attribute that can
+# change within a string is the font, so segments are broken by \fI, \fG,
+# etc. font select sequences embedded in the text. The segments are encoded
+# sequentially in the output string. The first character of each segment is
+# the font number. A segment is delimited by EOS. A font number of EOS
+# marks the end of the segment list. The output string is assumed to be
+# large enough to hold the segmented text string.
+
+int procedure stx_segment (text, n, out, start_font)
+
+short text[ARB] # input text
+int n # number of characters in text
+char out[ARB] # output string
+int start_font # initial font code
+
+int ip, op
+int totlen, font
+
+begin
+ out[1] = start_font
+ totlen = 0
+ op = 2
+
+ for (ip=1; ip <= n; ip=ip+1) {
+ if (text[ip] == '\\' && text[ip+1] == 'f') {
+ # Select font.
+ out[op] = EOS
+ op = op + 1
+ ip = ip + 2
+
+ switch (text[ip]) {
+ case 'B':
+ font = GT_BOLD
+ case 'I':
+ font = GT_ITALIC
+ case 'G':
+ font = GT_GREEK
+ default:
+ font = GT_ROMAN
+ }
+
+ out[op] = font
+ op = op + 1
+
+ } else {
+ # Deposit character in segment.
+ out[op] = text[ip]
+ op = op + 1
+ totlen = totlen + 1
+ }
+ }
+
+ # Terminate last segment and add null segment.
+
+ out[op] = EOS
+ out[op+1] = EOS
+
+ return (totlen)
+end
+
+
+# STX_PARAMETERS -- Set the text drawing parameters, i.e., the coordinates
+# of the lower left corner of the first character to be drawn, the spacing
+# between characters, and the polytext flag. Input consists of the coords
+# of the text string, the length of the string, and the text attributes
+# defining the character size, justification in X and Y of the coordinates,
+# and orientation of the string. All coordinates are in GKI units.
+
+procedure stx_parameters (xc, yc, totlen, x0, y0, dx, dy, polytext, orien)
+
+int xc, yc # coordinates at which string is to be drawn
+int totlen # number of characters to be drawn
+int x0, y0 # lower left corner of first char to be drawn
+int dx, dy # step in X and Y between characters
+int polytext # OK to output text segment all at once
+int orien # rotation angle of characters
+
+pointer tx
+int up, path
+real dir, ch, cw, cosv, sinv, space, sz
+real xsize, ysize, xvlen, yvlen, xu, yu, xv, yv, p, q
+
+include "../lib/ids.com"
+
+begin
+ tx = IDS_TXAP(i_kt)
+
+ # Get character sizes in GKI coords.
+ sz = GKI_UNPACKREAL (TX_SIZE(tx))
+ ch = IDS_CHARHEIGHT(i_kt,1) * sz
+ cw = IDS_CHARWIDTH(i_kt,1) * sz
+
+ # Compute the character rotation angle. This is independent of the
+ # direction in which characters are drawn. A character up vector of
+ # 90 degrees (normal) corresponds to a rotation angle of zero.
+
+ up = TX_UP(tx)
+ orien = up - 90
+
+ # Determine the direction in which characters are to be plotted.
+ # This depends on both the character up vector and the path, which
+ # is defined relative to the up vector.
+
+ path = TX_PATH(tx)
+ switch (path) {
+ case GT_UP:
+ dir = up
+ case GT_DOWN:
+ dir = up - 180
+ case GT_LEFT:
+ dir = up + 90
+ default: # GT_NORMAL, GT_RIGHT
+ dir = up - 90
+ }
+
+ # ------- DX, DY ---------
+ # Convert the direction vector into the step size between characters.
+ # Note CW and CH are in GKI coordinates, hence DX and DY are too.
+ # Additional spacing of some fraction of the character size is used
+ # if TX_SPACING is nonzero.
+
+ dir = -DEGTORAD(dir)
+ cosv = cos (dir)
+ sinv = sin (dir)
+
+ # Correct for spacing (unrotated).
+ space = (1.0 + TX_SPACING(tx))
+ if (path == GT_UP || path == GT_DOWN)
+ p = ch * space
+ else
+ p = cw * space
+ q = 0
+
+ # Correct for rotation.
+ dx = p * cosv + q * sinv
+ dy = -p * sinv + q * cosv
+
+ # ------- XU, YU ---------
+ # Determine the coordinates of the center of the first character req'd
+ # to justify the string, assuming dimensionless characters spaced on
+ # centers DX,DY apart.
+
+ xvlen = dx * (totlen - 1)
+ yvlen = dy * (totlen - 1)
+
+ switch (TX_HJUSTIFY(tx)) {
+ case GT_CENTER:
+ xu = - (xvlen / 2.0)
+ case GT_RIGHT:
+ # If right justify and drawing to the left, no offset req'd.
+ if (xvlen < 0)
+ xu = 0
+ else
+ xu = -xvlen
+ default: # GT_LEFT, GT_NORMAL
+ # If left justify and drawing to the left, full offset right req'd.
+ if (xvlen < 0)
+ xu = -xvlen
+ else
+ xu = 0
+ }
+
+ switch (TX_VJUSTIFY(tx)) {
+ case GT_CENTER:
+ yu = - (yvlen / 2.0)
+ case GT_TOP:
+ # If top justify and drawing downward, no offset req'd.
+ if (yvlen < 0)
+ yu = 0
+ else
+ yu = -yvlen
+ default: # GT_BOTTOM, GT_NORMAL
+ # If bottom justify and drawing downward, full offset up req'd.
+ if (yvlen < 0)
+ yu = -yvlen
+ else
+ yu = 0
+ }
+
+ # ------- XV, YV ---------
+ # Compute the offset from the center of a single character required
+ # to justify that character, given a particular character up vector.
+ # (This could be combined with the above case but is clearer if
+ # treated separately.)
+
+ p = -DEGTORAD(orien)
+ cosv = cos(p)
+ sinv = sin(p)
+
+ # Compute the rotated character in size X and Y.
+ xsize = abs ( cw * cosv + ch * sinv)
+ ysize = abs (-cw * sinv + ch * cosv)
+
+ switch (TX_HJUSTIFY(tx)) {
+ case GT_CENTER:
+ xv = 0
+ case GT_RIGHT:
+ xv = - (xsize / 2.0)
+ default: # GT_LEFT, GT_NORMAL
+ xv = xsize / 2
+ }
+
+ switch (TX_VJUSTIFY(tx)) {
+ case GT_CENTER:
+ yv = 0
+ case GT_TOP:
+ yv = - (ysize / 2.0)
+ default: # GT_BOTTOM, GT_NORMAL
+ yv = ysize / 2
+ }
+
+ # ------- X0, Y0 ---------
+ # The center coordinates of the first character to be drawn are given
+ # by the reference position plus the string justification vector plus
+ # the character justification vector.
+
+ x0 = xc + xu + xv
+ y0 = yc + yu + yv
+
+ # The character drawing primitive requires the coordinates of the
+ # lower left corner of the character (irrespective of orientation).
+ # Compute the vector from the center of a character to the lower left
+ # corner of a character, rotate to the given orientation, and correct
+ # the starting coordinates by addition of this vector.
+
+ p = - (cw / 2.0)
+ q = - (ch / 2.0)
+
+ x0 = x0 + ( p * cosv + q * sinv)
+ y0 = y0 + (-p * sinv + q * cosv)
+
+ # ------- POLYTEXT ---------
+ # Set the polytext flag. Polytext output is possible only if chars
+ # are to be drawn to the right with no extra spacing between chars.
+
+ if (abs(dy) == 0 && dx == cw)
+ polytext = YES
+ else
+ polytext = NO
+end
diff --git a/pkg/images/tv/iis/ids/idstxset.x b/pkg/images/tv/iis/ids/idstxset.x
new file mode 100644
index 00000000..3c9529da
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idstxset.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# IDS_TXSET -- Set the text drawing attributes.
+
+procedure ids_txset (gki)
+
+short gki[ARB] # attribute structure
+
+pointer tx
+
+include "../lib/ids.com"
+
+begin
+ tx = IDS_TXAP(i_kt)
+ TX_UP(tx) = gki[GKI_TXSET_UP]
+ TX_PATH(tx) = gki[GKI_TXSET_P ]
+ TX_HJUSTIFY(tx) = gki[GKI_TXSET_HJ]
+ TX_VJUSTIFY(tx) = gki[GKI_TXSET_VJ]
+ TX_FONT(tx) = gki[GKI_TXSET_F ]
+ TX_QUALITY(tx) = gki[GKI_TXSET_Q ]
+ TX_COLOR(tx) = gki[GKI_TXSET_CI]
+
+ TX_SPACING(tx) = GKI_UNPACKREAL (gki[GKI_TXSET_SP])
+ TX_SIZE(tx) = gki[GKI_TXSET_SZ]
+
+end
diff --git a/pkg/images/tv/iis/ids/idsvector.x b/pkg/images/tv/iis/ids/idsvector.x
new file mode 100644
index 00000000..6d1ec502
--- /dev/null
+++ b/pkg/images/tv/iis/ids/idsvector.x
@@ -0,0 +1,122 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <fset.h>
+include "../lib/ids.h"
+
+define MAXC 10000 # just a largish int here
+
+# IDS_VECTOR -- Plot a line in the current plane; the starting coordinates
+# are in ids.com: i_pt_x, i_pt_y. The end points are the arguments
+# to vector.
+# the code is Bresenham's algorithm, as taken from the line drawing
+# routine in Forth-11 image display code.
+
+procedure ids_vector (ax,ay)
+
+short ax,ay # vector end coordinates, GKI
+
+short x,y
+short xe ,ye # end coordinates, device
+short dx,dy,dd
+short xi,yi, xid,yid # increments
+short total, e # total change and error
+int bufsize # file i/o buffersize
+int fstati()
+int count, cmax
+
+include "../lib/ids.com"
+
+begin
+ x = ax
+ y = ay
+
+ bufsize = fstati(i_out, F_BUFSIZE)
+
+ # convert x,y to device coords.
+ xe = real(x) * i_xres /(GKI_MAXNDC+1)
+ ye = real(y) * i_yres /(GKI_MAXNDC+1)
+
+ # determine delta x and y, and x/y increments
+
+ dx = xe - i_pt_x
+ dy = ye - i_pt_y
+
+ # set movement increments, take absolute value of dx, dy
+ if ( dy >= 0 )
+ yi = 1
+ else {
+ yi = -1
+ dy = -dy
+ }
+ if ( dx >= 0 )
+ xi = 1
+ else {
+ xi = -1
+ dx = -dx
+ }
+
+ # set diagonal movement increments
+ xid = xi
+ yid = yi
+
+ # if, for instance, pos. slope less than 45 degrees, most movement
+ # is in x, so then set (the ususal) y increment to zero
+ if ( dy >= dx )
+ xi = 0
+ else
+ yi = 0
+
+ # Set up for buffer of one, and let code find best buffering
+ cmax = 0
+ call fseti(i_out, F_BUFSIZE, 1)
+ count = 0
+
+ # Plot the first point
+ call ids_rpoint (0, 0)
+
+ # Is there anything to do? determine total increments to plot; if
+ # zero, quit
+ total = dx + dy
+ if ( total == 0 ) {
+ call fseti (i_out, F_BUFSIZE, bufsize)
+ return
+ }
+
+ # set error to zero, determine difference in x,y change.
+ e = 0
+ dd = dy - dx
+ if ( dd >= 0 ) {
+ dd = -dd
+ dy = dx
+ }
+
+ # plot the line
+ repeat {
+ dx = dd + e
+ if ( (dy + e + dx) >= 0 ) {
+ # diagonal plot, accounts for two units of increment
+ if ( count > cmax ) {
+ # leaving current (x) line, so determine how many points
+ # have plotted on line and use this (maximum) as line
+ # buffering size
+ call fseti(i_out, F_BUFSIZE, count)
+ cmax = count
+ count = 0
+ }
+ call ids_rpoint ( xid, yid )
+ total = total - 2
+ e = dx
+ } else {
+ # move in x (or y) only; for the small positive slope line,
+ # real line will move up and finally over line being plotted,
+ # hence e increases.
+ call ids_rpoint ( xi, yi )
+ total = total - 1
+ e = e + dy
+ count = count + 1
+ }
+ } until ( total <= 0 )
+ # restore original buffer size
+ call fseti(i_out, F_BUFSIZE, bufsize)
+end
diff --git a/pkg/images/tv/iis/ids/mkpkg b/pkg/images/tv/iis/ids/mkpkg
new file mode 100644
index 00000000..79778100
--- /dev/null
+++ b/pkg/images/tv/iis/ids/mkpkg
@@ -0,0 +1,43 @@
+# Make the CV package library.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ idscancel.x ../lib/ids.com ../lib/ids.h <fset.h>
+ idschars.x ../lib/ids.com ../lib/ids.h
+ idsclear.x ../lib/ids.com ../lib/ids.h
+ idsclose.x ../lib/ids.com ../lib/ids.h
+ idsclosews.x ../lib/ids.h ../lib/ids.com
+ idscround.x ../lib/ids.h <gki.h>
+ idsdrawch.x font.com font.h <gki.h> <gset.h> <math.h>
+ idsescape.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idsfa.x ../lib/ids.com ../lib/ids.h
+ idsfaset.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idsflush.x ../lib/ids.com ../lib/ids.h
+ idsfont.x ../lib/ids.com ../lib/ids.h <gki.h> <gset.h>
+ idsgcell.x <mach.h> ../lib/ids.com ../lib/ids.h <gki.h> <gset.h>
+ idsgcur.x ../lib/ids.com ../lib/ids.h
+ idsinit.x ../lib/ids.com ../lib/ids.h <ctype.h> <gki.h> <mach.h>
+ idsline.x ../lib/ids.com ../lib/ids.h <gset.h>
+ idslutfill.x <gki.h>
+ idsopen.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idsopenws.x ../lib/ids.com ../lib/ids.h <error.h> <gki.h>\
+ <fset.h> <mach.h>
+ idspcell.x ../lib/ids.com ../lib/ids.h <gki.h> <gset.h>
+ idspl.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idsplset.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idspm.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idspmset.x ../lib/ids.com ../lib/ids.h <gki.h>
+ idspoint.x ../lib/ids.com ../lib/ids.h <fset.h> <gki.h>
+ idsreset.x ../lib/ids.com ../lib/ids.h <gset.h> <gki.h>
+ idsrestore.x ../lib/ids.com ../lib/ids.h
+ idssave.x ../lib/ids.com ../lib/ids.h
+ idsscur.x
+ idsstream.x ../lib/ids.com ../lib/ids.h
+ idstx.x ../lib/ids.com ../lib/ids.h <gki.h> <gset.h> <math.h>
+ idstxset.x ../lib/ids.com ../lib/ids.h <gki.h> <gset.h>
+ idsvector.x ../lib/ids.com ../lib/ids.h <fset.h> <gki.h>
+ ;
diff --git a/pkg/images/tv/iis/ids/testcode/README b/pkg/images/tv/iis/ids/testcode/README
new file mode 100644
index 00000000..31198b43
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/README
@@ -0,0 +1,2 @@
+This is junk code which I think should be thrown away. I will leave it here
+for the time just in case. (LED 22/4/91)
diff --git a/pkg/images/tv/iis/ids/testcode/box.x b/pkg/images/tv/iis/ids/testcode/box.x
new file mode 100644
index 00000000..e3c1d22b
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/box.x
@@ -0,0 +1,83 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+include <gki.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# create a box test image
+
+procedure t_im()
+
+pointer gp
+char output[SZ_FNAME], output_file[SZ_FNAME], device[SZ_FNAME]
+int fd
+
+pointer gopen()
+bool streq()
+int open()
+
+short i,data[DIM+1]
+short set_image[6]
+int key
+real x[30],y[30]
+real lb,ub,mid
+int mod()
+
+begin
+ call clgstr("output", output, SZ_FNAME)
+ if (!streq (output, "") ) {
+ call strcpy (output, output_file, SZ_FNAME)
+ fd = open (output_file, NEW_FILE, BINARY_FILE)
+ } else
+ fd = open ("dev$stdimage", NEW_FILE, BINARY_FILE)
+
+ call clgstr("device", device, SZ_FNAME)
+ gp = gopen ( device, NEW_FILE, fd)
+
+ # now set up boxes
+ set_image[1] = 1
+ set_image[2] = IMD_EOD
+ set_image[3] = IMD_BLUE
+ set_image[4] = IMD_EOD
+ call gescape ( gp, IMD_SET_GP, set_image, 4)
+ lb = 0.0
+ ub = 1.0
+ mid = (lb + ub)/2.
+ for ( i = 1; i <= 5 ; i = i + 1 ) {
+ if ( mod(i-1,2) == 0 ) {
+ x[1] = lb
+ y[1] = mid
+ x[2] = mid
+ y[2] = ub
+ x[3] = ub
+ y[3] = mid
+ x[4] = mid
+ y[4] = lb
+ x[5] = lb
+ y[5] = mid
+ } else {
+ x[1] = (mid-lb)/2 + lb
+ y[1] = x[1]
+ x[2] = x[1]
+ # x[2] = x[1] - .05
+ y[2] = y[1] + mid - lb
+ x[3] = y[2]
+ y[3] = y[2]
+ # y[3] = y[2] - .05
+ x[4] = y[2]
+ y[4] = x[1]
+ x[5] = x[1]
+ y[5] = y[1]
+ lb = x[1]
+ ub = y[2]
+ }
+ call gpline ( gp, x, y, 5)
+ }
+
+ # all done
+ call gclose ( gp )
+ call close ( fd )
+end
diff --git a/pkg/images/tv/iis/ids/testcode/boxin.x b/pkg/images/tv/iis/ids/testcode/boxin.x
new file mode 100644
index 00000000..e854935f
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/boxin.x
@@ -0,0 +1,98 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include "ids.h"
+include <gki.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# create a box test image
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+
+pointer gopen()
+int dd[LEN_GKIDD]
+
+short i,data[DIM+1]
+short set_image[6]
+int key, j
+real x[30],y[30]
+real lb,ub,mid
+int mod()
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+
+ # enable the blue plane
+ set_image[1] = IDS_ON
+ set_image[2] = IDS_EOD # all graphics frames
+ set_image[3] = IDS_BLUE # color
+ set_image[4] = IDS_EOD
+ set_image[5] = IDS_EOD # all quadrants
+ call gescape ( gp, IDS_DISPLAY_G, set_image, 5)
+
+ # set which plane to write into
+ set_image[1] = 1
+ set_image[2] = IDS_EOD # first graphics frame
+ set_image[3] = IDS_BLUE # color
+ set_image[4] = IDS_EOD
+ call gescape ( gp, IDS_SET_GP, set_image, 4)
+
+ # now set up boxes
+ lb = 0.0
+ ub = 1.0
+ mid = (lb + ub)/2.
+ for ( i = 1; i <= 5 ; i = i + 1 ) {
+ if ( mod(i-1,2) == 0 ) {
+ x[1] = lb
+ y[1] = mid
+ x[2] = mid
+ y[2] = ub
+ x[3] = ub
+ y[3] = mid
+ x[4] = mid
+ y[4] = lb
+ x[5] = lb
+ y[5] = mid
+ } else {
+ x[1] = (mid-lb)/2 + lb
+ y[1] = x[1]
+ x[2] = x[1]
+ y[2] = y[1] + mid - lb
+ x[3] = y[2]
+ y[3] = y[2]
+ x[4] = y[2]
+ y[4] = x[1]
+ x[5] = x[1]
+ y[5] = y[1]
+ lb = x[1]
+ ub = y[2]
+ }
+ do j = 1,5 {
+ x[j] = x[j] * 32768. / 32767.
+ if (x[j] > 1.0)
+ x[j] = 1.0
+ y[j] = y[j] * 32768. / 32767.
+ if (y[j] > 1.0)
+ y[j] = 1.0
+ }
+ call gpline ( gp, x, y, 5)
+ }
+
+ # all done
+ call gclose ( gp )
+ call ids_close
+end
diff --git a/pkg/images/tv/iis/ids/testcode/crin.x b/pkg/images/tv/iis/ids/testcode/crin.x
new file mode 100644
index 00000000..c9d27279
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/crin.x
@@ -0,0 +1,130 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include "ids.h"
+include <gki.h>
+include <gset.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# zoom
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+
+pointer gopen()
+int dd[LEN_GKIDD]
+
+short i, data[DIM+1]
+int key, but, fnum
+real x, y
+real xjunk, yjunk
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ # read first to clear box
+ call gseti(gp, G_CURSOR, IDS_BUT_RD)
+ call ggcur(gp, xjunk, yjunk, key)
+
+ i = 1
+ repeat {
+ call eprintf("set zoom and zoom center\n")
+ call gseti (gp, G_CURSOR, IDS_BUT_WT)
+ call ggcur(gp, x, y, but)
+ call gseti (gp, G_CURSOR, 1)
+ call ggcur(gp, x, y, key)
+ call zm(gp, but, x, y)
+ call eprintf("set frame, 4 to exit\n")
+ call gseti (gp, G_CURSOR, IDS_BUT_WT)
+ call ggcur(gp, xjunk, yjunk, fnum)
+ if ( fnum == 4)
+ break
+ call iset(gp, fnum)
+ repeat {
+ call gseti (gp, G_CURSOR, IDS_BUT_WT)
+ call ggcur(gp, xjunk, yjunk, but)
+ call gseti (gp, G_CURSOR, fnum)
+ call rpc(gp, x, y, key)
+ call ggcell (gp, data, 1, 1, x, y, x, y)
+ call eprintf("frame %d, datum: %d\n")
+ call pargi (fnum)
+ call pargs (data[1])
+ } until ( but == 4)
+ } until ( i == 0 )
+
+
+ # all done
+ call gclose ( gp )
+ call ids_close
+end
+
+# rpcursor --- read and print cursor
+
+procedure rpc(gp, sx, sy, key)
+
+pointer gp
+real sx,sy
+int key
+
+begin
+ call ggcur (gp, sx, sy, key)
+ call eprintf("cursor: (%f,%f) (%d,%d) key %d\n")
+ call pargr (sx)
+ call pargr (sy)
+ call pargi ( int(sx*32767)/64)
+ call pargi ( int(sy*32767)/64)
+ call pargi (key)
+end
+
+# zoom
+
+procedure zm(gp, pow, x, y)
+
+int pow
+pointer gp
+real x, y
+
+short data[9]
+
+begin
+ data[1] = IDS_ZOOM
+ data[2] = IDS_WRITE
+ data[3] = 3
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = 2**(pow-1)
+ data[8] = x * GKI_MAXNDC
+ data[9] = y * GKI_MAXNDC
+ call gescape ( gp, IDS_CONTROL, data[1], 9)
+end
+
+# set image plane for operation
+
+procedure iset (gp, frame)
+
+int frame
+pointer gp
+
+short data[10]
+
+begin
+ data[1] = frame
+ data[2] = IDS_EOD
+ data[3] = IDS_EOD # all bitplanes
+ call gescape (gp, IDS_SET_IP, data, 3)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/grey.x b/pkg/images/tv/iis/ids/testcode/grey.x
new file mode 100644
index 00000000..a7e16b83
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/grey.x
@@ -0,0 +1,90 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# create a grey scale test image, using frames 1 and 2, and
+# position the cursor in the upper right quadrant.
+
+procedure t_im()
+
+pointer gp
+char output[SZ_FNAME], output_file[SZ_FNAME], device[SZ_FNAME]
+int fd
+
+pointer gopen()
+bool streq()
+int open()
+
+short i,data[DIM+1]
+short display[6]
+short set_image[3]
+real y, sx, sy
+int key
+
+begin
+ call clgstr("output", output, SZ_FNAME)
+ if (!streq (output, "") ) {
+ call strcpy (output, output_file, SZ_FNAME)
+ fd = open (output_file, NEW_FILE, BINARY_FILE)
+ } else
+ fd = open ("dev$stdimage", NEW_FILE, BINARY_FILE)
+
+ call clgstr("device", device, SZ_FNAME)
+ gp = gopen ( device, NEW_FILE, fd)
+
+ data[1] = IMD_R_HARD
+ call gescape ( gp, IMD_RESET, data, 1)
+ # display all frames off
+ display[1] = IMD_OFF
+ display[2] = IMD_EOD # all frames
+ display[3] = IMD_EOD # all colors
+ display[4] = IMD_EOD # all quads
+ call gescape ( gp, IMD_DISPLAY_I, display, 6)
+ # display frames 1, 2 on -- 1 red, 2 green
+ display[1] = IMD_ON
+ display[2] = 1
+ display[3] = IMD_EOD
+ display[4] = IMD_RED
+ display[5] = IMD_EOD
+ display[6] = IMD_EOD # all quads
+ call gescape ( gp, IMD_DISPLAY_I, display, 6)
+ display[1] = IMD_ON
+ display[2] = 2
+ display[3] = IMD_EOD
+ display[4] = IMD_GREEN
+ display[5] = IMD_EOD
+ display[6] = IMD_EOD # all quads
+ call gescape ( gp, IMD_DISPLAY_I, display, 6)
+
+ # now set up grey scale changing upward in frame 1
+ set_image[1] = 1
+ set_image[2] = IMD_EOD
+ set_image[3] = IMD_EOD # all planes
+ call gescape ( gp, IMD_SET_IP, set_image, 3)
+ for ( i = 1; i <= DIM ; i = i + 1 ) {
+ call amovks ( i-1, data, DIM)
+ y = real(i-1)/(DIM-1)
+ call gpcell ( gp, data, DIM, 1, 0., y, 1., y)
+ }
+
+ # grey scale changing horizontally in frame 2
+ set_image[1] = 2
+ call gescape ( gp, IMD_SET_IP, set_image, 3)
+ do i = 1, DIM
+ data[i] = i
+ call gpcell ( gp, data, DIM, 1, 0., 0., 1., 1.)
+
+ # set the cursor
+ call gscur ( gp, 0.0, 1.0)
+
+ # read cursor
+ # call ggcur( gp, sx, sy, key)
+
+ # all done
+ call gclose ( gp )
+ call close ( fd )
+end
diff --git a/pkg/images/tv/iis/ids/testcode/grin.x b/pkg/images/tv/iis/ids/testcode/grin.x
new file mode 100644
index 00000000..b76e58b2
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/grin.x
@@ -0,0 +1,98 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include <gki.h>
+include "ids.h"
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# create a grey scale test image, using frames 1 and 2, and
+# position the cursor in the upper right quadrant.
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+
+pointer gopen()
+int open()
+int dd[LEN_GKIDD]
+
+short i,data[DIM+1]
+short display[6]
+short set_image[3]
+real y, sx, sy
+int key
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream(STDIMAGE)
+
+ data[1] = IDS_R_HARD
+ call gescape ( gp, IDS_RESET, data, 1)
+ # display all frames off
+ display[1] = IDS_OFF
+ display[2] = IDS_EOD # all frames
+ display[3] = IDS_EOD # all colors
+ display[4] = IDS_EOD # all quads
+ call gescape ( gp, IDS_DISPLAY_I, display, 6)
+ # display frames 1, 2 on -- 1 red, 2 green
+ display[1] = IDS_ON
+ display[2] = 1
+ display[3] = IDS_EOD
+ display[4] = IDS_RED
+ display[5] = IDS_EOD
+ display[6] = IDS_EOD # all quads
+ call gescape ( gp, IDS_DISPLAY_I, display, 6)
+ display[1] = IDS_ON
+ display[2] = 2
+ display[3] = IDS_EOD
+ display[4] = IDS_GREEN
+ display[5] = IDS_EOD
+ display[6] = IDS_EOD # all quads
+ call gescape ( gp, IDS_DISPLAY_I, display, 6)
+
+ # now set up grey scale changing upward in frame 1
+ set_image[1] = 1
+ set_image[2] = IDS_EOD
+ set_image[3] = IDS_EOD # all planes
+ call gescape ( gp, IDS_SET_IP, set_image, 3)
+ for ( i = 1; i <= DIM ; i = i + 1 ) {
+ call amovks ( i-1, data, DIM)
+ y = real(i-1)/(DIM-1)
+ call gpcell ( gp, data, DIM, 1, 0., y, 1., y)
+ }
+
+ # grey scale changing horizontally in frame 2
+ set_image[1] = 2
+ call gescape ( gp, IDS_SET_IP, set_image, 3)
+ do i = 1, DIM
+ data[i] = i-1
+ call gpcell ( gp, data, DIM, 1, 0., 0., 1., 1.)
+
+ # set the cursor
+ call gscur ( gp, 0.0, 1.0)
+
+ # read cursor
+ call ggcur (gp, sx, sy, key)
+ call eprintf("cursor read as : (%f,%f) (%d,%d), key %d\n")
+ call pargr (sx)
+ call pargr (sy)
+ call pargi ( int(sx*32767)/64)
+ call pargi ( int(sy*32767)/64)
+ call pargi (key)
+
+ # all done
+ call gclose (gp)
+ call ids_close
+end
diff --git a/pkg/images/tv/iis/ids/testcode/scr.x b/pkg/images/tv/iis/ids/testcode/scr.x
new file mode 100644
index 00000000..ec4821cf
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/scr.x
@@ -0,0 +1,130 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+include <gset.h>
+include <gki.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# scroll
+
+procedure t_im()
+
+pointer gp
+char output[SZ_FNAME], output_file[SZ_FNAME], device[SZ_FNAME]
+int fd
+
+pointer gopen()
+bool streq()
+int open()
+common /local/gp
+
+begin
+ call clgstr("output", output, SZ_FNAME)
+ if (!streq (output, "") ) {
+ call strcpy (output, output_file, SZ_FNAME)
+ fd = open (output_file, NEW_FILE, BINARY_FILE)
+ } else
+ fd = open ("dev$stdimage", NEW_FILE, BINARY_FILE)
+
+ call clgstr("device", device, SZ_FNAME)
+ gp = gopen ( device, NEW_FILE, fd)
+
+ call cl_button
+ call scroll(0,0)
+ call cursor(128,128)
+ call wt_button
+ call scroll(128,195)
+ call cursor(128,128)
+ call wt_button
+ call zm(4,128,128)
+ call wt_button
+ call cursor(128,128)
+ call wt_button
+ call zm(1,205,205)
+
+ # all done
+ call gclose ( gp )
+ call close ( fd )
+end
+
+procedure scroll(x,y)
+
+int x,y
+
+pointer gp
+common /local/gp
+short data[8]
+
+begin
+ data[1] = IMD_SCROLL
+ data[2] = IMD_WRITE
+ data[3] = 2
+ data[4] = IMD_EOD
+ data[5] = IMD_EOD
+ data[6] = 0
+ data[7] = (x-1) * MCXSCALE
+ data[8] = (y-1) * MCYSCALE
+ call gescape(gp, IMD_CONTROL, data, 8)
+end
+
+procedure cursor(x,y)
+
+int x,y
+pointer gp
+real xr, yr
+common /local/gp
+
+begin
+ xr = real((x-1)*MCXSCALE)/GKI_MAXNDC
+ yr = real((y-1)*MCXSCALE)/GKI_MAXNDC
+ call gseti(gp, G_CURSOR, 1)
+ call gscur(gp, xr, yr)
+end
+
+procedure wt_button
+
+real x,y
+int key
+pointer gp
+common /local/gp
+begin
+ call gseti(gp, G_CURSOR, IMD_BUT_WT)
+ call ggcur(gp, x, y, key)
+end
+
+procedure cl_button
+
+real x,y
+int key
+pointer gp
+common /local/gp
+
+begin
+ call gseti(gp, G_CURSOR, IMD_BUT_RD)
+ call ggcur(gp, x, y, key)
+end
+
+procedure zm(power, x,y)
+
+int power
+int x,y
+
+short data[9]
+pointer gp
+common /local/gp
+
+begin
+ data[1] = IMD_ZOOM
+ data[2] = IMD_WRITE
+ data[3] = 3
+ data[4] = IMD_EOD
+ data[5] = IMD_EOD
+ data[6] = 0
+ data[7] = power
+ data[8] = (x-1) * MCXSCALE
+ data[9] = (y-1) * MCYSCALE
+ call gescape(gp, IMD_CONTROL, data, 9)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/scrin.x b/pkg/images/tv/iis/ids/testcode/scrin.x
new file mode 100644
index 00000000..7a704fe4
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/scrin.x
@@ -0,0 +1,130 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include "ids.h"
+include <gset.h>
+include <gki.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# scroll
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+
+pointer gopen()
+int dd[LEN_GKIDD]
+common /local/gp
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ call cl_button
+ call scroll(1,1)
+ call cursor(129,129)
+ call wt_button
+ call scroll(129,195)
+ call cursor(129,129)
+ call wt_button
+ call zm(4,129,129)
+ call wt_button
+ call cursor(129,129)
+ call wt_button
+ call zm(1,205,205)
+
+ # all done
+ call gclose ( gp )
+ call ids_close
+end
+
+procedure scroll(x,y)
+
+int x,y
+
+pointer gp
+common /local/gp
+short data[8]
+
+begin
+ data[1] = IDS_SCROLL
+ data[2] = IDS_WRITE
+ data[3] = 2
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = (x-1) * MCXSCALE
+ data[8] = (y-1) * MCYSCALE
+ call gescape(gp, IDS_CONTROL, data, 8)
+end
+
+procedure cursor(x,y)
+
+int x,y
+pointer gp
+real xr, yr
+common /local/gp
+
+begin
+ xr = real((x-1)*MCXSCALE)/GKI_MAXNDC
+ yr = real((y-1)*MCXSCALE)/GKI_MAXNDC
+ call gseti(gp, G_CURSOR, 1)
+ call gscur(gp, xr, yr)
+end
+
+procedure wt_button
+
+real x,y
+int key
+pointer gp
+common /local/gp
+begin
+ call gseti(gp, G_CURSOR, IDS_BUT_WT)
+ call ggcur(gp, x, y, key)
+end
+
+procedure cl_button
+
+real x,y
+int key
+pointer gp
+common /local/gp
+
+begin
+ call gseti(gp, G_CURSOR, IDS_BUT_RD)
+ call ggcur(gp, x, y, key)
+end
+
+procedure zm(power, x,y)
+
+int power
+int x,y
+
+short data[9]
+pointer gp
+common /local/gp
+
+begin
+ data[1] = IDS_ZOOM
+ data[2] = IDS_WRITE
+ data[3] = 3
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = power
+ data[8] = (x-1) * MCXSCALE
+ data[9] = (y-1) * MCYSCALE
+ call gescape(gp, IDS_CONTROL, data, 9)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/sn.x b/pkg/images/tv/iis/ids/testcode/sn.x
new file mode 100644
index 00000000..ebce47c0
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/sn.x
@@ -0,0 +1,192 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include "ids.h"
+include <gki.h>
+include <gset.h>
+include <imhdr.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# snap
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+char cjunk[SZ_FNAME]
+
+pointer gopen()
+int dd[LEN_GKIDD]
+
+int key, fnum, zfac
+int ps, pe
+real x, y
+real xjunk, yjunk
+int clgeti
+bool image, clgetb
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ # read first to clear box
+ call gseti(gp, G_CURSOR, IDS_BUT_RD)
+ call ggcur(gp, xjunk, yjunk, key)
+
+ repeat {
+ if (clgetb ("done?"))
+ break
+
+ zfac = clgeti ("zoom factor")
+
+ call clgstr ("Set zoom center, press <cr>", cjunk, SZ_FNAME)
+ call gseti (gp, G_CURSOR, 1)
+ call ggcur(gp, x, y, key)
+ call zm(gp, zfac, x, y)
+
+ image = clgetb("Do you want a picture?")
+ if (image)
+ call snapi (gp)
+ else {
+ repeat {
+ ps = clgeti ("starting line")
+ if ( ps == -1)
+ break
+ pe = clgeti ("ending line")
+ call snap (gp, ps, pe)
+ }
+ }
+ }
+
+
+ # all done
+ call gclose ( gp )
+ call ids_close
+end
+
+# zoom
+
+procedure zm(gp, pow, x, y)
+
+int pow
+pointer gp
+real x, y
+
+short data[9]
+
+begin
+ data[1] = IDS_ZOOM
+ data[2] = IDS_WRITE
+ data[3] = 3
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = 2**(pow-1)
+ data[8] = x * GKI_MAXNDC
+ data[9] = y * GKI_MAXNDC
+ call gescape ( gp, IDS_CONTROL, data[1], 9)
+end
+
+procedure snap (gp, ps, pe)
+
+pointer gp
+int ps, pe
+
+real y
+short data[7]
+pointer sp
+pointer sndata
+int i,j
+
+begin
+ call smark (sp)
+ data[1] = IDS_SNAP
+ data[2] = IDS_WRITE
+ data[3] = 1
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = IDS_SNAP_RGB
+ call gescape (gp, IDS_CONTROL, data, 7)
+
+ if (pe < ps) {
+ call eprintf("Can't handle ending position < start \n")
+ return
+ }
+
+ call salloc ( sndata, DIM, TY_SHORT)
+ call eprintf ("snapping from %d through %d\n")
+ call pargi (ps)
+ call pargi (pe)
+ call eprintf ("data values 0-5 255 256 511\n")
+ do i = ps, pe {
+ y = real(i)*MCYSCALE / GKI_MAXNDC.
+ call ggcell (gp, Mems[sndata], DIM, 1, 0.0, y, 1.0, y)
+ call eprintf ("r%3d data:")
+ call pargi (i)
+ call eprintf (" %5d %5d %5d %5d %5d %5d %5d %5d %5d\n")
+ do j = 0, 5
+ call pargs (Mems[sndata+j])
+ call pargs (Mems[sndata+255])
+ call pargs (Mems[sndata+256])
+ call pargs (Mems[sndata+511])
+ }
+
+ data[1] = IDS_R_SNAPDONE
+ call gescape (gp, IDS_RESET, data, 1)
+
+ call sfree (sp)
+end
+
+procedure snapi (gp)
+
+pointer gp
+
+real y
+short data[7]
+pointer im, immap(), impl2s()
+char fname[SZ_FNAME]
+int i
+
+begin
+ call clgstr ("file", fname, SZ_FNAME)
+ im = immap(fname, NEW_FILE, 0)
+ IM_PIXTYPE(im) = TY_SHORT
+ IM_LEN(im,1) = DIM
+ IM_LEN(im,2) = DIM
+
+ data[1] = IDS_SNAP
+ data[2] = IDS_WRITE
+ data[3] = 1
+ data[4] = IDS_EOD
+ data[5] = IDS_EOD
+ data[6] = 0
+ data[7] = IDS_SNAP_RGB
+ call gescape (gp, IDS_CONTROL, data, 7)
+
+ do i = 0, 511 {
+ if ( mod(i,52) == 0) {
+ call eprintf ("%d ")
+ call pargi (100*i/DIM)
+ call flush (STDERR)
+ }
+ y = real(i)*MCYSCALE / GKI_MAXNDC.
+ call ggcell (gp, Mems[impl2s(im,i+1)], 512, 1, 0.0, y, 1.0, y)
+ }
+ call eprintf ("\n")
+
+ call imunmap(im)
+ data[1] = IDS_R_SNAPDONE
+ call gescape (gp, IDS_RESET, data, 1)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/t_giis.x b/pkg/images/tv/iis/ids/testcode/t_giis.x
new file mode 100644
index 00000000..601bc17b
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/t_giis.x
@@ -0,0 +1,67 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <gki.h>
+
+# GIIS -- Graphics kernel for image output to the IIS.
+# The whole package is copied as much as possible from the stdgraph package.
+
+procedure t_giis()
+
+int fd, list
+pointer gki, sp, fname, devname
+int dev[LEN_GKIDD], deb[LEN_GKIDD]
+int debug, verbose, gkiunits
+bool clgetb()
+int clpopni(), clgfil(), open(), btoi()
+int gki_fetch_next_instruction()
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+ call salloc (devname, SZ_FNAME, TY_CHAR)
+
+ # Open list of metafiles to be decoded.
+ list = clpopni ("input")
+
+ # Get parameters.
+ call clgstr ("device", Memc[devname], SZ_FNAME)
+ if (clgetb ("generic")) {
+ debug = NO
+ verbose = NO
+ gkiunits = NO
+ } else {
+ debug = btoi (clgetb ("debug"))
+ verbose = btoi (clgetb ("verbose"))
+ gkiunits = btoi (clgetb ("gkiunits"))
+ }
+
+ # Open the graphics kernel.
+ call ids_open (Memc[devname], dev)
+ call gkp_install (deb, STDERR, verbose, gkiunits)
+
+ # Process a list of metacode files, writing the decoded metacode
+ # instructions on the standard output.
+
+ while (clgfil (list, Memc[fname], SZ_FNAME) != EOF) {
+ # Open input file.
+ iferr (fd = open (Memc[fname], READ_ONLY, BINARY_FILE)) {
+ call erract (EA_WARN)
+ next
+ }
+
+ # Process the metacode instruction stream.
+ while (gki_fetch_next_instruction (fd, gki) != EOF) {
+ if (debug == YES)
+ call gki_execute (Mems[gki], deb)
+ call gki_execute (Mems[gki], dev)
+ }
+
+ call close (fd)
+ }
+
+ call gkp_close()
+ call ids_close()
+ call clpcls (list)
+ call sfree (sp)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/zm.x b/pkg/images/tv/iis/ids/testcode/zm.x
new file mode 100644
index 00000000..dff01cbe
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/zm.x
@@ -0,0 +1,64 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+include <gki.h>
+include <gset.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# zoom
+
+procedure t_im()
+
+pointer gp
+char output[SZ_FNAME], output_file[SZ_FNAME], device[SZ_FNAME]
+int fd
+
+pointer gopen()
+bool streq()
+int open()
+
+short i,data[DIM+1]
+short set_image[6]
+int key
+real x[30],y[30]
+int xjunk, yjunk
+
+begin
+ call clgstr("output", output, SZ_FNAME)
+ if (!streq (output, "") ) {
+ call strcpy (output, output_file, SZ_FNAME)
+ fd = open (output_file, NEW_FILE, BINARY_FILE)
+ } else
+ fd = open ("dev$stdimage", NEW_FILE, BINARY_FILE)
+
+ call clgstr("device", device, SZ_FNAME)
+ gp = gopen ( device, NEW_FILE, fd)
+
+ # now zoom after reading button presses
+ # read first to clear box
+ call gseti(gp, G_CURSOR, IMD_BUT_RD)
+ call ggcur(gp, xjunk, yjunk, key)
+
+ for ( i = 1 ; i < 5 ; i = i + 1) {
+ call gseti(gp, G_CURSOR, IMD_BUT_WT)
+ call ggcur(gp, xjunk, yjunk, key)
+
+ data[11] = IMD_ZOOM
+ data[12] = IMD_WRITE
+ data[13] = 3
+ data[14] = IMD_EOD
+ data[15] = IMD_EOD
+ data[16] = 0
+ data[17] = 4
+ data[18] = (((i-1)* 128)-1) * MCXSCALE
+ data[19] = (((i-1)* 128)-1) * MCYSCALE
+ call gescape ( gp, IMD_CONTROL, data[11], 9)
+ }
+
+ # all done
+ call gclose ( gp )
+ call close ( fd )
+end
diff --git a/pkg/images/tv/iis/ids/testcode/zmin.x b/pkg/images/tv/iis/ids/testcode/zmin.x
new file mode 100644
index 00000000..676a72f0
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/zmin.x
@@ -0,0 +1,84 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <fio.h>
+include <fset.h>
+include "ids.h"
+include <gki.h>
+include <gset.h>
+
+define DIM 512
+define MCXSCALE 64
+define MCYSCALE 64
+
+# zoom
+
+procedure t_im()
+
+pointer gp
+char device[SZ_FNAME]
+
+pointer gopen()
+int dd[LEN_GKIDD]
+
+short i,data[DIM+1]
+short set_image[6]
+int key
+real x[30],y[30]
+real xjunk, yjunk
+
+begin
+ call clgstr("device", device, SZ_FNAME)
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, NEW_FILE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ # now zoom after reading button presses
+ # read first to clear box
+ call gseti(gp, G_CURSOR, IDS_BUT_RD)
+ call ggcur(gp, xjunk, yjunk, key)
+
+ for ( i = 1 ; i < 5 ; i = i + 1) {
+ call gseti (gp, G_CURSOR, IDS_BUT_WT)
+ call ggcur(gp, xjunk, yjunk, key)
+ call gseti (gp, G_CURSOR, 1)
+ call rpc(gp, xjunk, yjunk, key)
+
+ data[11] = IDS_ZOOM
+ data[12] = IDS_WRITE
+ data[13] = 3
+ data[14] = IDS_EOD
+ data[15] = IDS_EOD
+ data[16] = 0
+ data[17] = 4
+ data[18] = min(((i-1)* 128) * MCXSCALE, GKI_MAXNDC)
+ data[19] = min(((i-1)* 128) * MCYSCALE, GKI_MAXNDC)
+ call gescape ( gp, IDS_CONTROL, data[11], 9)
+ }
+
+ # all done
+ call gclose ( gp )
+ call ids_close
+end
+
+# rpcursor --- read and print cursor
+
+procedure rpc(gp, sx, sy, key)
+
+pointer gp
+real sx,sy
+int key
+
+begin
+ call ggcur (gp, sx, sy, key)
+ call eprintf("cursor: (%f,%f) (%d,%d) key %d\n")
+ call pargr (sx)
+ call pargr (sy)
+ call pargi ( int(sx*32767)/64)
+ call pargi ( int(sy*32767)/64)
+ call pargi (key)
+end
diff --git a/pkg/images/tv/iis/ids/testcode/zztest.x b/pkg/images/tv/iis/ids/testcode/zztest.x
new file mode 100644
index 00000000..599b7103
--- /dev/null
+++ b/pkg/images/tv/iis/ids/testcode/zztest.x
@@ -0,0 +1,81 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include <gset.h>
+
+define XS 0.216
+define XE 0.719
+define YS 0.214
+define YE 0.929
+
+task test = t_test
+
+# T_TEST -- Test program for graphics plotting. A labelled grid is output.
+
+procedure t_test ()
+
+bool redir
+pointer sp, gp
+char command[SZ_LINE], image[SZ_FNAME], word[SZ_LINE]
+char output[SZ_FNAME], output_file[SZ_FNAME], device[SZ_FNAME]
+int cmd, input_fd, stat, fd
+
+pointer gopen()
+bool streq()
+int fstati(), open(), getline()
+
+begin
+ # If the input has been redirected, input is read from the named
+ # command file. If not, each image name in the input template is
+ # plotted.
+
+ if (fstati (STDIN, F_REDIR) == YES) {
+call eprintf ("Input has been redirected\n")
+ redir = true
+ cmd = open (STDIN, READ_ONLY, TEXT_FILE)
+ }
+
+ # Loop over commands until EOF
+ repeat {
+ if (redir) {
+ if (getline (STDIN, command, SZ_LINE) == EOF)
+ break
+ call sscan (command)
+ call gargwrd (word, SZ_LINE)
+ if (!streq (word, "plot")) {
+ # Pixel window has been stored as WCS 2
+ call gseti (gp, G_WCS, 2)
+ call gscan (command)
+ next
+ } else
+ call gargwrd (image)
+ }
+
+ call clgstr ("output", output, SZ_FNAME)
+ if (!streq (output, "")) {
+ call strcpy (output, output_file, SZ_FNAME)
+ fd = open (output_file, NEW_FILE, BINARY_FILE)
+ } else
+ fd = open ("dev$crt", NEW_FILE, BINARY_FILE)
+
+ call clgstr ("device", device, SZ_FNAME)
+ gp = gopen (device, NEW_FILE, fd)
+
+ call gseti (gp, G_XDRAWGRID, 1)
+ call gseti (gp, G_YDRAWGRID, 1)
+ call gseti (gp, G_NMAJOR, 21)
+ call glabax (gp, "TEST", "NDC_X", "NDC_Y")
+ call gline (gp, XS, YS, XE, YS)
+ call gline (gp, XE, YS, XE, YE)
+ call gline (gp, XE, YE, XS, YE)
+ call gline (gp, XS, YE, XS, YS)
+ call gmark (gp, 0.5, 0.5, GM_CROSS, 3.0, 3.0)
+ call gtext (gp, XS, YS-0.1, "DICOMED crtpict film area")
+ call gclose (gp)
+ call close (fd)
+ }
+
+ call clpcls (input_fd)
+ call sfree (sp)
+end