aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/tv/iis
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /pkg/images/tv/iis
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'pkg/images/tv/iis')
-rw-r--r--pkg/images/tv/iis/README3
-rw-r--r--pkg/images/tv/iis/blink.cl19
-rw-r--r--pkg/images/tv/iis/blink.par5
-rw-r--r--pkg/images/tv/iis/cv.par4
-rw-r--r--pkg/images/tv/iis/cvl.par25
-rw-r--r--pkg/images/tv/iis/doc/Cv.spc.hlp286
-rw-r--r--pkg/images/tv/iis/doc/blink.hlp46
-rw-r--r--pkg/images/tv/iis/doc/cv.doc332
-rw-r--r--pkg/images/tv/iis/doc/cv.hlp341
-rw-r--r--pkg/images/tv/iis/doc/cv.ms332
-rw-r--r--pkg/images/tv/iis/doc/cvl.hlp287
-rw-r--r--pkg/images/tv/iis/doc/erase.hlp26
-rw-r--r--pkg/images/tv/iis/doc/frame.hlp24
-rw-r--r--pkg/images/tv/iis/doc/lumatch.hlp28
-rw-r--r--pkg/images/tv/iis/doc/monochrome.hlp18
-rw-r--r--pkg/images/tv/iis/doc/pseudocolor.hlp41
-rw-r--r--pkg/images/tv/iis/doc/rgb.hlp33
-rw-r--r--pkg/images/tv/iis/doc/window.hlp38
-rw-r--r--pkg/images/tv/iis/doc/zoom.hlp31
-rw-r--r--pkg/images/tv/iis/erase.cl10
-rw-r--r--pkg/images/tv/iis/erase.par2
-rw-r--r--pkg/images/tv/iis/frame.cl5
-rw-r--r--pkg/images/tv/iis/giis.par7
-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
-rw-r--r--pkg/images/tv/iis/iis.cl22
-rw-r--r--pkg/images/tv/iis/iis.hd16
-rw-r--r--pkg/images/tv/iis/iis.men11
-rw-r--r--pkg/images/tv/iis/iis.par1
-rw-r--r--pkg/images/tv/iis/iism70/README5
-rw-r--r--pkg/images/tv/iis/iism70/idsexpand.x30
-rw-r--r--pkg/images/tv/iis/iism70/iis.com12
-rw-r--r--pkg/images/tv/iis/iism70/iis.h120
-rw-r--r--pkg/images/tv/iis/iism70/iisbutton.x44
-rw-r--r--pkg/images/tv/iis/iism70/iiscls.x27
-rw-r--r--pkg/images/tv/iis/iism70/iiscursor.x108
-rw-r--r--pkg/images/tv/iis/iism70/iishdr.x31
-rw-r--r--pkg/images/tv/iis/iism70/iishisto.x53
-rw-r--r--pkg/images/tv/iis/iism70/iisifm.x51
-rw-r--r--pkg/images/tv/iis/iism70/iisio.x35
-rw-r--r--pkg/images/tv/iis/iism70/iislut.x67
-rw-r--r--pkg/images/tv/iis/iism70/iismatch.x76
-rw-r--r--pkg/images/tv/iis/iism70/iisminmax.x87
-rw-r--r--pkg/images/tv/iis/iism70/iisoffset.x67
-rw-r--r--pkg/images/tv/iis/iism70/iisofm.x53
-rw-r--r--pkg/images/tv/iis/iism70/iisopn.x35
-rw-r--r--pkg/images/tv/iis/iism70/iispack.x21
-rw-r--r--pkg/images/tv/iis/iism70/iispio.x65
-rw-r--r--pkg/images/tv/iis/iism70/iisrange.x97
-rw-r--r--pkg/images/tv/iis/iism70/iisrd.x51
-rw-r--r--pkg/images/tv/iis/iism70/iisscroll.x101
-rw-r--r--pkg/images/tv/iis/iism70/iissplit.x68
-rw-r--r--pkg/images/tv/iis/iism70/iistball.x41
-rw-r--r--pkg/images/tv/iis/iism70/iiswr.x51
-rw-r--r--pkg/images/tv/iis/iism70/iiswt.x18
-rw-r--r--pkg/images/tv/iis/iism70/iiszoom.x98
-rw-r--r--pkg/images/tv/iis/iism70/mkpkg58
-rw-r--r--pkg/images/tv/iis/iism70/zardim.x16
-rw-r--r--pkg/images/tv/iis/iism70/zawrim.x14
-rw-r--r--pkg/images/tv/iis/iism70/zawtim.x16
-rw-r--r--pkg/images/tv/iis/iism70/zclear.x33
-rw-r--r--pkg/images/tv/iis/iism70/zclsim.x13
-rw-r--r--pkg/images/tv/iis/iism70/zcontrol.x116
-rw-r--r--pkg/images/tv/iis/iism70/zcursor_read.x96
-rw-r--r--pkg/images/tv/iis/iism70/zcursor_set.x100
-rw-r--r--pkg/images/tv/iis/iism70/zdisplay_g.x91
-rw-r--r--pkg/images/tv/iis/iism70/zdisplay_i.x124
-rw-r--r--pkg/images/tv/iis/iism70/zinit.x45
-rw-r--r--pkg/images/tv/iis/iism70/zopnim.x17
-rw-r--r--pkg/images/tv/iis/iism70/zreset.x164
-rw-r--r--pkg/images/tv/iis/iism70/zrestore.x30
-rw-r--r--pkg/images/tv/iis/iism70/zsave.x30
-rw-r--r--pkg/images/tv/iis/iism70/zseek.x21
-rw-r--r--pkg/images/tv/iis/iism70/zsetup.x34
-rw-r--r--pkg/images/tv/iis/iism70/zsnap.com26
-rw-r--r--pkg/images/tv/iis/iism70/zsnap.x239
-rw-r--r--pkg/images/tv/iis/iism70/zsnapinit.x314
-rw-r--r--pkg/images/tv/iis/iism70/zsttim.x14
-rw-r--r--pkg/images/tv/iis/lib/ids.com25
-rw-r--r--pkg/images/tv/iis/lib/ids.h175
-rw-r--r--pkg/images/tv/iis/lumatch.cl8
-rw-r--r--pkg/images/tv/iis/lumatch.par2
-rw-r--r--pkg/images/tv/iis/mkpkg25
-rw-r--r--pkg/images/tv/iis/monochrome.cl5
-rw-r--r--pkg/images/tv/iis/pseudocolor.cl24
-rw-r--r--pkg/images/tv/iis/pseudocolor.par7
-rw-r--r--pkg/images/tv/iis/rgb.cl11
-rw-r--r--pkg/images/tv/iis/rgb.par4
-rw-r--r--pkg/images/tv/iis/src/blink.x132
-rw-r--r--pkg/images/tv/iis/src/clear.x48
-rw-r--r--pkg/images/tv/iis/src/cv.com16
-rw-r--r--pkg/images/tv/iis/src/cv.h51
-rw-r--r--pkg/images/tv/iis/src/cv.x175
-rw-r--r--pkg/images/tv/iis/src/cvparse.x196
-rw-r--r--pkg/images/tv/iis/src/cvulut.x130
-rw-r--r--pkg/images/tv/iis/src/cvutil.x538
-rw-r--r--pkg/images/tv/iis/src/display.x104
-rw-r--r--pkg/images/tv/iis/src/gwindow.h34
-rw-r--r--pkg/images/tv/iis/src/load1.x324
-rw-r--r--pkg/images/tv/iis/src/load2.x335
-rw-r--r--pkg/images/tv/iis/src/map.x320
-rw-r--r--pkg/images/tv/iis/src/match.x172
-rw-r--r--pkg/images/tv/iis/src/maxmin.x52
-rw-r--r--pkg/images/tv/iis/src/mkpkg39
-rw-r--r--pkg/images/tv/iis/src/offset.x53
-rw-r--r--pkg/images/tv/iis/src/pan.x99
-rw-r--r--pkg/images/tv/iis/src/range.x57
-rw-r--r--pkg/images/tv/iis/src/rdcur.x111
-rw-r--r--pkg/images/tv/iis/src/reset.x37
-rw-r--r--pkg/images/tv/iis/src/sigl2.x677
-rw-r--r--pkg/images/tv/iis/src/snap.x64
-rw-r--r--pkg/images/tv/iis/src/split.x95
-rw-r--r--pkg/images/tv/iis/src/tell.x24
-rw-r--r--pkg/images/tv/iis/src/text.x71
-rw-r--r--pkg/images/tv/iis/src/window.x181
-rw-r--r--pkg/images/tv/iis/src/zoom.x60
-rw-r--r--pkg/images/tv/iis/src/zscale.x457
-rw-r--r--pkg/images/tv/iis/window.cl5
-rw-r--r--pkg/images/tv/iis/x_iis.x7
-rw-r--r--pkg/images/tv/iis/zoom.cl11
-rw-r--r--pkg/images/tv/iis/zoom.par2
173 files changed, 15049 insertions, 0 deletions
diff --git a/pkg/images/tv/iis/README b/pkg/images/tv/iis/README
new file mode 100644
index 00000000..1562fd6f
--- /dev/null
+++ b/pkg/images/tv/iis/README
@@ -0,0 +1,3 @@
+CV -- Control video package. This is a prototype package, used to load images
+into the image display (currently only the IIS), as well as to control the
+display and read the display memory.
diff --git a/pkg/images/tv/iis/blink.cl b/pkg/images/tv/iis/blink.cl
new file mode 100644
index 00000000..5cc437e5
--- /dev/null
+++ b/pkg/images/tv/iis/blink.cl
@@ -0,0 +1,19 @@
+#{ BLINK -- Blink 2, 3, or 4 frames.
+
+# frame1,i,a,,,,Frame1
+# frame2,i,a,,,,Frame2
+# frame3,i,a,,,,Frame3
+# frame4,i,a,,,,Frame4
+# rate,r,h,1.,,,Blink rate (sec per frame)
+
+{
+ if ($nargs == 3) {
+ _dcontrol (alternate = frame1 // " " // frame2 // " " //
+ frame3, blink+, rate=rate)
+ } else if ($nargs == 4) {
+ _dcontrol (alternate = frame1 // " " // frame2 // " " //
+ frame3 // " " // frame4, blink+, rate=rate)
+ } else {
+ _dcontrol (alternate = frame1 // " " // frame2, blink+, rate=rate)
+ }
+}
diff --git a/pkg/images/tv/iis/blink.par b/pkg/images/tv/iis/blink.par
new file mode 100644
index 00000000..bccfa8f2
--- /dev/null
+++ b/pkg/images/tv/iis/blink.par
@@ -0,0 +1,5 @@
+frame1,i,a,,,,Frame1
+frame2,i,a,,,,Frame2
+frame3,i,a,,,,Frame3
+frame4,i,a,,,,Frame4
+rate,r,h,1.,,,Blink rate (sec per frame)
diff --git a/pkg/images/tv/iis/cv.par b/pkg/images/tv/iis/cv.par
new file mode 100644
index 00000000..c33dd032
--- /dev/null
+++ b/pkg/images/tv/iis/cv.par
@@ -0,0 +1,4 @@
+# Package parameters for CV.
+
+snap_file,f,a,,,,output file for snap image
+textsize,r,a,1.0,,,character size
diff --git a/pkg/images/tv/iis/cvl.par b/pkg/images/tv/iis/cvl.par
new file mode 100644
index 00000000..c2eb9fab
--- /dev/null
+++ b/pkg/images/tv/iis/cvl.par
@@ -0,0 +1,25 @@
+# Package parameters for CVL.
+# All are from "display.par"
+
+image,f,a,,,,image to be displayed
+frame,i,a,1,1,4,frame to be written into
+border_erase,b,h,no,,,erase unfilled area of window
+erase,b,h,yes,,,display frame being loaded
+select_frame,b,h,yes,,,display frame being loaded
+#repeat,b,h,no,,,repeat previous display parameters
+fill,b,h,no,,,scale image to fit display window
+zscale,b,h,yes,,,display range of greylevels near median
+contrast,r,h,0.25,,,contrast adjustment for zscale algorithm
+zrange,b,h,yes,,,display full image intensity range
+nsample_lines,i,h,5,,,number of sample lines
+xcenter,r,h,0.5,0,1,display window horizontal center
+ycenter,r,h,0.5,0,1,display window vertical center
+xsize,r,h,1,0,1,display window horizontal size
+ysize,r,h,1,0,1,display window vertical size
+xmag,r,h,1.,,,display window horizontal magnification
+ymag,r,h,1.,,,display window vertical magnification
+z1,r,h,,,,minimum greylevel to be displayed
+z2,r,h,,,,maximum greylevel to be displayed
+ztrans,s,h,linear,,,greylevel transformation (linear|log|none)
+lutfile,f,h,"",,,name of textfile with user's transformation table
+version,s,h,"14May85"
diff --git a/pkg/images/tv/iis/doc/Cv.spc.hlp b/pkg/images/tv/iis/doc/Cv.spc.hlp
new file mode 100644
index 00000000..0b30ae1c
--- /dev/null
+++ b/pkg/images/tv/iis/doc/Cv.spc.hlp
@@ -0,0 +1,286 @@
+.help cv Jan86 tv.cv
+The \fIcv\fR program is used to control the image display from within
+\fIIRAF\fR. It differs from most \fIIRAF\fR programs since it has its
+own prompt and its own internal "language". Each of the available commands
+is described in the following paragraphs, but first a few comments on the
+command structure seem in order. Commands are distinguished by their
+first letter, except for a few instances where the second letter is needed.
+The rest of the command name can be typed if you wish. Commands often
+require specification of frames numbers, colors, quadrants, or numeric
+values. In most cases, the order is unimportant, but, zoom, for instance,
+does require the zoom power right after the command name. The order given
+in the \fIhelp\fR command will always work.
+
+A frame list is indicated in the \fIhelp\fR listing with an \fBF\fR. This
+is to be replaced in the typed command by an \fBf\fR followed (no spaces)
+with a list of the pertinent image planes. Thus, \fBf1\fR means
+\fIframe 1\fR while \fBf42\fR means \fIframes 4\fR
+and \fI2\fR. In most cases, the leading \fBf\fR can be omitted.
+The specification \fBfa\fR means \fIall frames\fR. In those
+cases in the \fIhelp\fR menu where the frame specification is optional,
+omitting the frame list is the same as typing \fBfa\fR; that is, operate
+on \fIall\fR frames.
+
+A color specification is a \fBc\fR followed by a set of letters.
+The letter \fBa\fR means \fIall\fR, just as in the frame specification.
+The letters \fBr, b,\fR and \fBg\fR are the other possibilities for all
+commands other than \fIdg\fR and \fIsnap\fR. For displaying graphics
+planes (\fBdg\fR), the other possibilities are \fBy, p, m, w\fR which
+stand for \fIyellow, purple, mauve,\fR and \fIwhite\fR. (\fIMauve\fR is
+the wrong name and will get changed.) The \fIsnap\fR command accepts, in
+addition to the standard three colors, \fBm, bw,\fR and \fBrgb\fR, which
+stand for \fImonochrome, black and white,\fR and \fIfull color\fR. (See
+the discussion under \fIsnap\fR for further explanation.)
+An omitted color specification is the same as \fIall colors\fR.
+
+Quadrants are given by a \fBq\fR followed by numbers from the set one through
+four, or the letter \fBa\fR as in the frame and color cases. Quadrants are
+numbered in the standard way, with the upper right being \fI1\fR, the upper
+left \fI2\fR, etc. Adjacent quadrants may be referenced by \fBt, b, l,\fR
+and \fBr\fR, standing for \fItop, bottom, left,\fR and \fIright\fR. An
+omitted quadrant specification is the same as \fIall quadrants\fR. Quadrants
+are effective only if the split screen command has set the split point to
+something other than the "origin".
+
+.ls \fBblink\fR N F (C Q) (F C Q)
+The blink rate is given by \fBN\fR, which is in tenths of a second. Although
+current timing routines in \fIIRAF\fR do not recognize partial seconds,
+for the NOAO 4.2BSD UNIX implementation, a non-portable timing routine is
+used so that tenth seconds are usable.
+Erratic timing is pretty much the rule when the system load is large.
+One frame must be given,
+followed by any color or quadrant specification, and then
+optionally followed by any number of similar triads. A specification of
+\fI10 f12 f3 f3 f4\fR would display frames one and two for one second, then
+frame three for two one second intervals, then frame 4, and then recycle.
+The first blink cycle may appear somewhat odd as the code "settles in",
+but the sequence should become regular after that (except for timing
+problems due to system load). In split screen mode, it is necessary to
+specify all the frames together with quadrants, which leads to a lot of
+typing: The reason is that blink simply cycles through a series of
+\fBdi\fR commands, and hence it requires the same information as that
+command.
+.le
+.ls \fBcursor\fR [on off F]
+This command is used to turn the cursor on or off, and to read coordinates
+and pixel values from a frame. Pixel coordinates for a feature are those
+of the image as loaded into the display, and do not change as the image
+is panned or zoomed. Fractional pixel positions are given for zoomed
+images, with a minimum number of decimal places printed (but the same number
+for both the \fIx\fR and \fIy\fR coordinates).
+For an unpanned, unzoomed image plane, the lower left corner
+of the \fIscreen\fR is (1,1)
+even if the image you loaded is smaller than 512x512, occupies only
+a portion of the display screen, and does not extend to the lower left
+corner of the screen. This defect will likely be remedied
+when the \fIcv\fR package is properly integrated into \fIIRAF\fR.
+Pixel information can be read from a frame that is not being displayed.
+.le
+.ls \fBdi\fR F (C Q) [on off]
+The \fId\fRisplay \fIi\fRmage command turns specified frames on (or off).
+Turning a frame off does not erase it. A frame need not have all colors
+turned on, nor appear in all quadrants of a split screen display.
+.le
+.ls \fBdg\fR C (F Q) [on off]
+The \fId\fRisplay \fIg\fRraphics command turns specific graphics planes
+on or off. For the IIS display, neither the frame nor the quadrant
+parameters are relevant. A side-effect of this command is that it
+resets the graphics hardware to the \fIcv\fR standard: red cursor and
+seven graphics planes, each colored differently. If the display is in
+a "weird" state that is not cured with the \fIreset r/t\fR commands,
+and a \fIreset i\fR would destroy images of interest, try a \fIdg ca on\fR
+command followed by \fIdg ca off\fR.
+.le
+.ls \fBerase\fR [F all graphics]
+This command erases the specified frame, or all the graphics planes, or
+all data planes. The command \fBclear\fR is a synonym.
+.le
+.ls \fBmatch\fR (o) (F) (C) (to) (F) (C)
+This command allows the user to copy a look-up table to a specified set
+of tables, and hence, to match the mapping function of frames (and/or
+colors) to a reference table. If the \fBo\fR parameter is omitted, the
+match is among the look-up tables associated with particular frames;
+otherwise, the \fIouput\fR tables are used (hence, the \fBo\fR). In the
+latter case, only colors are important; the frame information should
+be omitted. For the individual frame tables, colors can be omitted, in
+which case a match of frame one to two means to copy the three tables
+of frame two (red, green, and blue) to those of frame one. Only one
+reference frame or color should be given, but \fImatch f23 cgb f1 cr\fR
+is legal and means to match the green and blue color tables of both
+frames two and three to the red table of frame one.
+.le
+.ls \fBoffset\fR C N
+The value N, which can range from -4095 to +4095 is added to the data
+pipeline for color \fBC\fR, thus offsetting the data. This is useful
+if one needs to change the data range that is mapped into the useful part
+of the output tables.
+.le
+.ls \fBpan\fR (F)
+When invoked, this command connects the trackball to the specified frames
+and allows the user to move (pan/roam/scroll) the image about the screen.
+This function is automatically invoked whenever the zoom factor is changed.
+.le
+.ls \fBpseudo\fR (o) (F C) (rn sn)
+Look-up tables are changed with the \fIwindow\fR and the \fIpseudocolor\fR
+commands. Windowing provides linear functions and is discussed under that
+command; \fIpseudo\fR provides pseudo-coloring capabilities. Pseudo-color
+maps are usually best done in the output tables, rather than in the
+look-up tables associated with particular frames; hence, \fBps o\fR is
+the more likely invocation of the start of the command line. A color
+(or colors) can be specified for "output" pseudocolor, in which case, only
+those colors will be affected. For frame look-up tables,
+the frame must be specified.
+
+Two mappings are provided. One uses a set of randomly selected colors
+mapped to a specified number of pixel value ranges. The other uses
+triangle color mappings. The former is invoked with the \fI(rn sn)\fR
+options. In this case, the number following \fBr\fR gives the number of
+ranges/levels into which the input data range is to be divided; to
+each such range, a randomly selected color is assigned. The number
+following \fBs\fR is a seed for the random number generator; changing
+this while using the same number of levels gives different color mappings.
+The default seed is the number of levels. If only the seed is given (\fBr\fR
+omitted), the default number of levels is 8. This mapping is used when
+a contour type display is desired: each color represents an intensity range
+whose width is inversely proportional to the number of levels.
+
+The triangle mapping uses a different triangle in each of the three look-up
+tables (either the sets associated with the specified frames, or the output
+tables). The initial tables map low intensity to blue, middle values to
+green, and high values to red, as shown in the diagram. (The red and blue
+triangles are truncated as their centers are on a table boundary.)
+
+Once invoked, the program then allows the user to adjust the triangle
+mapping. In
+response to the prompt line, select the color to be changed and move the
+trackball: the center of the triangle is given by the \fIx\fR cursor
+coordinate and the width by the \fIy\fR coordinate. Narrow functions
+(small \fIy\fR) allow one to map colors to a limited range of intensity.
+When the mapping is satisfactory, a press of any button "fixes" the
+mapping and the user may then either select another color or exit.
+Before selecting a color, place the cursor at approximately the default
+position for the mapping (or where it was for the last mapping of that
+color under the current command); otherwise, the color map will change
+suddenly when the color is selected via the trackball buttons.
+.le
+.ls \fBrange\fR N (C) (N C ...)
+This command changes the range function in the specified color pipeline
+so that the data is scaled by (divided by) the value \fBN\fR. For the
+IIS, useful range values are 1,2,4 and 8; anything else will be changed
+to the next lowest legal value.
+.le
+.ls \fBreset\fR [r i t a]
+Various registers and tables are reset with this command. If the \fBr\fR
+option is used, the registers are reset. This means that zoom is set to
+one, all images are centered, split screen is removed, the range values are
+set to one and the offset values are set to zero. Also, the cursor is
+turned on and its shape is set. Option \fBi\fR causes all the image and
+graphics planes to be erased and turned off. Option \fBt\fR resets all
+the look-up tables to their default linear, positive slope, form, and
+removes any color mappings by making all the output tables the same, and
+all the frame specific tables the same. Option \fBa\fR does \fIall\fR
+the above.
+.le
+.ls \fBsnap\fR (C)
+This command creates an \fIIRAF\fR image file whose contents are a
+512x512 digital snapshot of the image display screen. If no color
+is specified,
+or if \fIcm\fR (color monochromatic) is given,
+the snapshot is of the \fIblue\fR image, which, if you
+have a black and white image, is the same as the red or the green
+image. Specifying \fBcg\fR for instance will take a snapshot of the
+image that you would get had you specified \fIcg\fR for each frame
+turned on by the \fIdi\fR command. Color is of interest only when
+the window or pseudo color commands have made the three colors distinguishable.
+If the "snapped" image is intended to be fed to the Dicomed film
+recorder, a black and white image is all that is usually provided and so
+a color snap is probably not appropriate.
+In the case of the "no color/monochromatic" snap, the graphics planes are
+all added together, while, if a real color is given, only the graphics
+planes that have some of that color are included in the image.
+The color \fBrgb\fR can be
+given, in which case the red, green, and blue images are weighted equally
+to produce a single image file. This image does not represent well what
+you see, partly because of the equal weight given all colors: some
+mapping of eye sensitivity is probably what is required, but it is not
+implemented.
+
+The program operates by first determining zoom, pan, offset, tables, etc,
+and, for each quadrant of the split screen, which images planes are active.
+Then, for each line of the display, those images are read out from the display's
+memory and the transformations done in hardware are duplicated pixel by pixel
+in software. The word "active" needs a bit of explanation. Any image plane
+whose pixels are contributing to the image is active. No image is active if
+it has been turned off (by the \fIdi\fR) command (or if all images were
+turned off and the one of interest not subsequently turned back on). If the
+image is all zeroes, or if it is not but split screen is active and the
+part of the image being displayed is all zeroes, it is not contributing to
+the output. However, the snap program cannot tell that an active image is
+not contributing anything useful,
+and so it dutifully reads out each pixel and adds zeroes to the output.
+The moral of this is that frames of no interest should be (turned) off before
+snap is called (unless you don't have anything better to do than wait for
+computer prompts). When split screen is active, frames are read only for
+the quadrants in which they are active.
+
+The fastest snaps are for single images that are zoomed but not panned
+and which are displayed (and snapped) in black and white, or snapped
+in a single color.
+.le
+.ls \fBsplit\fR [c o px,y nx,y]
+This command sets the split screen point. Option \fBc\fR is shorthand for
+\fIcenter\fR, which is the normal selection. Option \fBo\fR stands for
+\fIorigin\fR, and is the split position that corresponds to no split screen.
+If you wish to specify the split point in pixels, use the \fBpx,y\fR form, in
+which the coordinates are given as integers. If you prefer to specify
+the point in NDC (which range from 0 though 1.0), use the \fBnx,y\fR form
+in which the coordinates are decimal fractions.
+
+A peculiarity of the IIS hardware is that if no split screen is desired,
+the split point must be moved to the upper left corner of the display, rather
+than to the lower left (the \fIIRAF\fR 1,1 position). This means that no
+split screen (the \fBo\fR option, or what you get after \fBre r\fR) is really
+split screen with only quadrant \fBfour\fR displayed: if you use the \fIdi\fR
+command with quadrant specification, only quadrant 4 data will be seen.
+.le
+.ls \fBtell\fR
+This command displays what little it knows about the display status. At
+present, all it can say is whether any image plane is being displayed, and
+if any are, what is the number of one of them. This rather weak performance
+is the result of various design decisions both within \fIcv\fR and the
+\fIIRAF\fR display code, and may be improved.
+.le
+.ls \fBwindow\fR (o) (F C)
+This command operates just as the \fIpseudo\fR command, except that it
+applies a linear mapping to the output look-up tables (if option \fBo\fR
+is used) or to the frame specific tables. The mapping is controlled by
+the trackball, with the \fIy\fR cursor coordinate supplying the slope
+of the map, and \fIx\fR the offset. If different mappings are given to
+each color, a form of pseudo-color is generated.
+.le
+.ls \fBwrite\fR [F C] text
+This command writes the given text into either an image plane (or planes)
+or into the specified color graphics bit plane(s). The user is prompted
+to place the cursor at the (lower left) corner of the text, which is
+then written to the right in roman font. The user is also asked for
+a text size (default 1.0). If the text is written into a graphics
+plane, and a \fBsnap\fR is requested with no color specification, then
+text in any graphics plane will be included in the image. A color snap,
+on the other hand, will include graphics text to the extent that the
+text is displayed in that color.
+Text written into an image plane
+will have the same appearance as any "full on" pixel; that is, text
+in an image plane is written at maximum intensity,
+overwrites the image data,
+and is affected by look-up tables, offsets,
+and so forth, like any other image pixels.
+.le
+.ls \fBzoom\fR N (F)
+This command zooms the display to the power given by \fBN\fR. For the
+IIS, the power must be 1,2,4, or 8; anything else is changed to the next
+lower legal value. The model 70 zooms all planes together. The center
+of the zoom is determined by the cursor position relative to the first
+frame specified (if none, the lowest numbered active one). Once the zoom
+has taken place, the \fIpan\fR routine is called for the specified frames.
+.le
+.endhelp
diff --git a/pkg/images/tv/iis/doc/blink.hlp b/pkg/images/tv/iis/doc/blink.hlp
new file mode 100644
index 00000000..f1440ebf
--- /dev/null
+++ b/pkg/images/tv/iis/doc/blink.hlp
@@ -0,0 +1,46 @@
+.help blink Jan86 images.tv.iis
+.ih
+NAME
+blink -- Blink frames in the image display
+.ih
+USAGE
+blink frame1 frame2 [frame3 [frame4]]
+.ih
+PARAMETERS
+.ls frame1
+First frame in blink sequence.
+.le
+.ls frame2
+Second frame in blink sequence.
+.le
+.ls frame3
+Third frame in blink sequence.
+.le
+.ls frame4
+Fourth frame in blink sequence.
+.le
+.ls rate = 1.
+Blink rate in seconds per frame. May be any fraction of a second.
+.le
+.ih
+DESCRIPTION
+Two or more frames are alternately displayed on the image display monitor
+("stdimage") at a specified rate per frame.
+.ih
+EXAMPLES
+To blink two frames:
+
+ cl> blink 1 2
+
+To blink three frames at a rate of 2 seconds per frame:
+
+ cl> blink 3 1 2 rate=2
+.ih
+BUGS
+The blink rate is measured in
+software and, therefore, will not be exactly even in a time sharing
+environment.
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/cv.doc b/pkg/images/tv/iis/doc/cv.doc
new file mode 100644
index 00000000..d34ccaa0
--- /dev/null
+++ b/pkg/images/tv/iis/doc/cv.doc
@@ -0,0 +1,332 @@
+.TL
+The "cv" Display Package
+.AU
+Richard Wolff
+.DA
+.PP
+The \fIcv\fR program is used to control the image display from within
+\fIIRAF\fR. It differs from most \fIIRAF\fR programs since it has its
+own prompt and its own internal "language". Each of the available commands
+is described in the following paragraphs, but first a few comments on the
+command structure seem in order. Commands are distinguished by their
+first letter, except for a few instances where the second letter is needed.
+The rest of the command name can be typed if you wish. Commands often
+require specification of frames numbers, colors, quadrants, or numeric
+values. In most cases, the order is unimportant, but, zoom, for instance,
+does require the zoom power right after the command name. The order given
+in the \fIhelp\fR command will always work.
+.PP
+A frame list is indicated in the \fIhelp\fR listing with an \fBF\fR. This
+is to be replaced in the typed command by an \fBf\fR followed (no spaces)
+with a list of the pertinent image planes. Thus, \fBf1\fR means
+.I "frame 1"
+while \fBf42\fR means
+.I "frames 4"
+and \fI2\fR. In most cases, the leading \fBf\fR can be omitted.
+The specification \fBfa\fR means \fIall frames\fR. In those
+cases in the \fIhelp\fR menu where the frame specification is optional,
+omitting the frame list is the same as typing \fBfa\fR; that is, operate
+on \fIall\fR frames.
+.PP
+A color specification is a \fBc\fR followed by a set of letters.
+The letter \fBa\fR means \fIall\fR, just as in the frame specification.
+The letters \fBr, b,\fR and \fBg\fR are the other possibilities for all
+commands other than \fIdg\fR and \fIsnap\fR. For displaying graphics
+planes (\fBdg\fR), the other possibilities are \fBy, p, m, w\fR which
+stand for \fIyellow, purple, mauve,\fR and \fIwhite\fR. (\fIMauve\fR is
+the wrong name and will get changed.) The \fIsnap\fR command accepts, in
+addition to the standard three colors, \fBm, bw,\fR and \fBrgb\fR, which
+stand for \fImonochrome, black and white,\fR and \fIfull color\fR. (See
+the discussion under \fIsnap\fR for further explanation.)
+An omitted color specification is the same as \fIall colors\fR.
+.PP
+Quadrants are given by a \fBq\fR followed by numbers from the set one through
+four, or the letter \fBa\fR as in the frame and color cases. Quadrants are
+numbered in the standard way, with the upper right being \fI1\fR, the upper
+left \fI2\fR, etc. Adjacent quadrants may be referenced by \fBt, b, l,\fR
+and \fBr\fR, standing for \fItop, bottom, left,\fR and \fIright\fR. An
+omitted quadrant specification is the same as \fIall quadrants\fR. Quadrants
+are effective only if the split screen command has set the split point to
+something other than the "origin".
+.sp
+.SH
+\fBblink\fR N F (C Q) (F C Q)
+.IP
+The blink rate is given by \fBN\fR, which is in tenths of a second. Although
+current timing routines in \fIIRAF\fR do not recognize partial seconds,
+for the NOAO 4.2BSD UNIX implementation, a non-portable timing routine is
+used so that tenth seconds are usable.
+Erratic timing is pretty much the rule when the system load is large.
+One frame must be given,
+followed by any color or quadrant specification, and then
+optionally followed by any number of similar triads. A specification of
+\fI10 f12 f3 f3 f4\fR would display frames one and two for one second, then
+frame three for two one second intervals, then frame 4, and then recycle.
+The first blink cycle may appear somewhat odd as the code "settles in",
+but the sequence should become regular after that (except for timing
+problems due to system load). In split screen mode, it is necessary to
+specify all the frames together with quadrants, which leads to a lot of
+typing: The reason is that blink simply cycles through a series of
+\fBdi\fR commands, and hence it requires the same information as that
+command.
+.SH
+\fBcursor\fR [on off F]
+.IP
+This command is used to turn the cursor on or off, and to read coordinates
+and pixel values from a frame. Pixel coordinates for a feature are those
+of the image as loaded into the display, and do not change as the image
+is panned or zoomed. Fractional pixel positions are given for zoomed
+images, with a minimum number of decimal places printed (but the same number
+for both the \fIx\fR and \fIy\fR coordinates).
+For an unpanned, unzoomed image plane, the lower left corner
+of the \fIscreen\fR is (1,1)
+even if the image you loaded is smaller than 512x512, occupies only
+a portion of the display screen, and does not extend to the lower left
+corner of the screen. This defect will likely be remedied
+when the \fIcv\fR package is properly integrated into \fIIRAF\fR.
+Pixel information can be read from a frame that is not being displayed.
+.SH
+\fBdi\fR F (C Q) [on off]
+.IP
+The \fId\fRisplay \fIi\fRmage command turns specified frames on (or off).
+Turning a frame off does not erase it. A frame need not have all colors
+turned on, nor appear in all quadrants of a split screen display.
+.SH
+\fBdg\fR C (F Q) [on off]
+.IP
+The \fId\fRisplay \fIg\fRraphics command turns specific graphics planes
+on or off. For the IIS display, neither the frame nor the quadrant
+parameters are relevant. A side-effect of this command is that it
+resets the graphics hardware to the \fIcv\fR standard: red cursor and
+seven graphics planes, each colored differently. If the display is in
+a "weird" state that is not cured with the \fIreset r/t\fR commands,
+and a \fIreset i\fR would destroy images of interest, try a \fIdg ca on\fR
+command followed by \fIdg ca off\fR.
+.SH
+\fBerase\fR [F all graphics]
+.IP
+This command erases the specified frame, or all the graphics planes, or
+all data planes. The command \fBclear\fR is a synonym.
+.SH
+\fBmatch\fR (o) (F) (C) (to) (F) (C)
+.IP
+This command allows the user to copy a look-up table to a specified set
+of tables, and hence, to match the mapping function of frames (and/or
+colors) to a reference table. If the \fBo\fR parameter is omitted, the
+match is among the look-up tables associated with particular frames;
+otherwise, the \fIouput\fR tables are used (hence, the \fBo\fR). In the
+latter case, only colors are important; the frame information should
+be omitted. For the individual frame tables, colors can be omitted, in
+which case a match of frame one to two means to copy the three tables
+of frame two (red, green, and blue) to those of frame one. Only one
+reference frame or color should be given, but \fImatch f23 cgb f1 cr\fR
+is legal and means to match the green and blue color tables of both
+frames two and three to the red table of frame one.
+.SH
+\fBoffset\fR C N
+.IP
+The value N, which can range from -4095 to +4095 is added to the data
+pipeline for color \fBC\fR, thus offsetting the data. This is useful
+if one needs to change the data range that is mapped into the useful part
+of the output tables.
+.SH
+\fBpan\fR (F)
+.IP
+When invoked, this command connects the trackball to the specified frames
+and allows the user to move (pan/roam/scroll) the image about the screen.
+This function is automatically invoked whenever the zoom factor is changed.
+.SH
+\fBpseudo\fR (o) (F C) (rn sn)
+.IP
+Look-up tables are changed with the \fIwindow\fR and the \fIpseudocolor\fR
+commands. Windowing provides linear functions and is discussed under that
+command; \fIpseudo\fR provides pseudo-coloring capabilities. Pseudo-color
+maps are usually best done in the output tables, rather than in the
+look-up tables associated with particular frames; hence, \fBps o\fR is
+the more likely invocation of the start of the command line. A color
+(or colors) can be specified for "output" pseudocolor, in which case, only
+those colors will be affected. For frame look-up tables,
+the frame must be specified.
+.IP
+Two mappings are provided. One uses a set of randomly selected colors
+mapped to a specified number of pixel value ranges. The other uses
+triangle color mappings. The former is invoked with the \fI(rn sn)\fR
+options. In this case, the number following \fBr\fR gives the number of
+ranges/levels into which the input data range is to be divided; to
+each such range, a randomly selected color is assigned. The number
+following \fBs\fR is a seed for the random number generator; changing
+this while using the same number of levels gives different color mappings.
+The default seed is the number of levels. If only the seed is given (\fBr\fR
+omitted), the default number of levels is 8. This mapping is used when
+a contour type display is desired: each color represents an intensity range
+whose width is inversely proportional to the number of levels.
+.IP
+The triangle mapping uses a different triangle in each of the three look-up
+tables (either the sets associated with the specified frames, or the output
+tables). The initial tables map low intensity to blue, middle values to
+green, and high values to red, as shown in the diagram. (The red and blue
+triangles are truncated as their centers are on a table boundary.)
+.sp
+.KS
+.PS
+B: box
+move
+G: box
+move
+R: box
+move to B.sw left 0.375
+line dotted to B.nw
+line dashed to B.s
+move to G.sw
+line dashed to G.n
+line dashed to G.se
+move to R.s
+line dashed to R.ne
+line dotted to R.se right 0.375
+"blue" at B.s below
+"green" at G.s below
+"red" at R.s below
+.PE
+.sp
+.KE
+.IP
+Once invoked, the program then allows the user to adjust the triangle
+mapping. In
+response to the prompt line, select the color to be changed and move the
+trackball: the center of the triangle is given by the \fIx\fR cursor
+coordinate and the width by the \fIy\fR coordinate. Narrow functions
+(small \fIy\fR) allow one to map colors to a limited range of intensity.
+When the mapping is satisfactory, a press of any button "fixes" the
+mapping and the user may then either select another color or exit.
+Before selecting a color, place the cursor at approximately the default
+position for the mapping (or where it was for the last mapping of that
+color under the current command); otherwise, the color map will change
+suddenly when the color is selected via the trackball buttons.
+.SH
+\fBrange\fR N (C) (N C ...)
+.IP
+This command changes the range function in the specified color pipeline
+so that the data is scaled by (divided by) the value \fBN\fR. For the
+IIS, useful range values are 1,2,4 and 8; anything else will be changed
+to the next lowest legal value.
+.SH
+\fBreset\fR [r i t a]
+.IP
+Various registers and tables are reset with this command. If the \fBr\fR
+option is used, the registers are reset. This means that zoom is set to
+one, all images are centered, split screen is removed, the range values are
+set to one and the offset values are set to zero. Also, the cursor is
+turned on and its shape is set. Option \fBi\fR causes all the image and
+graphics planes to be erased and turned off. Option \fBt\fR resets all
+the look-up tables to their default linear, positive slope, form, and
+removes any color mappings by making all the output tables the same, and
+all the frame specific tables the same. Option \fBa\fR does \fIall\fR
+the above.
+.SH
+\fBsnap\fR (C)
+.IP
+This command creates an \fIIRAF\fR image file whose contents are a
+512x512 digital snapshot of the image display screen. If no color
+is specified,
+or if \fIcm\fR (color monochromatic) is given,
+the snapshot is of the \fIblue\fR image, which, if you
+have a black and white image, is the same as the red or the green
+image. Specifying \fBcg\fR for instance will take a snapshot of the
+image that you would get had you specified \fIcg\fR for each frame
+turned on by the \fIdi\fR command. Color is of interest only when
+the window or pseudo color commands have made the three colors distinguishable.
+If the "snapped" image is intended to be fed to the Dicomed film
+recorder, a black and white image is all that is usually provided and so
+a color snap is probably not appropriate.
+In the case of the "no color/monochromatic" snap, the graphics planes are
+all added together, while, if a real color is given, only the graphics
+planes that have some of that color are included in the image.
+The color \fBrgb\fR can be
+given, in which case the red, green, and blue images are weighted equally
+to produce a single image file. This image does not represent well what
+you see, partly because of the equal weight given all colors: some
+mapping of eye sensitivity is probably what is required, but it is not
+implemented.
+.IP
+The program operates by first determining zoom, pan, offset, tables, etc,
+and, for each quadrant of the split screen, which images planes are active.
+Then, for each line of the display, those images are read out from the display's
+memory and the transformations done in hardware are duplicated pixel by pixel
+in software. The word "active" needs a bit of explanation. Any image plane
+whose pixels are contributing to the image is active. No image is active if
+it has been turned off (by the \fIdi\fR) command (or if all images were
+turned off and the one of interest not subsequently turned back on). If the
+image is all zeroes, or if it is not but split screen is active and the
+part of the image being displayed is all zeroes, it is not contributing to
+the output. However, the snap program cannot tell that an active image is
+not contributing anything useful,
+and so it dutifully reads out each pixel and adds zeroes to the output.
+The moral of this is that frames of no interest should be (turned) off before
+snap is called (unless you don't have anything better to do than wait for
+computer prompts). When split screen is active, frames are read only for
+the quadrants in which they are active.
+.IP
+The fastest snaps are for single images that are zoomed but not panned
+and which are displayed (and snapped) in black and white, or snapped
+in a single color.
+.SH
+\fBsplit\fR [c o px,y nx,y]
+.IP
+This command sets the split screen point. Option \fBc\fR is shorthand for
+\fIcenter\fR, which is the normal selection. Option \fBo\fR stands for
+\fIorigin\fR, and is the split position that corresponds to no split screen.
+If you wish to specify the split point in pixels, use the \fBpx,y\fR form, in
+which the coordinates are given as integers. If you prefer to specify
+the point in NDC (which range from 0 though 1.0), use the \fBnx,y\fR form
+in which the coordinates are decimal fractions.
+.IP
+A peculiarity of the IIS hardware is that if no split screen is desired,
+the split point must be moved to the upper left corner of the display, rather
+than to the lower left (the \fIIRAF\fR 1,1 position). This means that no
+split screen (the \fBo\fR option, or what you get after \fBre r\fR) is really
+split screen with only quadrant \fBfour\fR displayed: if you use the \fIdi\fR
+command with quadrant specification, only quadrant 4 data will be seen.
+.SH
+\fBtell\fR
+.IP
+This command displays what little it knows about the display status. At
+present, all it can say is whether any image plane is being displayed, and
+if any are, what is the number of one of them. This rather weak performance
+is the result of various design decisions both within \fIcv\fR and the
+\fIIRAF\fR display code, and may be improved.
+.SH
+\fBwindow\fR (o) (F C)
+.IP
+This command operates just as the \fIpseudo\fR command, except that it
+applies a linear mapping to the output look-up tables (if option \fBo\fR
+is used) or to the frame specific tables. The mapping is controlled by
+the trackball, with the \fIy\fR cursor coordinate supplying the slope
+of the map, and \fIx\fR the offset. If different mappings are given to
+each color, a form of pseudo-color is generated.
+.SH
+\fBwrite\fR [F C] text
+.IP
+This command writes the given text into either an image plane (or planes)
+or into the specified color graphics bit plane(s). The user is prompted
+to place the cursor at the (lower left) corner of the text, which is
+then written to the right in roman font. The user is also asked for
+a text size (default 1.0). If the text is written into a graphics
+plane, and a \fBsnap\fR is requested with no color specification, then
+text in any graphics plane will be included in the image. A color snap,
+on the other hand, will include graphics text to the extent that the
+text is displayed in that color.
+Text written into an image plane
+will have the same appearance as any "full on" pixel; that is, text
+in an image plane is written at maximum intensity,
+overwrites the image data,
+and is affected by look-up tables, offsets,
+and so forth, like any other image pixels.
+.SH
+\fBzoom\fR N (F)
+.IP
+This command zooms the display to the power given by \fBN\fR. For the
+IIS, the power must be 1,2,4, or 8; anything else is changed to the next
+lower legal value. The model 70 zooms all planes together. The center
+of the zoom is determined by the cursor position relative to the first
+frame specified (if none, the lowest numbered active one). Once the zoom
+has taken place, the \fIpan\fR routine is called for the specified frames.
diff --git a/pkg/images/tv/iis/doc/cv.hlp b/pkg/images/tv/iis/doc/cv.hlp
new file mode 100644
index 00000000..6f90d74d
--- /dev/null
+++ b/pkg/images/tv/iis/doc/cv.hlp
@@ -0,0 +1,341 @@
+.help cv Jan86 images.tv.iis
+.ih
+NAME
+cv -- Control image device and take snapshots
+.ih
+USAGE
+cv
+.ih
+PARAMETERS
+.ls snap_file
+Output file for snap image.
+.le
+.ls textsize
+Character size for added text strings.
+.le
+.ih
+COMMANDS
+The following commands are available. This list is also available when
+running the task with the commands h(elp) or ?.
+
+.nf
+--- () : optional; [] : select one; N : number; C/F/Q : see below
+b(link) N F (C Q) (F (C Q)..) blink (N = 10 is one second)
+c(ursor) [on off F] cursor
+di F (C Q) [on off] display image
+dg C (F Q) [on off] display graphics
+e(rase) [N a(ll) g(raphics) F] erase (clear)
+m(atch) (o) F (C) (to) (F) (C) match (output) lookup table
+o(ffset) C N offset color (N: 0 to +- 4095)
+p(an) (F) pan images
+ps(eudo) (o) (F C) (rn sn) pseudo color mapping
+ rn/sn: random n/seed n
+r(ange) N (C) (N C ...) scale image (N: 1-8)
+re(set) [r i t a] reset display
+ registers/image/tables/all
+sn(ap) (C) snap a picture
+s(plit) [c o px,y nx,y] split picture
+t(ell) tell display state
+w(indow) (o) (F C) window (output) frames
+wr(ite) [F C] text write text to frame/graphics
+z(oom) N (F) zoom frames (N: 1-8)
+x or q exit/quit
+--- C: letter c followed by r/g/b/a or, for snap r,g,b,m,bw,rgb,
+--- or for dg r/g/b/y/p/m/w, as 'cr', 'ca', or 'cgb'
+--- F: f followed by a frame number or 'a' for all
+--- Q: q followed by quadrant number or t,b,l,r for top, bottom,...
+.fi
+.ih
+DESCRIPTION
+The \fIcv\fR program is used to control the image display from within
+\fIIRAF\fR. It differs from most \fIIRAF\fR programs since it has its
+own prompt and its own internal "language". Each of the available commands
+is described in the following paragraphs, but first a few comments on the
+command structure seem in order. Commands are distinguished by their
+first letter, except for a few instances where the second letter is needed.
+The rest of the command name can be typed if you wish. Commands often
+require specification of frames numbers, colors, quadrants, or numeric
+values. In most cases, the order is unimportant, but, zoom, for instance,
+does require the zoom power right after the command name. The order given
+in the \fIhelp\fR command will always work.
+
+A frame list is indicated in the \fIhelp\fR listing with an \fBF\fR. This
+is to be replaced in the typed command by an \fBf\fR followed (no spaces)
+with a list of the pertinent image planes. Thus, \fBf1\fR means
+\fIframe 1\fR while \fBf42\fR means \fIframes 4\fR
+and \fI2\fR. In most cases, the leading \fBf\fR can be omitted.
+The specification \fBfa\fR means \fIall frames\fR. In those
+cases in the \fIhelp\fR menu where the frame specification is optional,
+omitting the frame list is the same as typing \fBfa\fR; that is, operate
+on \fIall\fR frames.
+
+A color specification is a \fBc\fR followed by a set of letters.
+The letter \fBa\fR means \fIall\fR, just as in the frame specification.
+The letters \fBr, b,\fR and \fBg\fR are the other possibilities for all
+commands other than \fIdg\fR and \fIsnap\fR. For displaying graphics
+planes (\fBdg\fR), the other possibilities are \fBy, p, m, w\fR which
+stand for \fIyellow, purple, mauve,\fR and \fIwhite\fR. (\fIMauve\fR is
+the wrong name and will get changed.) The \fIsnap\fR command accepts, in
+addition to the standard three colors, \fBm, bw,\fR and \fBrgb\fR, which
+stand for \fImonochrome, black and white,\fR and \fIfull color\fR. (See
+the discussion under \fIsnap\fR for further explanation.)
+An omitted color specification is the same as \fIall colors\fR.
+
+Quadrants are given by a \fBq\fR followed by numbers from the set one through
+four, or the letter \fBa\fR as in the frame and color cases. Quadrants are
+numbered in the standard way, with the upper right being \fI1\fR, the upper
+left \fI2\fR, etc. Adjacent quadrants may be referenced by \fBt, b, l,\fR
+and \fBr\fR, standing for \fItop, bottom, left,\fR and \fIright\fR. An
+omitted quadrant specification is the same as \fIall quadrants\fR. Quadrants
+are effective only if the split screen command has set the split point to
+something other than the "origin".
+
+.ls \fBblink\fR N F (C Q) (F C Q)
+The blink rate is given by \fBN\fR, which is in tenths of a second. Although
+current timing routines in \fIIRAF\fR do not recognize partial seconds,
+for the NOAO 4.2BSD UNIX implementation, a non-portable timing routine is
+used so that tenth seconds are usable.
+Erratic timing is pretty much the rule when the system load is large.
+One frame must be given,
+followed by any color or quadrant specification, and then
+optionally followed by any number of similar triads. A specification of
+\fI10 f12 f3 f3 f4\fR would display frames one and two for one second, then
+frame three for two one second intervals, then frame 4, and then recycle.
+The first blink cycle may appear somewhat odd as the code "settles in",
+but the sequence should become regular after that (except for timing
+problems due to system load). In split screen mode, it is necessary to
+specify all the frames together with quadrants, which leads to a lot of
+typing: The reason is that blink simply cycles through a series of
+\fBdi\fR commands, and hence it requires the same information as that
+command.
+.le
+.ls \fBcursor\fR [on off F]
+This command is used to turn the cursor on or off, and to read coordinates
+and pixel values from a frame. Pixel coordinates for a feature are those
+of the image as loaded into the display, and do not change as the image
+is panned or zoomed. Fractional pixel positions are given for zoomed
+images, with a minimum number of decimal places printed (but the same number
+for both the \fIx\fR and \fIy\fR coordinates).
+For an unpanned, unzoomed image plane, the lower left corner
+of the \fIscreen\fR is (1,1)
+even if the image you loaded is smaller than 512x512, occupies only
+a portion of the display screen, and does not extend to the lower left
+corner of the screen. This defect will likely be remedied
+when the \fIcv\fR package is properly integrated into \fIIRAF\fR.
+Pixel information can be read from a frame that is not being displayed.
+.le
+.ls \fBdi\fR F (C Q) [on off]
+The \fId\fRisplay \fIi\fRmage command selects frames to be displayed on the
+monitor. If neither \fIon\fR or \fIoff\fR is given, the specified frames
+are turned on and all others are turned off. Turning a frame on with
+the \fIon\fR specification displays the frames along with whatever else
+is present; that is the new frame is added to the display. Note that
+turning a frame off does not erase it. A frame need not have all colors
+turned on, nor appear in all quadrants of a split screen display.
+.le
+.ls \fBdg\fR C (F Q) [on off]
+The \fId\fRisplay \fIg\fRraphics command turns specific graphics planes
+on or off. For the IIS display, neither the frame nor the quadrant
+parameters are relevant. A side-effect of this command is that it
+resets the graphics hardware to the \fIcv\fR standard: red cursor and
+seven graphics planes, each colored differently. If the display is in
+a "weird" state that is not cured with the \fIreset r/t\fR commands,
+and a \fIreset i\fR would destroy images of interest, try a \fIdg ca on\fR
+command followed by \fIdg ca off\fR.
+.le
+.ls \fBerase\fR [F all graphics]
+This command erases the specified frame, or all the graphics planes, or
+all data planes. The command \fBclear\fR is a synonym.
+.le
+.ls \fBmatch\fR (o) (F) (C) (to) (F) (C)
+This command allows the user to copy a look-up table to a specified set
+of tables, and hence, to match the mapping function of frames (and/or
+colors) to a reference table. If the \fBo\fR parameter is omitted, the
+match is among the look-up tables associated with particular frames;
+otherwise, the \fIouput\fR tables are used (hence, the \fBo\fR). In the
+latter case, only colors are important; the frame information should
+be omitted. For the individual frame tables, colors can be omitted, in
+which case a match of frame one to two means to copy the three tables
+of frame two (red, green, and blue) to those of frame one. Only one
+reference frame or color should be given, but \fImatch f23 cgb f1 cr\fR
+is legal and means to match the green and blue color tables of both
+frames two and three to the red table of frame one.
+.le
+.ls \fBoffset\fR C N
+The value N, which can range from -4095 to +4095 is added to the data
+pipeline for color \fBC\fR, thus offsetting the data. This is useful
+if one needs to change the data range that is mapped into the useful part
+of the output tables.
+.le
+.ls \fBpan\fR (F)
+When invoked, this command connects the trackball to the specified frames
+and allows the user to move (pan/roam/scroll) the image about the screen.
+This function is automatically invoked whenever the zoom factor is changed.
+.le
+.ls \fBpseudo\fR (o) (F C) (rn sn)
+Look-up tables are changed with the \fIwindow\fR and the \fIpseudocolor\fR
+commands. Windowing provides linear functions and is discussed under that
+command; \fIpseudo\fR provides pseudo-coloring capabilities. Pseudo-color
+maps are usually best done in the output tables, rather than in the
+look-up tables associated with particular frames; hence, \fBps o\fR is
+the more likely invocation of the start of the command line. A color
+(or colors) can be specified for "output" pseudocolor, in which case, only
+those colors will be affected. For frame look-up tables,
+the frame must be specified.
+
+Two mappings are provided. One uses a set of randomly selected colors
+mapped to a specified number of pixel value ranges. The other uses
+triangle color mappings. The former is invoked with the \fI(rn sn)\fR
+options. In this case, the number following \fBr\fR gives the number of
+ranges/levels into which the input data range is to be divided; to
+each such range, a randomly selected color is assigned. The number
+following \fBs\fR is a seed for the random number generator; changing
+this while using the same number of levels gives different color mappings.
+The default seed is the number of levels. If only the seed is given (\fBr\fR
+omitted), the default number of levels is 8. This mapping is used when
+a contour type display is desired: each color represents an intensity range
+whose width is inversely proportional to the number of levels.
+
+The triangle mapping uses a different triangle in each of the three look-up
+tables (either the sets associated with the specified frames, or the output
+tables). The initial tables map low intensity to blue, middle values to
+green, and high values to red, as shown in the diagram. (The red and blue
+triangles are truncated as their centers are on a table boundary.)
+
+Once invoked, the program then allows the user to adjust the triangle
+mapping. In
+response to the prompt line, select the color to be changed and move the
+trackball: the center of the triangle is given by the \fIx\fR cursor
+coordinate and the width by the \fIy\fR coordinate. Narrow functions
+(small \fIy\fR) allow one to map colors to a limited range of intensity.
+When the mapping is satisfactory, a press of any button "fixes" the
+mapping and the user may then either select another color or exit.
+Before selecting a color, place the cursor at approximately the default
+position for the mapping (or where it was for the last mapping of that
+color under the current command); otherwise, the color map will change
+suddenly when the color is selected via the trackball buttons.
+.le
+.ls \fBrange\fR N (C) (N C ...)
+This command changes the range function in the specified color pipeline
+so that the data is scaled by (divided by) the value \fBN\fR. For the
+IIS, useful range values are 1,2,4 and 8; anything else will be changed
+to the next lowest legal value.
+.le
+.ls \fBreset\fR [r i t a]
+Various registers and tables are reset with this command. If the \fBr\fR
+option is used, the registers are reset. This means that zoom is set to
+one, all images are centered, split screen is removed, the range values are
+set to one and the offset values are set to zero. Also, the cursor is
+turned on and its shape is set. Option \fBi\fR causes all the image and
+graphics planes to be erased and turned off. Option \fBt\fR resets all
+the look-up tables to their default linear, positive slope, form, and
+removes any color mappings by making all the output tables the same, and
+all the frame specific tables the same. Option \fBa\fR does \fIall\fR
+the above.
+.le
+.ls \fBsnap\fR (C)
+This command creates an \fIIRAF\fR image file whose contents are a
+512x512 digital snapshot of the image display screen. If no color
+is specified,
+or if \fIcm\fR (color monochromatic) is given,
+the snapshot is of the \fIblue\fR image, which, if you
+have a black and white image, is the same as the red or the green
+image. Specifying \fBcg\fR for instance will take a snapshot of the
+image that you would get had you specified \fIcg\fR for each frame
+turned on by the \fIdi\fR command. Color is of interest only when
+the window or pseudo color commands have made the three colors distinguishable.
+If the "snapped" image is intended to be fed to the Dicomed film
+recorder, a black and white image is all that is usually provided and so
+a color snap is probably not appropriate.
+In the case of the "no color/monochromatic" snap, the graphics planes are
+all added together, while, if a real color is given, only the graphics
+planes that have some of that color are included in the image.
+The color \fBrgb\fR can be
+given, in which case the red, green, and blue images are weighted equally
+to produce a single image file. This image does not represent well what
+you see, partly because of the equal weight given all colors: some
+mapping of eye sensitivity is probably what is required, but it is not
+implemented.
+
+The program operates by first determining zoom, pan, offset, tables, etc,
+and, for each quadrant of the split screen, which images planes are active.
+Then, for each line of the display, those images are read out from the display's
+memory and the transformations done in hardware are duplicated pixel by pixel
+in software. The word "active" needs a bit of explanation. Any image plane
+whose pixels are contributing to the image is active. No image is active if
+it has been turned off (by the \fIdi\fR) command (or if all images were
+turned off and the one of interest not subsequently turned back on). If the
+image is all zeroes, or if it is not but split screen is active and the
+part of the image being displayed is all zeroes, it is not contributing to
+the output. However, the snap program cannot tell that an active image is
+not contributing anything useful,
+and so it dutifully reads out each pixel and adds zeroes to the output.
+The moral of this is that frames of no interest should be (turned) off before
+snap is called (unless you don't have anything better to do than wait for
+computer prompts). When split screen is active, frames are read only for
+the quadrants in which they are active.
+
+The fastest snaps are for single images that are zoomed but not panned
+and which are displayed (and snapped) in black and white, or snapped
+in a single color.
+.le
+.ls \fBsplit\fR [c o px,y nx,y]
+This command sets the split screen point. Option \fBc\fR is shorthand for
+\fIcenter\fR, which is the normal selection. Option \fBo\fR stands for
+\fIorigin\fR, and is the split position that corresponds to no split screen.
+If you wish to specify the split point in pixels, use the \fBpx,y\fR form, in
+which the coordinates are given as integers. If you prefer to specify
+the point in NDC (which range from 0 though 1.0), use the \fBnx,y\fR form
+in which the coordinates are decimal fractions.
+
+A peculiarity of the IIS hardware is that if no split screen is desired,
+the split point must be moved to the upper left corner of the display, rather
+than to the lower left (the \fIIRAF\fR 1,1 position). This means that no
+split screen (the \fBo\fR option, or what you get after \fBre r\fR) is really
+split screen with only quadrant \fBfour\fR displayed: if you use the \fIdi\fR
+command with quadrant specification, only quadrant 4 data will be seen.
+.le
+.ls \fBtell\fR
+This command displays what little it knows about the display status. At
+present, all it can say is whether any image plane is being displayed, and
+if any are, what is the number of one of them. This rather weak performance
+is the result of various design decisions both within \fIcv\fR and the
+\fIIRAF\fR display code, and may be improved.
+.le
+.ls \fBwindow\fR (o) (F C)
+This command operates just as the \fIpseudo\fR command, except that it
+applies a linear mapping to the output look-up tables (if option \fBo\fR
+is used) or to the frame specific tables. The mapping is controlled by
+the trackball, with the \fIy\fR cursor coordinate supplying the slope
+of the map, and \fIx\fR the offset. If different mappings are given to
+each color, a form of pseudo-color is generated.
+.le
+.ls \fBwrite\fR [F C] text
+This command writes the given text into either an image plane (or planes)
+or into the specified color graphics bit plane(s). The user is prompted
+to place the cursor at the (lower left) corner of the text, which is
+then written to the right in roman font. The user is also asked for
+a text size (default 1.0). If the text is written into a graphics
+plane, and a \fBsnap\fR is requested with no color specification, then
+text in any graphics plane will be included in the image. A color snap,
+on the other hand, will include graphics text to the extent that the
+text is displayed in that color.
+Text written into an image plane
+will have the same appearance as any "full on" pixel; that is, text
+in an image plane is written at maximum intensity,
+overwrites the image data,
+and is affected by look-up tables, offsets,
+and so forth, like any other image pixels.
+.le
+.ls \fBzoom\fR N (F)
+This command zooms the display to the power given by \fBN\fR. For the
+IIS, the power must be 1,2,4, or 8; anything else is changed to the next
+lower legal value. The model 70 zooms all planes together. The center
+of the zoom is determined by the cursor position relative to the first
+frame specified (if none, the lowest numbered active one). Once the zoom
+has taken place, the \fIpan\fR routine is called for the specified frames.
+.le
+.ih
+SEE ALSO
+cvl
+.endhelp
diff --git a/pkg/images/tv/iis/doc/cv.ms b/pkg/images/tv/iis/doc/cv.ms
new file mode 100644
index 00000000..d34ccaa0
--- /dev/null
+++ b/pkg/images/tv/iis/doc/cv.ms
@@ -0,0 +1,332 @@
+.TL
+The "cv" Display Package
+.AU
+Richard Wolff
+.DA
+.PP
+The \fIcv\fR program is used to control the image display from within
+\fIIRAF\fR. It differs from most \fIIRAF\fR programs since it has its
+own prompt and its own internal "language". Each of the available commands
+is described in the following paragraphs, but first a few comments on the
+command structure seem in order. Commands are distinguished by their
+first letter, except for a few instances where the second letter is needed.
+The rest of the command name can be typed if you wish. Commands often
+require specification of frames numbers, colors, quadrants, or numeric
+values. In most cases, the order is unimportant, but, zoom, for instance,
+does require the zoom power right after the command name. The order given
+in the \fIhelp\fR command will always work.
+.PP
+A frame list is indicated in the \fIhelp\fR listing with an \fBF\fR. This
+is to be replaced in the typed command by an \fBf\fR followed (no spaces)
+with a list of the pertinent image planes. Thus, \fBf1\fR means
+.I "frame 1"
+while \fBf42\fR means
+.I "frames 4"
+and \fI2\fR. In most cases, the leading \fBf\fR can be omitted.
+The specification \fBfa\fR means \fIall frames\fR. In those
+cases in the \fIhelp\fR menu where the frame specification is optional,
+omitting the frame list is the same as typing \fBfa\fR; that is, operate
+on \fIall\fR frames.
+.PP
+A color specification is a \fBc\fR followed by a set of letters.
+The letter \fBa\fR means \fIall\fR, just as in the frame specification.
+The letters \fBr, b,\fR and \fBg\fR are the other possibilities for all
+commands other than \fIdg\fR and \fIsnap\fR. For displaying graphics
+planes (\fBdg\fR), the other possibilities are \fBy, p, m, w\fR which
+stand for \fIyellow, purple, mauve,\fR and \fIwhite\fR. (\fIMauve\fR is
+the wrong name and will get changed.) The \fIsnap\fR command accepts, in
+addition to the standard three colors, \fBm, bw,\fR and \fBrgb\fR, which
+stand for \fImonochrome, black and white,\fR and \fIfull color\fR. (See
+the discussion under \fIsnap\fR for further explanation.)
+An omitted color specification is the same as \fIall colors\fR.
+.PP
+Quadrants are given by a \fBq\fR followed by numbers from the set one through
+four, or the letter \fBa\fR as in the frame and color cases. Quadrants are
+numbered in the standard way, with the upper right being \fI1\fR, the upper
+left \fI2\fR, etc. Adjacent quadrants may be referenced by \fBt, b, l,\fR
+and \fBr\fR, standing for \fItop, bottom, left,\fR and \fIright\fR. An
+omitted quadrant specification is the same as \fIall quadrants\fR. Quadrants
+are effective only if the split screen command has set the split point to
+something other than the "origin".
+.sp
+.SH
+\fBblink\fR N F (C Q) (F C Q)
+.IP
+The blink rate is given by \fBN\fR, which is in tenths of a second. Although
+current timing routines in \fIIRAF\fR do not recognize partial seconds,
+for the NOAO 4.2BSD UNIX implementation, a non-portable timing routine is
+used so that tenth seconds are usable.
+Erratic timing is pretty much the rule when the system load is large.
+One frame must be given,
+followed by any color or quadrant specification, and then
+optionally followed by any number of similar triads. A specification of
+\fI10 f12 f3 f3 f4\fR would display frames one and two for one second, then
+frame three for two one second intervals, then frame 4, and then recycle.
+The first blink cycle may appear somewhat odd as the code "settles in",
+but the sequence should become regular after that (except for timing
+problems due to system load). In split screen mode, it is necessary to
+specify all the frames together with quadrants, which leads to a lot of
+typing: The reason is that blink simply cycles through a series of
+\fBdi\fR commands, and hence it requires the same information as that
+command.
+.SH
+\fBcursor\fR [on off F]
+.IP
+This command is used to turn the cursor on or off, and to read coordinates
+and pixel values from a frame. Pixel coordinates for a feature are those
+of the image as loaded into the display, and do not change as the image
+is panned or zoomed. Fractional pixel positions are given for zoomed
+images, with a minimum number of decimal places printed (but the same number
+for both the \fIx\fR and \fIy\fR coordinates).
+For an unpanned, unzoomed image plane, the lower left corner
+of the \fIscreen\fR is (1,1)
+even if the image you loaded is smaller than 512x512, occupies only
+a portion of the display screen, and does not extend to the lower left
+corner of the screen. This defect will likely be remedied
+when the \fIcv\fR package is properly integrated into \fIIRAF\fR.
+Pixel information can be read from a frame that is not being displayed.
+.SH
+\fBdi\fR F (C Q) [on off]
+.IP
+The \fId\fRisplay \fIi\fRmage command turns specified frames on (or off).
+Turning a frame off does not erase it. A frame need not have all colors
+turned on, nor appear in all quadrants of a split screen display.
+.SH
+\fBdg\fR C (F Q) [on off]
+.IP
+The \fId\fRisplay \fIg\fRraphics command turns specific graphics planes
+on or off. For the IIS display, neither the frame nor the quadrant
+parameters are relevant. A side-effect of this command is that it
+resets the graphics hardware to the \fIcv\fR standard: red cursor and
+seven graphics planes, each colored differently. If the display is in
+a "weird" state that is not cured with the \fIreset r/t\fR commands,
+and a \fIreset i\fR would destroy images of interest, try a \fIdg ca on\fR
+command followed by \fIdg ca off\fR.
+.SH
+\fBerase\fR [F all graphics]
+.IP
+This command erases the specified frame, or all the graphics planes, or
+all data planes. The command \fBclear\fR is a synonym.
+.SH
+\fBmatch\fR (o) (F) (C) (to) (F) (C)
+.IP
+This command allows the user to copy a look-up table to a specified set
+of tables, and hence, to match the mapping function of frames (and/or
+colors) to a reference table. If the \fBo\fR parameter is omitted, the
+match is among the look-up tables associated with particular frames;
+otherwise, the \fIouput\fR tables are used (hence, the \fBo\fR). In the
+latter case, only colors are important; the frame information should
+be omitted. For the individual frame tables, colors can be omitted, in
+which case a match of frame one to two means to copy the three tables
+of frame two (red, green, and blue) to those of frame one. Only one
+reference frame or color should be given, but \fImatch f23 cgb f1 cr\fR
+is legal and means to match the green and blue color tables of both
+frames two and three to the red table of frame one.
+.SH
+\fBoffset\fR C N
+.IP
+The value N, which can range from -4095 to +4095 is added to the data
+pipeline for color \fBC\fR, thus offsetting the data. This is useful
+if one needs to change the data range that is mapped into the useful part
+of the output tables.
+.SH
+\fBpan\fR (F)
+.IP
+When invoked, this command connects the trackball to the specified frames
+and allows the user to move (pan/roam/scroll) the image about the screen.
+This function is automatically invoked whenever the zoom factor is changed.
+.SH
+\fBpseudo\fR (o) (F C) (rn sn)
+.IP
+Look-up tables are changed with the \fIwindow\fR and the \fIpseudocolor\fR
+commands. Windowing provides linear functions and is discussed under that
+command; \fIpseudo\fR provides pseudo-coloring capabilities. Pseudo-color
+maps are usually best done in the output tables, rather than in the
+look-up tables associated with particular frames; hence, \fBps o\fR is
+the more likely invocation of the start of the command line. A color
+(or colors) can be specified for "output" pseudocolor, in which case, only
+those colors will be affected. For frame look-up tables,
+the frame must be specified.
+.IP
+Two mappings are provided. One uses a set of randomly selected colors
+mapped to a specified number of pixel value ranges. The other uses
+triangle color mappings. The former is invoked with the \fI(rn sn)\fR
+options. In this case, the number following \fBr\fR gives the number of
+ranges/levels into which the input data range is to be divided; to
+each such range, a randomly selected color is assigned. The number
+following \fBs\fR is a seed for the random number generator; changing
+this while using the same number of levels gives different color mappings.
+The default seed is the number of levels. If only the seed is given (\fBr\fR
+omitted), the default number of levels is 8. This mapping is used when
+a contour type display is desired: each color represents an intensity range
+whose width is inversely proportional to the number of levels.
+.IP
+The triangle mapping uses a different triangle in each of the three look-up
+tables (either the sets associated with the specified frames, or the output
+tables). The initial tables map low intensity to blue, middle values to
+green, and high values to red, as shown in the diagram. (The red and blue
+triangles are truncated as their centers are on a table boundary.)
+.sp
+.KS
+.PS
+B: box
+move
+G: box
+move
+R: box
+move to B.sw left 0.375
+line dotted to B.nw
+line dashed to B.s
+move to G.sw
+line dashed to G.n
+line dashed to G.se
+move to R.s
+line dashed to R.ne
+line dotted to R.se right 0.375
+"blue" at B.s below
+"green" at G.s below
+"red" at R.s below
+.PE
+.sp
+.KE
+.IP
+Once invoked, the program then allows the user to adjust the triangle
+mapping. In
+response to the prompt line, select the color to be changed and move the
+trackball: the center of the triangle is given by the \fIx\fR cursor
+coordinate and the width by the \fIy\fR coordinate. Narrow functions
+(small \fIy\fR) allow one to map colors to a limited range of intensity.
+When the mapping is satisfactory, a press of any button "fixes" the
+mapping and the user may then either select another color or exit.
+Before selecting a color, place the cursor at approximately the default
+position for the mapping (or where it was for the last mapping of that
+color under the current command); otherwise, the color map will change
+suddenly when the color is selected via the trackball buttons.
+.SH
+\fBrange\fR N (C) (N C ...)
+.IP
+This command changes the range function in the specified color pipeline
+so that the data is scaled by (divided by) the value \fBN\fR. For the
+IIS, useful range values are 1,2,4 and 8; anything else will be changed
+to the next lowest legal value.
+.SH
+\fBreset\fR [r i t a]
+.IP
+Various registers and tables are reset with this command. If the \fBr\fR
+option is used, the registers are reset. This means that zoom is set to
+one, all images are centered, split screen is removed, the range values are
+set to one and the offset values are set to zero. Also, the cursor is
+turned on and its shape is set. Option \fBi\fR causes all the image and
+graphics planes to be erased and turned off. Option \fBt\fR resets all
+the look-up tables to their default linear, positive slope, form, and
+removes any color mappings by making all the output tables the same, and
+all the frame specific tables the same. Option \fBa\fR does \fIall\fR
+the above.
+.SH
+\fBsnap\fR (C)
+.IP
+This command creates an \fIIRAF\fR image file whose contents are a
+512x512 digital snapshot of the image display screen. If no color
+is specified,
+or if \fIcm\fR (color monochromatic) is given,
+the snapshot is of the \fIblue\fR image, which, if you
+have a black and white image, is the same as the red or the green
+image. Specifying \fBcg\fR for instance will take a snapshot of the
+image that you would get had you specified \fIcg\fR for each frame
+turned on by the \fIdi\fR command. Color is of interest only when
+the window or pseudo color commands have made the three colors distinguishable.
+If the "snapped" image is intended to be fed to the Dicomed film
+recorder, a black and white image is all that is usually provided and so
+a color snap is probably not appropriate.
+In the case of the "no color/monochromatic" snap, the graphics planes are
+all added together, while, if a real color is given, only the graphics
+planes that have some of that color are included in the image.
+The color \fBrgb\fR can be
+given, in which case the red, green, and blue images are weighted equally
+to produce a single image file. This image does not represent well what
+you see, partly because of the equal weight given all colors: some
+mapping of eye sensitivity is probably what is required, but it is not
+implemented.
+.IP
+The program operates by first determining zoom, pan, offset, tables, etc,
+and, for each quadrant of the split screen, which images planes are active.
+Then, for each line of the display, those images are read out from the display's
+memory and the transformations done in hardware are duplicated pixel by pixel
+in software. The word "active" needs a bit of explanation. Any image plane
+whose pixels are contributing to the image is active. No image is active if
+it has been turned off (by the \fIdi\fR) command (or if all images were
+turned off and the one of interest not subsequently turned back on). If the
+image is all zeroes, or if it is not but split screen is active and the
+part of the image being displayed is all zeroes, it is not contributing to
+the output. However, the snap program cannot tell that an active image is
+not contributing anything useful,
+and so it dutifully reads out each pixel and adds zeroes to the output.
+The moral of this is that frames of no interest should be (turned) off before
+snap is called (unless you don't have anything better to do than wait for
+computer prompts). When split screen is active, frames are read only for
+the quadrants in which they are active.
+.IP
+The fastest snaps are for single images that are zoomed but not panned
+and which are displayed (and snapped) in black and white, or snapped
+in a single color.
+.SH
+\fBsplit\fR [c o px,y nx,y]
+.IP
+This command sets the split screen point. Option \fBc\fR is shorthand for
+\fIcenter\fR, which is the normal selection. Option \fBo\fR stands for
+\fIorigin\fR, and is the split position that corresponds to no split screen.
+If you wish to specify the split point in pixels, use the \fBpx,y\fR form, in
+which the coordinates are given as integers. If you prefer to specify
+the point in NDC (which range from 0 though 1.0), use the \fBnx,y\fR form
+in which the coordinates are decimal fractions.
+.IP
+A peculiarity of the IIS hardware is that if no split screen is desired,
+the split point must be moved to the upper left corner of the display, rather
+than to the lower left (the \fIIRAF\fR 1,1 position). This means that no
+split screen (the \fBo\fR option, or what you get after \fBre r\fR) is really
+split screen with only quadrant \fBfour\fR displayed: if you use the \fIdi\fR
+command with quadrant specification, only quadrant 4 data will be seen.
+.SH
+\fBtell\fR
+.IP
+This command displays what little it knows about the display status. At
+present, all it can say is whether any image plane is being displayed, and
+if any are, what is the number of one of them. This rather weak performance
+is the result of various design decisions both within \fIcv\fR and the
+\fIIRAF\fR display code, and may be improved.
+.SH
+\fBwindow\fR (o) (F C)
+.IP
+This command operates just as the \fIpseudo\fR command, except that it
+applies a linear mapping to the output look-up tables (if option \fBo\fR
+is used) or to the frame specific tables. The mapping is controlled by
+the trackball, with the \fIy\fR cursor coordinate supplying the slope
+of the map, and \fIx\fR the offset. If different mappings are given to
+each color, a form of pseudo-color is generated.
+.SH
+\fBwrite\fR [F C] text
+.IP
+This command writes the given text into either an image plane (or planes)
+or into the specified color graphics bit plane(s). The user is prompted
+to place the cursor at the (lower left) corner of the text, which is
+then written to the right in roman font. The user is also asked for
+a text size (default 1.0). If the text is written into a graphics
+plane, and a \fBsnap\fR is requested with no color specification, then
+text in any graphics plane will be included in the image. A color snap,
+on the other hand, will include graphics text to the extent that the
+text is displayed in that color.
+Text written into an image plane
+will have the same appearance as any "full on" pixel; that is, text
+in an image plane is written at maximum intensity,
+overwrites the image data,
+and is affected by look-up tables, offsets,
+and so forth, like any other image pixels.
+.SH
+\fBzoom\fR N (F)
+.IP
+This command zooms the display to the power given by \fBN\fR. For the
+IIS, the power must be 1,2,4, or 8; anything else is changed to the next
+lower legal value. The model 70 zooms all planes together. The center
+of the zoom is determined by the cursor position relative to the first
+frame specified (if none, the lowest numbered active one). Once the zoom
+has taken place, the \fIpan\fR routine is called for the specified frames.
diff --git a/pkg/images/tv/iis/doc/cvl.hlp b/pkg/images/tv/iis/doc/cvl.hlp
new file mode 100644
index 00000000..cda07b07
--- /dev/null
+++ b/pkg/images/tv/iis/doc/cvl.hlp
@@ -0,0 +1,287 @@
+.help cvl Jul87 images.tv.iis
+.ih
+NAME
+cvl -- load images in image display
+.ih
+USAGE
+cvl image frame
+.ih
+PARAMETERS
+.ls image
+Image to be loaded.
+.le
+.ls frame
+Display frame to be loaded.
+.le
+.ls erase = yes
+Erase frame before loading image?
+.le
+.ls border_erase = no
+Erase unfilled area of window in display frame if the whole frame is not
+erased?
+.le
+.ls select_frame = yes
+Display the frame to be loaded?
+.le
+.ls fill = no
+Interpolate or block average the image to fit the display window?
+.le
+.ls zscale = yes
+Apply an automatic intensity mapping algorithm when loading the image?
+.le
+.ls contrast = 0.25
+Contrast factor for the automatic intensity mapping algorithm.
+.le
+.ls zrange = yes
+If not using the automatic mapping algorithm (\fIzscale = no\fR) map the
+full range of the image intensity to the full range of the display?
+.le
+.ls nsample_lines = 5
+Number of sample lines to use in the automatic intensity mapping algorithm.
+.le
+.ls xcenter = 0.5, ycenter = 0.5
+Horizontal and vertical centers of the display window in normalized
+coordinates measured from the left and bottom respectively.
+.le
+.ls xsize = 1, ysize = 1
+Horizontal and vertical sizes of the display window in normalized coordinates.
+.le
+.ls xmag = 1., ymag = 1.
+Horizontal and vertical image magnifications when not filling the display
+window. Magnifications greater than 1 map image pixels into more than 1
+display pixel and magnifications less than 1 map more than 1 image pixel
+into a display pixel.
+.le
+.ls z1, z2
+Minimum and maximum image intensity to be mapped to the minimum and maximum
+display levels. These values apply when not using the automatic or range
+intensity mapping methods.
+.le
+.ls ztrans = "linear"
+Transformation of the image intensity levels to the display levels. The
+choices are:
+.ls "linear"
+Map the minimum and maximum image intensities linearly to the minimum and
+maximum display levels.
+.le
+.ls "log"
+Map the minimum and maximum image intensities linearly to the range 1 to 1000,
+take the logarithm (base 10), and then map the logarithms to the display
+range.
+.le
+.ls "none"
+Apply no mapping of the image intensities (regardless of the values of
+\fIzscale, zrange, z1, and z2\fR). For most image displays, values exceeding
+the maximum display value are truncated by masking the highest bits.
+This corresponds to applying a modulus operation to the intensity values
+and produces "wrap-around" in the display levels.
+.le
+.ls "user"
+User supplies a look up table of intensities and their corresponding
+greyscale values.
+.le
+.le
+.ls lutfile = ""
+Name of text file containing the look up table when \fIztrans\fR = user.
+The table should contain two columns per line; column 1 contains the
+intensity, column 2 the desired greyscale output.
+.le
+.ih
+DESCRIPTION
+The specified image is loaded into the specified frame of the standard
+image display device ("stdimage"). For devices with more than one
+frame it is possible to load an image in a frame different than that
+displayed on the monitor. An option allows the loaded frame to become
+the displayed frame. The previous contents of the frame may be erased
+(which can be done very quickly on most display devices) before the
+image is loaded. Without erasing, the image replaces only those pixels
+in the frame defined by the display window and spatial mapping
+described below. This allows displaying more than one image in a
+frame. An alternate erase option erases only those pixels in the
+defined display window which are not occupied by the image being
+loaded. This is generally slower than erasing the entire frame and
+should be used only if a display window is smaller than the entire
+frame.
+
+The image is mapped both in intensity and in space. The intensity is
+mapped from the image pixel values to the range of display values in
+the device. Spatial interpolation maps the image pixel coordinates
+into a part of the display frame called the display window. Many of
+the parameters of this task are related to these two transformations.
+
+A display window is defined in terms of the full frame. The lower left
+corner of the frame is (0, 0) and the upper right corner is (1, 1) as viewed on
+the monitor. The display window is specified by a center (defaulted to the
+center of the frame (0.5, 0.5)) and a size (defaulted to the full size of
+the frame, 1 by 1). The image is loaded only within the display window and
+does not affect data outside the window; though, of course, an initial
+frame erase erases the entire frame. By using different windows one may
+load several images in various parts of the display frame.
+
+If the option \fIfill\fR is selected the image is spatially interpolated
+to fill the display window in its largest dimension (with an aspect
+ratio of 1:1). When the display window is not automatically filled
+the image is scaled by the magnification factors (which need not be
+the same) and centered in the display window. If the number of image
+pixels exceeds the number of display pixels in the window only the central
+portion of the image which fills the window is loaded. By default
+the display window is the full frame, the image is not interpolated
+(no filling and magnification factors of 1), and is centered in the frame.
+The spatial interpolation algorithm is described in the section
+MAGNIFY AND FILL ALGORITHM.
+
+There are several options for mapping the pixel values to the display
+values. There are two steps; mapping a range of image intensities to
+the full display range and selecting the mapping function or
+transformation. The mapping transformation is set by the parameter
+\fIztrans\fR. The most direct mapping is "none" which loads the image
+pixel values directly without any transformation or range mapping.
+Most displays only use the lowest bits resulting in a wrap-around
+effect for images with a range exceeding the display range. This is
+sometimes desirable because it produces a contoured image which is not
+saturated at the brightest or weakest points. This transformation is
+also the fastest. Another transformation, "linear", maps the selected
+image range linearly to the full display range. The logarithmic
+transformation, "log", maps the image range linearly between 1 and 1000
+and then maps the logarithm (base 10) linearly to the full display
+range. In the latter transformations pixel values greater than
+selected maximum display intensity are set to the maximum display value
+and pixel values less than the minimum intensity are set to the minimum
+display value.
+
+Methods for setting of the range of image pixel values, \fIz1\fR and
+\fIz2\fR, to be mapped to the full display range are arranged in a
+hierarchy from an automatic mapping which gives generally good result
+for typical astronomical images to those requiring the user to specify
+the mapping in detail. The automatic mapping is selected with the
+parameter \fIzscale\fR. The automatic mapping algorithm is described
+in the section ZSCALE ALGORITHM and has two parameters,
+\fInsample_lines\fR and \fIcontrast\fR.
+
+When \fIztrans\fR = user, a look up table of intensity values and their
+corresponding greyscale levels is read from the file specified by the
+\fIlutfile\fR parameter. From this information, a piecewise linear
+look up table containing 4096 discrete values is composed. The text
+format table contains two columns per line; column 1 contains the
+intensity, column 2 the desired greyscale output. The greyscale values
+specified by the user must match those available on the output device.
+Task \fIshowcap\fR can be used to determine the range of acceptable
+greyscale levels. When \fIztrans\fR = user, parameters \fIzscale\fR,
+\fIzrange\fR and \fIzmap\fR are ignored.
+
+If the zscale algorithm is not selected the \fIzrange\fR parameter is
+examined. If \fIzrange\fR is yes then \fIz1\fR and \fIz2\fR are set to
+the minimum and maximum image pixels values, respectively. This insures
+that the full range of the image is displayed but is generally slower
+than the zscale algorithm (because all the image pixels must be examined)
+and, for images with a large dynamic range, will generally show only the
+brightest parts of the image.
+
+Finally, if the zrange algorithm is not selected the user specifies the
+values of \fIz1\fR and \fIz2\fR directly.
+.ih
+ZSCALE ALGORITHM
+The zscale algorithm is designed to display the image values near the median
+image value without the time consuming process of computing a full image
+histogram. This is particularly useful for astronomical images which
+generally have a very peaked histogram corresponding to the background
+sky in direct imaging or the continuum in a two dimensional spectrum.
+
+A subset of the image is examined. Approximately 600 pixels are
+sampled evenly over the image. The number of lines is a user parameter,
+\fInsample_lines\fR. The pixels are ranked in brightness to
+form the function I(i) where i is the rank of the pixel and I is its value.
+Generally the midpoint of this function (the median) is very near the peak
+of the image histogram and there is a well defined slope about the midpoint
+which is related to the width of the histogram. At the ends of the
+I(i) function there are a few very bright and dark pixels due to objects
+and defects in the field. To determine the slope a linear function is fit
+with iterative rejection;
+
+ I(i) = intercept + slope * (i - midpoint)
+
+If more than half of the points are rejected
+then there is no well defined slope and the full range of the sample
+defines \fIz1\fR and \fIz2\fR. Otherwise the endpoints of the linear
+function are used (provided they are within the original range of the
+sample):
+
+.nf
+ z1 = I(midpoint) + (slope / contrast) * (1 - midpoint)
+ z2 = I(midpoint) + (slope / contrast) * (npoints - midpoint)
+.fi
+
+As can be seen, the parameter \fIcontrast\fR may be used to adjust the contrast
+produced by this algorithm.
+.ih
+MAGNIFY AND FILL ALGORITHM
+The spatial interpolation algorithm magnifies (or demagnifies) the
+image along each axis by the desired amount. The fill option is a
+special case of magnification in that the magnification factors are set
+by the requirement that the image just fit the display window in its
+maximum dimension with an aspect ratio (ratio of magnifications) of 1.
+There are two requirements on the interpolation algorithm; all the
+image pixels must contribute to the interpolated image and the
+interpolation must be time efficient. The second requirement means that
+simple linear interpolation is used. If more complex interpolation is
+desired then tasks in the IMAGES package must be used to first
+interpolate the image to the desired size before loading the display
+frame.
+
+If the magnification factors are greater than 0.5 (sampling step size
+less than 2) then the image is simply interpolated. However, if the
+magnification factors are less than 0.5 (sampling step size greater
+than 2) the image is first block averaged by the smallest amount such
+that magnification in the reduced image is again greater than 0.5.
+Then the reduced image is interpolated to achieve the desired
+magnifications. The reason for block averaging rather than simply
+interpolating with a step size greater than 2 is the requirement that
+all of the image pixels contribute to the displayed image. If this is
+not desired then the user can explicitly subsample using image
+sections. The effective difference is that with subsampling the
+pixel-to-pixel noise is unchanged and small features may be lost due to
+the subsampling. With block averaging pixel-to-pixel noise is reduced
+and small scale features still contribute to the displayed image.
+.ih
+EXAMPLES
+For the purpose of these examples we assume a display with four frames,
+512 x 512 in size, and a display range of 0 to 255. Also consider two
+images, image1 is 100 x 200 with a range 200 to 2000 and image2 is
+2000 x 1000 with a range -1000 to 1000. To load the images with the
+default parameters:
+
+.nf
+ cl> cvl image1 1
+ cl> cvl image2 2
+.fi
+
+The image frames are first erased and image1 is loaded in the center of
+display frame 1 without spatial interpolation and with the automatic intensity
+mapping. Only the central 512x512 area of image2 is loaded in display frame 2
+
+To load the display without any intensity transformation:
+
+ cl> cvl image1 1 ztrans=none
+
+The next example interpolates image2 to fill the full 512 horizontal range
+of the frame and maps the full image range into the display range. Note
+that the spatial interpolation first block averages by a factor of 2 and then
+magnifies by 0.512.
+
+ cl> cvl image2 3 fill+ zscale-
+
+The next example makes image1 square and sets the intensity range explicitly.
+
+ cl> cvl image1 4 zscale- zrange- z1=800 z2=1200 xmag=2
+
+The next example loads the two images in the same frame side-by-side.
+
+.nf
+ cl> cvl.xsize=0.5
+ cl> cvl image1 fill+ xcen=0.25
+ cl> cvl image2 erase- fill+ xcen=0.75
+.fi
+.ih
+SEE ALSO
+display, magnify
+.endhelp
diff --git a/pkg/images/tv/iis/doc/erase.hlp b/pkg/images/tv/iis/doc/erase.hlp
new file mode 100644
index 00000000..6a3548e6
--- /dev/null
+++ b/pkg/images/tv/iis/doc/erase.hlp
@@ -0,0 +1,26 @@
+.help erase Jan86 images.tv.iis
+.ih
+NAME
+erase -- erase display frame
+.ih
+USAGE
+erase frame
+.ih
+PARAMETERS
+.ls frame
+Frame to be erased.
+.le
+.ih
+DESCRIPTION
+The specified frame in the image display ("stdimage") is erased.
+Note that the erased frame can be different than the frame currently
+being displayed on the monitor. The graphics frame is not erased.
+.ih
+EXAMPLES
+To erase frame 3:
+
+ cl> erase 3
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/frame.hlp b/pkg/images/tv/iis/doc/frame.hlp
new file mode 100644
index 00000000..ec3a9059
--- /dev/null
+++ b/pkg/images/tv/iis/doc/frame.hlp
@@ -0,0 +1,24 @@
+.help frame Jan86 images.tv.iis
+.ih
+NAME
+frame -- select frame to be displayed on the image display
+.ih
+USAGE
+frame frame
+.ih
+PARAMETERS
+.ls frame
+Frame to be displayed.
+.le
+.ih
+DESCRIPTION
+The specified frame is displayed on the image display monitor ("stdimage").
+.ih
+EXAMPLES
+To display frame 3:
+
+ cl> frame 3
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/lumatch.hlp b/pkg/images/tv/iis/doc/lumatch.hlp
new file mode 100644
index 00000000..95e6f800
--- /dev/null
+++ b/pkg/images/tv/iis/doc/lumatch.hlp
@@ -0,0 +1,28 @@
+.help lumatch Jan86 images.tv.iis
+.ih
+NAME
+lumatch -- match lookup tables for two display frames
+.ih
+USAGE
+lumatch frame ref_frame
+.ih
+PARAMETERS
+.ls frame
+Frame whose lookup table is to be adjusted.
+.le
+.ls ref_frame
+Frame whose lookup table is to be matched.
+.le
+.ih
+DESCRIPTION
+The lookup tables mapping the display frame values to the grey levels
+on the display monitor are matched in one frame to a reference frame.
+.ih
+EXAMPLES
+To match the lookup tables in frame 3 to those in frame 1:
+
+ cl> lumatch 3 1
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/monochrome.hlp b/pkg/images/tv/iis/doc/monochrome.hlp
new file mode 100644
index 00000000..70cc7aee
--- /dev/null
+++ b/pkg/images/tv/iis/doc/monochrome.hlp
@@ -0,0 +1,18 @@
+.help monochrome Jan86 images.tv.iis
+.ih
+NAME
+monochrome -- select monochrome enhancement
+.ih
+USAGE
+monochrome
+.ih
+DESCRIPTION
+Set the display monitor to display monochrome grey levels by setting
+the lookup tables for each color gun to the same values.
+.ih
+EXAMPLES
+ cl> monochrome
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/pseudocolor.hlp b/pkg/images/tv/iis/doc/pseudocolor.hlp
new file mode 100644
index 00000000..1c7bb70a
--- /dev/null
+++ b/pkg/images/tv/iis/doc/pseudocolor.hlp
@@ -0,0 +1,41 @@
+.help pseudocolor Jan86 images.tv.iis
+.ih
+NAME
+pseudocolor -- select pseudocolor enhancement
+.ih
+USAGE
+pseudocolor
+.ih
+PARAMETERS
+.ls enhancement
+Type of pseudocolor enhancement. The types are:
+.ls "random"
+A randomly chosen color is assigned to each display level.
+.le
+.ls "linear"
+The display levels are mapped into a spectrum.
+.le
+.ls "8color"
+Eight colors are chosen at random over the range of the display levels.
+.le
+.le
+.ls window = yes
+Window the lookup table for the frame after enabling the pseudocolor?
+.le
+.ih
+DESCRIPTION
+The display levels from the lookup table are mapped into various saturated
+colors to enhance an image. There is a choice of three color mappings.
+After the pseudocolor enhancement is enabled on the display monitor the
+user may, optionally, adjust the frame lookup table.
+.ih
+EXAMPLES
+.nf
+ cl> pseudocolor random
+ cl> pseudocolor 8color
+ cl> pseudocolor linear
+.fi
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/rgb.hlp b/pkg/images/tv/iis/doc/rgb.hlp
new file mode 100644
index 00000000..1bd9aa13
--- /dev/null
+++ b/pkg/images/tv/iis/doc/rgb.hlp
@@ -0,0 +1,33 @@
+.help rgb Jan86 images.tv.iis
+.ih
+NAME
+rgb - select true color mode (red, green, and blue frames)
+.ih
+USAGE
+rgb red_frame green_frame blue_frame
+.ih
+PARAMETERS
+.ls red_frame
+Frame to use for the red component.
+.le
+.ls green_frame
+Frame to use for the green component.
+.le
+.ls blue_frame
+Frame to use for the blue component.
+.le
+.ls window = no
+Window the rgb lookup tables?
+.le
+.ih
+DESCRIPTION
+Set the display monitor to display rgb colors by using three frames to
+drive the red, green, and blue guns of the color display monitor.
+Optionally, window the rgb lookup tables.
+.ih
+EXAMPLES
+ cl> rgb 1 2 3
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/window.hlp b/pkg/images/tv/iis/doc/window.hlp
new file mode 100644
index 00000000..f98130c3
--- /dev/null
+++ b/pkg/images/tv/iis/doc/window.hlp
@@ -0,0 +1,38 @@
+.help window Jan86 images.tv.iis
+.ih
+NAME
+window -- adjust the contrast and dc offset of the current frame
+.ih
+USAGE
+window
+.ih
+DESCRIPTION
+The lookup table between the display frame values and the values sent
+to the display monitor is adjusted interactively to enhance the display.
+The mapping is linear with two adjustable parameters; the intercept
+and the slope. The two values are set with the image display cursor
+in the two dimensional plane of the display. The horizontal position
+of the cursor sets the intercept or zero point of the transformation.
+Moving the cursor to the left lowers the zero point while moving the cursor to
+the right increases the zero point. The vertical position of the cursor
+sets the slope of the transformation. The middle of the display is zero
+slope (all frame values map into the same output value) while points above
+the middle have negative slope and points below the middle have positive
+slope. Positions near the middle have low contrast while positions near
+the top and bottom have very high contrast. By changing the slope from
+positive to negative the image may be displayed as positive or negative.
+
+The interactive loop is exited by pressing any button on the cursor control.
+.ih
+EXAMPLES
+.nf
+ cl> window
+ Window the display and push any button to exit:
+.fi
+.ih
+BUGS
+It may be necessary to execute FRAME before windowing.
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/doc/zoom.hlp b/pkg/images/tv/iis/doc/zoom.hlp
new file mode 100644
index 00000000..85a0b604
--- /dev/null
+++ b/pkg/images/tv/iis/doc/zoom.hlp
@@ -0,0 +1,31 @@
+.help zoom Jan86 images.tv.iis
+.ih
+NAME
+zoom - zoom in on the image (change magnification)
+.ih
+USAGE
+zoom
+.ls zoom_factor
+Zoom factor by the display is to be expanded. The factors are powers
+of 2; 1 = no zoom, 2 = factor of 2, 3 = factor of 4, and 4 = factor of 8.
+.le
+.ls window = no
+Window the enlarged image?
+.le
+.ih
+DESCRIPTION
+The display is zoomed by the specified factor. A zoom factor of 1 is no
+magnification and higher factors correspond to factors of 2. The zoom
+replicates pixels on the monitor and only a part of the display frame
+centered on the display cursor is visible. The window option allows
+the user to adjust interactively with the cursor the part of the zoomed
+frame.
+.ih
+EXAMPLES
+To magnify the displayed frame by a factor of 2:
+
+ cl> zoom 2
+.ih
+SEE ALSO
+cv
+.endhelp
diff --git a/pkg/images/tv/iis/erase.cl b/pkg/images/tv/iis/erase.cl
new file mode 100644
index 00000000..4da666bc
--- /dev/null
+++ b/pkg/images/tv/iis/erase.cl
@@ -0,0 +1,10 @@
+#{ ERASE -- Erase a greyscale display frame.
+
+# frame,i,a,1,1,4,frame to be erased
+# saveframe,i,h
+
+{
+ saveframe = _dcontrol.frame
+ _dcontrol (frame=frame, erase=yes)
+ _dcontrol (frame = saveframe)
+}
diff --git a/pkg/images/tv/iis/erase.par b/pkg/images/tv/iis/erase.par
new file mode 100644
index 00000000..0f84180f
--- /dev/null
+++ b/pkg/images/tv/iis/erase.par
@@ -0,0 +1,2 @@
+frame,i,a,1,1,4,frame to be erased
+saveframe,i,h
diff --git a/pkg/images/tv/iis/frame.cl b/pkg/images/tv/iis/frame.cl
new file mode 100644
index 00000000..1252f7da
--- /dev/null
+++ b/pkg/images/tv/iis/frame.cl
@@ -0,0 +1,5 @@
+#{ FRAME -- Select the frame to be displayed.
+
+{
+ _dcontrol (type="frame", frame=frame)
+}
diff --git a/pkg/images/tv/iis/giis.par b/pkg/images/tv/iis/giis.par
new file mode 100644
index 00000000..5e000c89
--- /dev/null
+++ b/pkg/images/tv/iis/giis.par
@@ -0,0 +1,7 @@
+input,s,a,,,,input metacode file
+device,s,h,"stdimage",,,output device
+generic,b,h,no,,,ignore remaining kernel dependent parameters
+debug,b,h,no,,,print decoded graphics instructions during processing
+verbose,b,h,no,,,"print elements of polylines, cell arrays, etc. in debug mode"
+gkiunits,b,h,no,,,print coordinates in GKI rather than NDC units
+txquality,s,h,"normal","normal|low|medium|high",,character generator quality
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
diff --git a/pkg/images/tv/iis/iis.cl b/pkg/images/tv/iis/iis.cl
new file mode 100644
index 00000000..becb72c4
--- /dev/null
+++ b/pkg/images/tv/iis/iis.cl
@@ -0,0 +1,22 @@
+plot
+
+#{ IIS -- The IIS Image Display Control package.
+
+package iis
+
+set iis = "images$tv/iis/"
+
+task cv,
+ cvl = "iis$x_iis.e"
+
+task blink = "iis$blink.cl"
+task erase = "iis$erase.cl"
+task $frame = "iis$frame.cl"
+task lumatch = "iis$lumatch.cl"
+task $monochrome = "iis$monochrome.cl"
+task pseudocolor = "iis$pseudocolor.cl"
+task rgb = "iis$rgb.cl"
+task $window = "iis$window.cl"
+task zoom = "iis$zoom.cl"
+
+clbye()
diff --git a/pkg/images/tv/iis/iis.hd b/pkg/images/tv/iis/iis.hd
new file mode 100644
index 00000000..a0be19f2
--- /dev/null
+++ b/pkg/images/tv/iis/iis.hd
@@ -0,0 +1,16 @@
+# Help directory for the IIS package
+
+$doc = "images$tv/iis/doc/"
+$iis = "images$tv/iis/"
+
+blink hlp=doc$blink.hlp, src=iis$blink.cl
+cv hlp=doc$cv.hlp src=iis$src/cv.x
+cvl hlp=doc$cvl.hlp
+erase hlp=doc$erase.hlp, src=iis$erase.cl
+frame hlp=doc$frame.hlp, src=iis$frame.cl
+lumatch hlp=doc$lumatch.hlp, src=iis$lumatch.cl
+monochrome hlp=doc$monochrome.hlp, src=iis$monochrome.cl
+pseudocolor hlp=doc$pseudocolor.hlp, src=iis$pseudocolor.cl
+rgb hlp=doc$rgb.hlp, src=iis$rgb.cl
+window hlp=doc$window.hlp, src=iis$window.cl
+zoom hlp=doc$zoom.hlp, src=iis$zoom.cl
diff --git a/pkg/images/tv/iis/iis.men b/pkg/images/tv/iis/iis.men
new file mode 100644
index 00000000..08123e61
--- /dev/null
+++ b/pkg/images/tv/iis/iis.men
@@ -0,0 +1,11 @@
+ blink - Blink two frames
+ cv - Control image device, display "snapshot"
+ cvl - Load image display (newer version of 'display')
+ erase - Erase an image frame
+ frame - Select the frame to be displayed
+ lumatch - Match the lookup tables of two frames
+ monochrome - Select monochrome enhancement
+ pseudocolor - Select pseudocolor enhancement
+ rgb - Select true color mode (red, green, and blue frames)
+ window - Adjust the contrast and dc offset of the current frame
+ zoom - Zoom in on the image (change magnification)
diff --git a/pkg/images/tv/iis/iis.par b/pkg/images/tv/iis/iis.par
new file mode 100644
index 00000000..db706f09
--- /dev/null
+++ b/pkg/images/tv/iis/iis.par
@@ -0,0 +1 @@
+version,s,h,"Apr91"
diff --git a/pkg/images/tv/iis/iism70/README b/pkg/images/tv/iis/iism70/README
new file mode 100644
index 00000000..05f01307
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/README
@@ -0,0 +1,5 @@
+IISM70 -- Device dependent interface subroutines for the IIS Model 70 image
+display device. This package uses the ZFIOGD device driver, which is
+responsible for physical i/o to the device. The source for the ZFIOGD driver
+is in host$gdev; this driver must be compiled and installed in a system library
+(libsys.a) before i/o to the IIS will work correctly.
diff --git a/pkg/images/tv/iis/iism70/idsexpand.x b/pkg/images/tv/iis/iism70/idsexpand.x
new file mode 100644
index 00000000..da2a172d
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/idsexpand.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# IDS_EXPAND -- expand FRAME/BITPL if first element is IDS_EOD
+# if the frames are not counted in order, as on the Model 75,
+# that should be dealt with here (use the "flag" boolean).
+
+procedure ids_expand(data, max, flag)
+
+short data[ARB] # data
+short max # max number of frames/bitplanes
+bool flag # true if frames ... e.g. for Model 75
+
+int i
+
+begin
+ if ( data[1] != IDS_EOD )
+ return
+ do i = 1, max {
+ data[i] = i
+ }
+ if ( flag) {
+ data[1+max] = GRCHNUM
+ data[2+max] = IDS_EOD
+ } else
+ data[1+max] = IDS_EOD
+end
diff --git a/pkg/images/tv/iis/iism70/iis.com b/pkg/images/tv/iis/iism70/iis.com
new file mode 100644
index 00000000..25a69d38
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iis.com
@@ -0,0 +1,12 @@
+# Common for IIS display
+
+int iischan # The device channel used by FIO
+int iisnopen # Number of times the display has been opened
+int iframe, iplane # frame, bitplanes to read/write
+int i_frame_on # Which frame is on...cursor readback
+short hdr[LEN_IISHDR] # Header
+short zoom[16] # zoom for each plane
+short xscroll[16] # scroll position for each plane
+short yscroll[16]
+common /iiscom/iischan, iisnopen, iframe, iplane, i_frame_on,
+ hdr, zoom, xscroll, yscroll
diff --git a/pkg/images/tv/iis/iism70/iis.h b/pkg/images/tv/iis/iism70/iis.h
new file mode 100644
index 00000000..96bb8b39
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iis.h
@@ -0,0 +1,120 @@
+# This file contains the hardware definitions for the iis model 70/f
+# at Kitt Peak.
+
+# Define header
+define LEN_IISHDR 8 # Length of IIS header
+
+define XFERID $1[1] # transfer id
+define THINGCT $1[2] # thing count
+define SUBUNIT $1[3] # subuint select
+define CHECKSUM $1[4] # check sum
+define XREG $1[5] # x register
+define YREG $1[6] # y register
+define ZREG $1[7] # z register
+define TREG $1[8] # t register
+
+# Transfer ID definitions
+define IREAD 100000B
+define IWRITE 0B
+define PACKED 40000B
+define BYPASSIFM 20000B
+define BYTE 10000B
+define ADDWRITE 4000B
+define ACCUM 2000B
+define BLOCKXFER 1000B
+define VRETRACE 400B
+define MUX32 200B
+
+# Subunits
+define REFRESH 1
+define LUT 2
+define OFM 3
+define IFM 4
+define FEEDBACK 5
+define SCROLL 6
+define VIDEOM 7
+define SUMPROC 8
+define GRAPHICS 9
+define CURSOR 10
+define ALU 11
+define ZOOM 12
+define IPB 15
+
+# Command definitions
+define COMMAND 100000B
+define ADVXONTC 100000B # Advance x on thing count
+define ADVXONYOV 40000B # Advance x on y overflow
+define ADVYONXOV 100000B # Advance y on x overflow
+define ADVYONTC 40000B # Advance y on thing count
+define ERASE 100000B # Erase
+
+# 4 - Button Trackball
+define PUSH 40000B
+define BUTTONA 400B
+define BUTTONB 1000B
+define BUTTONC 2000B
+define BUTTOND 4000B
+
+# Display channels
+define CHAN1 1B
+define CHAN2 2B
+define CHAN3 4B
+define CHAN4 10B
+define ALLCHAN 17B
+define GRCHAN 100000B
+define GRCHNUM 16
+
+define LEN_IISFRAMES 4
+define IISFRAMES CHAN1, CHAN2, CHAN3, CHAN4
+
+# Center coordinates for zoom/scroll
+define IIS_XCEN 256
+define IIS_YCEN 255
+# Inverted Y center is just IIS_YDIM - IIS_YCEN
+define IIS_YCEN_INV 256
+
+# Colors
+
+# these are bit plane mappings
+define BLUE 1B
+define GREEN 2B
+define RED 4B
+define MONO 7B
+# next colors used by snap code ... used as array indexes.
+define BLU 1
+define GR 2
+define RD 3
+
+
+# Bit plane selections
+define BITPL0 1B
+define BITPL1 2B
+define BITPL2 4B
+define BITPL3 10B
+define BITPL4 20B
+define BITPL5 40B
+define BITPL6 100B
+define BITPL7 200B
+define ALLBITPL 377B
+
+# IIS Sizes
+define IIS_XDIM 512
+define IIS_YDIM 512
+define MCXSCALE 64 # Metacode x scale
+define MCYSCALE 64 # Metacode y scale
+define SZB_IISHDR 16 # Size of IIS header in bytes
+define LEN_ZOOM 3 # Zoom parameters
+define LEN_CURSOR 3 # Cursor parameters
+define LEN_SELECT 12 # frame select
+define LEN_LUT 256 # Look up table
+define LEN_OFM 1024 # Output function look up table
+define LEN_IFM 8192 # Input function look up table
+define LEN_VIDEOM 2048 # videometer output memory
+define LEN_GRAM 256 # graphics ram
+define MAXX 512 # maximum x register + 1
+
+# IIS Status Words
+define IIS_FILSIZE (IIS_XDIM * IIS_YDIM * SZB_CHAR)
+define IIS_BLKSIZE 1
+define IIS_OPTBUFSIZE 32768
+define IIS_MAXBUFSIZE 32768
diff --git a/pkg/images/tv/iis/iism70/iisbutton.x b/pkg/images/tv/iis/iism70/iisbutton.x
new file mode 100644
index 00000000..50dfff7b
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisbutton.x
@@ -0,0 +1,44 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISBUTTON -- Read, button status
+
+procedure iisbutton (cnum, x, y, key)
+
+int cnum # cursor number
+int x,y # coordinates
+int key # key pressed
+
+short status
+int and()
+
+include "iis.com"
+
+begin
+ call iishdr (IREAD, 1, CURSOR+COMMAND, 0, 0, 0, 0)
+ call iisio (status, 1 * SZB_CHAR)
+
+ if ( cnum == IDS_BUT_WT ) {
+ while ( and (int(status), PUSH) == 0 ) {
+ call tsleep(1)
+ call iisio (status, 1 * SZB_CHAR)
+ }
+ }
+
+ if ( and ( int(status), PUSH) == 0 )
+ key = 0
+ else {
+ status = and ( int(status), 7400B) / 256
+ switch(status) {
+ case 4:
+ status = 3
+
+ case 8:
+ status = 4
+ }
+ key = status
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iiscls.x b/pkg/images/tv/iis/iism70/iiscls.x
new file mode 100644
index 00000000..c717f636
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iiscls.x
@@ -0,0 +1,27 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <knet.h>
+include "iis.h"
+
+define LEN_HID 5
+
+# IISCLS -- Close IIS display.
+
+procedure iiscls (chan, status)
+
+int chan[ARB]
+int status
+
+include "iis.com"
+
+begin
+ # first we need to tuck away the constants for zoom and scroll
+ # as we cannot read them on the model 70. Would that there were
+ # somewhere to put them. Alas not. So just drop them on the floor.
+
+ if (iisnopen == 1) {
+ call zclsgd (iischan, status)
+ iisnopen = 0
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iiscursor.x b/pkg/images/tv/iis/iism70/iiscursor.x
new file mode 100644
index 00000000..5ffc9131
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iiscursor.x
@@ -0,0 +1,108 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# cscale makes 0-32767 range from 0-62. The 62 results from the need
+# to describe a cursor with a center, and hence an ODD number of points.
+# Thus, we pretend the cursor ranges from 0-62 rather than 0-63, and
+# the center is at (31,31).
+# cwidth describes the (cursor) ram width, which is 64 ( by 64).
+
+define CSCALE 528
+define CWIDTH 64
+define CSIZE 4096
+
+# IISCURSOR -- Read, Write cursor shape, turn cursor on/off
+
+procedure iiscursor (rw, cur, n, data)
+
+short rw # read or write
+short cur # cursor number ... ignored for IIS M70
+short n # number of data values
+short data[ARB] # the data
+
+short command, len
+short shape[CSIZE]
+short status
+int rate
+int i,j,index
+int mod(), and(), or(), andi()
+
+include "iis.com"
+
+begin
+ len = 1
+ if (data[1] != IDS_CSHAPE) {
+ call iishdr (IREAD, len, CURSOR+COMMAND, 0, 0, 0, 0)
+ call iisio (status, len * SZB_CHAR)
+ }
+
+ if (rw == IDS_WRITE)
+ command = andi (IWRITE+VRETRACE, 177777B)
+ else
+ command = andi (IREAD+VRETRACE, 177777B)
+
+ if (data[1] != IDS_CSHAPE){
+ if (rw == IDS_WRITE) {
+ switch (data[1]) {
+ case IDS_OFF:
+ status = and(int(status), 177776B)
+
+ case IDS_ON:
+ status = or (int(status), 1)
+
+ case IDS_CBLINK:
+ rate = mod (int(data[2])-1, 4) * 8
+ status = or (rate, and (int(status),177747B))
+ }
+ call iishdr (command, len, CURSOR+COMMAND, 0, 0, 0, 0)
+ call iisio (status, len * SZB_CHAR)
+ } else {
+ if ( data[1] == IDS_CBLINK )
+ data[2] = ( and (int(status), 30B) / 8 ) + 1
+ else if ( and ( int(status), 1) == 0 )
+ data[1] = IDS_OFF
+ else
+ data[1] = IDS_ON
+ }
+
+ } else {
+ # deal with cursor shape.
+
+ len = CSIZE
+ if ( rw == IDS_WRITE) {
+ call aclrs (shape, CSIZE)
+ for ( i = 2 ; i <= n-1 ; i = i + 2 ) {
+ # given GKI data pairs for x,y cursor_on bits, set shape datum
+ # the first value is x, then y
+ if (data[i] == IDS_EOD)
+ break
+ j = data[i]/CSCALE
+ index = (data[i+1]/CSCALE) * CWIDTH + j + 1
+ shape[index] = 1
+ }
+ }
+
+ call iishdr (command, len, CURSOR, ADVXONTC, ADVYONXOV, 0, 0)
+ call iisio (shape, len * SZB_CHAR)
+
+ # if read command, return all set bits as GKI x,y pairs
+ if ( rw != IDS_WRITE) {
+ i = 2
+ for ( j = 1 ; j <= CSIZE ; j = j + 1 ) {
+ if ( shape[j] != 0 ) {
+ data[i] = mod(j,CWIDTH) * CSCALE
+ data[i+1] = (j/CWIDTH) * CSCALE
+ i = i + 2
+ if ( i > n-1 )
+ break
+ }
+ }
+ if ( i <= n )
+ data[i] = IDS_EOD
+ n = i
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iishdr.x b/pkg/images/tv/iis/iism70/iishdr.x
new file mode 100644
index 00000000..bf22d493
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iishdr.x
@@ -0,0 +1,31 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+
+# IISHDR -- Form IIS header.
+
+procedure iishdr (id, count, subunit, x, y, z, t)
+
+int id, count, subunit, x, y, z, t
+int i, sum
+include "iis.com"
+
+begin
+ XFERID(hdr) = id
+ THINGCT(hdr) = count
+ SUBUNIT(hdr) = subunit
+ XREG(hdr) = x
+ YREG(hdr) = y
+ ZREG(hdr) = z
+ TREG(hdr) = t
+ CHECKSUM(hdr) = 1
+
+ if (THINGCT(hdr) > 0)
+ THINGCT(hdr) = -THINGCT(hdr)
+
+ sum = 0
+ for (i = 1; i <= LEN_IISHDR; i = i + 1)
+ sum = sum + hdr[i]
+ CHECKSUM(hdr) = -sum
+end
diff --git a/pkg/images/tv/iis/iism70/iishisto.x b/pkg/images/tv/iis/iism70/iishisto.x
new file mode 100644
index 00000000..374342a0
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iishisto.x
@@ -0,0 +1,53 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISHISTO -- Activate, Read histogram.
+
+procedure iishisto (rw, color, offset, a_n, data)
+
+short rw # read or write
+short color[ARB] # color(s) to write
+short offset # offset into histogram table
+short a_n # number of data values
+short data[ARB] # the data
+
+int n, command, off, len, x, y, z
+include "iis.com"
+
+begin
+ n = a_n
+ if (n < 1)
+ return
+
+ # set the area to be histogrammed ... in data[1], currently
+ # device very specific ( 2 == whole region) . Need to fix this
+ # perhaps via specific graph plane filled with gkifill command to
+ # depict area desired.
+ # n must be twice the number of datum values. Upper level code
+ # must know this to leave enough room. Would be better if upper
+ # code could ignore this (fact).
+
+ if (rw == IDS_WRITE) {
+ command = IWRITE+VRETRACE
+ x = 0
+ y = 0
+ z = 0
+ len = 1
+ data[1] = 2
+ call iishdr (command, len, VIDEOM+COMMAND, x, y, z, 0)
+ call iisio (data[1], len * SZB_CHAR)
+ return
+ }
+
+ off = offset
+ command = IREAD+VRETRACE
+ len = min (n, LEN_VIDEOM-off+1)
+ off = min (LEN_VIDEOM, off) - 1
+ y = off/MAXX + ADVYONXOV
+ x = mod (off, MAXX) + ADVXONTC
+ call iishdr (command, len, VIDEOM, x, y, z, 0)
+ call iisio (data, len * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/iisifm.x b/pkg/images/tv/iis/iism70/iisifm.x
new file mode 100644
index 00000000..ef04a1be
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisifm.x
@@ -0,0 +1,51 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LUT_IMAX 255
+
+# IISIFM -- Read and Write INPUT look up table.
+# Written data is from line end points, read data
+# is full array.
+
+procedure iisifm (rw, offset, n, data)
+
+short rw # read or write
+short offset # offset into lut
+short n # number of data values
+short data[ARB] # the data
+
+int command,len,x,y
+pointer sp, idata
+
+include "iis.com"
+
+begin
+ if ( rw == IDS_WRITE) {
+ if (n < 4)
+ return
+
+ call smark (sp)
+ call salloc (idata, LEN_IFM, TY_SHORT)
+ call aclrs (Mems[idata], LEN_IFM)
+
+ command = IWRITE+VRETRACE
+ call idslfill (data, int(n), Mems[idata], LEN_IFM, 0, LUT_IMAX)
+ len = LEN_IFM
+ } else {
+ len = n
+ command = IREAD+VRETRACE
+ }
+
+ y = ADVYONXOV
+ x = ADVXONTC
+ call iishdr (command, len, IFM, x, y, 0, 0)
+
+ if (rw == IDS_WRITE) {
+ call iisio (Mems[idata], len * SZB_CHAR)
+ call sfree (sp)
+ } else
+ call iisio (data, len * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/iisio.x b/pkg/images/tv/iis/iism70/iisio.x
new file mode 100644
index 00000000..f8e005c6
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisio.x
@@ -0,0 +1,35 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <knet.h>
+include "iis.h"
+
+# IISIO -- Read/Write to IIS.
+
+procedure iisio (buf, nbytes)
+
+short buf[ARB]
+int nbytes
+
+int nbites
+int and()
+
+include "iis.com"
+
+begin
+ call iiswt (iischan, nbites)
+ if (nbites == ERR)
+ return
+
+ call zawrgd (iischan, hdr, SZB_IISHDR, 0)
+ call iiswt (iischan, nbites)
+ if (nbites == ERR)
+ return
+
+ if (and (int(XFERID(hdr)), IREAD) != 0)
+ call zardgd (iischan, buf, nbytes, 0)
+ else
+ call zawrgd (iischan, buf, nbytes, 0)
+
+ call iiswt (iischan, nbites)
+end
diff --git a/pkg/images/tv/iis/iism70/iislut.x b/pkg/images/tv/iis/iism70/iislut.x
new file mode 100644
index 00000000..07819247
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iislut.x
@@ -0,0 +1,67 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LUT_LMAX 255
+
+# IISLUT -- Read and Write look up table.
+# NOTE the ASYMMETRY ... written data is derived from end
+# points, but read data is the full array (see zsnapinit,
+# for instance, for read usage.)
+
+procedure iislut (rw, frame, color, offset, n, data)
+
+short rw # read or write
+short frame[ARB] # frame array
+short color[ARB] # color array
+short offset # offset into lut
+short n # number of data values
+short data[ARB] # the data
+
+int command,len,x,y,z,t
+short iispack()
+int mapcolor()
+pointer sp, ldata
+
+include "iis.com"
+
+begin
+ z = mapcolor (color)
+ t = iispack(frame)
+ if (t == GRCHAN) {
+ return
+ }
+
+ if ( rw == IDS_WRITE) {
+ if ( n < 4)
+ return
+ command = IWRITE+VRETRACE
+
+ # data space for manipulating lut information
+
+ call smark (sp)
+ call salloc (ldata, LEN_LUT, TY_SHORT)
+ call aclrs (Mems[ldata], LEN_LUT)
+
+ # We could have negative lut values, but don't bother for now
+ call idslfill (data, int(n), Mems[ldata], LEN_LUT, 0, LUT_LMAX)
+
+ len = LEN_LUT
+ } else {
+ len = n
+ command = IREAD+VRETRACE
+ }
+
+ x = ADVXONTC
+ y = 0
+
+ call iishdr (command, len, LUT, x, y, z, t)
+
+ if ( rw == IDS_WRITE) {
+ call iisio (Mems[ldata], len * SZB_CHAR)
+ call sfree (sp)
+ } else
+ call iisio (data, len * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/iismatch.x b/pkg/images/tv/iis/iism70/iismatch.x
new file mode 100644
index 00000000..a2435fdc
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iismatch.x
@@ -0,0 +1,76 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISMATCH -- copy (match) a set of look up tables to a given table;
+# frames/color specify the given table, data gives frame/color for
+# set to be changed.
+
+procedure iismatch (code, frames, color, n, data)
+
+short code # which table type
+short frames[ARB] # reference frame
+short color[ARB] # reference color
+short n # count of data items
+short data[ARB] # frame/color to be changed.
+
+pointer sp, ldata
+int len, x,y,z,t
+int unit, i
+int mapcolor(), ids_dcopy()
+short temp[IDS_MAXIMPL+1]
+short iispack()
+
+include "../lib/ids.com"
+
+begin
+ switch (code) {
+ case IDS_FRAME_LUT:
+ len = LEN_LUT
+ x = ADVXONTC
+ y = 0
+ z = mapcolor (color)
+ t = iispack (frames)
+ if (t == GRCHAN)
+ return
+ unit = LUT
+
+ case IDS_OUTPUT_LUT:
+ len = LEN_OFM
+ x = ADVXONTC
+ y = ADVYONXOV
+ z = mapcolor (color)
+ t = 0
+
+ default:
+ return
+ }
+
+ call smark (sp)
+ call salloc (ldata, len, TY_SHORT)
+
+ call iishdr (IREAD+VRETRACE, len, unit, x, y, z, t)
+ call iisio (Mems[ldata], len * SZB_CHAR)
+
+ i = ids_dcopy (data, temp)
+ switch (code) {
+ case IDS_FRAME_LUT:
+ call ids_expand (temp, i_maxframes, true)
+ t = iispack (temp)
+ i = ids_dcopy (data[i+1], temp)
+ call ids_expand (temp, 3, false) # 3...max colors
+ z = mapcolor (temp)
+
+ case IDS_OUTPUT_LUT:
+ i = ids_dcopy (data[i+1], temp)
+ call ids_expand (temp, 3, false)
+ z = mapcolor (temp)
+ }
+
+ call iishdr (IWRITE+VRETRACE, len, unit, x, y, z, t)
+ call iisio (Mems[ldata], len * SZB_CHAR)
+
+ call sfree (sp)
+end
diff --git a/pkg/images/tv/iis/iism70/iisminmax.x b/pkg/images/tv/iis/iism70/iisminmax.x
new file mode 100644
index 00000000..22a3062e
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisminmax.x
@@ -0,0 +1,87 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LEN_MM 6
+
+# IISMIN -- Read minimum registers
+
+procedure iismin (rw, color, n, data)
+
+short rw # read or write
+short color[ARB] # color
+short n # number of data values
+short data[ARB] # the data
+
+int command,x
+short const[LEN_MM]
+int i,j
+
+include "iis.com"
+
+begin
+ if ( rw == IDS_WRITE)
+ return
+ command = IREAD+VRETRACE
+ x = ADVXONTC
+ call iishdr(command, LEN_MM, SUMPROC+COMMAND, x, 0, 0, 0)
+ call iisio (const, LEN_MM * SZB_CHAR)
+ j = 1
+ for ( i = 1 ; i <= n ; i = i + 1 ) {
+ switch(color[j]) {
+ case IDS_RED:
+ data[i] = const[5]
+
+ case IDS_GREEN:
+ data[i] = const[3]
+
+ case IDS_BLUE:
+ data[i] = const[1]
+ }
+ j = j+1
+ if ( color[j] == IDS_EOD )
+ j = j - 1
+ }
+end
+
+# IISMAX -- Read maximum registers
+
+procedure iismax (rw, color, n, data)
+
+short rw # read or write
+short color[ARB] # color
+short n # number of data values
+short data[ARB] # the data
+
+int command,x
+short const[LEN_MM]
+int i,j
+
+include "iis.com"
+
+begin
+ if ( rw == IDS_WRITE)
+ return
+ command = IREAD+VRETRACE
+ x = ADVXONTC
+ call iishdr(command, LEN_MM, SUMPROC+COMMAND, x, 0, 0, 0)
+ call iisio (const, LEN_MM * SZB_CHAR)
+ j = 1
+ for ( i = 1 ; i <= n ; i = i + 1 ) {
+ switch(color[j]) {
+ case IDS_RED:
+ data[i] = const[6]
+
+ case IDS_GREEN:
+ data[i] = const[4]
+
+ case IDS_BLUE:
+ data[i] = const[2]
+ }
+ j = j+1
+ if ( color[j] == IDS_EOD )
+ j = j - 1
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iisoffset.x b/pkg/images/tv/iis/iism70/iisoffset.x
new file mode 100644
index 00000000..d7f618dc
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisoffset.x
@@ -0,0 +1,67 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LEN_CONST 3
+
+# IISOFFSET -- Read and Write output bias registers
+
+procedure iisoffset (rw, color, n, data)
+
+short rw # read or write
+short color[ARB] # color
+short n # number of data values
+short data[ARB] # the data
+
+int command,len,x
+short const[3]
+int i,j
+
+include "iis.com"
+
+begin
+ command = IREAD+VRETRACE
+ x = 8 + ADVXONTC
+ len = LEN_CONST
+ call iishdr(command, len, SUMPROC+COMMAND, x, 0, 0, 0)
+ call iisio (const, len * SZB_CHAR)
+ if ( rw == IDS_WRITE) {
+ command = IWRITE+VRETRACE
+ j = 1
+ for ( i =1 ; color[i] != IDS_EOD ; i = i + 1) {
+ switch(color[i]) {
+ case IDS_RED:
+ const[3] = data[j]
+
+ case IDS_GREEN:
+ const[2] = data[j]
+
+ case IDS_BLUE:
+ const[1] = data[j]
+ }
+ if ( j < n)
+ j = j + 1
+ }
+ call iishdr (command, len, SUMPROC+COMMAND, x, 0, 0, 0)
+ call iisio (const, len * SZB_CHAR)
+ } else {
+ j = 1
+ for ( i = 1 ; i <= n ; i = i + 1 ) {
+ switch(color[j]) {
+ case IDS_RED:
+ data[i] = const[3]
+
+ case IDS_GREEN:
+ data[i] = const[2]
+
+ case IDS_BLUE:
+ data[i] = const[1]
+ }
+ j = j+1
+ if ( color[j] == IDS_EOD )
+ j = j - 1
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iisofm.x b/pkg/images/tv/iis/iism70/iisofm.x
new file mode 100644
index 00000000..0c19c117
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisofm.x
@@ -0,0 +1,53 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LUT_OMAX 1023
+
+# IISOFM -- Read and Write OUTPUT look up table.
+# Written data is from end points, read data is full
+# array.
+
+procedure iisofm (rw, color, offset, n, data)
+
+short rw # read or write
+short color[ARB] # color(s) to write
+short offset # offset into lut
+short n # number of data values
+short data[ARB] # the data
+
+int command,len,x,y,z
+int mapcolor()
+pointer sp, odata
+
+include "iis.com"
+
+begin
+ z = mapcolor (color)
+ if ( rw == IDS_WRITE) {
+ if (n < 4)
+ return
+
+ call smark (sp)
+ call salloc (odata, LEN_OFM, TY_SHORT)
+ call aclrs (Mems[odata], LEN_OFM)
+
+ command = IWRITE+VRETRACE
+ call idslfill (data, int(n), Mems[odata], LEN_OFM, 0, LUT_OMAX)
+ len = LEN_OFM
+ }
+ else {
+ len = n
+ command = IREAD+VRETRACE
+ }
+ y = ADVYONXOV
+ x = ADVXONTC
+ call iishdr (command, len, OFM, x, y, z, 0)
+ if (rw == IDS_WRITE) {
+ call iisio (Mems[odata], len * SZB_CHAR)
+ call sfree (sp)
+ } else
+ call iisio (data, len * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/iisopn.x b/pkg/images/tv/iis/iism70/iisopn.x
new file mode 100644
index 00000000..29335c62
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisopn.x
@@ -0,0 +1,35 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <knet.h>
+include "iis.h"
+
+# IISOPN -- Open IIS display.
+
+procedure iisopn (devinfo, mode, chan)
+
+char devinfo[ARB] # device info for zopen
+int mode # access mode
+int chan[ARB] # receives IIS descriptor
+
+bool first_time
+data first_time /true/
+include "iis.com"
+
+begin
+ if (first_time) {
+ iisnopen = 0
+ first_time = false
+ }
+
+ # We permit multiple opens but only open the physical device once.
+ if (iisnopen == 0)
+ call zopngd (devinfo, mode, iischan)
+
+ if (iischan == ERR)
+ chan[1] = ERR
+ else {
+ iisnopen = iisnopen + 1
+ chan[1] = iischan
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iispack.x b/pkg/images/tv/iis/iism70/iispack.x
new file mode 100644
index 00000000..4c2c70f3
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iispack.x
@@ -0,0 +1,21 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+
+# IISPACK -- Pack color or frame data into a single word.
+
+short procedure iispack (data)
+
+short data[ARB]
+int value, bit, i
+int or()
+
+begin
+ value = 0
+ for (i=1; data[i] != IDS_EOD; i=i+1) {
+ bit = data[i] - 1
+ value = or (value, 2 ** bit)
+ }
+
+ return (value)
+end
diff --git a/pkg/images/tv/iis/iism70/iispio.x b/pkg/images/tv/iis/iism70/iispio.x
new file mode 100644
index 00000000..f8c57138
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iispio.x
@@ -0,0 +1,65 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <knet.h>
+include "iis.h"
+
+# IISPIO -- Pixel i/o to the IIS.
+
+procedure iispio (buf, ny)
+
+short buf[IIS_XDIM,ny] # Cell array
+int ny # number of image lines
+
+pointer iobuf
+bool first_time
+int xferid, status, npacked, szline, i
+int and()
+include "iis.com"
+data first_time /true/
+
+begin
+ if (first_time) {
+ call malloc (iobuf, IIS_MAXBUFSIZE, TY_CHAR)
+ first_time = false
+ }
+
+ # Wait for the last i/o transfer.
+ call iiswt (iischan, status)
+ if (status == ERR)
+ return
+
+ # Transmit the packet header.
+ call zawrgd (iischan, hdr, SZB_IISHDR, 0)
+ call iiswt (iischan, status)
+ if (status == ERR)
+ return
+
+ # Read or write the data block.
+ npacked = ny * IIS_XDIM
+ szline = IIS_XDIM / (SZ_SHORT * SZB_CHAR)
+
+ # Transmit the data byte-packed to increase the i/o bandwith
+ # when using network i/o.
+
+ xferid = XFERID(hdr)
+ if (and (xferid, IREAD) != 0) {
+ # Read from the IIS.
+
+ call zardgd (iischan, Memc[iobuf], npacked, 0)
+ call iiswt (iischan, status)
+
+ # Unpack and line flip the packed data.
+ do i = 0, ny-1
+ call achtbs (Memc[iobuf+i*szline], buf[1,ny-i], IIS_XDIM)
+
+ } else {
+ # Write to the IIS.
+
+ # Bytepack the image lines, doing a line flip in the process.
+ do i = 0, ny-1
+ call achtsb (buf[1,ny-i], Memc[iobuf+i*szline], IIS_XDIM)
+
+ call zawrgd (iischan, Memc[iobuf], npacked, 0)
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iisrange.x b/pkg/images/tv/iis/iism70/iisrange.x
new file mode 100644
index 00000000..8fad856b
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisrange.x
@@ -0,0 +1,97 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define LEN_RANGE 1
+
+# IISRANGE -- Read and write range scaling registers
+# Input data is of form 1-->range "0", 2,3 --> "1", 4-7 --> "2"
+# and anything beyond 7 --> "4". This is just like zoom.
+# However, on readback, the actual range values are returned. If
+# this should change, the zsnapinit code must change too (the only
+# place where a range read is done).
+
+procedure iisrange (rw, color, n, data)
+
+short rw # read or write
+short color[ARB] # color
+short n # number of data values
+short data[ARB] # the data
+
+short range
+int i, j
+int command, x, itemp, ival
+int and(), or()
+include "iis.com"
+
+begin
+ if (data[1] == IDS_EOD)
+ return
+
+ command = IREAD
+ x = ADVXONTC
+
+ call iishdr (command, LEN_RANGE, OFM+COMMAND, x, 0, 0, 0)
+ call iisio (range, LEN_RANGE * SZB_CHAR)
+
+ if (rw == IDS_WRITE) {
+ command = IWRITE+VRETRACE
+ j = 1
+ for (i=1; color[i] != IDS_EOD; i=i+1) {
+ switch (data[j]) {
+ case 1,2:
+ ival = data[j]-1
+ case 3:
+ ival = 1
+ case 4,5,6,7:
+ ival = 2
+
+ default:
+ if (ival < 0)
+ ival = 0
+ else
+ ival = 3
+ }
+
+ itemp = range
+ switch(color[i]) {
+ case IDS_RED:
+ range = or (ival*16, and (itemp, 17B))
+
+ case IDS_GREEN:
+ range = or (ival*4, and (itemp, 63B))
+
+ case IDS_BLUE:
+ range = or (ival, and (itemp, 74B))
+ }
+
+ if ( j < n)
+ j = j + 1
+ }
+
+ call iishdr (command, LEN_RANGE, OFM+COMMAND, x, 0, 0, 0)
+ call iisio (range, LEN_RANGE * SZB_CHAR)
+
+ } else {
+ # Return a range value
+ j = 1
+ for (i=1; i <= n; i=i+1) {
+ itemp = range
+ switch (color[j]) {
+ case IDS_RED:
+ data[i] = and (itemp, 60B) / 16
+
+ case IDS_GREEN:
+ data[i] = and (itemp, 14B) / 4
+
+ case IDS_BLUE:
+ data[i] = and (itemp, 3B)
+ }
+ j = j+1
+ if (color[j] == IDS_EOD)
+ j = j - 1
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iisrd.x b/pkg/images/tv/iis/iism70/iisrd.x
new file mode 100644
index 00000000..20e99cb2
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisrd.x
@@ -0,0 +1,51 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+
+# IISRD -- Read data from IIS. Reads are packed when can.
+# The data is line-flipped.
+
+procedure iisrd (chan, buf, nbytes, offset)
+
+int chan[ARB]
+short buf[ARB]
+int nbytes
+long offset
+
+long off1, off2
+int nchars, thing_count, tid, y1, y2, x
+int or()
+include "iis.com"
+
+begin
+ # Convert to chars and clip at the top of the display.
+ off1 = (offset - 1) / SZB_CHAR + 1
+ off2 = min (IIS_XDIM * IIS_YDIM, (offset + nbytes - 1) / SZB_CHAR) + 1
+ nchars = off2 - off1
+
+ y1 = (off1-1 ) / IIS_XDIM
+ y2 = (off2-1 - IIS_XDIM) / IIS_XDIM
+ y2 = max (y1,y2)
+
+ # Pack only if start at x=0
+ x = (off1 - 1) - y1 * IIS_XDIM
+ if ( x == 0 )
+ tid = IREAD+PACKED
+ else
+ tid = IREAD
+
+ # If only a few chars, don't pack...have trouble with count of 1
+ # and this maeks code same as iiswr.x
+ if ( nchars < 4 )
+ tid = IREAD
+
+ thing_count = nchars
+
+ call iishdr (tid, thing_count, REFRESH,
+ or (x, ADVXONTC), or (IIS_YDIM-1-y2, ADVYONXOV), iframe, iplane)
+ if ( tid == IREAD)
+ call iisio (buf, nbytes)
+ else
+ call iispio (buf, y2 - y1 + 1)
+end
diff --git a/pkg/images/tv/iis/iism70/iisscroll.x b/pkg/images/tv/iis/iism70/iisscroll.x
new file mode 100644
index 00000000..a583e4a4
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iisscroll.x
@@ -0,0 +1,101 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISSCROLL -- Read and Write scroll registers
+# We scroll multiple frames to multiple centers; if there are not
+# enough data pairs to match the number of frames, use the last
+# pair repeatedly.
+
+procedure iisscroll (rw, frame, n, data)
+
+short rw # read or write
+short frame[ARB] # frame data
+short n # number of data values
+short data[ARB] # the data
+
+int z
+short iispack()
+int i,total, pl, index
+
+include "iis.com"
+
+begin
+ total = n/2
+ if ( rw != IDS_WRITE) {
+ # Scroll registers are write only
+ do i = 1, total {
+ pl = frame[i]
+ if (pl == IDS_EOD)
+ break
+ data[2*i-1] = xscroll[pl] * MCXSCALE
+ data[2*i] = yscroll[pl] * MCYSCALE
+ }
+
+ if (2*total < n)
+ data[2*total+1] = IDS_EOD
+ return
+ }
+
+ # Set all the scroll offsets.
+ index = 1
+ for (i=1; frame[i] != IDS_EOD; i=i+1) {
+ pl = frame[i]
+ xscroll[pl] = data[2*index-1] / MCXSCALE
+ yscroll[pl] = data[2*index ] / MCYSCALE
+ if (i < total)
+ index = index + 1
+ }
+
+ # Now do the scrolling.
+ for (i=1; frame[i] != IDS_EOD; i=i+1) {
+ pl = frame[i]
+ if (i == total) {
+ z = iispack (frame[i])
+ call do_scroll (z, xscroll[pl], yscroll[pl])
+ break
+ } else
+ call do_scroll (short(2**(pl-1)), xscroll[pl], yscroll[pl])
+ }
+end
+
+
+procedure do_scroll (planes, x, y)
+
+short planes # bit map for planes
+short x,y # where to scroll
+
+short command
+short scr[2]
+short xs,ys
+
+include "iis.com"
+
+begin
+ xs = x
+ ys = y
+ command = IWRITE+VRETRACE
+ scr[1] = xs
+ scr[2] = ys
+
+ # If x/y scroll at "center", scr[1/2] are now IIS_[XY]CEN
+ # y = 0 is at top for device while y = 1 is bottom for user
+ # so for y, center now moves to IIS_YCEN_INV !!
+
+ scr[2] = IIS_YDIM - 1 - scr[2]
+
+ # Scroll is given for center, but hardware wants corner coords.
+ scr[1] = scr[1] - IIS_XCEN
+ scr[2] = scr[2] - IIS_YCEN_INV
+
+ if (scr[1] < 0)
+ scr[1] = scr[1] + IIS_XDIM
+ if (scr[2] < 0)
+ scr[2] = scr[2] + IIS_YDIM
+
+ call iishdr (command, 2, SCROLL, ADVXONTC, 0, int(planes), 0)
+ call iisio (scr, 2 * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/iissplit.x b/pkg/images/tv/iis/iism70/iissplit.x
new file mode 100644
index 00000000..2badb7cb
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iissplit.x
@@ -0,0 +1,68 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define X_SPLIT 12
+
+# IISSPLIT -- Read and Write split screen coordinates
+
+procedure iissplit (rw, n, data)
+
+short rw # read or write
+short n # number of data values
+short data[ARB] # the data
+
+int command,len,x
+short coord[2]
+
+include "iis.com"
+
+begin
+ len = min (int(n), 2)
+ if ( len < 1) {
+ data[1] = IDS_EOD
+ return
+ }
+
+ if (rw == IDS_WRITE) {
+ if (data[1] == IDS_EOD)
+ return
+ command = IWRITE+VRETRACE
+ coord[1] = data[1] / MCXSCALE
+
+
+ # Split screen will display the full screen from one lut ONLY
+ # if the split coordinate is zero. Setting the split to 511
+ # means that all the screen BUT the last pixel is from one lut.
+ # Hence the y coordinate for full screen in one quad is
+ # (device) 0 , (user) 511. If the user requests split at (0,0),
+ # we honor this as a (device) (0,0). This will remove the
+ # ability to split the screen with just the bottom line
+ # in the "other" lut, which shouldn't bother anyone.
+
+ if (len == 2)
+ coord[2] = (IIS_YDIM - 1) - data[2]/MCYSCALE
+
+ if (coord[2] == IIS_YDIM - 1)
+ coord[2] = 0
+
+ } else
+ command = IREAD+VRETRACE
+
+ # at most, read/write the x,y registers
+ x = X_SPLIT + ADVXONTC
+
+ call iishdr (command, len, LUT+COMMAND, x, 0, 0, 0)
+ call iisio (coord, len * SZB_CHAR)
+
+ if ( rw != IDS_WRITE ) {
+ data[1] = coord[1] * MCXSCALE
+ if ( len == 2 ) {
+ if ( coord[2] == 0)
+ coord[2] = IIS_YDIM - 1
+ data[2] = (IIS_YDIM - 1 - coord[2] ) * MCYSCALE
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iistball.x b/pkg/images/tv/iis/iism70/iistball.x
new file mode 100644
index 00000000..ebcc6566
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iistball.x
@@ -0,0 +1,41 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISTBALL -- Read, Write tball status to turn tball on/off
+
+procedure iistball (rw, data)
+
+short rw # read or write
+short data[ARB] # the data
+
+int command,len
+short status
+int and(), or()
+
+include "iis.com"
+
+begin
+ len = 1
+ call iishdr (IREAD, len, CURSOR+COMMAND, 0, 0, 0, 0)
+ call iisio (status, len * SZB_CHAR)
+ if ( rw == IDS_WRITE) {
+ command = IWRITE+VRETRACE
+ switch (data[1]) {
+ case IDS_OFF:
+ status = and (int(status), 177771B)
+
+ case IDS_ON:
+ status = or ( int(status), 6)
+ }
+ call iishdr (command, 1, CURSOR+COMMAND, 0, 0, 0, 0)
+ call iisio (status, 1 * SZB_CHAR)
+ } else {
+ if ( and ( int(status), 6) == 0 )
+ data[2] = IDS_OFF
+ else
+ data[2] = IDS_ON
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/iiswr.x b/pkg/images/tv/iis/iism70/iiswr.x
new file mode 100644
index 00000000..11bb2803
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iiswr.x
@@ -0,0 +1,51 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+
+# IISWR -- Write pixel data to IIS. Writes are packed with full lines only.
+# The data is line-flipped, causing the first line to be displayed at the bottom
+# of the screen.
+
+procedure iiswr (chan, buf, nbytes, offset)
+
+int chan[ARB]
+short buf[ARB]
+int nbytes
+long offset
+
+long off1, off2
+int nchars, thing_count, tid, y1, y2, x
+int or()
+include "iis.com"
+
+begin
+ # Convert to chars and clip at the top of the display.
+ off1 = (offset - 1) / SZB_CHAR + 1
+ off2 = min (IIS_XDIM * IIS_YDIM, (offset + nbytes - 1) / SZB_CHAR) + 1
+ nchars = off2 - off1
+
+ y1 = (off1-1 ) / IIS_XDIM
+ y2 = (off2-1 - IIS_XDIM) / IIS_XDIM
+ y2 = max (y1,y2)
+
+ # Pack only if full lines
+ x = (off1 - 1) - y1 * IIS_XDIM
+ if ( x == 0 )
+ tid = IWRITE+BYPASSIFM+PACKED+BLOCKXFER+BYTE
+ else
+ tid = IWRITE+BYPASSIFM
+
+ # If only a few chars, don't pack (BLOCKXFER needs nchar>=4)
+ if ( nchars < 4 )
+ tid = IWRITE+BYPASSIFM
+
+ thing_count = nchars
+
+ call iishdr (tid, thing_count, REFRESH,
+ or (x, ADVXONTC), or (IIS_YDIM-1-y2, ADVYONXOV), iframe, iplane)
+ if ( tid == IWRITE+BYPASSIFM)
+ call iisio (buf, nbytes)
+ else
+ call iispio (buf, y2 - y1 + 1)
+end
diff --git a/pkg/images/tv/iis/iism70/iiswt.x b/pkg/images/tv/iis/iism70/iiswt.x
new file mode 100644
index 00000000..93f1e04a
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iiswt.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <knet.h>
+include "iis.h"
+
+# IISWT -- Wait for IIS display.
+
+procedure iiswt (chan, nbytes)
+
+int chan[ARB]
+int nbytes
+include "iis.com"
+
+begin
+ call zawtgd (iischan, nbytes)
+ nbytes = nbytes * SZB_CHAR
+end
diff --git a/pkg/images/tv/iis/iism70/iiszoom.x b/pkg/images/tv/iis/iism70/iiszoom.x
new file mode 100644
index 00000000..d703beec
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/iiszoom.x
@@ -0,0 +1,98 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# IISZOOM -- Read and Write zoom magnification and coordinates.
+# the zoom coordinates give the point that should appear in the
+# center of the screen. For the I2S model 70, this requires a
+# scroll. In order for the scroll to be "determinable", we always
+# set the I2S "zoom center" to (IIS_XCEN,IIS_YCEN_INV). The IIS_YCEN_INV
+# results from specifying IIS_YCEN for y center and then having to "invert" y
+# to put GKI(y) = 0 at bottom.
+# This routine implements a command of the form "zoom these frames
+# to the coordinates given, with each triple of data setting a
+# zoom factor and a zoom center for the corresponding frame".
+# If there are excess frames (rel. to "n"), use the last triple.
+
+procedure iiszoom (rw, frames, n, data)
+
+short rw # read or write
+short frames[ARB] # which frames to zoom
+short n # number of data values
+short data[ARB] # the data
+
+int command,x
+int i, total,pl,index
+short zm,temp[4]
+short scroll[2*IDS_MAXIMPL + 1]
+short center[3]
+# magnification, and "zoom center"
+data temp /0,IIS_XCEN,IIS_YCEN_INV, 0/
+# center in GKI x=256 y=255
+data center/ 16384, 16320, 0/
+
+include "iis.com"
+
+begin
+ total = n/3
+
+ if ( rw != IDS_WRITE) {
+ # hardware is write only
+ do i = 1, total {
+ index = (i-1) * 3 + 1
+ pl = frames[i]
+ if ( pl == IDS_EOD)
+ break
+ data[index] = zoom[pl]
+ data[index+1] = xscroll[pl] * MCXSCALE
+ data[index+2] = yscroll[pl] * MCYSCALE
+ }
+ if ( 3*total < n)
+ data[index+3] = IDS_EOD
+ return
+ }
+
+ # can't have in data statements as IDS_EOD == (-2) and
+ # fortran won't allow () in data statements!!!
+
+ temp[4] = IDS_EOD
+ center[3] = IDS_EOD
+ command = IWRITE+VRETRACE
+ x = ADVXONTC
+
+ # the model 70 zooms all frames together. So ignore "frames"
+ # argument here, though needed for subsequent scroll.
+
+ zm = data[1]
+ if ( zm <= 1 )
+ zm = 0
+ else if (zm >= 8)
+ zm = 3
+ else
+ switch(zm) {
+ case 2,3:
+ zm = 1
+
+ case 4,5,6,7:
+ zm = 2
+ }
+ call amovks(short(2**zm), zoom, 16)
+ temp[1] = zm
+ call iishdr (command, 3, ZOOM, x, 0, 0, 0)
+ call iisio (temp, 3 * SZB_CHAR)
+
+ # now we have to scroll to the desired location (in GKI).
+ # If zoom is zero, don't do anything: this will leave the
+ # various images panned to some previously set place, but
+ # that is what is wanted when doing split screen and we pan
+ # some of the images.
+
+ if (zm != 0) {
+ do i = 1, total
+ call amovs (data[i * 3 - 1 ], scroll[i*2-1], 2)
+ scroll[total*2+1] = IDS_EOD
+ call iisscroll(short(IDS_WRITE), frames, short(total*2+1), scroll)
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/mkpkg b/pkg/images/tv/iis/iism70/mkpkg
new file mode 100644
index 00000000..9944d732
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/mkpkg
@@ -0,0 +1,58 @@
+# Makelib file for the image display interface. An image display device is
+# accessed by high level code via the GKI interface.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ idsexpand.x <gki.h> ../lib/ids.h iis.h
+ iisbutton.x <mach.h> iis.h ../lib/ids.h iis.com
+ iiscls.x <mach.h> iis.h iis.com <knet.h>
+ iiscursor.x <mach.h> iis.h ../lib/ids.h iis.com
+ iishdr.x <mach.h> iis.h iis.com
+ iishisto.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisifm.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisio.x <mach.h> iis.h iis.com <knet.h>
+ iislut.x <mach.h> iis.h ../lib/ids.h iis.com
+ iismatch.x <mach.h> iis.h ../lib/ids.h ../lib/ids.com
+ iisminmax.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisoffset.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisofm.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisopn.x <mach.h> iis.h iis.com <knet.h>
+ iispack.x ../lib/ids.h
+ iispio.x <mach.h> iis.h <knet.h> iis.com
+ iisrange.x <mach.h> iis.h ../lib/ids.h iis.com
+ iisrd.x <mach.h> iis.h iis.com
+ iisscroll.x <gki.h> <mach.h> iis.h ../lib/ids.h iis.com
+ iissplit.x <mach.h> iis.h ../lib/ids.h iis.com
+ iistball.x <mach.h> iis.h ../lib/ids.h iis.com
+ iiswr.x <mach.h> iis.h iis.com
+ iiswt.x <mach.h> iis.h iis.com <knet.h>
+ iiszoom.x <mach.h> iis.h ../lib/ids.h iis.com
+ zardim.x iis.h
+ zawrim.x
+ zawtim.x <mach.h> iis.h iis.com
+ zclear.x <mach.h> ../lib/ids.h iis.h
+ zclsim.x
+ zcontrol.x ../lib/ids.h iis.h
+ zcursor_read.x <gki.h> <mach.h> iis.h ../lib/ids.h iis.com
+ zcursor_set.x <gki.h> <mach.h> iis.h ../lib/ids.h iis.com
+ zdisplay_g.x <mach.h> iis.h ../lib/ids.h
+ zdisplay_i.x <mach.h> iis.h ../lib/ids.h ../lib/ids.com iis.com
+ zinit.x <mach.h> iis.h ../lib/ids.h ../lib/ids.com iis.com
+ zopnim.x
+ zreset.x <gki.h> <mach.h> ../lib/ids.h iis.h iis.com
+ zrestore.x <mach.h> ../lib/ids.h iis.h
+ zsave.x <mach.h> ../lib/ids.h iis.h
+ zseek.x <fset.h> <mach.h> ../lib/ids.h iis.h
+
+ zsetup.x <fset.h> <mach.h> ../lib/ids.h iis.h ../lib/ids.com\
+ iis.com
+ zsnap.x <fset.h> <mach.h> iis.h ../lib/ids.h zsnap.com iis.com\
+ ../lib/ids.com
+ zsnapinit.x <fset.h> <mach.h> iis.h ../lib/ids.h zsnap.com iis.com\
+ ../lib/ids.com
+ zsttim.x <knet.h>
+ ;
diff --git a/pkg/images/tv/iis/iism70/zardim.x b/pkg/images/tv/iis/iism70/zardim.x
new file mode 100644
index 00000000..e6811840
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zardim.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "iis.h"
+
+# ZARDIM -- Read data from a binary file display device.
+
+procedure zardim (chan, buf, nbytes, offset)
+
+int chan[ARB]
+short buf[ARB]
+int nbytes
+long offset
+
+begin
+ call iisrd (chan, buf, nbytes, offset)
+end
diff --git a/pkg/images/tv/iis/iism70/zawrim.x b/pkg/images/tv/iis/iism70/zawrim.x
new file mode 100644
index 00000000..7e5fa266
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zawrim.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# ZAWRIM -- Write data to a binary file display device.
+
+procedure zawrim (chan, buf, nbytes, offset)
+
+int chan[ARB]
+short buf[ARB]
+int nbytes
+long offset
+
+begin
+ call iiswr (chan, buf, nbytes, offset)
+end
diff --git a/pkg/images/tv/iis/iism70/zawtim.x b/pkg/images/tv/iis/iism70/zawtim.x
new file mode 100644
index 00000000..ef857bdd
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zawtim.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "iis.h"
+
+# ZAWTIM -- Wait for an image display frame which is addressable as
+# a binary file.
+
+procedure zawtim (chan, nbytes)
+
+int chan[ARB], nbytes
+include "iis.com"
+
+begin
+ call iiswt (chan, nbytes)
+end
diff --git a/pkg/images/tv/iis/iism70/zclear.x b/pkg/images/tv/iis/iism70/zclear.x
new file mode 100644
index 00000000..a03d429c
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zclear.x
@@ -0,0 +1,33 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZCLEAR -- Erase IIS frame.
+
+procedure zclear (frame, bitplane, flag)
+
+short frame[ARB] # frame array
+short bitplane[ARB] # bitplane array
+bool flag # true if image plane
+
+int z, t
+short erase
+int and(), andi()
+short iispack()
+
+begin
+ if (flag) {
+ z = iispack (frame)
+ z = and (z, ALLCHAN)
+ } else
+ z = GRCHAN
+
+ t = iispack (bitplane)
+ erase = andi (ERASE, 177777B)
+
+ call iishdr (IWRITE+BYPASSIFM+BLOCKXFER, 1, FEEDBACK,
+ ADVXONTC, ADVYONXOV, z, t)
+ call iisio (erase, SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/zclsim.x b/pkg/images/tv/iis/iism70/zclsim.x
new file mode 100644
index 00000000..a2bd2029
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zclsim.x
@@ -0,0 +1,13 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# ZCLSIM -- Close an image display frame which is addressable as
+# a binary file.
+
+procedure zclsim (chan, status)
+
+int chan[ARB]
+int status
+
+begin
+ call iiscls (chan, status)
+end
diff --git a/pkg/images/tv/iis/iism70/zcontrol.x b/pkg/images/tv/iis/iism70/zcontrol.x
new file mode 100644
index 00000000..56d8caeb
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zcontrol.x
@@ -0,0 +1,116 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+include "iis.h"
+
+# ZCONTROL -- call the device dependent control routines
+
+procedure zcontrol(device, rw, frame, color, offset, n, data)
+
+short device # which device/register to control
+short rw # write/read/wait,read
+short frame[ARB] # array of image frames
+short color[ARB] # array of color
+short offset # generalized offset or datum
+short n # count of items in data array
+short data[ARB] # data array
+
+begin
+ switch(device) {
+ case IDS_FRAME_LUT:
+ call iislut(rw, frame, color, offset, n, data)
+
+ case IDS_GR_MAP:
+ # for now, nothing
+
+ case IDS_INPUT_LUT:
+ call iisifm(rw, offset, n, data)
+
+ case IDS_OUTPUT_LUT:
+ call iisofm(rw, color, offset, n, data)
+
+ case IDS_SPLIT:
+ call iissplit(rw, n, data)
+
+ case IDS_SCROLL:
+ call iisscroll(rw, frame, n, data)
+
+ case IDS_ZOOM:
+ call iiszoom(rw, frame, n, data)
+
+ case IDS_OUT_OFFSET:
+ call iisoffset(rw, color, n, data)
+
+ case IDS_MIN:
+ call iismin(rw, color, n, data)
+
+ case IDS_MAX:
+ call iismax(rw, color, n, data)
+
+ case IDS_RANGE:
+ call iisrange(rw, color, n, data)
+
+ case IDS_HISTOGRAM:
+ call iishisto(rw, color, offset, n, data)
+
+ case IDS_ALU_FCN:
+ # for now, nothing
+
+ case IDS_FEEDBACK:
+ # for now, nothing
+
+ case IDS_SLAVE:
+ # for now, nothing
+
+ case IDS_CURSOR:
+ call iiscursor(rw, offset, n, data)
+
+ case IDS_TBALL:
+ call iistball(rw, data)
+
+ case IDS_DIGITIZER:
+ # for now, nothing
+
+ case IDS_BLINK:
+ # for now, nothing
+
+ case IDS_SNAP:
+ call zsnap_init(data[1])
+
+ case IDS_MATCH:
+ call iismatch (rw, frame, color, n, data)
+ }
+end
+
+
+# MAPCOLOR - modify the color array to map rgb for iis
+
+int procedure mapcolor(color)
+
+short color[ARB] # input data
+
+int i
+int val, result
+int or()
+
+begin
+ result = 0
+ for ( i = 1; color[i] != IDS_EOD ; i = i + 1 ) {
+ val = color[i]
+ switch (val) {
+ case IDS_RED:
+ val = RED
+
+ case IDS_GREEN:
+ val = GREEN
+
+ case IDS_BLUE:
+ val = BLUE
+
+ default:
+ val = 2**(val-1)
+ }
+ result = or (result, val)
+ }
+ return (result)
+end
diff --git a/pkg/images/tv/iis/iism70/zcursor_read.x b/pkg/images/tv/iis/iism70/zcursor_read.x
new file mode 100644
index 00000000..6de5bc8e
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zcursor_read.x
@@ -0,0 +1,96 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# ZCURSOR_READ -- Read cursor from display. This assumes that the cursor
+# is centered at (31,31)
+
+procedure zcursor_read (cnum, xcur, ycur, key)
+
+int cnum # cursor number
+int xcur, ycur # cursor position...GKI coordinates
+int key # key pressed
+
+short cursor[2] # local storage
+real x,y
+int frame
+real zm
+int mod(), and()
+define exit_ 10
+
+include "iis.com"
+
+begin
+ # Computations must be done in floating point when zoomed
+ # or values are off by a pixel. Also, want fractional
+ # pixel returned values in the zoomed case.
+
+ call iishdr(IREAD, 2, COMMAND+CURSOR, 1+ADVXONTC, 0,0,0)
+ call iisio (cursor, 2 * SZB_CHAR)
+
+ # which frame is the cursor relative to? We assume that cnum
+ # mod IDS_CSET refers to the image plane (graphics fits in
+ # here as an image plane for iism70), and cnum / IDS_CSET
+ # sets which cursor.
+ # If cursor is #0, then take lowest numbered frame that is
+ # being displayed.
+ # Return frame number as the "key".
+
+ if (cnum == 0) {
+ frame = i_frame_on
+ if ((frame == ERR) || (frame < 1) ) {
+ key = ERR
+ return
+ }
+ } else if (cnum != IDS_CRAW) {
+ frame = mod(cnum-1, IDS_CSET) + 1
+ } else {
+ zm = 1.
+ frame = 0 # return unusual frame num. if raw read
+ }
+
+ # deal with cursor offset--hardware fault sometimes adds extra
+ # bit, so chop it off with and().
+ x = mod (and (int(cursor[1]), 777B)+ 31, 512)
+ y = mod (and (int(cursor[2]), 777B)+ 31, 512)
+
+ if (cnum == IDS_CRAW)
+ goto exit_
+
+ # x,y now in device coordinates for screen but not world.
+ # next, we determine number of pixels from screen center.
+
+ zm = zoom[frame]
+ x = x/zm - IIS_XCEN./zm
+ y = y/zm - IIS_YCEN_INV./zm
+
+ # Now add in scroll offsets, which are to screen center.
+ x = x + xscroll[frame]
+
+ # Note that the Y one is inverted
+ y = y + (IIS_YDIM-1) - yscroll[frame]
+
+ if (x < 0)
+ x = x + IIS_XDIM
+ else if (x > IIS_XDIM)
+ x = x - IIS_XDIM
+
+ if (y < 0)
+ y = y + IIS_YDIM
+ else if (y > IIS_YDIM)
+ y = y - IIS_YDIM
+exit_
+ # invert y for user
+ y = (IIS_YDIM -1) - y
+
+ # The Y inversion really complicates things...
+ y = y + 1.0 - (1.0/zm)
+
+ # convert to GKI
+ xcur = x * MCXSCALE
+ ycur = y * MCYSCALE
+ key = frame
+end
diff --git a/pkg/images/tv/iis/iism70/zcursor_set.x b/pkg/images/tv/iis/iism70/zcursor_set.x
new file mode 100644
index 00000000..50b1d446
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zcursor_set.x
@@ -0,0 +1,100 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZCURSOR_SET -- Write cursor to display. This code assumes the standard
+# cursor which is centered on (31,31).
+
+procedure zcursor_set (cnum, xcur, ycur)
+
+int cnum # cursor number
+int xcur, ycur # GKI x,y cursor position
+
+short cursor[2] # local storage
+real x,y,zm
+int xedge
+int yedge, frame
+int mod()
+define output 10
+
+include "iis.com"
+
+begin
+ # which frame does cursor refer to? ( see zcursor_read() for
+ # more information. )
+
+ if (cnum == IDS_CRAW) {
+ x = real(xcur)/MCXSCALE
+ y = real(ycur)/MCYSCALE
+ zm = 1
+ xedge = 0
+ yedge = 0
+ goto output
+ }
+
+ if (cnum == 0) {
+ frame = i_frame_on
+ if ((frame == ERR) || (frame < 1))
+ return # WHAT SHOULD WE DO?
+ } else
+ frame = mod( cnum-1, IDS_CSET) + 1
+ zm = zoom[frame]
+
+ # Find the left/upper edge of the display
+ # xedge is real as we can't drop the fraction of IIS_XCEN/zm
+ # (This was true when XCEN was 255; now is 256 so can use int
+ # since 256 is a multiple of all possible values of zm.)
+
+ xedge = xscroll[frame] - IIS_XCEN/zm
+ if (xedge < 0)
+ xedge = xedge + IIS_XDIM
+ yedge = ( (IIS_YDIM-1) - yscroll[frame]) - int(IIS_YCEN_INV/zm)
+ if (yedge < 0)
+ yedge = yedge + IIS_YDIM
+
+ # xcur, ycur are in gki. Check if value too big...this will
+ # happen if NDC = 1.0, for instance which should be acceptable
+ # but will be "out of range".
+
+ x = real(xcur)/MCXSCALE
+ if ( x > (IIS_XDIM - 1.0/zm) )
+ x = IIS_XDIM - 1.0/zm
+ y = real(ycur)/MCYSCALE
+ if ( y > (IIS_YDIM - 1.0/zm) )
+ y = IIS_YDIM - 1.0/zm
+
+ # Invert y value to get device orientation; account for
+ # fractional pixels
+
+output
+ y = (IIS_YDIM - 1.0/zm) - y
+
+ # Account for the mod 512 nature of the display
+
+ if (x < xedge)
+ x = x + IIS_XDIM
+ if (y < yedge)
+ y = y + IIS_YDIM
+
+ # Are we still on screen ?
+
+ if ((x >= (xedge + IIS_XDIM/zm)) || (y >= (yedge + IIS_YDIM/zm)) ) {
+ call eprintf("cursor set off screen -- ignored\n")
+ return
+ }
+
+ # Calculate cursor positioning coordinates.
+
+ cursor[1] = int ((x-real(xedge)) * zm ) - 31
+ if ( cursor[1] < 0 )
+ cursor[1] = cursor[1] + IIS_XDIM
+ cursor[2] = int ((y-real(yedge)) * zm ) - 31
+ if ( cursor[2] < 0 )
+ cursor[2] = cursor[2] + IIS_YDIM
+
+ call iishdr (IWRITE+VRETRACE, 2, COMMAND+CURSOR, 1+ADVXONTC, 0,0,0)
+ call iisio (cursor, 2 * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/zdisplay_g.x b/pkg/images/tv/iis/iism70/zdisplay_g.x
new file mode 100644
index 00000000..21cf9e09
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zdisplay_g.x
@@ -0,0 +1,91 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+define INSERT 100000B
+
+# ZDISPLAY_G -- Display the referenced graphics bitplanes in the given color(s)
+
+procedure zdisplay_g (sw, bitpl, color, quad )
+
+short sw # on or off
+short bitpl[ARB] # bitpl list
+short color[ARB] # color list
+short quad[ARB] # quadrants to activate
+
+short gram[LEN_GRAM]
+bool off
+int i, lbound, val
+short mask[7]
+short fill
+# red a bit weak so have contrast with cursor
+#colors of graph: blue grn red yellow rd-bl gn-bl white
+data mask /37B, 1740B, 74000B, 77740B, 74037B, 1777B, 77777B/
+
+begin
+ if ( sw == IDS_OFF )
+ off = true
+ else {
+ off = false
+ }
+
+ # ignore bitpl argument since only one set of them and "color"
+ # fully specifies them.
+ # ignore quad for now
+ # much manipulation of color graphics ram table required!!
+ # strictly speaking, when we turn a plane off, we ought to be
+ # sure that any plane which is on, and "beneath", is turned on;
+ # this is a lot of trouble, so for starters, we don't.
+ # first find out what is on
+
+ call iishdr(IREAD+VRETRACE, LEN_GRAM, GRAPHICS, ADVXONTC, 0, 0, 0)
+ call iisio (gram, LEN_GRAM * SZB_CHAR)
+
+ # Check for red graphics plane for cursor
+
+ if ( gram[LEN_GRAM/2+1] != 176000B )
+ call amovks ( short(176000B), gram[LEN_GRAM/2+1], LEN_GRAM/2)
+
+ for ( i = 1 ; color[i] != IDS_EOD ; i = i + 1 ) {
+ # Bit plane 8 reserved for cursor
+ if ( color[i] > 7 )
+ next
+ # map IDS colors to IIS bit planes -- one-based.
+ switch (color[i]) {
+ case IDS_RED:
+ val = RD
+ case IDS_GREEN:
+ val = GR
+ case IDS_BLUE:
+ val = BLU
+ default:
+ val = color[i]
+ }
+ lbound = 2 ** (val - 1)
+ if ( off )
+ call aclrs ( gram[lbound+1], lbound)
+ else
+ call amovks ( short(INSERT+mask[val]), gram[lbound+1], lbound)
+ }
+ gram[1] = 0
+
+ # If a bit plane is off, reset it with next "lower" one, thus
+ # uncovering any planes masked by the one turned off.
+
+ if (off) {
+ fill = 0
+ do i = 2, LEN_GRAM/2 {
+ if (gram[i] == 0 )
+ gram[i] = fill
+ else
+ fill = gram[i]
+ }
+ }
+
+ # Write out the data
+
+ call iishdr(IWRITE+VRETRACE, LEN_GRAM, GRAPHICS, ADVXONTC, 0, 0, 0)
+ call iisio (gram, LEN_GRAM * SZB_CHAR)
+end
diff --git a/pkg/images/tv/iis/iism70/zdisplay_i.x b/pkg/images/tv/iis/iism70/zdisplay_i.x
new file mode 100644
index 00000000..e08db8c3
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zdisplay_i.x
@@ -0,0 +1,124 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZDISPLAY_I -- Display the referenced image planes in the given color(s)
+# and in the given quadrants of the screen.
+
+procedure zdisplay_i (sw, frames, color, quad)
+
+short sw # on or off
+short frames[ARB] # frame list
+short color[ARB] # color list
+short quad[ARB] # quadrant list
+
+
+bool off
+short channels
+short select[LEN_SELECT]
+int q,c,index, temp
+int mq # mapped quadrant
+int mapquad()
+short iispack()
+int and(), or(), xor()
+
+include "iis.com"
+include "../lib/ids.com" # for i_maxframes! only
+
+begin
+ if ( sw == IDS_ON ) {
+ off = false
+ } else
+ off = true
+
+ # first find out what is on
+ call iishdr(IREAD+VRETRACE, LEN_SELECT, COMMAND+LUT, ADVXONTC, 0,0,0)
+ call iisio (select, LEN_SELECT * SZB_CHAR)
+
+ # then add in/remove frames
+ channels = iispack(frames)
+
+ for ( q = 1 ; quad[q] != IDS_EOD ; q = q + 1 ) {
+ mq = mapquad(quad[q])
+ if ( ! off ) {
+ for ( c =1 ; color[c] != IDS_EOD ; c = c + 1 ) {
+ switch ( color[c] ) {
+ case IDS_RED:
+ index = mq + 8
+
+ case IDS_GREEN:
+ index = mq + 4
+
+ case IDS_BLUE:
+ index = mq
+ }
+ select[index] = or ( int(channels), int(select[index]) )
+ }
+ } else {
+ for ( c =1 ; color[c] != IDS_EOD ; c = c + 1 ) {
+ switch ( color[c] ) {
+ case IDS_RED:
+ index = mq + 8
+
+ case IDS_GREEN:
+ index = mq + 4
+
+ case IDS_BLUE:
+ index = mq
+ }
+ select[index] = and ( xor ( 177777B, int(channels)),
+ int(select[index]))
+ }
+ }
+ }
+
+ # Record which frame is being displayed for cursor readback.
+ temp = 0
+ do q = 1, LEN_SELECT
+ temp = or (temp, int(select[q]))
+
+ if ( temp == 0)
+ i_frame_on = ERR
+ else {
+ do q = 1, i_maxframes {
+ if (and (temp, 2**(q-1)) != 0) {
+ i_frame_on = q
+ break
+ }
+ }
+ }
+ call iishdr(IWRITE+VRETRACE, LEN_SELECT, COMMAND+LUT, ADVXONTC, 0,0,0)
+ call iisio (select, LEN_SELECT * SZB_CHAR)
+end
+
+
+# MAPQUAD -- map user quadrant to device ... returns ONE-based quadrant
+# if prefer ZERO-based, add one to "index" computation above.
+
+int procedure mapquad (quadrant)
+
+short quadrant
+
+int mq
+
+begin
+ switch ( quadrant ) {
+ case 1:
+ mq = 2
+
+ case 2:
+ mq = 1
+
+ case 3:
+ mq = 3
+
+ case 4:
+ mq = 4
+
+ default:
+ mq = 1 # should never happen
+ }
+ return (mq)
+end
diff --git a/pkg/images/tv/iis/iism70/zinit.x b/pkg/images/tv/iis/iism70/zinit.x
new file mode 100644
index 00000000..e03fd57c
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zinit.x
@@ -0,0 +1,45 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZINIT -- initialize for IIS operation
+# in general case, would use nfr and ngr to determine maximum file size
+# which would encompass all the images and graphics planes and all the
+# devices too. Then, file mapped i/o could move most of the device indep.
+# code to the reading and writing routines.
+# not done for IIS
+
+procedure zinit (nfr, ngr, filesize)
+
+short nfr # maximum number of image frames
+short ngr # maximum number of graphics bit planes
+long filesize # returned value
+
+short pl[IDS_MAXIMPL+2]
+short zm[4]
+
+include "../lib/ids.com"
+include "iis.com"
+
+begin
+ i_snap = false
+ # we have no place to store all the zoom and scroll information.
+ # so we initialize to zoom = 1 and scroll = center for all planes
+ pl[1] = IDS_EOD
+ call ids_expand(pl, i_maxframes, true)
+ zm[1] = 1
+ zm[2] = IIS_XCEN * MCXSCALE
+ zm[3] = IIS_YCEN * MCYSCALE
+ zm[4] = IDS_EOD
+ call iiszoom(short(IDS_WRITE), pl, short(4), zm)
+ call iisscroll(short(IDS_WRITE), pl, short(3), zm[2])
+
+ # We also need to set the i_frame_on variable (iis.com), which
+ # we do with a "trick": We call zdisplay_i with quad == EOD;
+ # this is a "nop" for the display code, but will set the variable.
+
+ call zdisplay_i (short(IDS_ON), short(IDS_EOD), short(IDS_EOD),
+ short(IDS_EOD))
+end
diff --git a/pkg/images/tv/iis/iism70/zopnim.x b/pkg/images/tv/iis/iism70/zopnim.x
new file mode 100644
index 00000000..25df2f21
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zopnim.x
@@ -0,0 +1,17 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# ZOPNIM -- Open an image display frame which is addressable as
+# a binary file.
+
+procedure zopnim (devinfo, mode, chan)
+
+char devinfo[ARB] # packed devinfo string
+int mode # access mode
+int chan
+
+int iischan[2] # Kludge
+
+begin
+ call iisopn (devinfo, mode, iischan)
+ chan = iischan[1]
+end
diff --git a/pkg/images/tv/iis/iism70/zreset.x b/pkg/images/tv/iis/iism70/zreset.x
new file mode 100644
index 00000000..3d067d04
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zreset.x
@@ -0,0 +1,164 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# cfactor is conversion from integer to NDC coordinates (max 32767) for cursor
+# see iiscursor.x
+# The "hardness" notion is now somewhat obsolete...a range of reset values
+# would be better, especially if better named.
+
+define CFACTOR 528
+
+# ZRESET -- reset IIS
+
+procedure zreset (hardness)
+
+short hardness # soft, medium, hard
+
+short data[LEN_IFM]
+short frames[IDS_MAXIMPL+1]
+short colors[IDS_MAXGCOLOR+1]
+short quad[5]
+int i,j
+
+include "iis.com"
+
+begin
+ if ( hardness == IDS_R_SNAPDONE ) {
+ call zsnap_done
+ return
+ }
+
+ # mark all frames
+ do i = 1,IDS_MAXIMPL
+ frames[i] = i
+ frames[IDS_MAXIMPL+1] = IDS_EOD
+ # mark all colors
+ do i = 1, IDS_MAXGCOLOR
+ colors[i] = i
+ colors[IDS_MAXGCOLOR+1] = IDS_EOD
+ # all quadrants
+ do i = 1,4
+ quad[i] = i
+ quad[5] = IDS_EOD
+
+ if ( hardness == IDS_R_SOFT) {
+ # all coordinates are NDC ( 0 - 32767 )
+ # Reseting the "soft" parameters: scroll, constant offsets,
+ # split point, alu, zoom; turn cursor and tball on.
+
+ # constants
+ call aclrs (data,3)
+ call iisoffset(short(IDS_WRITE), colors, short(3), data)
+
+ # range
+ data[1] = 1
+ call iisrange (short(IDS_WRITE), colors, short(1), data)
+
+ # split point
+ call aclrs ( data, 2)
+ call iissplit(short(IDS_WRITE), short(2), data)
+
+ # alu
+ data[1] = 0
+ call iishdr(IWRITE, 1, ALU+COMMAND, 0, 0, 0, 0)
+ call iisio (data, 1 * SZB_CHAR)
+
+ # graphics status register
+ data[1] = 0
+ call iishdr(IWRITE, 1, GRAPHICS+COMMAND, 0, 0, 0, 0)
+ call iisio (data, 1 * SZB_CHAR)
+
+ # zoom
+ data[1] = 1
+ data[2] = IIS_XCEN * MCXSCALE # gki mid point
+ data[3] = IIS_YCEN * MCYSCALE
+ data[4] = IDS_EOD
+ call iiszoom(short(IDS_WRITE), frames, short(4), data)
+
+ # scroll -- screen center to be centered
+ # zoom does affect scroll if zoom not power==1
+ # so to be safe, do scroll after zoom.
+ data[1] = IIS_XCEN * MCXSCALE
+ data[2] = IIS_YCEN * MCYSCALE
+ data[3] = IDS_EOD
+ call iisscroll(short(IDS_WRITE), frames, short(3), data)
+
+ # cursor and tball; no blink for cursor
+ data[1] = IDS_ON
+ call iiscursor(short(IDS_WRITE), short(1), short(1), data)
+ call iistball (short(IDS_WRITE), data)
+ data[1] = IDS_CBLINK
+ data[2] = IDS_CSTEADY
+ call iiscursor(short(IDS_WRITE), short(1), short(1), data)
+
+ # standard cursor shape
+ data[1] = IDS_CSHAPE
+ j = 2
+ # don't use last line/column so have a real center
+ for ( i = 0 ; i <= 62 ; i = i + 1 ) {
+ # make the puka in the middle
+ if ( (i == 30) || (i == 31) || (i == 32) )
+ next
+ # fill in the lines
+ data[j] = 31 * CFACTOR
+ data[j+1] = i * CFACTOR
+ j = j + 2
+ data[j] = i * CFACTOR
+ data[j+1] = 31 * CFACTOR
+ j = j + 2
+ }
+ data[j] = IDS_EOD
+ call iiscursor ( short(IDS_WRITE), short(1), short(j), data)
+
+ return
+ }
+
+ if ( hardness == IDS_R_MEDIUM) {
+ # reset all tables to linear--ofm, luts, ifm
+ # ofm (0,0) to (0.25,1.0) to (1.0,1.0)
+ data[1] = 0
+ data[2] = 0
+ data[3] = 0.25 * GKI_MAXNDC
+ data[4] = GKI_MAXNDC
+ data[5] = GKI_MAXNDC
+ data[6] = GKI_MAXNDC
+ call iisofm(short(IDS_WRITE), colors, short(1), short(6), data)
+
+ # luts
+ data[1] = 0
+ data[2] = 0
+ data[3] = GKI_MAXNDC
+ data[4] = GKI_MAXNDC
+ call iislut(short(IDS_WRITE), frames, colors, short(1),
+ short(4), data)
+
+ # ifm (0,0) to (1/32, 1.0) to (1.,1.)
+ # ifm is length 8192, but output is only 255. So map linearly for
+ # first 256, then flat. Other possibility is ifm[i] = i-1 ( for
+ # i = 1,8192) which relies on hardware dropping high bits.
+
+ data[1] = 0
+ data[2] = 0
+ data[3] = (1./32.) * GKI_MAXNDC
+ data[4] = GKI_MAXNDC
+ data[5] = GKI_MAXNDC
+ data[6] = GKI_MAXNDC
+ call iisifm(short(IDS_WRITE), short(1), short(6), data)
+
+ return
+ }
+
+ if (hardness == IDS_R_HARD) {
+ # clear all image/graph planes, and set channel selects to
+ # mono
+ call zclear(frames, frames, true)
+ call zclear(frames, frames, false)
+ # reset all to no display
+ call zdisplay_i(short(IDS_OFF), frames, colors, quad)
+ call zdisplay_g(short(IDS_OFF), frames, colors, quad)
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/zrestore.x b/pkg/images/tv/iis/iism70/zrestore.x
new file mode 100644
index 00000000..ed478a20
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zrestore.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# restore device, image, graphics data
+
+procedure zdev_restore(fd)
+
+int fd # file descriptor to read from
+
+begin
+end
+
+procedure zim_restore(fd, frame)
+
+int fd
+short frame[ARB] # frame numbers to restore
+
+begin
+end
+
+procedure zgr_restore(fd, plane)
+
+int fd
+short plane[ARB]
+
+begin
+end
diff --git a/pkg/images/tv/iis/iism70/zsave.x b/pkg/images/tv/iis/iism70/zsave.x
new file mode 100644
index 00000000..666f1b1f
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsave.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# save device, image, graphics data
+
+procedure zdev_save(fd)
+
+int fd # file descriptor to write to
+
+begin
+end
+
+procedure zim_save(fd, frame)
+
+int fd
+short frame[ARB] # frame numbers to save
+
+begin
+end
+
+procedure zgr_save(fd, plane)
+
+int fd
+short plane[ARB]
+
+begin
+end
diff --git a/pkg/images/tv/iis/iism70/zseek.x b/pkg/images/tv/iis/iism70/zseek.x
new file mode 100644
index 00000000..6f3fed25
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zseek.x
@@ -0,0 +1,21 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZSEEK -- Seek for an image frame
+
+procedure zseek (fd, x, y)
+
+int fd # file to write
+int x, y # device coordinates
+
+long offset
+
+begin
+ offset = max (1, 1 + (x + y * IIS_XDIM) * SZ_SHORT)
+
+ call seek (fd, offset)
+end
diff --git a/pkg/images/tv/iis/iism70/zsetup.x b/pkg/images/tv/iis/iism70/zsetup.x
new file mode 100644
index 00000000..0803ac3a
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsetup.x
@@ -0,0 +1,34 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include "../lib/ids.h"
+include "iis.h"
+
+# ZSETUP -- Setup up common block information for read/write
+
+procedure zsetup (frame, bitpl, flag)
+
+short frame[ARB] # frame information
+short bitpl[ARB] # bitplane information
+bool flag # true if image, false if graphics
+
+short iispack()
+int mapcolor()
+
+include "iis.com"
+include "../lib/ids.com"
+
+begin
+ # If don't flush, then last line of "previous" frame
+ # may get steered to wrong image plane
+ call flush (i_out)
+ call fseti (i_out, F_CANCEL, OK)
+ if ( flag ) {
+ iframe = iispack ( frame )
+ iplane = iispack ( bitpl )
+ } else {
+ iframe = GRCHAN
+ iplane = mapcolor( bitpl )
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/zsnap.com b/pkg/images/tv/iis/iism70/zsnap.com
new file mode 100644
index 00000000..8dd6796c
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsnap.com
@@ -0,0 +1,26 @@
+# snap common block
+int sn_fd # device file descriptor
+int sn_frame, sn_bitpl # save current iframe, iplane
+int zbufsize # fio buffer size--save here
+pointer lutp[3,LEN_IISFRAMES] # look up table storage
+pointer ofmp[3] # rgb ofm tables
+pointer grp[3] # graphics tables
+pointer result[3] # rgb results
+pointer answer # final answer
+pointer input # input data
+pointer zs # zoom/scrolled data; scratch
+pointer grbit_on # graphics bit on
+bool gr_in_use # graphics RAM not all zeroes
+bool on[LEN_IISFRAMES] # if frames on at all
+bool multi_frame # snap using >1 frame
+short range[3] # range and offset for rgb
+short offset[3]
+short left[3,2,LEN_IISFRAMES] # left boundary of line
+short right[3,2,LEN_IISFRAMES] # right boundary of line
+short ysplit # split point for y
+short prev_y # previous line read
+short sn_start, sn_end # color range to snap
+
+common / zsnap / sn_fd, sn_frame, sn_bitpl, zbufsize, lutp, ofmp, grp,
+ result, answer, input, zs, grbit_on, gr_in_use, on, multi_frame,
+ range, offset, left, right, ysplit, prev_y, sn_start, sn_end
diff --git a/pkg/images/tv/iis/iism70/zsnap.x b/pkg/images/tv/iis/iism70/zsnap.x
new file mode 100644
index 00000000..c0f9b230
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsnap.x
@@ -0,0 +1,239 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include "iis.h"
+include "../lib/ids.h"
+
+# DO_SNAP -- Return a line of the active image display, as seen
+# by the viewer.
+
+procedure do_snap (buf, nchar, xpos, ypos)
+
+short buf[ARB] # buffer to read into
+int nchar # how many to read
+int xpos, ypos # and from where
+
+int y, yindex, xs, xe
+int line, previous
+int i,j
+int yedge
+int zm, count
+bool first
+
+include "../lib/ids.com"
+include "iis.com"
+include "zsnap.com"
+
+begin
+ # Check if read is for one line only
+
+ if (nchar > IIS_XDIM) {
+ call eprintf("ZSNAP -- too many pixels (%d) requested.\n")
+ call pargi (nchar)
+ call aclrs (buf, nchar)
+ return
+ }
+
+ # Determine x and y coordinates on screen.
+
+ y = IIS_YDIM - 1 - ypos
+ xs = xpos
+ xe = xs + nchar - 1
+ count = nchar
+
+ # See if we are dealing with (a part of only) one line
+
+ if (xe >= IIS_XDIM) {
+ call eprintf("ZSNAP -- line overlap error (xend is %d).\n")
+ call pargi (xe)
+ call aclrs (buf, nchar)
+ return
+ }
+
+ # Determine whether above or below split point.
+
+ if (y < ysplit)
+ yindex = 1
+ else
+ yindex = 2
+
+ # Clear accumulators
+
+ do j = sn_start, sn_end
+ call aclrs (Mems[result[j]], IIS_XDIM)
+
+ # Fetch and massage data for each active frame
+
+ first = true
+ previous = -1 # a bit of safety if no frames on
+ do i = 1, i_maxframes {
+ if (on[i]) {
+ # If frame not active in any color for this half of screen,
+ # ignore it
+ if (sn_start != sn_end) {
+ if ((left[BLU, yindex, i] == -1) &&
+ (left[GR , yindex, i] == -1) &&
+ (left[RD , yindex, i] == -1) )
+ next
+ } else if (left[sn_start, yindex, i] == -1)
+ next
+
+ zm = zoom[i]
+ iplane = 377B # all bit planes
+ iframe = 2**(i-1)
+
+ # y edge of frame (top) [ see zcursor_set for more information]
+ yedge = IIS_YCEN - yscroll[i] + IIS_YCEN_INV - IIS_YCEN_INV/zm
+ if (yedge < 0)
+ yedge = yedge + IIS_YDIM
+
+ # Desired y (screen) coordinate
+ line = yedge + y/zm
+ if (line >= IIS_YDIM)
+ line = line - IIS_YDIM
+ # If have done this line before, just return the same answer
+
+ if (first) {
+ if (line == prev_y) {
+ call amovs (Mems[answer], buf, nchar)
+ return
+ }
+ previous = line
+ first = false
+ }
+
+ # Turn line into file position.
+ line = IIS_YDIM - 1 - line
+ if (multi_frame)
+ call fseti (sn_fd, F_CANCEL, OK)
+ call zseek (sn_fd, xs, line)
+ call read (sn_fd, Mems[input], count)
+ call zmassage (zm, xscroll[i], yindex, i, xs, xe)
+ }
+ }
+
+ # Apply scaling
+
+ do j = sn_start, sn_end {
+ # Note...xs, xe are zero-based indices
+ if ( offset[j] != 0)
+ call aaddks (Mems[result[j]+xs], offset[j],
+ Mems[result[j]+xs], count)
+ if ( range[j] != 1)
+ call adivks (Mems[result[j]+xs], range[j],
+ Mems[result[j]+xs], count)
+ call aluts (Mems[result[j]+xs], Mems[result[j]+xs], count,
+ Mems[ofmp[j]])
+ }
+
+ # Or in the graphics ... use of "select" (asel) depends on design
+ # decision in zdisplay_g.x
+
+ if (gr_in_use) {
+ iframe = GRCHAN
+ iplane = 177B # ignore cursor plane
+ zm = zoom[GRCHNUM]
+
+ yedge = IIS_YCEN - yscroll[GRCHNUM] + IIS_YCEN_INV - IIS_YCEN_INV/zm
+ if (yedge < 0)
+ yedge = yedge + IIS_YDIM
+
+ line = yedge + y/zm
+ if (line >= IIS_YDIM)
+ line = line - IIS_YDIM
+ line = IIS_YDIM - 1 - line
+
+ if (multi_frame)
+ call fseti (sn_fd, F_CANCEL, OK)
+
+ call zseek (sn_fd, xs, line)
+ call read (sn_fd, Mems[input], count)
+ call zmassage (zm, xscroll[GRCHNUM], yindex, GRCHNUM, xs, xe)
+
+ do j = sn_start, sn_end {
+ call aluts (Mems[input+xs], Mems[zs], count, Mems[grp[j]])
+
+ # Build boolean which says if have graphics on
+ call abneks (Mems[zs], short(0), Memi[grbit_on], count)
+
+ # With INSERT on: replace data with graphics.
+ call asels (Mems[zs], Mems[result[j]+xs], Mems[result[j]+xs],
+ Memi[grbit_on], count)
+ }
+ }
+
+ # The answer is:
+
+ if (sn_start != sn_end) {
+ call aadds (Mems[result[BLU]], Mems[result[GR]],
+ Mems[answer], IIS_XDIM)
+ call aadds (Mems[answer], Mems[result[RD]], Mems[answer], IIS_XDIM)
+ call adivks (Mems[answer], short(3), Mems[answer], IIS_XDIM)
+ } else {
+ # Put in "answer" so repeated lines are in known location
+ call amovs (Mems[result[sn_start]], Mems[answer], nchar)
+ }
+
+ # Set the previous line and return the answer
+
+ prev_y = previous
+ call amovs (Mems[answer], buf, nchar)
+end
+
+
+# ZMASSAGE --- do all the boring massaging of the data: zoom, scroll, look
+# up tables.
+
+procedure zmassage (zm, xscr, yi, i, xstart, xend)
+
+int zm # zoom factor
+short xscr # x scroll
+int yi # y-index
+int i # frame index
+int xstart, xend # indices for line start and end
+
+int lb, count # left bound, count of number of items
+int j, x1, x2, itemp
+include "zsnap.com"
+
+begin
+ if ( (xscr != IIS_XCEN) || (zm != 1)) {
+ if (xscr == IIS_XCEN)
+ # Scrolling not needed
+ call amovs (Mems[input], Mems[zs], IIS_XDIM)
+ else {
+ # Scroll the data
+ lb = xscr - IIS_XCEN
+ if ( lb < 0 )
+ lb = lb + IIS_XDIM
+ count = IIS_XDIM - lb
+ call amovs (Mems[input+lb], Mems[zs], count)
+ call amovs (Mems[input], Mems[zs+count], lb)
+ }
+ # Now zoom it
+ if (zm == 1)
+ call amovs (Mems[zs], Mems[input], IIS_XDIM)
+ else
+ call ids_blockit (Mems[zs+IIS_XCEN-IIS_XCEN/zm], Mems[input],
+ IIS_XDIM, real(zm))
+ }
+
+ if (i == GRCHNUM)
+ return
+
+ # With the aligned data, perform the lookup. Note that left is
+ # 0 based, right is (0-based) first excluded value.
+
+ do j = sn_start, sn_end {
+ if (left[j, yi, i] == -1)
+ next
+ itemp = left[j,yi,i]
+ x1 = max (itemp, xstart)
+ itemp = right[j,yi,i]
+ x2 = min (itemp - 1, xend)
+ call aluts (Mems[input+x1], Mems[zs], x2-x1+1, Mems[lutp[j,i]])
+ call aadds (Mems[zs], Mems[result[j]+x1], Mems[result[j]+x1],
+ x2-x1+1)
+ }
+end
diff --git a/pkg/images/tv/iis/iism70/zsnapinit.x b/pkg/images/tv/iis/iism70/zsnapinit.x
new file mode 100644
index 00000000..48ed083c
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsnapinit.x
@@ -0,0 +1,314 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <fset.h>
+include "iis.h"
+include "../lib/ids.h"
+
+define XSPLIT LEN_SELECT+1
+define YSPLIT LEN_SELECT+2
+
+# ZSNAP_INIT -- initialize snap data structures.
+
+procedure zsnap_init(kind)
+
+short kind
+
+pointer ptr
+short gram[LEN_GRAM]
+short select[LEN_SELECT+2] # include split points
+short color[4]
+short frame[2]
+short cds, off, num
+short xsplit, x_right
+
+int i, j, k, temp
+int khp, val, frame_count
+bool used, mono
+int and(), or(), fstati()
+
+include "zsnap.com"
+include "iis.com"
+include "../lib/ids.com"
+
+begin
+ i_snap = true
+ sn_frame = iframe
+ sn_bitpl = iplane
+ sn_fd = i_out
+ call flush(sn_fd)
+ call fseti(sn_fd, F_CANCEL, OK)
+ prev_y = -1
+
+ # Determine what snap range to do
+ if (kind == IDS_SNAP_MONO)
+ mono= true
+ else
+ mono = false
+
+ switch (kind) {
+ case IDS_SNAP_RGB:
+ # Note: BLU < RD and covers full color range
+ sn_start = BLU
+ sn_end = RD
+
+ case IDS_SNAP_MONO, IDS_SNAP_BLUE:
+ sn_start = BLU
+ sn_end = BLU
+
+ case IDS_SNAP_GREEN:
+ sn_start = GR
+ sn_end = GR
+
+ case IDS_SNAP_RED:
+ sn_start = RD
+ sn_end = RD
+ }
+
+ # Find out which planes are active -- any quadrant
+
+ call iishdr (IREAD, LEN_SELECT+2, COMMAND+LUT, ADVXONTC, 0, 0, 0)
+ call iisio (select, (LEN_SELECT+2)*SZB_CHAR)
+
+ # record split point. Adjust x_split so 511 becomes
+ # 512. This is so the "right" side of a quadrant is given by one
+ # plus the last used point.
+
+ ysplit = select[YSPLIT]
+ xsplit = select[XSPLIT]
+ x_right = xsplit
+ if (x_right == IIS_XDIM-1)
+ x_right = IIS_XDIM
+
+
+ # For certain split positions, some quadrants don't appear at all.
+
+ if (xsplit == 0)
+ call nullquad (0, 2, select)
+ else if (xsplit == IIS_XDIM-1)
+ call nullquad (1, 3, select)
+ if (ysplit == 0)
+ call nullquad (0, 1, select)
+ else if (ysplit == IIS_YDIM-1)
+ call nullquad (2, 3, select)
+
+ # Which frames are active, in any quadrant?
+
+ temp = 0
+ do i = 1, LEN_SELECT
+ temp = or (temp, int(select[i]))
+ do i = 1, i_maxframes {
+ if ( and (temp, 2**(i-1)) != 0)
+ on[i] = true
+ else
+ on[i] = false
+ }
+
+ # Find out where each active plane starts and stops. Split points
+ # are screen coordinates, not picture coordinates. Graphics does
+ # not split (!). left coord is inclusive, right is one beyond end.
+ # left/right dimensions: color, above/below_ysplit, image_plane.
+ # Frame_count counts frames in use. Could be clever and only count
+ # active frames whose pixels are on the screen (pan/zoom effects).
+
+ frame_count = 0
+ do i = 1, i_maxframes {
+ if ( !on[i] )
+ next
+ else
+ frame_count = frame_count + 1
+ do j = sn_start, sn_end { # implicit BLUE (GREEN RED)
+ # quadrants for IIS are UL:0, UR:1, LL:2, LR:3
+ do k = 0, 3 {
+ temp = select[(j-1)*4 + k + 1]
+ used = (and(temp, 2**(i-1)) != 0)
+ khp = k/2 + 1
+ switch (k) {
+ case 0, 2:
+ if (used) {
+ left[j,khp,i] = 0
+ right[j,khp,i] = x_right
+ } else {
+ left[j,khp,i] = -1
+ }
+
+ case 1, 3:
+ if (used) {
+ if ( left[j,khp,i] == -1)
+ left[j,khp,i] = xsplit
+ right[j,khp,i] = IIS_XDIM
+ }
+ } # end switch
+ } # end k ( quad loop)
+ } # end j ( color loop)
+ } # end i ( frame loop)
+
+ # now do range and offset
+
+ cds = IDS_READ
+ num = 3
+ color[1] = IDS_BLUE
+ color[2] = IDS_GREEN
+ color[3] = IDS_RED
+ color[4] = IDS_EOD
+ call iisrange(cds, color, num, range)
+ call iisoffset(cds, color, num, offset)
+ do i = sn_start, sn_end
+ range[i] = 2**range[i]
+
+ # now allocate memory for all the various tables
+
+ call malloc (input, IIS_XDIM, TY_SHORT)
+ call malloc (answer, IIS_XDIM, TY_SHORT)
+ call malloc (zs, IIS_XDIM, TY_SHORT)
+ # for each color:
+ do j = sn_start, sn_end {
+ call malloc (result[j], IIS_XDIM, TY_SHORT)
+ call malloc (ofmp[j], LEN_OFM, TY_SHORT)
+ call malloc (grp[j], LEN_GRAM/2, TY_SHORT)
+ do i = 1, i_maxframes {
+ if ( on[i] )
+ call malloc (lutp[j,i], LEN_LUT, TY_SHORT)
+ }
+ }
+ call malloc (grbit_on, IIS_XDIM, TY_INT)
+
+ # fill these up
+
+ cds = IDS_READ
+ off = 1
+ frame[2] = IDS_EOD
+ color[2] = IDS_EOD
+ do j = sn_start, sn_end {
+ if (j == BLU)
+ color[1] = IDS_BLUE
+ else if ( j == GR)
+ color[1] = IDS_GREEN
+ else
+ color[1] = IDS_RED
+ num = LEN_OFM
+ call iisofm (cds, color, off, num, Mems[ofmp[j]])
+ do i = 1, i_maxframes {
+ if (on[i]) {
+ frame[1] = i
+ num = LEN_LUT
+ call iislut (cds, frame, color, off, num, Mems[lutp[j,i]])
+ }
+ }
+ }
+
+ # the graphics planes ... assume insert mode!!
+ # Note if any graphics mapping ram is in use...if no graphics on,
+ # snap can run faster.
+
+ call iishdr (IREAD, LEN_GRAM, GRAPHICS, ADVXONTC, 0, 0, 0)
+ call iisio (gram, LEN_GRAM * SZB_CHAR)
+
+ gr_in_use = false
+ do j = sn_start, sn_end
+ call aclrs(Mems[grp[j]], LEN_GRAM/2)
+ # Leave first one 0; don't mess with cursor plane
+ do i = 2, LEN_GRAM/2 {
+ temp = and (77777B, int(gram[i]))
+ if (temp != 0)
+ gr_in_use = true
+ if (! mono) {
+ do j = sn_start, sn_end
+ switch (j) {
+ case RD:
+ Mems[grp[RD]+i-1] = and (temp,76000B)/32
+ case GR:
+ Mems[grp[GR]+i-1] = and (temp, 1740B)
+ case BLU:
+ Mems[grp[BLU]+i-1] = and (temp, 37B)*32
+ }
+ } else {
+ # All graphics planes
+ val = or ( and (temp, 76000B)/32, and (temp, 1740B))
+ val = or ( and (temp, 37B)*32, val)
+ Mems[grp[sn_start]+i-1] = val
+ }
+ }
+
+ if (gr_in_use)
+ frame_count = frame_count + 1
+ if (frame_count > 1) {
+ multi_frame = true
+ # set buffer to size of one line
+ zbufsize = fstati (sn_fd, F_BUFSIZE)
+ call fseti (sn_fd, F_BUFSIZE, IIS_XDIM)
+ } else
+ multi_frame = false
+
+ # Now adjust look up tables for fact that they do 9 bit 2's complement
+ # arithmetic!
+ do j = sn_start, sn_end {
+ do i = 1, i_maxframes {
+ if (on[i]) {
+ ptr = lutp[j,i]
+ do k = 1, LEN_LUT {
+ if (Mems[ptr+k-1] > 255 )
+ Mems[ptr+k-1] = Mems[ptr+k-1] - 512
+ }
+ }
+ }
+ }
+end
+
+
+# NULLQUAD -- zero out lut mapping for quadrants that cannot appear on
+# screen
+
+procedure nullquad (q, p, sel)
+
+int q, p # two quadrants to eliminate, zero based
+short sel[ARB] # the mapping array
+
+int i
+
+begin
+ do i = 0,2 {
+ sel[i*4 + q + 1] = 0
+ sel[i*4 + p + 1] = 0
+ }
+end
+
+
+# ZSNAP_DONE -- reset paramters
+
+procedure zsnap_done()
+
+int i,j
+
+include "iis.com"
+include "zsnap.com"
+include "../lib/ids.com"
+
+begin
+ if ( ! i_snap )
+ return
+ i_snap = false
+ call fseti(sn_fd, F_CANCEL, OK)
+ if (multi_frame) {
+ # restore buffering
+ call fseti (sn_fd, F_BUFSIZE, zbufsize)
+ }
+ iframe = sn_frame
+ iplane = sn_bitpl
+
+ # release storage
+ call mfree (grbit_on, TY_INT)
+ do j = sn_start, sn_end {
+ call mfree (result[j], TY_SHORT)
+ call mfree (ofmp[j], TY_SHORT)
+ call mfree (grp[j], TY_SHORT)
+ do i = 1, i_maxframes {
+ if ( on[i] )
+ call mfree (lutp[j,i], TY_SHORT)
+ }
+ }
+
+ call mfree (zs, TY_SHORT)
+ call mfree (answer, TY_SHORT)
+ call mfree (input, TY_SHORT)
+end
diff --git a/pkg/images/tv/iis/iism70/zsttim.x b/pkg/images/tv/iis/iism70/zsttim.x
new file mode 100644
index 00000000..2f441ed7
--- /dev/null
+++ b/pkg/images/tv/iis/iism70/zsttim.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <knet.h>
+
+# ZSTTIM -- Return status on binary file display device.
+
+procedure zsttim (chan, what, lvalue)
+
+int chan[ARB], what
+long lvalue
+
+begin
+ call zsttgd (chan, what, lvalue)
+end
diff --git a/pkg/images/tv/iis/lib/ids.com b/pkg/images/tv/iis/lib/ids.com
new file mode 100644
index 00000000..cd6bc086
--- /dev/null
+++ b/pkg/images/tv/iis/lib/ids.com
@@ -0,0 +1,25 @@
+# IDS common. A common is necessary since there is no graphics descriptor
+# in the argument list of the kernel procedures. The data structures
+# are designed along the lines of FIO: a small common is used to hold the time
+# critical data elements, and an auxiliary dynamically allocated descriptor is
+# used for everything else.
+
+pointer i_kt # kernel image display descriptor
+pointer i_tty # graphcap descriptor
+int i_in, i_out # input file, output file
+int i_xres, i_yres # desired device resolution
+long i_frsize # frame size in chars
+short i_maxframes, i_maxgraph # max num. of image frames, gr. planes
+int i_linemask # current linemask
+int i_linewidth # current line width
+int i_linecolor # current line color
+short i_pt_x, i_pt_y # current plot point, device coords
+int i_csize # text character size
+int i_font # text font
+bool i_snap # true if a snap in progress
+bool i_image # frame/bitplane data is for image
+char i_device[SZ_IDEVICE] # force output to named device
+
+common /idscom/ i_kt, i_tty, i_in, i_out, i_xres, i_yres, i_frsize,
+ i_maxframes, i_maxgraph, i_linemask, i_linewidth, i_linecolor,
+ i_pt_x, i_pt_y, i_csize, i_font, i_snap, i_image, i_device
diff --git a/pkg/images/tv/iis/lib/ids.h b/pkg/images/tv/iis/lib/ids.h
new file mode 100644
index 00000000..bbf36392
--- /dev/null
+++ b/pkg/images/tv/iis/lib/ids.h
@@ -0,0 +1,175 @@
+# IDS definitions.
+
+define MAX_CHARSIZES 10 # max discreet device char sizes
+define SZ_SBUF 1024 # initial string buffer size
+define SZ_IDEVICE 31 # maxsize forced device name
+
+# The IDS state/device descriptor.
+
+define LEN_IDS 81
+
+define IDS_SBUF Memi[$1] # string buffer
+define IDS_SZSBUF Memi[$1+1] # size of string buffer
+define IDS_NEXTCH Memi[$1+2] # next char pos in string buf
+define IDS_NCHARSIZES Memi[$1+3] # number of character sizes
+define IDS_POLYLINE Memi[$1+4] # device supports polyline
+define IDS_POLYMARKER Memi[$1+5] # device supports polymarker
+define IDS_FILLAREA Memi[$1+6] # device supports fillarea
+define IDS_CELLARRAY Memi[$1+7] # device supports cell array
+define IDS_ZRES Memi[$1+8] # device resolution in Z
+define IDS_FILLSTYLE Memi[$1+9] # number of fill styles
+define IDS_ROAM Memi[$1+10] # device supports roam
+define IDS_CANZM Memi[$1+11] # device supports zoom
+define IDS_SELERASE Memi[$1+12] # device has selective erase
+define IDS_FRAME Memi[$1+13] # pointer to frames area
+define IDS_BITPL Memi[$1+14] # pointer to bitplane area
+ # extra space
+define IDS_FRCOLOR Memi[$1+18] # frame color
+define IDS_GRCOLOR Memi[$1+19] # graphics color
+define IDS_LCURSOR Memi[$1+20] # last cursor accessed
+define IDS_COLOR Memi[$1+21] # last color set
+define IDS_TXSIZE Memi[$1+22] # last text size set
+define IDS_TXFONT Memi[$1+23] # last text font set
+define IDS_TYPE Memi[$1+24] # last line type set
+define IDS_WIDTH Memi[$1+25] # last line width set
+define IDS_DEVNAME Memi[$1+26] # name of open device
+define IDS_CHARHEIGHT Memi[$1+30+$2-1] # character height
+define IDS_CHARWIDTH Memi[$1+40+$2-1] # character width
+define IDS_CHARSIZE Memr[P2R($1+50+$2-1)] # text sizes permitted
+define IDS_PLAP ($1+60) # polyline attributes
+define IDS_PMAP ($1+64) # polymarker attributes
+define IDS_FAAP ($1+68) # fill area attributes
+define IDS_TXAP ($1+71) # default text attributes
+
+# Substructure definitions.
+
+define LEN_PL 4
+define PL_STATE Memi[$1] # polyline attributes
+define PL_LTYPE Memi[$1+1]
+define PL_WIDTH Memi[$1+2]
+define PL_COLOR Memi[$1+3]
+
+define LEN_PM 4
+define PM_STATE Memi[$1] # polymarker attributes
+define PM_LTYPE Memi[$1+1]
+define PM_WIDTH Memi[$1+2]
+define PM_COLOR Memi[$1+3]
+
+define LEN_FA 3 # fill area attributes
+define FA_STATE Memi[$1]
+define FA_STYLE Memi[$1+1]
+define FA_COLOR Memi[$1+2]
+
+define LEN_TX 10 # text attributes
+define TX_STATE Memi[$1]
+define TX_UP Memi[$1+1]
+define TX_SIZE Memi[$1+2]
+define TX_PATH Memi[$1+3]
+define TX_SPACING Memr[P2R($1+4)]
+define TX_HJUSTIFY Memi[$1+5]
+define TX_VJUSTIFY Memi[$1+6]
+define TX_FONT Memi[$1+7]
+define TX_QUALITY Memi[$1+8]
+define TX_COLOR Memi[$1+9]
+
+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 # auxillary 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
diff --git a/pkg/images/tv/iis/lumatch.cl b/pkg/images/tv/iis/lumatch.cl
new file mode 100644
index 00000000..1890152b
--- /dev/null
+++ b/pkg/images/tv/iis/lumatch.cl
@@ -0,0 +1,8 @@
+#{ LUMATCH -- Match the lookup tables for two frames.
+
+# frame,i,a,,1,4,frame to be adjusted
+# ref_frame,i,a,,1,4,reference frame
+
+{
+ _dcontrol (frame=frame, alternate=ref_frame, match=yes)
+}
diff --git a/pkg/images/tv/iis/lumatch.par b/pkg/images/tv/iis/lumatch.par
new file mode 100644
index 00000000..60e3b7b3
--- /dev/null
+++ b/pkg/images/tv/iis/lumatch.par
@@ -0,0 +1,2 @@
+frame,i,a,,1,4,frame to be adjusted
+ref_frame,i,a,,1,4,frame to be matched
diff --git a/pkg/images/tv/iis/mkpkg b/pkg/images/tv/iis/mkpkg
new file mode 100644
index 00000000..7b45b437
--- /dev/null
+++ b/pkg/images/tv/iis/mkpkg
@@ -0,0 +1,25 @@
+# Make the CV (Control Video) display load and control package.
+
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $update libpkg.a
+ $omake x_iis.x
+ $link x_iis.o libpkg.a -o xx_iis.e
+ ;
+
+install:
+ $move xx_iis.e bin$x_iis.e
+ ;
+
+libpkg.a:
+ @ids
+ @iism70
+ @src
+ ;
diff --git a/pkg/images/tv/iis/monochrome.cl b/pkg/images/tv/iis/monochrome.cl
new file mode 100644
index 00000000..91de948f
--- /dev/null
+++ b/pkg/images/tv/iis/monochrome.cl
@@ -0,0 +1,5 @@
+#{ MONOCHROME -- Set monochrome enhancement on display.
+
+{
+ _dcontrol (map="mono")
+}
diff --git a/pkg/images/tv/iis/pseudocolor.cl b/pkg/images/tv/iis/pseudocolor.cl
new file mode 100644
index 00000000..74d66a82
--- /dev/null
+++ b/pkg/images/tv/iis/pseudocolor.cl
@@ -0,0 +1,24 @@
+#{ PSEUDOCOLOR -- Select pseudocolor enhancement.
+
+# enhancement,s,a,linear,,,"type of pseudocolor enhancement:\n\
+# linear - map greyscale into a spectrum\n\
+# random - one randomly chosen color is assigned each greylevel\n\
+# 8color - eight random colors\n\
+# enter selection"
+# window,b,h,yes,,,window display after enabling pseudocolor
+# enhance,s,h
+
+{
+ # Query for enchancement and copy into local param, otherwise each
+ # reference will cause a query.
+ enhance = enhancement
+
+ if (enhance == "linear")
+ _dcontrol (map = "linear", window=window)
+ else if (enhance == "random")
+ _dcontrol (map = "random", window=window)
+ else if (enhance == "8color")
+ _dcontrol (map = "8color", window=window)
+ else
+ error (0, "unknown enhancement")
+}
diff --git a/pkg/images/tv/iis/pseudocolor.par b/pkg/images/tv/iis/pseudocolor.par
new file mode 100644
index 00000000..e99d8d80
--- /dev/null
+++ b/pkg/images/tv/iis/pseudocolor.par
@@ -0,0 +1,7 @@
+enhancement,s,a,random,,,"type of pseudocolor enhancement:\n\
+ linear - map greyscale into a spectrum\n\
+ random - a randomly chosen color is assigned to each greylevel\n\
+ 8color - use eight colors chosen at random\n\
+enter selection"
+window,b,h,yes,,,window display after enabling pseudocolor
+enhance,s,h
diff --git a/pkg/images/tv/iis/rgb.cl b/pkg/images/tv/iis/rgb.cl
new file mode 100644
index 00000000..4fada018
--- /dev/null
+++ b/pkg/images/tv/iis/rgb.cl
@@ -0,0 +1,11 @@
+#{ RGB -- Select rgb display mode.
+
+# red_frame,i,a,1,1,4,red frame
+# green_frame,i,a,2,1,4,green frame
+# blue_frame,i,a,3,1,4,blue frame
+# window,b,h,no,,,window RGB frames
+
+{
+ _dcontrol (type="rgb", red_frame=red_frame, green_frame=green_frame,
+ blue_frame=blue_frame, rgb_window=window)
+}
diff --git a/pkg/images/tv/iis/rgb.par b/pkg/images/tv/iis/rgb.par
new file mode 100644
index 00000000..86d11871
--- /dev/null
+++ b/pkg/images/tv/iis/rgb.par
@@ -0,0 +1,4 @@
+red_frame,i,a,1,1,4,red frame
+green_frame,i,a,2,1,4,green frame
+blue_frame,i,a,3,1,4,blue frame
+window,b,h,no,,,window RGB frames
diff --git a/pkg/images/tv/iis/src/blink.x b/pkg/images/tv/iis/src/blink.x
new file mode 100644
index 00000000..fc176f7a
--- /dev/null
+++ b/pkg/images/tv/iis/src/blink.x
@@ -0,0 +1,132 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# BLINK -- blink the display.
+
+procedure blink()
+
+char token[SZ_LINE]
+int tok, count, rate
+int sets, button, i
+int ctoi(), ip
+pointer sp, setp, ptr
+int cv_rdbut()
+int val, nchar
+
+define errmsg 10
+
+include "cv.com"
+
+begin
+ # get rate for blink
+
+ call gargtok (tok, token, SZ_LINE)
+ if (tok != TOK_NUMBER) {
+ call eprintf ("Bad blink rate: %s\n")
+ call pargstr (token)
+ return
+ }
+ ip = 1
+ count = ctoi(token, ip, rate)
+ if (rate < 0) {
+ call eprintf ("negative rate not legal\n")
+ return
+ }
+
+ call smark (sp)
+ # The "3" is to hold frame/color/quad for one frame;
+ # the "2" is to allow duplication of each frame so that
+ # some frames can stay "on" longer. The extra "1" is for graphics.
+ call salloc (setp, 2 * 3 * (cv_maxframes+1), TY_POINTER)
+ sets = 0
+
+ # which frames to blink
+
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ while ( (sets <= cv_maxframes+1) && (tok != TOK_NEWLINE) ) {
+ sets = sets + 1
+ ptr = setp + (3 * (sets-1))
+ call salloc (Memi[ptr], IDS_MAXIMPL+1, TY_SHORT)
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'f') {
+ call cv_frame (token[2], Mems[Memi[ptr]])
+ if (Mems[Memi[ptr]] == ERR) {
+ call sfree (sp)
+ return
+ }
+ }
+ } else if (tok == TOK_NUMBER) {
+ ip = 1
+ nchar = ctoi (token[1], ip, val)
+ if ( (val < 0) || (val > cv_maxframes)) {
+ call eprintf ("illegal frame value: %s\n")
+ call pargstr (token)
+ call sfree (sp)
+ return
+ }
+ Mems[Memi[ptr]] = val
+ Mems[Memi[ptr]+1] = IDS_EOD
+ } else {
+errmsg
+ call eprintf ("Unexpected input: %s\n")
+ call pargstr (token)
+ call sfree (sp)
+ return
+ }
+ ptr = ptr + 1
+ call salloc (Memi[ptr], IDS_MAXGCOLOR+1, TY_SHORT)
+ call salloc (Memi[ptr+1], 5, TY_SHORT)
+ Mems[Memi[ptr]] = IDS_EOD # default all colors
+ Mems[Memi[ptr+1]] = IDS_EOD # default all quads
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if ( (tok != TOK_IDENTIFIER) && (tok != TOK_NEWLINE))
+ goto errmsg
+ if ((tok == TOK_IDENTIFIER) && (token[1] == 'c')) {
+ call cv_color (token[2], Mems[Memi[ptr]])
+ if (Mems[Memi[ptr]] == ERR) {
+ call sfree (sp)
+ return
+ }
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+ if ( (tok != TOK_IDENTIFIER) && (tok != TOK_NEWLINE))
+ goto errmsg
+ if ((tok == TOK_IDENTIFIER) && (token[1] == 'q')) {
+ call cv_quad (token[2], Mems[Memi[ptr+1]])
+ if (Mems[Memi[ptr+1]] == ERR) {
+ call sfree (sp)
+ return
+ }
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+ } # end while
+
+ button = cv_rdbut() # clear any buttons pressed
+ call eprintf ("Press any button to terminate blink\n")
+ repeat {
+ do i = 1, sets {
+ ptr = setp + 3 * (i-1)
+ call cvdisplay (IDS_ON, IDS_DISPLAY_I, Mems[Memi[ptr]],
+ Mems[Memi[ptr+1]], Mems[Memi[ptr+2]])
+ # Delay for "rate*100" milliseconds
+ call zwmsec (rate * 100)
+
+ # Leave something on screen when button pushed
+ button = cv_rdbut()
+ if (button > 0)
+ break
+ call cvdisplay (IDS_OFF, IDS_DISPLAY_I, Mems[Memi[ptr]],
+ Mems[Memi[ptr+1]], Mems[Memi[ptr+2]])
+ }
+ } until (button > 0)
+
+ call sfree (sp)
+end
diff --git a/pkg/images/tv/iis/src/clear.x b/pkg/images/tv/iis/src/clear.x
new file mode 100644
index 00000000..60cf69eb
--- /dev/null
+++ b/pkg/images/tv/iis/src/clear.x
@@ -0,0 +1,48 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# CLEAR -- clear certain frames in the display
+
+procedure clear()
+
+char token[SZ_LINE]
+int tok
+short frames[IDS_MAXIMPL+1]
+
+define nexttok 10
+
+include "cv.com"
+
+begin
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+
+ while ( (tok == TOK_IDENTIFIER) || (tok == TOK_NUMBER) ) {
+ if (tok == TOK_IDENTIFIER) {
+ switch (token[1]) {
+ case 'a', 'g':
+ # all colors
+ call cvclearg (short(IDS_EOD), short (IDS_EOD))
+ if (token[1] == 'g')
+ goto nexttok
+ frames[1] = IDS_EOD
+
+ case 'f':
+ call cv_frame (token[2], frames)
+ }
+ } else
+ call cv_frame (token[1], frames)
+
+ call cvcleari (frames)
+ if (token[1] == 'a')
+ return
+
+ # get next token
+nexttok
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+end
diff --git a/pkg/images/tv/iis/src/cv.com b/pkg/images/tv/iis/src/cv.com
new file mode 100644
index 00000000..ec9c70e7
--- /dev/null
+++ b/pkg/images/tv/iis/src/cv.com
@@ -0,0 +1,16 @@
+# common block for cv
+
+pointer cv_gp # file descriptor to write
+pointer cv_stack # working space for escape sequences
+int cv_maxframes # device max frames
+int cv_maxgraph # device max graph planes
+int cv_xcen, cv_ycen # user pixel coords of center of dev.
+int cv_xres, cv_yres # device resolution
+int cv_zres # device z resolution
+real cv_xcon, cv_ycon # conversion from NDC to GKI
+int cv_grch # graphics channel
+real cv_xwinc, cv_ywinc # cursor position for window command
+
+common /cvcom/ cv_gp, cv_stack, cv_maxframes, cv_maxgraph, cv_xcen, cv_ycen,
+ cv_xres, cv_yres, cv_zres, cv_xcon, cv_ycon, cv_grch,
+ cv_xwinc, cv_ywinc
diff --git a/pkg/images/tv/iis/src/cv.h b/pkg/images/tv/iis/src/cv.h
new file mode 100644
index 00000000..80f3016b
--- /dev/null
+++ b/pkg/images/tv/iis/src/cv.h
@@ -0,0 +1,51 @@
+# constants for cv package...should come from a graphcap entry
+
+# These are one based.
+define CV_XCEN 257
+define CV_YCEN 256
+
+define CV_XRES 512
+define CV_YRES 512
+define CV_ZRES 256
+
+define CV_MAXF 4
+define CV_MAXG 7
+
+define CV_GRCHNUM 16
+
+# CVLEN is just the *estimated* never to be exceeded amount of storage needed
+# to set up the escape sequence. It could be determined dynamically by
+# changing cv_move to count elements instead of moving them. Then the known
+# counts would be used with amovs to hustle the elements into the "salloc'ed"
+# space. Instead, with a static count, we can salloc once upon entering
+# the cv program and free up at exit.
+
+define CVLEN 128
+
+# Following are from "display.h"... only SAMPLE_SIZE and MAXLOG needed
+# as of May, 1985. But we might incorporate other programs from "tv",
+# so leave them.
+
+# Size limiting parameters.
+
+define MAXCHAN 2
+define SAMPLE_SIZE 600
+
+# If a logarithmic greyscale transformation is desired, the input range Z1:Z2
+# will be mapped into the range 1.0 to 10.0 ** MAXLOG before taking the log
+# to the base 10.
+
+define MAXLOG 3
+
+# The following parameter is used to compare display pixel coordinates for
+# equality. It determines the maximum permissible magnification. The machine
+# epsilon is not used because the computations are nontrivial and accumulation
+# of error is a problem.
+
+define DS_TOL (1E-4)
+
+# These parameters are needed for user defined transfer functions.
+
+define SZ_BUF 4096
+define STARTPT 0.0E0
+define ENDPT 4095.0E0
diff --git a/pkg/images/tv/iis/src/cv.x b/pkg/images/tv/iis/src/cv.x
new file mode 100644
index 00000000..a169a402
--- /dev/null
+++ b/pkg/images/tv/iis/src/cv.x
@@ -0,0 +1,175 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fio.h>
+include <fset.h>
+include "../lib/ids.h"
+include <gki.h>
+include <ctotok.h>
+include <error.h>
+include "cv.h"
+
+# Captain Video
+
+procedure t_cv()
+
+pointer gp
+char device[SZ_FNAME]
+char command[SZ_LINE]
+
+pointer gopen(), sp
+int dd[LEN_GKIDD]
+
+int scan, tok, envgets()
+
+include "cv.com"
+
+begin
+ call smark (sp)
+ call salloc (cv_stack, CVLEN, TY_SHORT)
+
+ if (envgets ("stdimage", device, SZ_FNAME) == 0)
+ call error (EA_FATAL,
+ "variable 'stdimage' not defined in environment")
+
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, READ_WRITE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ # to do:
+ # initialize local variables: image display size, etc
+ # instead of defines such as MCXSCALE, etc
+ cv_maxframes = CV_MAXF
+ cv_maxgraph = CV_MAXG
+ cv_xcen = CV_XCEN
+ cv_ycen = CV_YCEN
+ cv_xres = CV_XRES
+ cv_yres = CV_YRES
+ cv_zres = CV_ZRES
+ cv_gp = gp
+ cv_xcon = real(GKI_MAXNDC+1)/CV_XRES
+ cv_ycon = real(GKI_MAXNDC+1)/CV_YRES
+ cv_grch = CV_GRCHNUM
+ cv_xwinc = -1. # Flag: Don't know what lut is
+
+ repeat {
+ call printf (":-) ")
+ call flush (STDOUT)
+ if (scan() == EOF)
+ break
+ call gargtok(tok, command, SZ_LINE)
+ if ((tok == TOK_EOS) || (tok == TOK_NEWLINE))
+ next
+ # decode next command
+ call strlwr(command)
+ switch (command[1]) {
+ case 'x', 'q':
+ break
+
+
+ case 'b':
+ call blink
+
+ case 'c':
+ if (command[2] == 'l')
+ call clear
+ else
+ call rdcur
+
+ case 'd':
+ call display(command[2])
+
+ case 'e': # erase means clear
+ call clear
+
+ case 'h', '?':
+ call help
+
+ # case 'l':
+ # call load
+
+ case 'm':
+ call match
+
+ case 'o':
+ call offset
+
+ case 'p':
+ if ( command[2] == 's')
+ call map(command[2]) # pseudo color
+ else
+ call pan
+
+ case 'r':
+ if (command[2] == 'e')
+ call reset
+ else
+ call range
+
+ case 's':
+ if (command[2] == 'n')
+ call snap
+ else
+ call split
+
+ case 't':
+ call tell
+
+ case 'w':
+ if (command[2] == 'r')
+ call text
+ else
+ call window
+
+ case 'z':
+ call zoom
+
+ default:
+ call eprintf("unknown command: %s\n")
+ call pargstr(command[1])
+
+ } # end switch statement
+
+ } # end repeat statment
+
+ # all done
+
+ call gclose ( gp )
+ call ids_close
+ call sfree (sp)
+end
+
+
+# HELP -- print informative message
+
+procedure help()
+
+begin
+ call eprintf ("--- () : optional; [] : select one; N : number; C/F/Q : see below\n")
+ call eprintf ("b(link) N F (C Q) (F (C Q)..) blink N = 10 is one second\n")
+ call eprintf ("c(ursor) [on off F] cursor\n")
+ call eprintf ("di F (C Q) [on off] display image\n")
+ call eprintf ("dg C (F Q) [on off] display graphics\n")
+ call eprintf ("e(rase) [N a(ll) g(raphics) F] erase (clear)\n")
+ #call eprintf ("l(oad) load a frame\n")
+ call eprintf ("m(atch) (o) F (C) (to) (F) (C) match (output) lookup table\n")
+ call eprintf ("o(ffset) C N offset color N: 0 to +- 4095\n")
+ call eprintf ("p(an) (F) pan images\n")
+ call eprintf ("ps(eudo) (o) (F C) (rn sn) pseudo color mapping rn/sn: random n/seed n\n")
+ call eprintf ("r(ange) N (C) (N C ...) scale image N: 1-8\n")
+ call eprintf ("re(set) [r i t a] reset display registers/image/tables/all\n")
+ call eprintf ("sn(ap) (C) snap a picture\n")
+ call eprintf ("s(plit) [c o px,y nx,y] split picture\n")
+ call eprintf ("t(ell) tell display state\n")
+ call eprintf ("w(indow) (o) (F C) window (output) frames\n")
+ call eprintf ("wr(ite) [F C] text write text to frame/graphics\n")
+ call eprintf ("z(oom) N (F) zoom frames N: 1-8\n")
+ call eprintf ("x or q exit/quit\n")
+ call eprintf ("--- C: letter c followed by r/g/b/a or, for snap r,g,b,m,bw,rgb,\n")
+ call eprintf ("--- or for dg r/g/b/y/p/m/w, as 'cr', 'ca', or 'cgb'\n")
+ call eprintf ("--- F: f followed by a frame number or 'a' for all\n")
+ call eprintf ("--- Q: q followed by quadrant number or t,b,l,r for top, bottom,...\n")
+end
diff --git a/pkg/images/tv/iis/src/cvparse.x b/pkg/images/tv/iis/src/cvparse.x
new file mode 100644
index 00000000..46aba66b
--- /dev/null
+++ b/pkg/images/tv/iis/src/cvparse.x
@@ -0,0 +1,196 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "../lib/ids.h"
+include <ctype.h>
+
+# CVPARSE -- parsing routines for the cv package
+
+# CV_FRAME -- parse a frame specification
+
+procedure cv_frame(str, result)
+
+char str[ARB] # input string
+short result[ARB] # result string
+
+int ip
+int op
+int i
+int used[IDS_MAXIMPL]
+int gused
+
+include "cv.com"
+
+begin
+ if (str[1] == 'a') {
+ result[1] = IDS_EOD
+ return
+ }
+ call aclrs(used,IDS_MAXIMPL)
+ gused = 0
+ op = 1
+ for (ip = 1; str[ip] != EOS; ip = ip + 1) {
+ if (!IS_DIGIT(str[ip])) {
+ if (str[ip] == 'g')
+ gused = 1
+ else {
+ call eprintf("unknown frame specifier: %c\n")
+ call pargc(str[ip])
+ }
+ next
+ }
+ i = TO_INTEG (str[ip]) # fail if > than 9 planes! use ctoi()
+ if ((i < 1) || (i > cv_maxframes) ) {
+ call eprintf ("out of bounds frame: %d\n")
+ call pargi(i)
+ next
+ } else
+ used[i] = 1
+ }
+ do i= 1,IDS_MAXIMPL
+ if (used[i] != 0) {
+ result[op] = i
+ op = op + 1
+ }
+ if (gused != 0) {
+ result[op] = cv_grch
+ op = op + 1
+ }
+ if (op > 1)
+ result[op] = IDS_EOD
+ else
+ result[op] = ERR
+end
+
+
+# CV_COLOR -- parse a color specification
+
+procedure cv_color(str, result)
+
+char str[ARB] # input string
+short result[ARB] # result string
+
+int ip
+int op
+int i
+short val
+short used[IDS_MAXGCOLOR+1]
+
+include "cv.com"
+
+begin
+ if (str[1] == 'a') {
+ result[1] = IDS_EOD
+ return
+ }
+ call aclrs (used, IDS_MAXGCOLOR+1)
+ op = 1
+ for (ip = 1; str[ip] != EOS; ip = ip + 1) {
+ switch (str[ip]) {
+ case 'r':
+ val = IDS_RED
+
+ case 'g':
+ val = IDS_GREEN
+
+ case 'b':
+ val = IDS_BLUE
+
+ case 'y':
+ val = IDS_YELLOW
+
+ case 'w':
+ val = IDS_WHITE
+
+ case 'p':
+ val = IDS_RDBL
+
+ case 'm':
+ val = IDS_GRBL
+
+ default:
+ call eprintf("unknown color: %c\n")
+ call pargc(str[ip])
+ next
+ }
+ used[val] = 1
+ }
+ do i = 1, IDS_MAXGCOLOR+1
+ if (used[i] != 0) {
+ result[op] = i
+ op = op + 1
+ }
+ if (op > 1)
+ result[op] = IDS_EOD
+ else
+ result[op] = ERR
+end
+
+
+# CV_QUAD -- parse a quad specification
+
+procedure cv_quad(str, result)
+
+char str[ARB] # input string
+short result[ARB] # result string
+
+int ip
+int op
+int i
+short used[4]
+
+include "cv.com"
+
+begin
+ if (str[1] == 'a') {
+ result[1] = IDS_EOD
+ return
+ }
+ call aclrs(used, 4)
+ op = 1
+ for (ip = 1; str[ip] != EOS; ip = ip + 1) {
+ if (!IS_DIGIT(str[ip])) {
+ switch(str[ip]) {
+ case 'a':
+ call amovks (1, used, 4)
+
+ case 't':
+ used[1] = 1
+ used[2] = 1
+
+ case 'b':
+ used[3] = 1
+ used[4] = 1
+
+ case 'l':
+ used[2] = 1
+ used[3] = 1
+
+ case 'r':
+ used[1] = 1
+ used[4] = 1
+
+ default:
+ call eprintf("unknown quad specifier: %c\n")
+ call pargc(str[ip])
+ }
+ } else {
+ i = TO_INTEG (str[ip])
+ if ((i < 1) || (i > 4)) {
+ call eprintf ("out of bounds quad: %d\n")
+ call pargi(i)
+ next
+ } else
+ used[i] = 1
+ }
+ }
+ do i = 1,4 {
+ if (used[i] != 0) {
+ result[op] = i
+ op = op + 1
+ }
+ }
+ if (op > 1)
+ result[op] = IDS_EOD
+ else
+ result[op] = ERR
+end
diff --git a/pkg/images/tv/iis/src/cvulut.x b/pkg/images/tv/iis/src/cvulut.x
new file mode 100644
index 00000000..683c9500
--- /dev/null
+++ b/pkg/images/tv/iis/src/cvulut.x
@@ -0,0 +1,130 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <ctype.h>
+include "cv.h"
+
+# CV_ULUT -- Generates a look up table from data supplied by user. The
+# data is read from a two column text file of intensity, greyscale values.
+# The input data are sorted, then mapped to the x range [0-4096]. A
+# piecewise linear look up table of 4096 values is then constructed from
+# the (x,y) pairs given. A pointer to the look up table, as well as the z1
+# and z2 intensity endpoints, is returned.
+
+procedure cv_ulut (fname, z1, z2, lut)
+
+char fname[SZ_FNAME] # Name of file with intensity, greyscale values
+real z1 # Intensity mapped to minimum gs value
+real z2 # Intensity mapped to maximum gs value
+pointer lut # Look up table - pointer is returned
+
+pointer sp, x, y
+int nvalues, i, j, x1, x2, y1
+real delta_gs, delta_xv, slope
+errchk cv_rlut, cv_sort, malloc
+
+begin
+ call smark (sp)
+ call salloc (x, SZ_BUF, TY_REAL)
+ call salloc (y, SZ_BUF, TY_REAL)
+
+ # Read intensities and greyscales from the user's input file. The
+ # intensity range is then mapped into a standard range and the
+ # values sorted.
+
+ call cv_rlut (fname, Memr[x], Memr[y], nvalues)
+ call alimr (Memr[x], nvalues, z1, z2)
+ call amapr (Memr[x], Memr[x], nvalues, z1, z2, STARTPT, ENDPT)
+ call cv_sort (Memr[x], Memr[y], nvalues)
+
+ # Fill lut in straight line segments - piecewise linear
+ call malloc (lut, SZ_BUF, TY_SHORT)
+ do i = 1, nvalues-1 {
+ delta_gs = Memr[y+i] - Memr[y+i-1]
+ delta_xv = Memr[x+i] - Memr[x+i-1]
+ slope = delta_gs / delta_xv
+ x1 = int (Memr[x+i-1])
+ x2 = int (Memr[x+i])
+ y1 = int (Memr[y+i-1])
+ do j = x1, x2-1
+ Mems[lut+j-1] = y1 + slope * (j-x1)
+ }
+
+ call sfree (sp)
+end
+
+
+# CV_RLUT -- Read text file of x, y, values.
+
+procedure cv_rlut (utab, x, y, nvalues)
+
+char utab[SZ_FNAME] # Name of list file
+real x[SZ_BUF] # Array of x values, filled on return
+real y[SZ_BUF] # Array of y values, filled on return
+int nvalues # Number of values in x, y vectors - returned
+
+int n, fd
+pointer sp, lbuf, ip
+real xval, yval
+int getline(), open()
+errchk open, sscan, getline, malloc
+
+begin
+ call smark (sp)
+ call salloc (lbuf, SZ_LINE, TY_CHAR)
+
+ iferr (fd = open (utab, READ_ONLY, TEXT_FILE))
+ call error (0, "Error opening user table")
+
+ n = 0
+
+ while (getline (fd, Memc[lbuf]) != EOF) {
+ # Skip comment lines and blank lines.
+ if (Memc[lbuf] == '#')
+ next
+ for (ip=lbuf; IS_WHITE(Memc[ip]); ip=ip+1)
+ ;
+ if (Memc[ip] == '\n' || Memc[ip] == EOS)
+ next
+
+ # Decode the points to be plotted.
+ call sscan (Memc[ip])
+ call gargr (xval)
+ call gargr (yval)
+
+ n = n + 1
+ if (n > SZ_BUF)
+ call error (0,
+ "Intensity transformation table cannot exceed 4096 values")
+
+ x[n] = xval
+ y[n] = yval
+ }
+
+ nvalues = n
+ call close (fd)
+ call sfree (sp)
+end
+
+
+# CV_SORT -- Bubble sort of paired arrays.
+
+procedure cv_sort (xvals, yvals, nvals)
+
+real xvals[nvals] # Array of x values
+real yvals[nvals] # Array of y values
+int nvals # Number of values in each array
+
+int i, j
+real temp
+define swap {temp=$1;$1=$2;$2=temp}
+
+begin
+ for (i = nvals; i > 1; i = i - 1)
+ for (j = 1; j < i; j = j + 1)
+ if (xvals[j] > xvals[j+1]) {
+ # Out of order; exchange y values
+ swap (xvals[j], xvals[j+1])
+ swap (yvals[j], yvals[j+1])
+ }
+end
diff --git a/pkg/images/tv/iis/src/cvutil.x b/pkg/images/tv/iis/src/cvutil.x
new file mode 100644
index 00000000..81721081
--- /dev/null
+++ b/pkg/images/tv/iis/src/cvutil.x
@@ -0,0 +1,538 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <gki.h>
+include <imhdr.h>
+include "cv.h"
+include "../lib/ids.h"
+
+# CVUTIL -- utility control routines for cv package
+
+############ CLEAR display ############
+# CVCLEARG -- clear all of graphics (bit) planes
+
+procedure cvclearg (frame, color)
+
+short frame[ARB]
+short color[ARB]
+
+int count
+int cv_move()
+
+include "cv.com"
+
+begin
+ count = cv_move (frame, Mems[cv_stack])
+ count = count + cv_move (color, Mems[cv_stack+count])
+ call gescape (cv_gp, IDS_SET_GP, Mems[cv_stack], count)
+ call gclear (cv_gp)
+end
+
+# CVCLEARI -- clear specified image frames
+
+procedure cvcleari (frames)
+
+short frames[ARB]
+
+include "cv.com"
+
+begin
+ call cv_iset (frames)
+ call gclear (cv_gp)
+end
+
+############ CURSOR and BUTTON ############
+# 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_WTBUT -- wait for button to be pressed, then read it
+
+int procedure cv_wtbut()
+
+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_WT)
+ 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_RCRAW -- read the raw cursor (return actual screen coordinates).
+
+procedure cv_rcraw (x, y)
+
+real x,y
+
+include "cv.com"
+
+begin
+ call cv_rcur (IDS_CRAW, x, y)
+end
+
+# CV_SCRAW -- set raw cursor
+
+procedure cv_scraw (x, y)
+
+real x,y
+
+include "cv.com"
+
+begin
+ call cv_scur (IDS_CRAW, x, y)
+end
+
+
+# cvcur -- turn cursor on or off
+
+procedure cvcur (instruction)
+
+int instruction
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_CURSOR
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = 1
+ Mems[cv_stack+3] = IDS_EOD
+ Mems[cv_stack+4] = IDS_EOD
+ Mems[cv_stack+5] = 1
+ Mems[cv_stack+6] = instruction
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 7)
+end
+
+############ DISPLAY ############
+# cvdisplay
+
+procedure cvdisplay (instruction, device, frame, color, quad)
+
+int instruction
+int device
+short frame, color, quad
+
+int i
+int cv_move()
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = instruction
+ i = cv_move (frame, Mems[cv_stack+1])
+ i = i + cv_move (color, Mems[cv_stack+1+i])
+ i = i + cv_move (quad, Mems[cv_stack+1+i])
+ call gescape (cv_gp, device, Mems[cv_stack], 1+i)
+end
+
+############ MATCH ############
+# cvmatch -- build match escape sequence
+
+procedure cvmatch (lt, fr, cr, frames, color)
+
+int lt # type
+short fr[ARB] # reference frame and color
+short cr[ARB]
+short frames[ARB] # frames to be changed
+short color[ARB] # and colors
+
+int count, n
+int cv_move()
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_MATCH
+ Mems[cv_stack+1] = lt
+ count = cv_move (fr, Mems[cv_stack+3])
+ count = count + cv_move (cr, Mems[cv_stack+3+count])
+ n = count
+ Mems[cv_stack+count+3] = 0 # unused offset
+ count = count + cv_move (frames, Mems[cv_stack+4+count])
+ count = count + cv_move (color, Mems[cv_stack+4+count])
+ Mems[cv_stack+2] = count - n
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+4)
+end
+
+############ OFFSET ############
+# cvoffset -- set offset registers
+
+procedure cvoffset( color, data)
+
+short color[ARB]
+short data[ARB]
+
+int count, cv_move()
+int i
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_OUT_OFFSET
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+3] = IDS_EOD # no-op the frames slot
+ count = cv_move (color, Mems[cv_stack+4])
+ Mems[cv_stack+4+count] = 1 # (unused) offset
+ i = cv_move (data, Mems[cv_stack+5+count])
+ i = i - 1 # don't include EOD of "data"
+ Mems[cv_stack+2] = i
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], i+count+5)
+end
+
+############ PAN ############
+# cvpan -- move the image(s) around
+# The x,y coordinates are NDC that, it is assumed, came from a cursor
+# read, and therefore are of the form
+# ((one_based_pixel-1)/(resolution)) *(GKI_MAXNDC+1) / GKI_MAXNDC
+# The division by GKI_MAXNDC turns into NDC what was GKI ranging from
+# 0 through 511*64 (for IIS) which conforms to the notion of specifying
+# each pixel by its left/bottom GKI boundary.
+
+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
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = 3
+ count = cv_move (frames, Mems[cv_stack+3])
+ Mems[cv_stack+3+count] = IDS_EOD # 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
+
+############ RANGE ############
+# cvrange -- scale ouput before final look up table
+
+procedure cvrange ( color, range)
+
+short color[ARB]
+short range[ARB]
+
+int cv_move(), count, i
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_RANGE
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+3] = IDS_EOD # all frames
+ count = cv_move (color, Mems[cv_stack+4])
+ Mems[cv_stack+4+count] = 1 # (unused) offset
+ i = cv_move (range, Mems[cv_stack+5+count])
+ i = i - 1 # don't include EOD of "range"
+ Mems[cv_stack+2] = i
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], i+count+5)
+end
+
+############ RESET display ############
+# cvreset -- reset display
+# SOFT -- everything but lookup tables and image/graphics planes
+# MEDIUM -- everything but image/graphics planes
+# HARD -- everything...planes are cleared, all images OFF
+
+procedure cvreset (hardness)
+
+int hardness
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = hardness
+ call gescape (cv_gp, IDS_RESET, Mems[cv_stack], 1)
+end
+
+
+############ SNAP a picture ############
+# cvsnap -- takes a full picture of image display
+
+procedure cvsnap (fname, snap_color)
+
+char fname[ARB] # image file name
+int snap_color
+
+pointer im, immap(), impl2s()
+int i, factor
+real y
+
+include "cv.com"
+
+begin
+ im = immap(fname, NEW_FILE, 0)
+ IM_PIXTYPE(im) = TY_SHORT
+ IM_LEN(im,1) = cv_xres
+ IM_LEN(im,2) = cv_yres
+
+ Mems[cv_stack] = IDS_SNAP
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = 1 # frame, color are not relevant
+ Mems[cv_stack+3] = IDS_EOD
+ Mems[cv_stack+4] = IDS_EOD
+ Mems[cv_stack+5] = 0
+ Mems[cv_stack+6] = snap_color
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 7)
+
+ factor = cv_yres/10 + 1
+ call eprintf (" (%% done: ")
+ call flush (STDERR)
+ do i = 0, cv_yres-1 {
+ if ( mod(i,factor) == 0) {
+ call eprintf ("%d ")
+ call pargi (int(10*i/cv_yres)*10)
+ call flush (STDERR)
+ }
+ y = real(i)*cv_ycon / GKI_MAXNDC.
+ call ggcell (cv_gp, Mems[impl2s(im,i+1)], cv_xres, 1, 0.0,
+ y, 1.0, y)
+ }
+ call eprintf ("100)\n")
+
+ call imunmap(im)
+ Mems[cv_stack] = IDS_R_SNAPDONE
+ call gescape (cv_gp, IDS_RESET, Mems[cv_stack], 1)
+end
+
+############ SPLIT ############
+# cvsplit -- set split screen position
+
+procedure cvsplit (x, y)
+
+real x,y # NDC coordinates
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_SPLIT
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = 2
+ Mems[cv_stack+3] = IDS_EOD # no-op frame and color
+ Mems[cv_stack+4] = IDS_EOD
+ Mems[cv_stack+5] = 1 # (unused) offset
+ # NOTE multiplacation by MAXNDC+1 ... x, and y, are never == 1.0
+ # ( see split.x)
+ # and truncation effects will work out just right, given what the
+ # image display kernel does with these numbers
+ Mems[cv_stack+6] = x * (GKI_MAXNDC+1)
+ Mems[cv_stack+7] = y * (GKI_MAXNDC+1)
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], 8)
+end
+
+############ TEXT ############
+# Write text
+
+procedure cvtext (x, y, text, size)
+
+real x, y, size
+char text[ARB]
+
+char format[SZ_LINE]
+
+include "cv.com"
+
+begin
+ call sprintf (format, SZ_LINE, "s=%f")
+ call pargr (size)
+ call gtext (cv_gp, x, y, text, format)
+end
+
+############ WHICH ############
+# Tell which frames are one. The best we can do now is
+# tell if any, and if so, which is the "first"
+
+procedure cvwhich (fr)
+
+short fr[ARB]
+
+real x,y
+int cnum, oldcnum
+int gstati
+
+include "cv.com"
+
+begin
+ # Use here the fact that if cursor number is zero, the
+ # kernel will return the number of the first displayed
+ # frame, or "ERR" if none.
+ oldcnum = gstati (cv_gp, G_CURSOR)
+ cnum = 0
+ call gseti (cv_gp, G_CURSOR, cnum)
+ call ggcur (cv_gp, x, y, cnum)
+ call gseti (cv_gp, G_CURSOR, oldcnum)
+ fr[1] = cnum
+ fr[2] = IDS_EOD
+end
+
+############ WLUT ############
+# cvwlut ... change lookup tables
+# the data is in form of line endpoints.
+
+procedure cvwlut (device, frames, color, data, n)
+
+int device
+short frames[ARB]
+short color[ARB]
+short data[ARB]
+int n
+
+int count, cv_move()
+
+include "cv.com"
+
+begin
+ # Device had better refer to a look-up table, or who knows
+ # what will happen!
+ Mems[cv_stack] = device
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = n
+ count = cv_move (frames, Mems[cv_stack+3])
+ count = count + cv_move (color, Mems[cv_stack+3+count])
+ Mems[cv_stack+3+count] = 1 # (unused) offset
+ call amovs (data, Mems[cv_stack+count+4],n)
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], n+count+4)
+end
+
+############ ZOOM ############
+# cvzoom -- zoom the image
+# See comment under PAN about x and y.
+
+procedure cvzoom (frames, power, x, y)
+
+short frames[ARB]
+int power
+real x,y
+
+int count, cv_move()
+
+include "cv.com"
+
+begin
+ Mems[cv_stack] = IDS_ZOOM
+ Mems[cv_stack+1] = IDS_WRITE
+ Mems[cv_stack+2] = 3
+ count = cv_move (frames, Mems[cv_stack+3])
+ Mems[cv_stack+3+count] = IDS_EOD # (unused) color
+ Mems[cv_stack+4+count] = IDS_EOD # (unused) offset
+ Mems[cv_stack+5+count] = power
+ Mems[cv_stack+6+count] = x * GKI_MAXNDC
+ Mems[cv_stack+7+count] = y * GKI_MAXNDC
+ call gescape (cv_gp, IDS_CONTROL, Mems[cv_stack], count+8)
+end
+
+############ SUBROUTINES ##############
+# CV_MOVE -- transfer an array into the escape data array; returns number
+# of items transfered.
+
+int procedure cv_move (in, out)
+
+short in[ARB]
+short out[ARB]
+
+int count
+
+begin
+ count = 0
+ repeat {
+ count = count + 1
+ out[count] = in[count]
+ } until (in[count] == IDS_EOD)
+ return (count)
+end
+
+# CV_ISET -- Tell the image kernel that i/o is to be done for the
+# specified frame/frames.
+
+procedure cv_iset (frames)
+
+short frames[ARB]
+
+short idata[30]
+int i, cv_move()
+
+include "cv.com"
+
+begin
+ i = cv_move (frames, idata)
+ idata[i+1] = IDS_EOD # all bit planes
+ call gescape (cv_gp, IDS_SET_IP, idata, i+1)
+end
+
+# CV_GSET -- Tell the image kernel that i/o is to be done for the
+# specified colors.
+
+procedure cv_gset (colors)
+
+short colors[ARB]
+
+short idata[30]
+int i, cv_move()
+
+include "cv.com"
+
+begin
+ idata[1] = IDS_EOD # all "frames"
+ i = cv_move (colors, idata[2])
+ call gescape (cv_gp, IDS_SET_GP, idata, i+1)
+end
diff --git a/pkg/images/tv/iis/src/display.x b/pkg/images/tv/iis/src/display.x
new file mode 100644
index 00000000..d04b1365
--- /dev/null
+++ b/pkg/images/tv/iis/src/display.x
@@ -0,0 +1,104 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# DISPLAY -- Turn frames on or off
+
+procedure display(command)
+
+char command[ARB]
+
+int tok
+char token[SZ_LINE]
+short color[IDS_MAXGCOLOR+1]
+short frames[IDS_MAXIMPL+1]
+short quad[5]
+short instruction
+int escape
+include "cv.com"
+
+begin
+ if (command[1] == 'i')
+ escape = IDS_DISPLAY_I
+ else if (command[1] == 'g')
+ escape = IDS_DISPLAY_G
+ else {
+ call eprintf ("Only 'di' or 'dg' are understood\n")
+ return
+ }
+
+ instruction = ERR
+ frames[1] = ERR
+ color[1] = ERR
+ quad[1] = IDS_EOD
+
+ repeat {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if ( tok == TOK_IDENTIFIER) {
+ switch (token[1]) {
+ case 'c':
+ call cv_color (token[2], color)
+ if (color[1] == ERR)
+ return
+
+ case 'f':
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+
+
+ case 'o':
+ if (token[2] == 'n')
+ instruction = IDS_ON
+ else if (token[2] == 'f')
+ instruction = IDS_OFF
+
+ case 'q':
+ call cv_quad (token[2], quad)
+ if (quad[1] == ERR)
+ return
+ }
+ } else if (tok == TOK_NUMBER) {
+ call cv_frame (token[1], frames)
+ if (frames[1] == ERR)
+ return
+ }
+ } until ( tok == TOK_NEWLINE )
+
+
+ # Require a frame number, but allow default of color and quad to "all".
+ # But, for graphics, default the frame and require a color.
+ # In either case, for OFF, allow all defaults.
+ if (escape == IDS_DISPLAY_I) {
+ if ((instruction == IDS_OFF) && (frames[1] == ERR))
+ frames[1] = IDS_EOD
+ if ( color[1] == ERR)
+ color[1] = IDS_EOD
+ } else {
+ if ((instruction == IDS_OFF) && ( color[1] == ERR) )
+ color[1] = IDS_EOD
+ if ( frames[1] == ERR)
+ frames[1] = IDS_EOD
+ }
+
+ if (frames[1] == ERR) {
+ call eprintf ("Frame specification required\n")
+ return
+ }
+ if (color[1] == ERR) {
+ call eprintf ("Color specification required\n")
+ return
+ }
+
+ # if neither "on" nor "off", then turn off all, and turn
+ # on the specified frames
+ if (instruction == ERR) {
+ call cvdisplay (IDS_OFF , escape, short(IDS_EOD),
+ short(IDS_EOD), short(IDS_EOD))
+ instruction = IDS_ON
+ }
+ call cvdisplay (instruction, escape, frames, color, quad)
+end
diff --git a/pkg/images/tv/iis/src/gwindow.h b/pkg/images/tv/iis/src/gwindow.h
new file mode 100644
index 00000000..5050b304
--- /dev/null
+++ b/pkg/images/tv/iis/src/gwindow.h
@@ -0,0 +1,34 @@
+# Window descriptor structure.
+
+define LEN_WDES (5+(W_MAXWC+1)*LEN_WC+80)
+define LEN_WC 10 # 4=[XbXeYbYe]+2=tr_type[xy]
+define W_MAXWC 5 # max world coord systems
+define W_SZIMSECT 79 # image section string
+
+define W_DEVICE Memi[$1]
+define W_FRAME Memi[$1+1] # device frame number
+define W_XRES Memi[$1+2] # device resolution, x
+define W_YRES Memi[$1+3] # device resolution, y
+define W_WC ($1+$2*LEN_WC+5) # ptr to coord descriptor
+define W_IMSECT Memc[($1+65-1)*SZ_STRUCT+1]
+
+# Fields of the WC coordinate descriptor, a substructure of the window
+# descriptor. "W_XB(W_WC(w,0))" is the XB field of wc 0 of window W.
+
+define W_XS Memr[P2R($1)] # starting X value
+define W_XE Memr[P2R($1+1)] # ending X value
+define W_XT Memi[$1+2] # X transformation type
+define W_YS Memr[P2R($1+3)] # starting Y value
+define W_YE Memr[P2R($1+4)] # ending Y value
+define W_YT Memi[$1+5] # Y transformation type
+define W_ZS Memr[P2R($1+6)] # starting Z value (greyscale)
+define W_ZE Memr[P2R($1+7)] # ending Z value
+define W_ZT Memi[$1+8] # Z transformation type
+define W_UPTR Memi[$1+9] # LUT when ZT=USER
+
+# Types of coordinate and greyscale transformations.
+
+define W_UNITARY 0 # values map without change
+define W_LINEAR 1 # linear mapping
+define W_LOG 2 # logarithmic mapping
+define W_USER 3 # user specifies transformation
diff --git a/pkg/images/tv/iis/src/load1.x b/pkg/images/tv/iis/src/load1.x
new file mode 100644
index 00000000..c33cc1dd
--- /dev/null
+++ b/pkg/images/tv/iis/src/load1.x
@@ -0,0 +1,324 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+#### load1.x (from load.x) ####
+
+include <mach.h>
+include <imset.h>
+include <imhdr.h>
+include <error.h>
+include <gki.h>
+include <fio.h>
+include <fset.h>
+include "gwindow.h"
+include "../lib/ids.h"
+include "cv.h"
+
+# LOAD - Load an image. The specified image section is mapped into
+# the specified section of an image display frame. The mapping involves
+# a linear transformation in X and Y and a linear or logarithmic transformation
+# in Z (greyscale). Images of all pixel datatypes are supported, and there
+# no upper limit on the size of an image. The display device is interfaced
+# via GIO metacode.
+
+procedure t_load()
+
+char image[SZ_FNAME]
+short frame[IDS_MAXIMPL+1]
+bool frame_erase, border_erase
+pointer im, wdes, sp
+
+pointer gp
+char device[SZ_FNAME]
+int dd[LEN_GKIDD]
+
+int envgets()
+short clgets()
+bool clgetb()
+pointer immap(), gopen()
+
+include "cv.com"
+errchk immap, imunmap, ds_getparams
+
+begin
+ call smark (sp)
+ call salloc (cv_stack, CVLEN, TY_SHORT)
+ call salloc (wdes, LEN_WDES, TY_STRUCT)
+
+ if (envgets ("stdimage", device, SZ_FNAME) == 0)
+ call error (EA_FATAL,
+ "variable 'stdimage' not defined in environment")
+
+ call ids_open (device, dd)
+ call gki_inline_kernel (STDIMAGE, dd)
+ # Need READ_WRITE so can call cvdisplay
+ gp = gopen ( device, READ_WRITE, STDIMAGE)
+
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ call ids_grstream (STDIMAGE)
+
+ # to do:
+ # initialize local variables: image display size, etc
+ # instead of defines such as MCXSCALE, etc
+
+ cv_maxframes = CV_MAXF
+ cv_maxgraph = CV_MAXG
+ cv_xcen = CV_XCEN
+ cv_ycen = CV_YCEN
+ cv_xres = CV_XRES
+ cv_yres = CV_YRES
+ cv_zres = CV_ZRES
+ cv_gp = gp
+ cv_xcon = real(GKI_MAXNDC+1)/CV_XRES
+ cv_ycon = real(GKI_MAXNDC+1)/CV_YRES
+ cv_grch = CV_GRCHNUM
+ cv_xwinc = -1. # Flag: Don't know what lut is
+
+ # Open input imagefile.
+ call clgstr ("image", image, SZ_FNAME)
+ im = immap (image, READ_ONLY, 0)
+
+ # Ultimately, we should get a sequence of frames, all of which get
+ # loaded with the same image.
+
+ frame[1] = clgets ("frame")
+ frame[2] = IDS_EOD
+ frame_erase = clgetb ("erase")
+
+ # Optimize for sequential i/o.
+ call imseti (im, IM_ADVICE, SEQUENTIAL)
+
+ # The frame being displayed does not necessarily change when a new
+ # frame is loaded. (We might consider letting user select via the
+ # cv package)
+
+ if (clgetb ("select_frame")) {
+ call cvdisplay (IDS_OFF, IDS_DISPLAY_I, short(IDS_EOD),
+ short(IDS_EOD), short(IDS_EOD))
+ call cvdisplay (IDS_ON, IDS_DISPLAY_I, frame, short(IDS_EOD),
+ short(IDS_EOD))
+ }
+
+ if (frame_erase)
+ call cvcleari (frame)
+
+ # Tell GIO what frame(s) to write
+ call cv_iset (frame)
+
+ # Done with all possible read/write calls to cv package. Fix up so
+ # don't read device if we erase the frame, so need WRITE_ONLY mode.
+ # fseti on STDIMAGE didn't work.
+
+ if (frame_erase) {
+ call gclose (gp)
+ call gki_inline_kernel (STDIMAGE, dd)
+ gp = gopen ( device, WRITE_ONLY, STDIMAGE)
+ cv_gp = gp
+ call fseti (STDIMAGE, F_TYPE, SPOOL_FILE)
+ call fseti (STDIMAGE, F_CANCEL, OK)
+ }
+
+ # Get display parameters and set up transformation.
+ call ds_getparams (im, wdes, image, frame)
+
+ # Erase the border (space between displayed image section and edge of
+ # window) only if screen was not erased and border erasing is enabled.
+
+ if (frame_erase)
+ border_erase = false
+ else
+ border_erase = clgetb ("border_erase")
+
+ # Display the image.
+ call ds_load_display (im, wdes, border_erase)
+
+ call imunmap (im)
+
+ # All done.
+ call gclose (gp)
+ call ids_close()
+ call sfree (sp)
+end
+
+
+# DS_GETPARAMS -- Get the parameters controlling how the image is mapped
+# into the display frame. Set up the transformations and save in the graphics
+# descriptor file.
+
+procedure ds_getparams (im, wdes, image, frame)
+
+pointer im, wdes # Image and graphics descriptors
+char image[SZ_FNAME] # Should be determined from im
+short frame[ARB]
+
+bool fill, zscale_flag, zrange_flag, zmap_flag
+real xcenter, ycenter
+real xsize, ysize, pxsize, pysize
+real xmag, ymag, xscale, yscale
+real z1, z2, contrast
+int nsample_lines, ncols, nlines, len_stdline
+pointer sp, w, ztrans, lut, lutfile
+
+bool clgetb()
+int clgeti()
+real clgetr()
+bool streq()
+
+include "cv.com"
+
+begin
+ call smark (sp)
+ call salloc (ztrans, SZ_FNAME, TY_CHAR)
+
+ # Set up a new graphics descriptor structure defining the coordinate
+ # transformation used to map the image into the display frame.
+
+ call strcpy (image, W_IMSECT(wdes), W_SZIMSECT)
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ # The fill, zscale, and zrange parameters determine the algorithms to
+ # be used to scale the image in the spatial and greyscale dimensions.
+ # If greyscale mapping is disabled the zscale and zrange options are
+ # disabled. Greyscale mapping can also be disabled by turning off
+ # zscale and zrange and setting Z1 and Z2 to the device greyscale min
+ # and max values, producing a unitary transformation.
+
+ fill = clgetb ("fill")
+ call clgstr ("ztrans", Memc[ztrans], SZ_FNAME)
+ if (streq (Memc[ztrans], "none") || streq (Memc[ztrans], "user")) {
+ zscale_flag = false
+ zrange_flag = false
+ zmap_flag = false
+ } else {
+ zmap_flag = true
+ zscale_flag = clgetb ("zscale")
+ if (!zscale_flag)
+ zrange_flag = clgetb ("zrange")
+ }
+
+ # Determine Z1 and Z2, the range of input greylevels to be mapped into
+ # the fixed range of display greylevels.
+
+ if (zscale_flag) {
+ # Autoscaling is desired. Compute Z1 and Z2 which straddle the
+ # median computed by sampling a portion of the image.
+
+ contrast = clgetr ("contrast")
+ nsample_lines = clgeti ("nsample_lines")
+ len_stdline = SAMPLE_SIZE / nsample_lines
+ call zscale (im, z1, z2, contrast, SAMPLE_SIZE, len_stdline)
+
+ } else if (zrange_flag) {
+ nsample_lines = clgeti ("nsample_lines")
+ call maxmin (im, z1, z2, nsample_lines)
+
+ } else if (zmap_flag) {
+ z1 = clgetr ("z1")
+ z2 = clgetr ("z2")
+ }
+
+ # Determine the display window into which the image is to be mapped
+ # in normalized device coordinates.
+
+ xcenter = max(0.0, min(1.0, clgetr ("xcenter")))
+ ycenter = max(0.0, min(1.0, clgetr ("ycenter")))
+ xsize = max(0.0, min(1.0, clgetr ("xsize")))
+ ysize = max(0.0, min(1.0, clgetr ("ysize")))
+
+ # Determine X and Y scaling ratios required to map the image into the
+ # normalized display window. If spatial scaling is not desired filling
+ # must be disabled and XMAG and YMAG must be set to 1.0 in the
+ # parameter file. Fill mode will always produce an aspect ratio of 1;
+ # if nonequal scaling is required then the magnification ratios must
+ # be set explicitly by the user.
+
+ if (fill) {
+ # Compute scale in units of window coords per data pixel required
+ # to scale image to fit window.
+
+ xscale = xsize / max (1, (ncols - 1))
+ yscale = ysize / max (1, (nlines - 1))
+
+ if (xscale < yscale)
+ yscale = xscale
+ else
+ xscale = yscale
+
+ } else {
+ # Compute scale required to provide image magnification ratios
+ # specified by the user. Magnification is specified in units of
+ # display pixels, i.e, a magnification ratio of 1.0 means that
+ # image pixels will map to display pixels without scaling.
+
+ xmag = clgetr ("xmag")
+ ymag = clgetr ("ymag")
+ xscale = 1.0 / ((cv_xres - 1) / xmag)
+ yscale = 1.0 / ((cv_yres - 1) / ymag)
+ }
+
+ # Set device window limits in normalized device coordinates.
+ # World coord system 0 is used for the device window.
+
+ w = W_WC(wdes,0)
+ W_XS(w) = xcenter - xsize / 2.0
+ W_XE(w) = xcenter + xsize / 2.0
+ W_YS(w) = ycenter - ysize / 2.0
+ W_YE(w) = ycenter + ysize / 2.0
+
+ # Set pixel coordinates of window, world coordinate system #1.
+
+ w = W_WC(wdes,1)
+ pxsize = xsize / xscale
+ pysize = ysize / yscale
+
+ # If the image is too large to fit in the window given the scaling
+ # factors XSCALE and YSCALE, the following will set starting and ending
+ # pixel coordinates in the interior of the image. If the image is too
+ # small to fill the window then the pixel coords will reference beyond
+ # the bounds of the image.
+
+ W_XS(w) = (ncols - 1) / 2.0 + 1 - (pxsize / 2.0)
+ W_XE(w) = W_XS(w) + pxsize
+ W_YS(w) = (nlines - 1) / 2.0 + 1 - (pysize / 2.0)
+ W_YE(w) = W_YS(w) + pysize
+
+ # All spatial transformations are linear.
+ W_XT(w) = W_LINEAR
+ W_YT(w) = W_LINEAR
+
+ # Determine whether a log or linear greyscale transformation is
+ # desired.
+ if (streq (Memc[ztrans], "log"))
+ W_ZT(w) = W_LOG
+ else if (streq (Memc[ztrans], "linear"))
+ W_ZT(w) = W_LINEAR
+ else if (streq (Memc[ztrans], "none"))
+ W_ZT(w) = W_UNITARY
+ else if (streq (Memc[ztrans], "user")) {
+ W_ZT(w) = W_USER
+ call salloc (lutfile, SZ_FNAME, TY_CHAR)
+ call clgstr ("lutfile", Memc[lutfile], SZ_FNAME)
+ call cv_ulut (Memc[lutfile], z1, z2, lut)
+ W_UPTR(w) = lut
+ } else {
+ call eprintf ("Bad greylevel transformation '%s'\n")
+ call pargstr (Memc[ztrans])
+ W_ZT(w) = W_LINEAR
+ }
+
+ # Set up the greyscale transformation.
+ W_ZS(w) = z1
+ W_ZE(w) = z2
+
+ # Tell the user what values were used.
+ call printf ("cvl: z1 %6.1f, z2 %6.1f\n")
+ call pargr (z1)
+ call pargr (z2)
+
+ # The user world coordinate system should be set from the CTRAN
+ # structure in the image header, but for now we just make it equal
+ # to the pixel coordinate system.
+
+ call amovi (Memi[w], Memi[W_WC(wdes,2)], LEN_WC)
+end
diff --git a/pkg/images/tv/iis/src/load2.x b/pkg/images/tv/iis/src/load2.x
new file mode 100644
index 00000000..5372907f
--- /dev/null
+++ b/pkg/images/tv/iis/src/load2.x
@@ -0,0 +1,335 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+#### load2.x (from load.x) ####
+
+include <mach.h>
+include <imset.h>
+include <imhdr.h>
+include <error.h>
+include <gki.h>
+include <fio.h>
+include <fset.h>
+include "gwindow.h"
+include "../lib/ids.h"
+include "cv.h"
+
+# DS_LOAD_DISPLAY -- Map an image into the display window. In general this
+# involves independent linear transformations in the X, Y, and Z (greyscale)
+# dimensions. If a spatial dimension is larger than the display window then
+# the image is block averaged. If a spatial dimension or a block averaged
+# dimension is smaller than the display window then linear interpolation is
+# used to expand the image. Both the input image and the output device appear
+# to us as images, accessed via IMIO.
+#
+# World coordinate system 0 (WCS 0) defines the position and size of the device
+# window in NDC coordinates (0-1 in either axis). WCS 1 assigns a pixel
+# coordinate system to the same window. If we convert the NDC coordinates of
+# the window into device coordinates in pixels, then the ratios of the window
+# coordinates in pixels to the image coordinates in pixels defines the real
+# magnification factors for the two spatial axes. If the pixel coordinates
+# are out of bounds then the image will be displayed centered in the window
+# with zero fill at the edges. If the frame has not been erased then the fill
+# areas must be explicitly zeroed.
+
+procedure ds_load_display (im, wdes, border_erase)
+
+pointer im # input image
+pointer wdes # graphics window descriptor
+bool border_erase
+
+int wx1, wx2, wy1, wy2 # device window to be filled with image data
+real px1, px2, py1, py2 # image coords in fractional image pixels
+real pxsize, pysize # size of image section in fractional pixels
+real wxcenter, wycenter # center of device window in frac device pixels
+real xmag, ymag # x,y magnification ratios
+pointer w0, w1 # world coord systems 0 (NDC) and 1 (pixel)
+
+include "cv.com"
+
+begin
+ # Compute pointers to WCS 0 and 1.
+ w0 = W_WC(wdes,0)
+ w1 = W_WC(wdes,1)
+
+ # Compute X and Y magnification ratios required to map image into
+ # the device window in device pixel units.
+
+ xmag = (W_XE(w0) - W_XS(w0)) * cv_xres / (W_XE(w1) - W_XS(w1))
+ ymag = (W_YE(w0) - W_YS(w0)) * cv_yres / (W_YE(w1) - W_YS(w1))
+
+ # Compute the coordinates of the image section to be displayed.
+ # This is not necessarily the same as WCS 1 since the WCS coords
+ # need not be inbounds.
+
+ px1 = max (1.0, W_XS(w1))
+ px2 = min (real (IM_LEN(im,1)), W_XE(w1))
+ py1 = max (1.0, W_YS(w1))
+ py2 = min (real (IM_LEN(im,2)), W_YE(w1))
+
+ # Now compute the coordinates of the image section to be written in
+ # device pixel units. This section must lie within or on the device
+ # window.
+ # This computation for I2S will give 257, which does differ by one
+ # for the Y center (due to inversion in I2S). This should not matter,
+ # but if it does, this comment will change!
+
+ pxsize = px2 - px1
+ pysize = py2 - py1
+ wxcenter = (W_XE(w0) + W_XS(w0)) / 2.0 * cv_xres + 1
+ wycenter = (W_YE(w0) + W_YS(w0)) / 2.0 * cv_yres + 1
+
+ wx1 = max (1, int (wxcenter - (pxsize / 2.0 * xmag)))
+ wx2 = max (wx1, min (cv_xres, int (wx1 + (pxsize * xmag))))
+ wy1 = max (1, int (wycenter - (pysize / 2.0 * ymag)))
+ wy2 = max (wy1, min (cv_yres, int (wy1 + (pysize * ymag))))
+
+ # Display the image data, ignoring zero filling at the boundaries.
+
+ call ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2,
+ W_ZS(w1), W_ZE(w1), W_ZT(w1), W_UPTR(w1))
+
+ # Zero the border of the window if the frame has not been erased,
+ # and if the displayed section does not occupy the full window.
+
+ if (border_erase)
+ call ds_erase_border (im, wdes, wx1,wx2,wy1,wy2)
+end
+
+
+# DS_MAP_IMAGE -- Map an image section from the input image to a section
+# (window) of the output image (the display device). All spatial scaling is
+# handled by the "scaled input" package, i.e., SIGL2[SR]. Our task is to
+# get lines from the scaled input image, transform the greyscale if necessary,
+# and write the lines to the output device.
+
+procedure ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2, z1,z2,zt, uptr)
+
+pointer im # input image
+real px1,px2,py1,py2 # input section
+int wx1,wx2,wy1,wy2 # output section
+real z1,z2 # range of input greylevels to be mapped.
+int zt # log or linear greylevel transformation
+pointer uptr # pointer to user transformation table
+
+bool unitary_greyscale_transformation
+short lut1, lut2, z1_s, z2_s, dz1_s, dz2_s
+real dz1, dz2
+int wy, nx, ny, xblk, yblk
+pointer in, out, si
+pointer sigl2s(), sigl2r(), sigl2_setup()
+errchk sigl2s, sigl2r, sigl2_setup
+real xs, xe, y
+pointer sp, outr
+bool fp_equalr()
+real if_elogr()
+extern if_elogr
+
+include "cv.com"
+
+begin
+ call smark (sp)
+
+ # Set up for scaled image input.
+
+ nx = wx2 - wx1 + 1
+ ny = wy2 - wy1 + 1
+ xblk = INDEFI
+ yblk = INDEFI
+ si = sigl2_setup (im, px1,px2,nx,xblk, py1,py2,ny,yblk)
+
+ # Output array, and limiting x values in NDC
+
+ call salloc (out, nx, TY_SHORT)
+ xs = real(wx1 - 1) * cv_xcon / GKI_MAXNDC
+ # Don't subtract 1 from wx2 as we want it to be first one not filled
+ xe = real(wx2) * cv_xcon / GKI_MAXNDC
+ if ( xe > 1.0)
+ xe = 1.0
+
+ # The device ZMIN and ZMAX parameters define the acceptable range
+ # of greyscale values for the output device (e.g., 0-255 for most 8-bit
+ # display devices). For the general display, we use 0 and the
+ # device "z" resolution. Values Z1 and Z2 are mapped linearly or
+ # logarithmically into these.
+
+ dz1 = 0
+ dz2 = cv_zres-1
+
+ # If the user specified the transfer function, see that the
+ # intensity and greyscale values are in range.
+
+ if (zt == W_USER) {
+ call alims (Mems[uptr], SZ_BUF, lut1, lut2)
+ dz1_s = short (dz1)
+ dz2_s = short (dz2)
+ if (lut2 < dz1_s || lut1 > dz2_s)
+ call eprintf ("User specified greyscales out of range\n")
+ if (z2 < IM_MIN(im) || z1 > IM_MAX(im))
+ call eprintf ("User specified intensities out of range\n")
+ }
+
+ # Type short pixels are treated as a special case to minimize vector
+ # operations for such images (which are common). If the image pixels
+ # are either short or real then only the ALTR (greyscale transformation)
+ # vector operation is required. The ALTR operator linearly maps
+ # greylevels in the range Z1:Z2 to DZ1:DZ2, and does a floor ceiling
+ # of DZ1:DZ2 on all pixels outside the range. If unity mapping is
+ # employed the data is simply copied, i.e., floor ceiling constraints
+ # are not applied. This is very fast and will produce a contoured
+ # image on the display which will be adequate for some applications.
+
+ if (zt == W_UNITARY)
+ unitary_greyscale_transformation = true
+ else
+ unitary_greyscale_transformation =
+ (fp_equalr (dz1,z1) && fp_equalr (dz2,z2)) || fp_equalr (z1,z2)
+
+ if (IM_PIXTYPE(im) == TY_SHORT && zt != W_LOG) {
+
+ # Set dz1_s and dz2_s depending on transformation
+ if (zt != W_USER) {
+ dz1_s = short (dz1)
+ dz2_s = short (dz2)
+ } else {
+ dz1_s = short (STARTPT)
+ dz2_s = short (ENDPT)
+ }
+ z1_s = short (z1)
+ z2_s = short (z2)
+
+ for (wy=wy1; wy <= wy2; wy=wy+1) {
+ in = sigl2s (si, wy - wy1 + 1)
+ y = real(wy-1) * cv_ycon / GKI_MAXNDC
+ if (unitary_greyscale_transformation)
+ call gpcell (cv_gp, Mems[in], nx, 1, xs, y, xe, y)
+ else if (zt == W_USER) {
+ call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s)
+ call aluts (Mems[out], Mems[out], nx, Mems[uptr])
+ call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
+ } else {
+ call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s)
+ call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
+ }
+ }
+ } else {
+ call salloc (outr, nx, TY_REAL)
+ for (wy=wy1; wy <= wy2; wy=wy+1) {
+ in = sigl2r (si, wy - wy1 + 1)
+ y = real(wy - 1) * cv_ycon / GKI_MAXNDC
+
+ if (zt == W_LOG) {
+ call amapr (Memr[in], Memr[outr], nx,
+ z1, z2, 1.0, 10.0 ** MAXLOG)
+ call alogr (Memr[outr], Memr[outr], nx, if_elogr)
+ call amapr (Memr[outr], Memr[outr], nx,
+ 1.0, real(MAXLOG), dz1, dz2)
+ call achtrs (Memr[outr], Mems[out], nx)
+ } else if (unitary_greyscale_transformation) {
+ call achtrs (Memr[in], Mems[out], nx)
+ } else if (zt == W_USER) {
+ call amapr (Memr[in], Memr[outr], nx, z1,z2, STARTPT,ENDPT)
+ call achtrs (Memr[outr], Mems[out], nx)
+ call aluts (Mems[out], Mems[out], nx, Mems[uptr])
+ } else {
+ call amapr (Memr[in], Memr[outr], nx, z1, z2, dz1, dz2)
+ call achtrs (Memr[outr], Mems[out], nx)
+ }
+ call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
+ }
+ }
+
+ call sfree (sp)
+ call sigl2_free (si)
+end
+
+
+# DS_ERASE_BORDER -- Zero the border of the window if the frame has not been
+# erased, and if the displayed section does not occupy the full window.
+# It would be more efficient to do this while writing the greyscale data to
+# the output image, but that would complicate the display procedures and frames
+# are commonly erased before displaying an image.
+
+procedure ds_erase_border (im, wdes, wx1,wx2,wy1,wy2)
+
+pointer im # input image
+pointer wdes # window descriptor
+int wx1,wx2,wy1,wy2 # section of display window filled by image data
+
+int dx1,dx2,dy1,dy2 # coords of full display window in device pixels
+int j, n, n1
+pointer w0
+pointer sp, zero
+real xls, xle, xrs, xre, y
+
+include "cv.com"
+
+begin
+ call smark (sp)
+ call salloc (zero, cv_xres, TY_SHORT)
+ call aclrs (Mems[zero], cv_xres)
+
+ # Compute device pixel coordinates of the full display window.
+ w0 = W_WC(wdes,0)
+ dx1 = W_XS(w0) * (cv_xres - 1) + 1
+ dx2 = W_XE(w0) * (cv_xres - 1) + 1
+ dy1 = W_YS(w0) * (cv_yres - 1) + 1
+ dy2 = W_YE(w0) * (cv_yres - 1) + 1
+
+ # Determine left and right (exclusive), start and end, x values in NDC
+ # for pixels not already filled.
+ # If, say, dx1 < wx1, we want to clear dx1 through wx1-1, which means
+ # that for gpcell, we want the (right) end points to be the first
+ # pixel not cleared.
+ xls = real(dx1 - 1) * cv_xcon / GKI_MAXNDC
+ xle = real(wx1) * cv_xcon / GKI_MAXNDC
+ if (xle > 1.0)
+ xle = 1.0
+ xre = real(dx2 - 1) * cv_xcon / GKI_MAXNDC
+ xrs = real(wx2) * cv_xcon / GKI_MAXNDC
+ if (xre > 1.0)
+ xre = 1.0
+
+ # Erase lower margin.
+ n = dx2 - dx1 + 1
+ for (j=dy1; j < wy1; j=j+1) {
+ y = real(j-1) * cv_ycon / GKI_MAXNDC
+ call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y)
+ }
+
+ # Erase left and right margins. By doing the right margin of a line
+ # immediately after the left margin we have a high liklihood that the
+ # display line will still be in the FIO buffer.
+
+ n = wx1 - dx1
+ n1 = dx2 - wx2
+ for (j=wy1; j <= wy2; j=j+1) {
+ y = real(j-1) * cv_ycon / GKI_MAXNDC
+ if (dx1 < wx1)
+ call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xle, y)
+ if (wx2 < dx2)
+ call gpcell (cv_gp, Mems[zero], n1, 1, xrs, y, xre, y)
+ }
+
+ # Erase upper margin.
+ n = dx2 - dx1 + 1
+ for (j=wy2+1; j <= dy2; j=j+1) {
+ y = real(j-1) * cv_ycon / GKI_MAXNDC
+ call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y)
+ }
+
+ call sfree (sp)
+end
+
+
+# IF_ELOG -- The error function for log10. Note that MAX_EXPONENT is
+# currently an integer so it is converted to the appropriate data type
+# before being returned.
+
+real procedure if_elogr (x)
+
+real x # the input pixel value
+
+begin
+ return (real(-MAX_EXPONENT))
+end
+
diff --git a/pkg/images/tv/iis/src/map.x b/pkg/images/tv/iis/src/map.x
new file mode 100644
index 00000000..5ea7c230
--- /dev/null
+++ b/pkg/images/tv/iis/src/map.x
@@ -0,0 +1,320 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# MAP -- set fixed or variable LUT mapping
+
+procedure map(command)
+
+char command[ARB]
+
+char token[SZ_LINE]
+int tok
+short frames[IDS_MAXIMPL+2] # frames, graphics, EOD
+short colors[IDS_MAXGCOLOR]
+int device
+short pcolor[2]
+real limit
+long seed
+real urand(), xfactor
+int ctoi()
+int i, ip, iseed, level, nchar
+bool triangle
+pointer sp, rdata, gdata, bdata, rp, gp, bp
+
+include "cv.com"
+
+begin
+ # Find out if want to change output tables
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (( tok == TOK_IDENTIFIER) && (token[1] == 'o' )) {
+ device = IDS_OUTPUT_LUT
+ } else {
+ device = IDS_FRAME_LUT
+ # reset input pointers; same as having pushed back token
+ call reset_scan
+ call gargtok (tok, token, SZ_LINE)
+ }
+
+ # Default to all frames, all colors
+ frames[1] = IDS_EOD
+ colors[1] = IDS_EOD
+ triangle = true # default to simple three function type
+ seed = -1
+ level = 8
+
+ # which frames to change, colors, etc
+
+ repeat {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'f') {
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (token[1] == 'c') {
+ call cv_color (token[2], colors)
+ if (colors[1] == ERR)
+ return
+ } else if (token[1] == 'r') { # (random) level count
+ ip = 2
+ nchar = ctoi (token, ip, level)
+ if (nchar <= 0) {
+ call eprintf ("Incorrect random count: %s\n")
+ call pargstr (token[2])
+ return
+ }
+ if (level < 4)
+ level = 4
+ else if (level > 128)
+ level = 128
+ triangle = false
+ } else if (token[1] == 's') { # seed
+ ip = 2
+ nchar = ctoi (token, ip, iseed)
+ if (nchar <= 0) {
+ call eprintf ("Incorrect seed: %s\n")
+ call pargstr (token[2])
+ return
+ }
+ seed = iseed
+ triangle = false
+ } else {
+ call eprintf ("Unknown map argument: %s\n")
+ call pargstr (token)
+ return
+ }
+ } else if (tok != TOK_NEWLINE) {
+ call eprintf ("Unexpected map input: %s\n")
+ call pargstr (token)
+ return
+ }
+ } until ( tok == TOK_NEWLINE)
+
+ pcolor[2] = IDS_EOD
+ # Sorry, but we "know" that ofm shouldn't go beyond first
+ # 256 for common NOAO use.
+ if ( device == IDS_FRAME_LUT)
+ limit = 1.0
+ else
+ limit = 0.25
+
+ # Build the three functions and load them.
+ # First, expand colors if using all
+
+ if (colors[1] == IDS_EOD) {
+ colors[1] = IDS_RED
+ colors[2] = IDS_GREEN
+ colors[3] = IDS_BLUE
+ colors[4] = IDS_EOD
+ }
+
+ # if standard pseudocolor, let kodak do it
+
+ if (triangle) {
+ call kodak (device, frames, colors, limit)
+ return
+ }
+
+ # Not standard pseudo color -- do random one
+ # First, set up arrays
+
+ call smark (sp)
+ call salloc (rdata, level*4, TY_SHORT)
+ call salloc (gdata, level*4, TY_SHORT)
+ call salloc (bdata, level*4, TY_SHORT)
+
+ if (seed == -1)
+ seed = level
+
+ call aclrs (Mems[rdata], level*4)
+ call aclrs (Mems[gdata], level*4)
+ call aclrs (Mems[bdata], level*4)
+
+ xfactor = real(GKI_MAXNDC)/level * limit
+
+ # set first data points to zero (0,0) to (1/level,0)
+ Mems[rdata+2] = xfactor
+ Mems[gdata+2] = xfactor
+ Mems[bdata+2] = xfactor
+ # Set last segment to white ((level-1)/level,1.0) to (1.0,1.0)
+ Mems[rdata+level*4-4] = real(level-1) * xfactor
+ Mems[gdata+level*4-4] = real(level-1) * xfactor
+ Mems[bdata+level*4-4] = real(level-1) * xfactor
+ Mems[rdata+level*4-3] = GKI_MAXNDC
+ Mems[gdata+level*4-3] = GKI_MAXNDC
+ Mems[bdata+level*4-3] = GKI_MAXNDC
+ Mems[rdata+level*4-2] = GKI_MAXNDC
+ Mems[gdata+level*4-2] = GKI_MAXNDC
+ Mems[bdata+level*4-2] = GKI_MAXNDC
+ Mems[rdata+level*4-1] = GKI_MAXNDC
+ Mems[gdata+level*4-1] = GKI_MAXNDC
+ Mems[bdata+level*4-1] = GKI_MAXNDC
+
+ # Do the intermediate ones
+ do i=2, level-1 {
+ rp = rdata + (i-1)*4
+ gp = gdata + (i-1)*4
+ bp = bdata + (i-1)*4
+ Mems[rp] = real(i-1) * xfactor
+ Mems[gp] = real(i-1) * xfactor
+ Mems[bp] = real(i-1) * xfactor
+ Mems[rp+1] = urand(seed) * GKI_MAXNDC
+ Mems[gp+1] = urand(seed) * GKI_MAXNDC
+ Mems[bp+1] = urand(seed) * GKI_MAXNDC
+ Mems[rp+2] = real(i) * xfactor
+ Mems[gp+2] = real(i) * xfactor
+ Mems[bp+2] = real(i) * xfactor
+ Mems[rp+3] = Mems[rp+1]
+ Mems[gp+3] = Mems[gp+1]
+ Mems[bp+3] = Mems[bp+1]
+ }
+
+ # If color requested, do it
+ for ( i = 1; colors[i] != IDS_EOD; i = i + 1 ) {
+ pcolor[1] = colors[i]
+ switch (colors[i]) {
+ case IDS_RED:
+ call cvwlut (device, frames, pcolor, Mems[rdata], level*4)
+
+ case IDS_GREEN:
+ call cvwlut (device, frames, pcolor, Mems[gdata], level*4)
+
+ case IDS_BLUE:
+ call cvwlut (device, frames, pcolor, Mems[bdata], level*4)
+ }
+ }
+
+ call sfree (sp)
+end
+
+# KODAK -- provides three variable width and variable center triangular
+# color mapping functions.
+
+procedure kodak (device, frames, colors, limit)
+
+int device # IDS_FRAME_LUT or IDS_OUTPUT_LUT
+short frames[ARB] # frames to change
+short colors[ARB] # colors to affect
+real limit # factor to apply to limit x range
+
+short wdata[20], pcolor[2]
+real center, width
+int n, ksub(), button, i
+int cv_rdbut(), cv_wtbut()
+
+begin
+ pcolor[2] = IDS_EOD
+ for (i = 1; colors[i] != IDS_EOD; i = i + 1) {
+ pcolor[1] = colors[i]
+ switch (colors[i]) {
+ case IDS_RED:
+ n = ksub (1.0, 0.5, wdata, limit)
+
+ case IDS_GREEN:
+ n = ksub (0.5, 0.5, wdata, limit)
+
+ case IDS_BLUE:
+ n = ksub (0.0, 0.5, wdata, limit)
+ }
+
+ call cvwlut (device, frames, pcolor, wdata, n)
+ }
+
+ button = cv_rdbut() # clear buttons
+ repeat {
+ call eprintf ("Press A, B, C for red, green, blue; D to exit\n")
+ button = cv_wtbut()
+ if (button == 4)
+ break
+ switch (button) {
+ case 1:
+ pcolor[1] = IDS_RED
+
+ case 2:
+ pcolor[1] = IDS_GREEN
+
+ case 3:
+ pcolor[1] = IDS_BLUE
+ }
+
+ # Loop, reading cursor and modifying the display for the
+ # selected color.
+
+ repeat {
+ call cv_rcraw(center, width)
+ width = width * 2. # flatten it
+ n = ksub (center, width, wdata, limit)
+ call cvwlut (device, frames, pcolor, wdata, n)
+ button = cv_rdbut()
+ } until (button != 0)
+ }
+end
+
+# KSUB -- determines data points for a triangular mapping function
+# Returns number of points in data array.
+
+int procedure ksub (center, width, data, limit)
+
+real center, width, limit
+short data[ARB]
+
+int n
+real xs, xe, ys, ye, xscale
+
+include "cv.com"
+
+begin
+ n = 0
+ xscale = GKI_MAXNDC * limit
+ if (width < (1.0/cv_yres))
+ width = 1.0/cv_yres
+
+ if (center > 0.) {
+ xs = center - width
+ if (xs < 0.)
+ xs = 0.
+ else if (xs > 0.) {
+ data[1] = 0.
+ data[2] = 0.
+ n = n + 2
+ }
+ ys = (xs - center)/width + 1.0
+ data[n+1] = xs * xscale
+ data[n+2] = ys * GKI_MAXNDC
+ data[n+3] = center * xscale
+ data[n+4] = GKI_MAXNDC
+ n = n + 4
+ }
+
+ if (center < 1.0) {
+ xe = width + center
+ if (xe > 1.0)
+ xe = 1.0
+ ye = (center - xe)/width + 1.0
+ data[n+1] = center * xscale
+ data[n+2] = GKI_MAXNDC
+ data[n+3] = xe * xscale
+ data[n+4] = ye * GKI_MAXNDC
+ n = n + 4
+ if (xe < 1.0) {
+ data[n+1] = xscale
+ data[n+2] = 0
+ n = n + 2
+ }
+ }
+
+ # Extend last value to end
+ if (limit != 1.0) {
+ data[n+1] = GKI_MAXNDC
+ data[n+2] = data[n]
+ n = n + 2
+ }
+
+ return (n)
+end
diff --git a/pkg/images/tv/iis/src/match.x b/pkg/images/tv/iis/src/match.x
new file mode 100644
index 00000000..ebbe523d
--- /dev/null
+++ b/pkg/images/tv/iis/src/match.x
@@ -0,0 +1,172 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include "../lib/ids.h"
+
+# MATCH -- Match look up tables. The command reads
+# match this_one (to) that one
+
+procedure match
+
+char token[SZ_LINE]
+int tok
+short f_ref[2]
+short c_ref[IDS_MAXGCOLOR+1]
+short frames[IDS_MAXIMPL+1]
+short colors[IDS_MAXGCOLOR+1]
+short nextcolor
+int nchar, i, val, ctoi()
+int ltype
+
+include "cv.com"
+
+begin
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if ( (tok == TOK_IDENTIFIER) && (token[1] == 'o') ) {
+ ltype = IDS_OUTPUT_LUT
+ } else {
+ ltype = IDS_FRAME_LUT
+ # "Push back" the token
+ call reset_scan
+ call gargtok (tok, token, SZ_LINE)
+ }
+
+ # All this parsing tells us why YACC and LEX were invented
+ # Use "i" to tell if have parsed something useful
+
+ i = -1
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if ((tok == TOK_IDENTIFIER) && (token[1] == 'f')) {
+ i = 1
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (tok == TOK_NUMBER) {
+ i = 1
+ nchar = ctoi (token, i, val)
+ if ((val < 1) || (val > cv_maxframes)) {
+ call eprintf ("Invalid frame specification: %d\n")
+ call pargi (val)
+ return
+ } else {
+ frames[1] = val
+ frames[2] = IDS_EOD
+ }
+ } else if (ltype == IDS_FRAME_LUT) {
+ call eprintf ("missing frame arguement\n")
+ return
+ } else
+ frames[1] = IDS_EOD
+
+ # default first color argument to all colors for both FRAME and OUTPUT
+ # tables...means make all colors the same.
+
+ colors[1] = IDS_EOD # default all colors
+
+ # Advance if previous token was useful
+
+ if ( i != -1 ) {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+
+ # Look for a color
+
+ if ((tok == TOK_IDENTIFIER) && (token[1] == 'c')) {
+ call cv_color (token[2], colors)
+ if (colors[1] == ERR)
+ return
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+
+ # look for fill word "to"
+
+ if ((tok == TOK_IDENTIFIER) && (token[1] == 't')) {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+
+ # if FRAME LUT, we default frame to first frame to be changed.
+ # if OUTPUT LUT, frame is irrelevant
+
+ i = -1
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'f')
+ i = 2
+ else if (token[1] != 'c') {
+ call eprintf ("Unexpected argument: %s\n")
+ call pargstr (token)
+ return
+ }
+ } else if (tok == TOK_NUMBER)
+ i = 1
+
+ # if ltype is OUTPUT lut, don't care about frame type, but can't
+ # omit it...so default to EOD
+
+ f_ref[1] = IDS_EOD
+ f_ref[2] = IDS_EOD
+ if (ltype == IDS_FRAME_LUT) {
+ if (i == -1) {
+ f_ref[1] = frames[1]
+ } else {
+ nchar = ctoi (token, i, val)
+ if ((val < 1) || (val > cv_maxframes)) {
+ call eprintf ("Invalid frame specification: %d\n")
+ call pargi (val)
+ return
+ }
+ f_ref[1] = val
+ }
+ }
+
+ # Only thing left should be the reference color.
+ # If found a frame before, advance the token.
+
+ if (i != -1) {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ }
+ if ((tok != TOK_NEWLINE) && (tok != TOK_IDENTIFIER)) {
+ call eprintf ("Unexpected input: %s\n")
+ call pargstr (token)
+ return
+ }
+ c_ref[1] = IDS_EOD
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] != 'c') {
+ call eprintf ("Unexpected input (color required): %s\n")
+ call pargstr (token)
+ return
+ } else {
+ call cv_color (token[2], c_ref)
+ if (c_ref[1] == ERR)
+ return
+ }
+ }
+
+ if (c_ref[1] != IDS_EOD)
+ call cvmatch (ltype, f_ref, c_ref, frames, colors)
+ else {
+ # No specific color for reference. If no color specified
+ # to copy into, do all.
+ c_ref[2] = IDS_EOD
+ if ( colors[1] == IDS_EOD ) {
+ colors[1] = IDS_RED
+ colors[2] = IDS_GREEN
+ colors[3] = IDS_BLUE
+ colors[4] = IDS_EOD
+ }
+ # Match for each color given in "colors"
+ for ( i = 1 ; colors[i] != IDS_EOD; i = i + 1) {
+ nextcolor = colors[i+1]
+ colors[i+1] = IDS_EOD
+ c_ref[1] = colors[i]
+ call cvmatch (ltype, f_ref, c_ref, frames, colors[i])
+ colors[i+1] = nextcolor
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/src/maxmin.x b/pkg/images/tv/iis/src/maxmin.x
new file mode 100644
index 00000000..d16874e9
--- /dev/null
+++ b/pkg/images/tv/iis/src/maxmin.x
@@ -0,0 +1,52 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <imhdr.h>
+
+# MAXMIN -- Get the minimum and maximum pixel values of an image. If valid
+# header values are available they are used, otherwise the image is sampled
+# on an even grid and the min and max values of this sample are returned.
+
+procedure maxmin (im, zmin, zmax, nsample_lines)
+
+pointer im
+real zmin, zmax # min and max intensity values
+int nsample_lines # amount of image to sample
+
+int step, ncols, nlines, sample_size, imlines, i
+real minval, maxval
+pointer imgl2r()
+
+begin
+ # Only calculate minimum, maximum pixel values if the current
+ # values are unknown, or if the image was modified since the
+ # old values were computed.
+
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ if (IM_LIMTIME(im) >= IM_MTIME(im)) {
+ # Use min and max values in image header if they are up to date.
+ zmin = IM_MIN(im)
+ zmax = IM_MAX(im)
+
+ } else {
+ zmin = MAX_REAL
+ zmax = -MAX_REAL
+
+ # Try to include a constant number of pixels in the sample
+ # regardless of the image size. The entire image is used if we
+ # have a small image, and at least sample_lines lines are read
+ # if we have a large image.
+
+ sample_size = 512 * nsample_lines
+ imlines = min(nlines, max(nsample_lines, sample_size / ncols))
+ step = nlines / (imlines + 1)
+
+ do i = 1 + step, nlines, max (1, step) {
+ call alimr (Memr[imgl2r(im,i)], ncols, minval, maxval)
+ zmin = min (zmin, minval)
+ zmax = max (zmax, maxval)
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/src/mkpkg b/pkg/images/tv/iis/src/mkpkg
new file mode 100644
index 00000000..34ee515c
--- /dev/null
+++ b/pkg/images/tv/iis/src/mkpkg
@@ -0,0 +1,39 @@
+# Make the CV display load and control package.
+
+$checkout libpkg.a ../
+$update libpkg.a
+$checkin libpkg.a ../
+$exit
+
+libpkg.a:
+ blink.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com
+ clear.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ cv.x cv.com cv.h ../lib/ids.h <ctotok.h> <error.h> <fio.h>\
+ <fset.h> <gki.h>
+ cvparse.x cv.com ../lib/ids.h <ctype.h>
+ cvulut.x cv.h <ctype.h> <error.h>
+ cvutil.x cv.com cv.h ../lib/ids.h <gki.h> <gset.h> <imhdr.h>\
+ cv.com
+ display.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ load1.x cv.com cv.h ../lib/ids.h <error.h> <gki.h> gwindow.h\
+ <fio.h> <fset.h> <imhdr.h> <imset.h> <mach.h>
+ load2.x cv.com cv.h ../lib/ids.h <error.h> <gki.h> gwindow.h\
+ cv.com <fio.h> <fset.h> <imhdr.h> <imset.h> <mach.h>
+ map.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com
+ match.x ../lib/ids.h <ctotok.h> cv.com
+ maxmin.x <imhdr.h> <mach.h>
+ offset.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ pan.x cv.com ../lib/ids.h <ctotok.h> <ctype.h> <gki.h>
+ range.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ rdcur.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com <gki.h>
+ reset.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ sigl2.x <error.h> <imhdr.h>
+ snap.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com <gki.h>\
+ <imhdr.h>
+ split.x ../lib/ids.h <ctotok.h> <ctype.h> cv.com
+ tell.x ../lib/ids.h cv.com
+ text.x ../lib/ids.h <ctotok.h> <ctype.h>
+ window.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com
+ zoom.x ../lib/ids.h <ctotok.h> <ctype.h> <gki.h> cv.com
+ zscale.x <imhdr.h>
+ ;
diff --git a/pkg/images/tv/iis/src/offset.x b/pkg/images/tv/iis/src/offset.x
new file mode 100644
index 00000000..356ae55f
--- /dev/null
+++ b/pkg/images/tv/iis/src/offset.x
@@ -0,0 +1,53 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# OFFSET -- Change the bias (offset) for certain colors
+
+procedure offset()
+
+int tok, i, nchar, ip
+char token[SZ_LINE]
+short color[IDS_MAXGCOLOR+1]
+short offsetdata[4] # extra space for cvmove EOD
+int count, ctoi()
+
+include "cv.com"
+
+begin
+ # In principle, we should be able to accept input for color group
+ # followed by offset value(s) or "vice versa" or for a series of
+ # color/offset pairs. We try for most of that.
+ color[1] = ERR
+ offsetdata[1] = ERR
+ count = 1
+ # anything but TOK_NEWLINE
+ tok = TOK_NUMBER
+ repeat {
+ if (tok == TOK_NEWLINE) {
+ call eprintf ("Insufficient offset specification\n")
+ return
+ }
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (token[1] == 'c') {
+ call cv_color (token[2], color)
+ if (color[1] == ERR)
+ return
+ } else if (tok == TOK_NUMBER) {
+ ip = 1
+ nchar = ctoi (token, ip, i)
+ if ( count <= 3) {
+ offsetdata[count] = i
+ count = count + 1
+ }
+ }
+ } until ( (color[1] != ERR) && (offsetdata[1] != ERR) &&
+ (tok == TOK_NEWLINE) )
+
+ offsetdata[count] = IDS_EOD # mark end
+
+ call cvoffset (color, offsetdata)
+end
diff --git a/pkg/images/tv/iis/src/pan.x b/pkg/images/tv/iis/src/pan.x
new file mode 100644
index 00000000..b8929510
--- /dev/null
+++ b/pkg/images/tv/iis/src/pan.x
@@ -0,0 +1,99 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# PAN -- pan some or all of the frames
+
+procedure pan()
+
+char token[SZ_LINE]
+int tok
+short frames[IDS_MAXIMPL+2] # frames, graphics, EOD
+
+include "cv.com"
+
+begin
+ frames[1] = IDS_EOD # default all frames
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (token[1] == 'f') {
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (tok == TOK_NUMBER) {
+ call cv_frame (token[1], frames)
+ if (frames[1] == ERR)
+ return
+ } else {
+ call eprintf ("Unexpected input: %s\n")
+ call pargstr (token)
+ return
+ }
+
+ call pansub (frames)
+end
+
+
+# PANSUB -- Pan subroutine, handles code common to pan and zoom
+
+procedure pansub (frames)
+
+short frames[ARB] # frames to pan
+
+int button
+int cnum, cv_rdbut()
+real x,y, xc, yc
+real oldx, oldy
+
+include "cv.com"
+
+begin
+ button = cv_rdbut() # clear buttons by reading them
+ call eprintf ("Press any button when done\n")
+
+ # Where is cursor now?
+
+ call cv_rcraw (xc,yc)
+
+ # Calculate NDC screen center and cursor number.
+ # x,y are NDC, but always < 1.0 The transformation applied here
+ # insures that the correct pixel is calculated by the kernel
+ # after passing x,y through the gio cursor routines.
+ x = real(cv_xcen - 1) * cv_xcon / GKI_MAXNDC
+ y = real(cv_ycen - 1) * cv_ycon / GKI_MAXNDC
+ cnum = frames[1]
+ if (cnum == IDS_EOD)
+ cnum = 0
+ call cv_scraw (x, y) # put cursor at screen center
+
+ # Determine NDC there for frame of interest
+ call cv_rcur (cnum, x, y)
+
+ # Restore cursor
+ 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 > 1.0)
+ x = x - 1.0
+ else if (x < 0)
+ x = x + 1.0
+ if (y > 1.0)
+ y = y - 1.0
+ else if (y < 0)
+ y = y + 1.0
+ call cvpan (frames, x, y)
+ } until (button > 0)
+end
diff --git a/pkg/images/tv/iis/src/range.x b/pkg/images/tv/iis/src/range.x
new file mode 100644
index 00000000..664e3ab8
--- /dev/null
+++ b/pkg/images/tv/iis/src/range.x
@@ -0,0 +1,57 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# RANGE -- set the scaling (range) registers
+
+procedure range()
+
+char token[SZ_LINE]
+int tok, i, nchar, ip
+short color[IDS_MAXGCOLOR+1]
+short rdata[4] # extra space for cvmove EOD
+int count, ctoi()
+
+include "cv.com"
+
+begin
+ # In principle, we should be able to accept input for color group
+ # followed by range value(s) or "vice versa" or for a series of
+ # color/range pairs. We try for most of that.
+ color[1] = IDS_EOD
+ rdata[1] = ERR
+ count = 1
+ # anything but TOK_NEWLINE
+ tok = TOK_NUMBER
+ repeat {
+ if (tok == TOK_NEWLINE) {
+ call eprintf ("Insufficient range specification\n")
+ return
+ }
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (token[1] == 'c') {
+ call cv_color (token[2], color)
+ if (color[1] == ERR)
+ return
+ } else if (tok == TOK_NUMBER) {
+ ip = 1
+ nchar = ctoi (token, ip, i)
+ if (i < 1) {
+ call eprintf ("bad range specification: %d\n")
+ call pargi (i)
+ return
+ }
+ if ( count <= 3) {
+ rdata[count] = i
+ count = count + 1
+ }
+ }
+ } until ( (rdata[1] != ERR) && (tok == TOK_NEWLINE ))
+
+ rdata[count] = IDS_EOD # mark end
+
+ call cvrange ( color, rdata)
+end
diff --git a/pkg/images/tv/iis/src/rdcur.x b/pkg/images/tv/iis/src/rdcur.x
new file mode 100644
index 00000000..5d27097e
--- /dev/null
+++ b/pkg/images/tv/iis/src/rdcur.x
@@ -0,0 +1,111 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# RDCUR -- read cursor and datum
+
+procedure rdcur()
+
+char token[SZ_LINE], ch
+int tok, cnum, px, py
+int junk, ip, fx, fy
+real x,y
+short datum
+short frames[IDS_MAXIMPL+2] # frames, one graphics, EOD
+int scan(), ctoi(), mod(), and()
+
+include "cv.com"
+
+begin
+ cnum = ERR
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_NUMBER) {
+ ip = 1
+ junk = ctoi (token, ip, cnum)
+ frames[1] = cnum
+ frames[2] = IDS_EOD
+ }
+ else if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'o') {
+ if (token[2] == 'n')
+ call cvcur(IDS_ON)
+ else if (token[2] == 'f')
+ call cvcur(IDS_OFF)
+ else {
+ call eprintf ("Unrecognized cursor command: %s\n")
+ call pargstr (token)
+ }
+ return
+ }
+ call cv_frame (token[2], frames)
+ cnum = frames[1]
+ if ( cnum == IDS_EOD) {
+ call eprintf ("Please specify a particular frame\n")
+ return
+ }
+ }
+ if ( (cnum == ERR) || (cnum < 1) ) {
+ call eprintf ("bad cursor number: %d\n")
+ call pargi (cnum)
+ return
+ }
+
+ # set kernel to do i/o on specified frames (for ggcell routine)
+ call cv_iset (frames)
+
+ call eprintf ("Press <cr> for each read; any key but <sp>, and then <cr>, to exit\n")
+ repeat {
+ if (scan() != EOS)
+ break
+ repeat {
+ call scanc (ch)
+ } until (ch != ' ')
+ if (ch != '\n')
+ break
+ call cv_rcur (cnum, x, y)
+ call ggcell (cv_gp, datum, 1, 1, x, y, x, y)
+ x = x * GKI_MAXNDC / cv_xcon + 1.
+ y = y * GKI_MAXNDC / cv_ycon + 1.
+ px = int(x)
+ py = int(y)
+ # Only allow fractions to 1/8 as that is max zoom for IIS
+ x = real (int((x - px)*8))/8.
+ y = real (int((y - py)*8))/8.
+ # Print minimum number of decimal places, but do x and y the same
+ call eprintf ("frame %d, pixel (")
+ call pargi (cnum)
+ fx = x * 8
+ fy = y * 8
+ if ((fx == 0) && (fy == 0)) {
+ call eprintf ("%d,%d")
+ call pargi (px)
+ call pargi (py)
+ junk = 0
+ } else {
+ call eprintf ("%.*f,%.*f")
+
+ if ( (mod(fx,4) == 0) && (mod(fy,4) == 0) )
+ junk = 1
+ else if ( (and(fx,1) != 0) || (and(fy,1) != 0) )
+ junk = 3
+ else
+ junk = 2
+
+ call pargi (junk)
+ call pargr (px+x)
+ call pargi (junk)
+ call pargr (py+y)
+ }
+ if (junk == 0)
+ junk = 8
+ else
+ junk = 6 - 2 * junk
+ call eprintf ("): %*w%4d\n")
+ call pargi (junk)
+ call pargs (datum)
+ }
+end
diff --git a/pkg/images/tv/iis/src/reset.x b/pkg/images/tv/iis/src/reset.x
new file mode 100644
index 00000000..3a2e60e9
--- /dev/null
+++ b/pkg/images/tv/iis/src/reset.x
@@ -0,0 +1,37 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# RESET -- reset the display
+
+procedure reset()
+
+char token[SZ_LINE]
+int tok
+
+include "cv.com"
+
+begin
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ switch(token[1]) {
+ case 'r':
+ call cvreset( IDS_R_SOFT)
+
+ case 't':
+ call cvreset( IDS_R_MEDIUM)
+
+ case 'i':
+ call cvreset( IDS_R_HARD)
+
+ case 'a':
+ call cvreset( IDS_R_SOFT)
+ call cvreset( IDS_R_MEDIUM)
+ call cvreset( IDS_R_HARD)
+
+ }
+ }
+end
diff --git a/pkg/images/tv/iis/src/sigl2.x b/pkg/images/tv/iis/src/sigl2.x
new file mode 100644
index 00000000..226d4f5b
--- /dev/null
+++ b/pkg/images/tv/iis/src/sigl2.x
@@ -0,0 +1,677 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+include <error.h>
+
+.help sigl2, sigl2_setup
+.nf ___________________________________________________________________________
+SIGL2 -- Get a line from a spatially scaled 2-dimensional image. This procedure
+works like the regular IMIO get line procedure, but rescales the input
+2-dimensional image in either or both axes upon input. If the magnification
+ratio required is greater than 0 and less than 2 then linear interpolation is
+used to resample the image. If the magnification ratio is greater than or
+equal to 2 then the image is block averaged by the smallest factor which
+reduces the magnification to the range 0-2 and then interpolated back up to
+the desired size. In some cases this will smooth the data slightly, but the
+operation is efficient and avoids aliasing effects.
+
+ si = sigl2_setup (im, x1,x2,nx, y1,y2,ny)
+ sigl2_free (si)
+ ptr = sigl2[sr] (si, linenumber)
+
+SIGL2_SETUP must be called to set up the transformations after mapping the
+image and before performing any scaled i/o to the image. SIGL2_FREE must be
+called when finished to return buffer space.
+.endhelp ______________________________________________________________________
+
+# Scaled image descriptor for 2-dim images
+
+define SI_LEN 15
+define SI_MAXDIM 2 # images of 2 dimensions supported
+define SI_NBUFS 3 # nbuffers used by SIGL2
+
+define SI_IM Memi[$1] # pointer to input image header
+define SI_GRID Memi[$1+1+$2-1] # pointer to array of X coords
+define SI_NPIX Memi[$1+3+$2-1] # number of X coords
+define SI_BAVG Memi[$1+5+$2-1] # X block averaging factor
+define SI_INTERP Memi[$1+7+$2-1] # interpolate X axis
+define SI_BUF Memi[$1+9+$2-1] # line buffers
+define SI_TYBUF Memi[$1+12] # buffer type
+define SI_XOFF Memi[$1+13] # offset in input image to first X
+define SI_INIT Memi[$1+14] # YES until first i/o is done
+
+define OUTBUF SI_BUF($1,3)
+
+define SI_TOL (1E-5) # close to a pixel
+define INTVAL (abs ($1 - nint($1)) < SI_TOL)
+define SWAPI {tempi=$2;$2=$1;$1=tempi}
+define SWAPP {tempp=$2;$2=$1;$1=tempp}
+define NOTSET (-9999)
+
+# SIGL2_SETUP -- Set up the spatial transformation for SIGL2[SR]. Compute
+# the block averaging factors (1 if no block averaging is required) and
+# the sampling grid points, i.e., pixel coordinates of the output pixels in
+# the input image.
+#
+# Valdes - Jan 9, 1985:
+# Nx or ny can be 1 and blocking factors can be specified.
+
+pointer procedure sigl2_setup (im, px1, px2, nx, xblk, py1, py2, ny, yblk)
+
+pointer im # the input image
+real px1, px2 # range in X to be sampled on an even grid
+int nx # number of output pixels in X
+int xblk # blocking factor in x
+real py1, py2 # range in Y to be sampled on an even grid
+int ny # number of output pixels in Y
+int yblk # blocking factor in y
+
+int npix, noldpix, nbavpix, i, j
+int npts[SI_MAXDIM] # number of output points for axis
+int blksize[SI_MAXDIM] # block averaging factor (npix per block)
+real tau[SI_MAXDIM] # tau = p(i+1) - p(i) in fractional pixels
+real p1[SI_MAXDIM] # starting pixel coords in each axis
+real p2[SI_MAXDIM] # ending pixel coords in each axis
+real scalar, start
+pointer si, gp
+
+begin
+ iferr (call calloc (si, SI_LEN, TY_STRUCT))
+ call erract (EA_FATAL)
+
+ SI_IM(si) = im
+ SI_NPIX(si,1) = nx
+ SI_NPIX(si,2) = ny
+ SI_INIT(si) = YES
+
+ p1[1] = px1 # X = index 1
+ p2[1] = px2
+ npts[1] = nx
+ blksize[1] = xblk
+
+ p1[2] = py1 # Y = index 2
+ p2[2] = py2
+ npts[2] = ny
+ blksize[2] = yblk
+
+ # Compute block averaging factors if not defined.
+ # If there is only one pixel then the block average is the average
+ # between the first and last point.
+
+ do i = 1, SI_MAXDIM {
+ if ((blksize[i] >= 1) && !IS_INDEFI (blksize[i])) {
+ if (npts[i] == 1)
+ tau[i] = 0.
+ else
+ tau[i] = (p2[i] - p1[i]) / (npts[i] - 1)
+ } else {
+ if (npts[i] == 1) {
+ tau[i] = 0.
+ blksize[i] = int (p2[i] - p1[i] + 1)
+ } else {
+ tau[i] = (p2[i] - p1[i]) / (npts[i] - 1)
+ if (tau[i] >= 2.0) {
+
+ # If nx or ny is not an integral multiple of the block
+ # averaging factor, noldpix is the next larger number
+ # which is an integral multiple. When the image is
+ # block averaged pixels will be replicated as necessary
+ # to fill the last block out to this size.
+
+ blksize[i] = int (tau[i])
+ npix = p2[i] - p1[i] + 1
+ noldpix = (npix+blksize[i]-1) / blksize[i] * blksize[i]
+ nbavpix = noldpix / blksize[i]
+ scalar = real (nbavpix - 1) / real (noldpix - 1)
+ p1[i] = (p1[i] - 1.0) * scalar + 1.0
+ p2[i] = (p2[i] - 1.0) * scalar + 1.0
+ tau[i] = (p2[i] - p1[i]) / (npts[i] - 1)
+ } else
+ blksize[i] = 1
+ }
+ }
+ }
+
+ SI_BAVG(si,1) = blksize[1]
+ SI_BAVG(si,2) = blksize[2]
+
+ if (IS_INDEFI (xblk))
+ xblk = blksize[1]
+ if (IS_INDEFI (yblk))
+ yblk = blksize[2]
+
+ # Allocate and initialize the grid arrays, specifying the X and Y
+ # coordinates of each pixel in the output image, in units of pixels
+ # in the input (possibly block averaged) image.
+
+ do i = 1, SI_MAXDIM {
+ # The X coordinate is special. We do not want to read entire
+ # input image lines if only a range of input X values are needed.
+ # Since the X grid vector passed to ALUI (the interpolator) must
+ # contain explicit offsets into the vector being interpolated,
+ # we must generate interpolator grid points starting near 1.0.
+ # The X origin, used to read the block averaged input line, is
+ # given by XOFF.
+
+ if (i == 1) {
+ SI_XOFF(si) = int (p1[i])
+ start = p1[1] - int (p1[i]) + 1.0
+ } else
+ start = p1[i]
+
+ # Do the axes need to be interpolated?
+ if (INTVAL(start) && INTVAL(tau[i]))
+ SI_INTERP(si,i) = NO
+ else
+ SI_INTERP(si,i) = YES
+
+ # Allocate grid buffer and set the grid points.
+ iferr (call malloc (gp, npts[i], TY_REAL))
+ call erract (EA_FATAL)
+ SI_GRID(si,i) = gp
+ do j = 0, npts[i]-1
+ Memr[gp+j] = start + (j * tau[i])
+ }
+
+ return (si)
+end
+
+
+# SIGL2_FREE -- Free storage associated with an image opened for scaled
+# input. This does not close and unmap the image.
+
+procedure sigl2_free (si)
+
+pointer si
+int i
+
+begin
+ # Free SIGL2 buffers.
+ do i = 1, SI_NBUFS
+ if (SI_BUF(si,i) != NULL)
+ call mfree (SI_BUF(si,i), SI_TYBUF(si))
+
+ # Free GRID buffers.
+ do i = 1, SI_MAXDIM
+ if (SI_GRID(si,i) != NULL)
+ call mfree (SI_GRID(si,i), TY_REAL)
+
+ call mfree (si, TY_STRUCT)
+end
+
+
+# SIGL2S -- Get a line of type short from a scaled image. Block averaging is
+# done by a subprocedure; this procedure gets a line from a possibly block
+# averaged image and if necessary interpolates it to the grid points of the
+# output line.
+
+pointer procedure sigl2s (si, lineno)
+
+pointer si # pointer to SI descriptor
+int lineno
+
+pointer rawline, tempp, gp
+int i, buf_y[2], new_y[2], tempi, curbuf, altbuf
+int npix, nblks_y, ybavg, x1, x2
+real x, y, weight_1, weight_2
+pointer si_blkavgs()
+errchk si_blkavgs
+
+begin
+ npix = SI_NPIX(si,1)
+
+ # Determine the range of X (in pixels on the block averaged input image)
+ # required for the interpolator.
+
+ gp = SI_GRID(si,1)
+ x1 = SI_XOFF(si)
+ x = Memr[gp+npix-1]
+ x2 = x1 + int(x)
+ if (INTVAL(x))
+ x2 = x2 - 1
+ x2 = max (x1 + 1, x2)
+
+ gp = SI_GRID(si,2)
+ y = Memr[gp+lineno-1]
+
+ # The following is an optimization provided for the case when it is
+ # not necessary to interpolate in either X or Y. Block averaging is
+ # permitted.
+
+ if (SI_INTERP(si,1) == NO && SI_INTERP(si,2) == NO)
+ return (si_blkavgs (SI_IM(si), x1, x2, int(y),
+ SI_BAVG(si,1), SI_BAVG(si,2)))
+
+ # If we are interpolating in Y two buffers are required, one for each
+ # of the two input image lines required to interpolate in Y. The lines
+ # stored in these buffers are interpolated in X to the output grid but
+ # not in Y. Both buffers are not required if we are not interpolating
+ # in Y, but we use them anyhow to simplify the code.
+
+ if (SI_INIT(si) == YES) {
+ do i = 1, 2 {
+ if (SI_BUF(si,i) != NULL)
+ call mfree (SI_BUF(si,i), SI_TYBUF(si))
+ call malloc (SI_BUF(si,i), npix, TY_SHORT)
+ SI_TYBUF(si) = TY_SHORT
+ buf_y[i] = NOTSET
+ }
+ if (OUTBUF(si) != NULL)
+ call mfree (OUTBUF(si), SI_TYBUF(si))
+ call malloc (OUTBUF(si), npix, TY_SHORT)
+ SI_INIT(si) = NO
+ }
+
+ # If the Y value of the new line is not in range of the contents of the
+ # current line buffers, refill one or both buffers. To refill we must
+ # read a (possibly block averaged) input line and interpolate it onto
+ # the X grid. The X and Y values herein are in the coordinate system
+ # of the (possibly block averaged) input image.
+
+ new_y[1] = int(y)
+ new_y[2] = int(y) + 1
+
+ # Get the pair of lines whose integral Y values form an interval
+ # containing the fractional Y value of the output line. Sometimes the
+ # desired line will happen to be in the other buffer already, in which
+ # case we just have to swap buffers. Often the new line will be the
+ # current line, in which case nothing is done. This latter case occurs
+ # frequently when the magnification ratio is large.
+
+ curbuf = 1
+ altbuf = 2
+
+ do i = 1, 2 {
+ if (new_y[i] == buf_y[i]) {
+ ;
+ } else if (new_y[i] == buf_y[altbuf]) {
+ SWAPP (SI_BUF(si,1), SI_BUF(si,2))
+ SWAPI (buf_y[1], buf_y[2])
+
+ } else {
+ # Get line and interpolate onto output grid. If interpolation
+ # is not required merely copy data out. This code is set up
+ # to always use two buffers; in effect, there is one buffer of
+ # look ahead, even when Y[i] is integral. This means that we
+ # will go out of bounds by one line at the top of the image.
+ # This is handled by copying the last line.
+
+ ybavg = SI_BAVG(si,2)
+ nblks_y = (IM_LEN (SI_IM(si), 2) + ybavg-1) / ybavg
+ if (new_y[i] <= nblks_y)
+ rawline = si_blkavgs (SI_IM(si), x1, x2, new_y[i],
+ SI_BAVG(si,1), SI_BAVG(si,2))
+
+ if (SI_INTERP(si,1) == NO)
+ call amovs (Mems[rawline], Mems[SI_BUF(si,i)], npix)
+ else {
+ call aluis (Mems[rawline], Mems[SI_BUF(si,i)],
+ Memr[SI_GRID(si,1)], npix)
+ }
+
+ buf_y[i] = new_y[i]
+ }
+
+ SWAPI (altbuf, curbuf)
+ }
+
+ # We now have two line buffers straddling the output Y value,
+ # interpolated to the X grid of the output line. To complete the
+ # bilinear interpolation operation we take a weighted sum of the two
+ # lines. If the range from buf_y[1] to buf_y[2] is repeatedly
+ # interpolated in Y no additional i/o occurs and the linear
+ # interpolation operation (ALUI) does not have to be repeated (only the
+ # weighted sum is required). If the distance of Y from one of the
+ # buffers is zero then we do not even have to take a weighted sum.
+ # This is not unusual because we may be called with a magnification
+ # of 1.0 in Y.
+
+ weight_1 = 1.0 - (y - buf_y[1])
+ weight_2 = 1.0 - weight_1
+
+ if (weight_2 < SI_TOL)
+ return (SI_BUF(si,1))
+ else if (weight_1 < SI_TOL)
+ return (SI_BUF(si,2))
+ else {
+ call awsus (Mems[SI_BUF(si,1)], Mems[SI_BUF(si,2)],
+ Mems[OUTBUF(si)], npix, weight_1, weight_2)
+ return (OUTBUF(si))
+ }
+end
+
+
+# SI_BLKAVGS -- Get a line from a block averaged image of type short.
+# For example, block averaging by a factor of 2 means that pixels 1 and 2
+# are averaged to produce the first output pixel, 3 and 4 are averaged to
+# produce the second output pixel, and so on. If the length of an axis
+# is not an integral multiple of the block size then the last pixel in the
+# last block will be replicated to fill out the block; the average is still
+# defined even if a block is not full.
+
+pointer procedure si_blkavgs (im, x1, x2, y, xbavg, ybavg)
+
+pointer im # input image
+int x1, x2 # range of x blocks to be read
+int y # y block to be read
+int xbavg, ybavg # X and Y block averaging factors
+
+short temp_s
+int nblks_x, nblks_y, ncols, nlines, xoff, i, j
+int first_line, nlines_in_sum, npix, nfull_blks, count
+real sum
+pointer sp, a, b
+pointer imgs2s()
+errchk imgs2s
+
+begin
+ call smark (sp)
+
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xoff = (x1 - 1) * xbavg + 1
+ npix = min (ncols, xoff + (x2 - x1 + 1) * xbavg - 1)
+
+ if ((xbavg < 1) || (ybavg < 1))
+ call error (1, "si_blkavg: illegal block size")
+ else if (x1 < 1 || x2 > ncols)
+ call error (2, "si_blkavg: column index out of bounds")
+ else if ((xbavg == 1) && (ybavg == 1))
+ return (imgs2s (im, xoff, xoff + npix - 1, y, y))
+
+ nblks_x = (npix + xbavg-1) / xbavg
+ nblks_y = (nlines + ybavg-1) / ybavg
+
+ if (y < 1 || y > nblks_y)
+ call error (2, "si_blkavg: block number out of range")
+
+ call salloc (b, nblks_x, TY_SHORT)
+
+ if (ybavg > 1) {
+ call aclrs (Mems[b], nblks_x)
+ nlines_in_sum = 0
+ }
+
+ # Read and accumulate all input lines in the block.
+ first_line = (y - 1) * ybavg + 1
+
+ do i = first_line, min (nlines, first_line + ybavg - 1) {
+ # Get line from input image.
+ a = imgs2s (im, xoff, xoff + npix - 1, i, i)
+
+ # Block average line in X.
+ if (xbavg > 1) {
+ # First block average only the full blocks.
+ nfull_blks = npix / xbavg
+ call abavs (Mems[a], Mems[a], nfull_blks, xbavg)
+
+ # Now average the final partial block, if any.
+ if (nfull_blks < nblks_x) {
+ sum = 0.0
+ count = 0
+ do j = nfull_blks * xbavg + 1, npix {
+ sum = sum + Mems[a+j-1]
+ count = count + 1
+ }
+ Mems[a+nblks_x-1] = sum / count
+ }
+ }
+
+ # Add line into block sum. Keep track of number of lines in sum
+ # so that we can compute block average later.
+ if (ybavg > 1) {
+ call aadds (Mems[a], Mems[b], Mems[b], nblks_x)
+ nlines_in_sum = nlines_in_sum + 1
+ }
+ }
+
+ # Compute the block average in Y from the sum of all lines block
+ # averaged in X. Overwrite buffer A, the buffer returned by IMIO.
+ # This is kosher because the block averaged line is never longer
+ # than an input line.
+
+ if (ybavg > 1) {
+ temp_s = nlines_in_sum
+ call adivks (Mems[b], temp_s, Mems[a], nblks_x)
+ }
+
+ call sfree (sp)
+ return (a)
+end
+
+
+# SIGL2R -- Get a line of type real from a scaled image. Block averaging is
+# done by a subprocedure; this procedure gets a line from a possibly block
+# averaged image and if necessary interpolates it to the grid points of the
+# output line.
+
+pointer procedure sigl2r (si, lineno)
+
+pointer si # pointer to SI descriptor
+int lineno
+
+pointer rawline, tempp, gp
+int i, buf_y[2], new_y[2], tempi, curbuf, altbuf
+int npix, nblks_y, ybavg, x1, x2
+real x, y, weight_1, weight_2
+pointer si_blkavgr()
+errchk si_blkavgr
+
+begin
+ npix = SI_NPIX(si,1)
+
+ # Deterine the range of X (in pixels on the block averaged input image)
+ # required for the interpolator.
+
+ gp = SI_GRID(si,1)
+ x1 = SI_XOFF(si)
+ x = Memr[gp+npix-1]
+ x2 = x1 + int(x)
+ if (INTVAL(x))
+ x2 = x2 - 1
+ x2 = max (x1 + 1, x2)
+
+ gp = SI_GRID(si,2)
+ y = Memr[gp+lineno-1]
+
+ # The following is an optimization provided for the case when it is
+ # not necessary to interpolate in either X or Y. Block averaging is
+ # permitted.
+
+ if (SI_INTERP(si,1) == NO && SI_INTERP(si,2) == NO)
+ return (si_blkavgr (SI_IM(si), x1, x2, int(y),
+ SI_BAVG(si,1), SI_BAVG(si,2)))
+
+ # If we are interpolating in Y two buffers are required, one for each
+ # of the two input image lines required to interpolate in Y. The lines
+ # stored in these buffers are interpolated in X to the output grid but
+ # not in Y. Both buffers are not required if we are not interpolating
+ # in Y, but we use them anyhow to simplify the code.
+
+ if (SI_INIT(si) == YES) {
+ do i = 1, 2 {
+ if (SI_BUF(si,i) != NULL)
+ call mfree (SI_BUF(si,i), SI_TYBUF(si))
+ call malloc (SI_BUF(si,i), npix, TY_REAL)
+ SI_TYBUF(si) = TY_REAL
+ buf_y[i] = NOTSET
+ }
+ if (OUTBUF(si) != NULL)
+ call mfree (OUTBUF(si), SI_TYBUF(si))
+ call malloc (OUTBUF(si), npix, TY_REAL)
+ SI_INIT(si) = NO
+ }
+
+ # If the Y value of the new line is not in range of the contents of the
+ # current line buffers, refill one or both buffers. To refill we must
+ # read a (possibly block averaged) input line and interpolate it onto
+ # the X grid. The X and Y values herein are in the coordinate system
+ # of the (possibly block averaged) input image.
+
+ new_y[1] = int(y)
+ new_y[2] = int(y) + 1
+
+ # Get the pair of lines whose integral Y values form an interval
+ # containing the fractional Y value of the output line. Sometimes the
+ # desired line will happen to be in the other buffer already, in which
+ # case we just have to swap buffers. Often the new line will be the
+ # current line, in which case nothing is done. This latter case occurs
+ # frequently when the magnification ratio is large.
+
+ curbuf = 1
+ altbuf = 2
+
+ do i = 1, 2 {
+ if (new_y[i] == buf_y[i]) {
+ ;
+ } else if (new_y[i] == buf_y[altbuf]) {
+ SWAPP (SI_BUF(si,1), SI_BUF(si,2))
+ SWAPI (buf_y[1], buf_y[2])
+
+ } else {
+ # Get line and interpolate onto output grid. If interpolation
+ # is not required merely copy data out. This code is set up
+ # to always use two buffers; in effect, there is one buffer of
+ # look ahead, even when Y[i] is integral. This means that we
+ # will go out of bounds by one line at the top of the image.
+ # This is handled by copying the last line.
+
+ ybavg = SI_BAVG(si,2)
+ nblks_y = (IM_LEN (SI_IM(si), 2) + ybavg-1) / ybavg
+ if (new_y[i] <= nblks_y)
+ rawline = si_blkavgr (SI_IM(si), x1, x2, new_y[i],
+ SI_BAVG(si,1), SI_BAVG(si,2))
+
+ if (SI_INTERP(si,1) == NO)
+ call amovr (Memr[rawline], Memr[SI_BUF(si,i)], npix)
+ else {
+ call aluir (Memr[rawline], Memr[SI_BUF(si,i)],
+ Memr[SI_GRID(si,1)], npix)
+ }
+
+ buf_y[i] = new_y[i]
+ }
+
+ SWAPI (altbuf, curbuf)
+ }
+
+ # We now have two line buffers straddling the output Y value,
+ # interpolated to the X grid of the output line. To complete the
+ # bilinear interpolation operation we take a weighted sum of the two
+ # lines. If the range from buf_y[1] to buf_y[2] is repeatedly
+ # interpolated in Y no additional i/o occurs and the linear
+ # interpolation operation (ALUI) does not have to be repeated (only the
+ # weighted sum is required). If the distance of Y from one of the
+ # buffers is zero then we do not even have to take a weighted sum.
+ # This is not unusual because we may be called with a magnification
+ # of 1.0 in Y.
+
+ weight_1 = 1.0 - (y - buf_y[1])
+ weight_2 = 1.0 - weight_1
+
+ if (weight_2 < SI_TOL)
+ return (SI_BUF(si,1))
+ else if (weight_1 < SI_TOL)
+ return (SI_BUF(si,2))
+ else {
+ call awsur (Memr[SI_BUF(si,1)], Memr[SI_BUF(si,2)],
+ Memr[OUTBUF(si)], npix, weight_1, weight_2)
+ return (OUTBUF(si))
+ }
+end
+
+
+# SI_BLKAVGR -- Get a line from a block averaged image of type short.
+# For example, block averaging by a factor of 2 means that pixels 1 and 2
+# are averaged to produce the first output pixel, 3 and 4 are averaged to
+# produce the second output pixel, and so on. If the length of an axis
+# is not an integral multiple of the block size then the last pixel in the
+# last block will be replicated to fill out the block; the average is still
+# defined even if a block is not full.
+
+pointer procedure si_blkavgr (im, x1, x2, y, xbavg, ybavg)
+
+pointer im # input image
+int x1, x2 # range of x blocks to be read
+int y # y block to be read
+int xbavg, ybavg # X and Y block averaging factors
+
+int nblks_x, nblks_y, ncols, nlines, xoff, i, j
+int first_line, nlines_in_sum, npix, nfull_blks, count
+real sum
+pointer sp, a, b
+pointer imgs2r()
+errchk imgs2r
+
+begin
+ call smark (sp)
+
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+ xoff = (x1 - 1) * xbavg + 1
+ npix = min (ncols, xoff + (x2 - x1 + 1) * xbavg - 1)
+
+ if ((xbavg < 1) || (ybavg < 1))
+ call error (1, "si_blkavg: illegal block size")
+ else if (x1 < 1 || x2 > ncols)
+ call error (2, "si_blkavg: column index out of bounds")
+ else if ((xbavg == 1) && (ybavg == 1))
+ return (imgs2r (im, xoff, xoff + npix - 1, y, y))
+
+ nblks_x = (npix + xbavg-1) / xbavg
+ nblks_y = (nlines + ybavg-1) / ybavg
+
+ if (y < 1 || y > nblks_y)
+ call error (2, "si_blkavg: block number out of range")
+
+ call salloc (b, nblks_x, TY_REAL)
+
+ if (ybavg > 1) {
+ call aclrr (Memr[b], nblks_x)
+ nlines_in_sum = 0
+ }
+
+ # Read and accumulate all input lines in the block.
+ first_line = (y - 1) * ybavg + 1
+
+ do i = first_line, min (nlines, first_line + ybavg - 1) {
+ # Get line from input image.
+ a = imgs2r (im, xoff, xoff + npix - 1, i, i)
+
+ # Block average line in X.
+ if (xbavg > 1) {
+ # First block average only the full blocks.
+ nfull_blks = npix / xbavg
+ call abavr (Memr[a], Memr[a], nfull_blks, xbavg)
+
+ # Now average the final partial block, if any.
+ if (nfull_blks < nblks_x) {
+ sum = 0.0
+ count = 0
+ do j = nfull_blks * xbavg + 1, npix {
+ sum = sum + Memr[a+j-1]
+ count = count + 1
+ }
+ Memr[a+nblks_x-1] = sum / count
+ }
+ }
+
+ # Add line into block sum. Keep track of number of lines in sum
+ # so that we can compute block average later.
+ if (ybavg > 1) {
+ call aaddr (Memr[a], Memr[b], Memr[b], nblks_x)
+ nlines_in_sum = nlines_in_sum + 1
+ }
+ }
+
+ # Compute the block average in Y from the sum of all lines block
+ # averaged in X. Overwrite buffer A, the buffer returned by IMIO.
+ # This is kosher because the block averaged line is never longer
+ # than an input line.
+
+ if (ybavg > 1)
+ call adivkr (Memr[b], real(nlines_in_sum), Memr[a], nblks_x)
+
+ call sfree (sp)
+ return (a)
+end
diff --git a/pkg/images/tv/iis/src/snap.x b/pkg/images/tv/iis/src/snap.x
new file mode 100644
index 00000000..12694568
--- /dev/null
+++ b/pkg/images/tv/iis/src/snap.x
@@ -0,0 +1,64 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <imhdr.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# SNAP -- Take a picture!!
+
+procedure snap()
+
+char token[SZ_LINE]
+int tok
+char fname[SZ_FNAME]
+int snap_color
+
+include "cv.com"
+
+begin
+ snap_color = IDS_SNAP_MONO # default color for snap
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] != 'c') {
+ call eprintf ("unknown snap argument: %s\n")
+ call pargstr (token)
+ return
+ } else {
+ # snap colors: r, g, b, rgb, m (monochrome) == bw (black/white)
+ switch (token[2]) {
+ case 'm':
+ snap_color = IDS_SNAP_MONO
+
+ case 'r':
+ if ((token[3] == 'g') && (token[4] == 'b') )
+ snap_color = IDS_SNAP_RGB
+ else
+ snap_color = IDS_SNAP_RED
+
+ case 'g':
+ snap_color = IDS_SNAP_GREEN
+
+ case 'b':
+ if (token[3] == 'w')
+ snap_color = IDS_SNAP_MONO
+ else
+ snap_color = IDS_SNAP_BLUE
+
+ default:
+ call eprintf ("Unknown snap color: %c\n")
+ call pargc (token[2])
+ return
+ }
+ }
+ } else if (tok != TOK_NEWLINE) {
+ call eprintf ("unexpected argument to snap: %s\n")
+ call pargstr (token)
+ return
+ }
+
+ call clgstr("snap_file", fname, SZ_FNAME)
+ call cvsnap (fname, snap_color)
+end
diff --git a/pkg/images/tv/iis/src/split.x b/pkg/images/tv/iis/src/split.x
new file mode 100644
index 00000000..393fc218
--- /dev/null
+++ b/pkg/images/tv/iis/src/split.x
@@ -0,0 +1,95 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# SPLIT -- set the split screen point
+
+procedure split()
+
+char token[SZ_LINE]
+int tok
+int nchar, ctoi()
+int i, x, y
+real xr, yr
+int ctor()
+bool a_real
+
+define errmsg 10
+
+include "cv.com"
+
+begin
+ a_real = false
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ switch(token[1]) {
+ case 'c':
+ x = cv_xcen
+ y = cv_ycen
+
+ case 'o':
+ x = 1
+ y = 1
+
+ case 'n', 'p': # n: ndc, p: pixel
+ if (token[1] == 'n')
+ a_real = true
+ if (IS_DIGIT(token[2]))
+ i = 2
+ else {
+ call gargtok (tok, token, SZ_LINE)
+ if (tok != TOK_NUMBER) {
+errmsg
+ call eprintf ("bad split pixel: %s\n")
+ call pargstr (token)
+ return
+ } else
+ i = 1
+ }
+ if (a_real)
+ nchar = ctor (token, i, xr)
+ else
+ nchar = ctoi (token, i, x)
+ if (nchar == 0) {
+ call eprintf ("No conversion, ")
+ goto errmsg
+ }
+ call gargtok (tok, token, SZ_LINE)
+ if (tok == TOK_PUNCTUATION)
+ call gargtok (tok, token, SZ_LINE)
+ i = 1
+ if (a_real)
+ nchar = ctor (token, i, yr)
+ else
+ nchar = ctoi (token, i, y)
+ if (nchar == 0) {
+ call eprintf ("No conversion, ")
+ goto errmsg
+ }
+
+ default:
+ call eprintf ("unknown split code: %c\n")
+ call pargc (token[1])
+ return
+ }
+ }
+ # Convert to NDC, BUT note, that as x and y range from 1 through
+ # cv_[xy]res, xr and yr will never be 1.0---and they must not be
+ # (see cvsplit())
+ if (!a_real ) {
+ xr = real(x-1) / cv_xres
+ yr = real(y-1) / cv_xres
+ }
+ if ( xr < 0 )
+ xr = 0
+ if ( yr < 0 )
+ yr = 0
+ if ( xr >= 1.0 )
+ xr = real(cv_xres-1)/cv_xres
+ if ( yr >= 1.0 )
+ yr = real(cv_yres-1)/cv_yres
+ call cvsplit (xr, yr)
+end
diff --git a/pkg/images/tv/iis/src/tell.x b/pkg/images/tv/iis/src/tell.x
new file mode 100644
index 00000000..cce4987e
--- /dev/null
+++ b/pkg/images/tv/iis/src/tell.x
@@ -0,0 +1,24 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+
+include "../lib/ids.h"
+
+# TELL -- Tell user about display state
+
+procedure tell()
+
+short f[IDS_MAXIMPL+2] # Ultimately, want an array terminated
+ # with IDS_EOD as usual
+
+include "cv.com"
+
+begin
+ # We don't know much, do we?
+
+ call cvwhich(f)
+ if ( f[1] > 0) {
+ call eprintf ("Frame %d, at least, is on.\n")
+ call pargs (f[1])
+ } else
+ call eprintf ("No frames are on.\n")
+end
diff --git a/pkg/images/tv/iis/src/text.x b/pkg/images/tv/iis/src/text.x
new file mode 100644
index 00000000..32623786
--- /dev/null
+++ b/pkg/images/tv/iis/src/text.x
@@ -0,0 +1,71 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include "../lib/ids.h"
+
+# TEXT -- put text into image planes or graphics bit planes
+
+procedure text()
+
+char token[SZ_LINE]
+int tok, ip, cnum
+short frames[IDS_MAXIMPL+2] # frames, graphics, EOD
+short colors[IDS_MAXGCOLOR]
+real x, y
+int button, cv_wtbut()
+char line[SZ_LINE]
+real size, clgetr()
+
+begin
+ frames[1] = ERR
+ colors[1] = ERR
+
+ # which frames for text
+
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'f') {
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (token[1] == 'c') {
+ call cv_color (token[2], colors)
+ if (colors[1] == ERR)
+ return
+ }
+ } else if (tok == TOK_NUMBER) {
+ call cv_frame (token[1], frames)
+ if (frames[1] == ERR)
+ return
+ }
+ if ( (frames[1] == ERR) && (colors[1] == ERR)) {
+ call eprintf ("Inadequate text specification: %s\n")
+ call pargstr (token)
+ return
+ }
+
+ call gargstr (line, SZ_LINE)
+
+ # Prompt user to set cursor
+
+ call eprintf ("Set cursor to desired location, then press any button\n")
+ button = cv_wtbut()
+
+ # Set up kernel for write
+ if (frames[1] != ERR) {
+ cnum = frames[1]
+ call cv_iset (frames)
+ } else {
+ cnum = 16 # SORRY, is IIS specific - we should do better
+ call cv_gset (colors)
+ }
+ call cv_rcur (cnum, x, y)
+
+ size = clgetr("textsize")
+ ip = 1
+ while (IS_WHITE(line[ip]))
+ ip = ip + 1
+ call cvtext (x, y, line[ip], size)
+end
diff --git a/pkg/images/tv/iis/src/window.x b/pkg/images/tv/iis/src/window.x
new file mode 100644
index 00000000..e3523a90
--- /dev/null
+++ b/pkg/images/tv/iis/src/window.x
@@ -0,0 +1,181 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# WINDOW -- window the display.
+
+procedure window()
+
+char token[SZ_LINE]
+int tok, cnum
+short frames[IDS_MAXIMPL+2] # frames, graphics, EOD
+short colors[IDS_MAXGCOLOR]
+real x, y
+real xold, yold
+int device, button, cv_rdbut()
+short wdata[16]
+int n, first, last
+real istart, iend, slope
+
+include "cv.com"
+
+begin
+ # Find out if want to change output tables
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (( tok == TOK_IDENTIFIER) && (token[1] == 'o')) {
+ device = IDS_OUTPUT_LUT
+ slope = 4.0 # Device dependent !!
+ } else {
+ device = IDS_FRAME_LUT
+ slope = 1.0
+ # reset input pointers; same as having pushed back token
+ call reset_scan
+ call gargtok (tok, token, SZ_LINE)
+ }
+
+ # Default to all frames, all colors
+ frames[1] = IDS_EOD
+ colors[1] = IDS_EOD
+
+ # which frames to window
+
+ repeat {
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (tok == TOK_IDENTIFIER) {
+ if (token[1] == 'f') {
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (token[1] == 'c') {
+ call cv_color (token[2], colors)
+ if (colors[1] == ERR)
+ return
+ } else {
+ call eprintf ("Unknown window argument: %s\n")
+ call pargstr (token)
+ return
+ }
+ } else if (tok == TOK_NUMBER) {
+ call cv_frame (token[1], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (tok != TOK_NEWLINE) {
+ call eprintf ("Unexpected window input: %s\n")
+ call pargstr (token)
+ return
+ }
+ } until ( tok == TOK_NEWLINE)
+
+ # rememeber current cursor postion
+
+ cnum = 0
+ call cv_rcur (cnum, xold, yold)
+
+ # Now set up loop to window display; we need to read back
+ # display but cannot, so for now, use "common" variables
+ # If first time, use defaults.
+
+ if (cv_xwinc == -1) {
+ if (slope == 1.0) {
+ cv_xwinc = 0.25
+ cv_ywinc = .75
+ } else {
+ cv_xwinc = .0625
+ cv_ywinc = .9375
+ }
+ }
+ call cv_scraw (cv_xwinc, cv_ywinc)
+
+ button = cv_rdbut() # clear buttons by reading them
+ call eprintf ("Press any button when done\n")
+
+ # The mapping equation is table value = 0.25 + y * (i-x)
+ # where i runs from 0 to 1.0, x ranges from 0. to 1.0 and y
+ # from 0 to large.
+
+ repeat {
+ call cv_rcraw (cv_xwinc, cv_ywinc)
+ x = cv_xwinc
+ y = (cv_ywinc - 0.5) * 4
+ # Keep y from equalling 2 or -2 :
+ if (y >= 2.)
+ y = 1.99
+ else if ( y <= -2.0)
+ y = -1.99
+ if (y > 1.)
+ y = 1. / (2. - y)
+ else if (y < -1.)
+ y = -1. / (2. + y)
+
+ if ( y == 0.0) {
+ iend = 1.0
+ istart = 0.0
+ first = 0
+ last = GKI_MAXNDC
+ } else if ( y > 0.) {
+ istart = x - 0.25/y
+ iend = 1.0/y + istart
+ first = 0
+ last = GKI_MAXNDC
+ } else {
+ iend = x - 0.25/y
+ istart = 1.0/y + iend
+ first = GKI_MAXNDC
+ last = 0
+ }
+ if (istart < 0.)
+ istart = 0.
+ if (iend > 1.0)
+ iend = 1.0
+ if (istart > 1.0)
+ istart = 1.0
+ if (iend < istart)
+ iend = istart
+ wdata[1] = 0
+ if ( istart > 0.) {
+ wdata[2] = first
+ wdata[3] = istart * GKI_MAXNDC
+ wdata[4] = first
+ n = 5
+ } else {
+ wdata[2] = (0.25 -x*y) * GKI_MAXNDC
+ n = 3
+ }
+ wdata[n] = iend * GKI_MAXNDC
+ if ( iend < 1.0) {
+ # In this case, we reach max/min y value before end of table, so
+ # extend it horizontally to end
+ wdata[n+1] = last
+ wdata[n+2] = GKI_MAXNDC
+ wdata[n+3] = last
+ n = n + 3
+ } else {
+ wdata[n+1] = (0.25 + y * (1.0 - x)) * GKI_MAXNDC
+ n = n + 1
+ }
+ call cvwlut (device, frames, colors, wdata, n)
+ button = cv_rdbut()
+ } until (button > 0)
+
+ # Restore old cursor position
+ call cv_rcur (cnum, xold, yold)
+
+ # Tell the user what final mapping was
+ call printf ("window: from (%5.3f,%5.3f) to (%5.3f,%5.3f)\n")
+ call pargr (istart)
+ if (istart > 0.)
+ call pargr (real(first)/GKI_MAXNDC)
+ else
+ call pargr (real(wdata[2])/GKI_MAXNDC)
+ call pargr (iend)
+ if (iend < 1.0)
+ call pargr (real(last)/GKI_MAXNDC)
+ else
+ call pargr (real(wdata[n])/GKI_MAXNDC)
+
+end
diff --git a/pkg/images/tv/iis/src/zoom.x b/pkg/images/tv/iis/src/zoom.x
new file mode 100644
index 00000000..c7e7bff7
--- /dev/null
+++ b/pkg/images/tv/iis/src/zoom.x
@@ -0,0 +1,60 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctotok.h>
+include <ctype.h>
+include <gki.h>
+include "../lib/ids.h"
+
+# ZOOM -- zoom, then pan, the display. If zoom power == 1, then
+# don't bother panning.
+
+procedure zoom()
+
+char token[SZ_LINE]
+int tok, count, power, cnum
+short frames[IDS_MAXIMPL+2] # frames, graphics, EOD
+real x, y
+int ctoi, ip
+
+include "cv.com"
+
+begin
+ # get power for zoom
+
+ call gargtok (tok, token, SZ_LINE)
+ if (tok != TOK_NUMBER) {
+ call eprintf ("Bad zoom power: %s\n")
+ call pargstr (token)
+ return
+ }
+ ip = 1
+ count = ctoi(token, ip, power)
+
+ # which frames to zoom
+
+ frames[1] = IDS_EOD # default all frames
+ call gargtok (tok, token, SZ_LINE)
+ call strlwr (token)
+ if (token[1] == 'f') {
+ call cv_frame (token[2], frames)
+ if (frames[1] == ERR)
+ return
+ } else if (tok == TOK_NUMBER) {
+ call cv_frame (token[1], frames)
+ if (frames[1] == ERR)
+ return
+ } else {
+ call eprintf ("Unexpected input: %s\n")
+ call pargstr (token)
+ return
+ }
+
+ # where to zoom ... find which frame to read cursor position from
+
+ cnum = frames[1]
+ if (cnum == IDS_EOD)
+ cnum = 0
+ call cv_rcur (cnum, x, y)
+ call cvzoom (frames, power, x, y)
+ call pansub (frames)
+end
diff --git a/pkg/images/tv/iis/src/zscale.x b/pkg/images/tv/iis/src/zscale.x
new file mode 100644
index 00000000..bfb0b116
--- /dev/null
+++ b/pkg/images/tv/iis/src/zscale.x
@@ -0,0 +1,457 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <imhdr.h>
+
+.help zscale
+.nf ___________________________________________________________________________
+ZSCALE -- Compute the optimal Z1, Z2 (range of greyscale values to be
+displayed) of an image. For efficiency a statistical subsample of an image
+is used. The pixel sample evenly subsamples the image in x and y. The entire
+image is used if the number of pixels in the image is smaller than the desired
+sample.
+
+The sample is accumulated in a buffer and sorted by greyscale value.
+The median value is the central value of the sorted array. The slope of a
+straight line fitted to the sorted sample is a measure of the standard
+deviation of the sample about the median value. Our algorithm is to sort
+the sample and perform an iterative fit of a straight line to the sample,
+using pixel rejection to omit gross deviants near the endpoints. The fitted
+straight line is the transfer function used to map image Z into display Z.
+If more than half the pixels are rejected the full range is used. The slope
+of the fitted line is divided by the user-supplied contrast factor and the
+final Z1 and Z2 are computed, taking the origin of the fitted line at the
+median value.
+.endhelp ______________________________________________________________________
+
+define MIN_NPIXELS 5 # smallest permissible sample
+define MAX_REJECT 0.5 # max frac. of pixels to be rejected
+define GOOD_PIXEL 0 # use pixel in fit
+define BAD_PIXEL 1 # ignore pixel in all computations
+define REJECT_PIXEL 2 # reject pixel after a bit
+define KREJ 2.5 # k-sigma pixel rejection factor
+define MAX_ITERATIONS 5 # maximum number of fitline iterations
+
+
+# ZSCALE -- Sample the image and compute Z1 and Z2.
+
+procedure zscale (im, z1, z2, contrast, optimal_sample_size, len_stdline)
+
+pointer im # image to be sampled
+real z1, z2 # output min and max greyscale values
+real contrast # adj. to slope of transfer function
+int optimal_sample_size # desired number of pixels in sample
+int len_stdline # optimal number of pixels per line
+
+int npix, minpix, ngoodpix, center_pixel, ngrow
+real zmin, zmax, median
+real zstart, zslope
+pointer sample, left
+int zsc_sample_image(), zsc_fit_line()
+
+begin
+ # Subsample the image.
+ npix = zsc_sample_image (im, sample, optimal_sample_size, len_stdline)
+ center_pixel = max (1, (npix + 1) / 2)
+
+ # Sort the sample, compute the minimum, maximum, and median pixel
+ # values.
+
+ call asrtr (Memr[sample], Memr[sample], npix)
+ zmin = Memr[sample]
+ zmax = Memr[sample+npix-1]
+
+ # The median value is the average of the two central values if there
+ # are an even number of pixels in the sample.
+
+ left = sample + center_pixel - 1
+ if (mod (npix, 2) == 1 || center_pixel >= npix)
+ median = Memr[left]
+ else
+ median = (Memr[left] + Memr[left+1]) / 2
+
+ # Fit a line to the sorted sample vector. If more than half of the
+ # pixels in the sample are rejected give up and return the full range.
+ # If the user-supplied contrast factor is not 1.0 adjust the scale
+ # accordingly and compute Z1 and Z2, the y intercepts at indices 1 and
+ # npix.
+
+ minpix = max (MIN_NPIXELS, int (npix * MAX_REJECT))
+ ngrow = max (1, nint (npix * .01))
+ ngoodpix = zsc_fit_line (Memr[sample], npix, zstart, zslope,
+ KREJ, ngrow, MAX_ITERATIONS)
+
+ if (ngoodpix < minpix) {
+ z1 = zmin
+ z2 = zmax
+ } else {
+ if (contrast > 0)
+ zslope = zslope / contrast
+ z1 = max (zmin, median - (center_pixel - 1) * zslope)
+ z2 = min (zmax, median + (npix - center_pixel) * zslope)
+ }
+
+ call mfree (sample, TY_REAL)
+end
+
+
+# ZSC_SAMPLE_IMAGE -- Extract an evenly gridded subsample of the pixels from
+# a two-dimensional image into a one-dimensional vector.
+
+int procedure zsc_sample_image (im, sample, optimal_sample_size, len_stdline)
+
+pointer im # image to be sampled
+pointer sample # output vector containing the sample
+int optimal_sample_size # desired number of pixels in sample
+int len_stdline # optimal number of pixels per line
+
+int ncols, nlines, col_step, line_step, maxpix, line
+int opt_npix_per_line, npix_per_line
+int opt_nlines_in_sample, min_nlines_in_sample, max_nlines_in_sample
+pointer op
+pointer imgl2r()
+
+begin
+ ncols = IM_LEN(im,1)
+ nlines = IM_LEN(im,2)
+
+ # Compute the number of pixels each line will contribute to the sample,
+ # and the subsampling step size for a line. The sampling grid must
+ # span the whole line on a uniform grid.
+
+ opt_npix_per_line = min (ncols, len_stdline)
+ col_step = (ncols + opt_npix_per_line-1) / opt_npix_per_line
+ npix_per_line = (ncols + col_step-1) / col_step
+
+ # Compute the number of lines to sample and the spacing between lines.
+ # We must ensure that the image is adequately sampled despite its
+ # size, hence there is a lower limit on the number of lines in the
+ # sample. We also want to minimize the number of lines accessed when
+ # accessing a large image, because each disk seek and read is expensive.
+ # The number of lines extracted will be roughly the sample size divided
+ # by len_stdline, possibly more if the lines are very short.
+
+ min_nlines_in_sample = max (1, optimal_sample_size / len_stdline)
+ opt_nlines_in_sample = max(min_nlines_in_sample, min(nlines,
+ (optimal_sample_size + npix_per_line-1) / npix_per_line))
+ line_step = max (1, nlines / (opt_nlines_in_sample))
+ max_nlines_in_sample = (nlines + line_step-1) / line_step
+
+ # Allocate space for the output vector. Buffer must be freed by our
+ # caller.
+
+ maxpix = npix_per_line * max_nlines_in_sample
+ call malloc (sample, maxpix, TY_REAL)
+
+# call eprintf ("sample: x[%d:%d:%d] y[%d:%d:%d]\n")
+# call pargi(1);call pargi(ncols); call pargi(col_step)
+# call pargi((line_step+1)/2); call pargi(nlines); call pargi(line_step)
+
+ # Extract the vector.
+ op = sample
+ do line = (line_step + 1) / 2, nlines, line_step {
+ call zsc_subsample (Memr[imgl2r(im,line)], Memr[op],
+ npix_per_line, col_step)
+ op = op + npix_per_line
+ if (op - sample + npix_per_line > maxpix)
+ break
+ }
+
+ return (op - sample)
+end
+
+
+# ZSC_SUBSAMPLE -- Subsample an image line. Extract the first pixel and
+# every "step"th pixel thereafter for a total of npix pixels.
+
+procedure zsc_subsample (a, b, npix, step)
+
+real a[ARB]
+real b[npix]
+int npix, step
+int ip, i
+
+begin
+ if (step <= 1)
+ call amovr (a, b, npix)
+ else {
+ ip = 1
+ do i = 1, npix {
+ b[i] = a[ip]
+ ip = ip + step
+ }
+ }
+end
+
+
+# ZSC_FIT_LINE -- Fit a straight line to a data array of type real. This is
+# an iterative fitting algorithm, wherein points further than ksigma from the
+# current fit are excluded from the next fit. Convergence occurs when the
+# next iteration does not decrease the number of pixels in the fit, or when
+# there are no pixels left. The number of pixels left after pixel rejection
+# is returned as the function value.
+
+int procedure zsc_fit_line (data, npix, zstart, zslope, krej, ngrow, maxiter)
+
+real data[npix] # data to be fitted
+int npix # number of pixels before rejection
+real zstart # Z-value of pixel data[1] (output)
+real zslope # dz/pixel (output)
+real krej # k-sigma pixel rejection factor
+int ngrow # number of pixels of growing
+int maxiter # max iterations
+
+int i, ngoodpix, last_ngoodpix, minpix, niter
+real xscale, z0, dz, x, z, mean, sigma, threshold
+double sumxsqr, sumxz, sumz, sumx, rowrat
+pointer sp, flat, badpix, normx
+int zsc_reject_pixels(), zsc_compute_sigma()
+
+begin
+ call smark (sp)
+
+ if (npix <= 0)
+ return (0)
+ else if (npix == 1) {
+ zstart = data[1]
+ zslope = 0.0
+ return (1)
+ } else
+ xscale = 2.0 / (npix - 1)
+
+ # Allocate a buffer for data minus fitted curve, another for the
+ # normalized X values, and another to flag rejected pixels.
+
+ call salloc (flat, npix, TY_REAL)
+ call salloc (normx, npix, TY_REAL)
+ call salloc (badpix, npix, TY_SHORT)
+ call aclrs (Mems[badpix], npix)
+
+ # Compute normalized X vector. The data X values [1:npix] are
+ # normalized to the range [-1:1]. This diagonalizes the lsq matrix
+ # and reduces its condition number.
+
+ do i = 0, npix - 1
+ Memr[normx+i] = i * xscale - 1.0
+
+ # Fit a line with no pixel rejection. Accumulate the elements of the
+ # matrix and data vector. The matrix M is diagonal with
+ # M[1,1] = sum x**2 and M[2,2] = ngoodpix. The data vector is
+ # DV[1] = sum (data[i] * x[i]) and DV[2] = sum (data[i]).
+
+ sumxsqr = 0
+ sumxz = 0
+ sumx = 0
+ sumz = 0
+
+ do i = 1, npix {
+ x = Memr[normx+i-1]
+ z = data[i]
+ sumxsqr = sumxsqr + (x ** 2)
+ sumxz = sumxz + z * x
+ sumz = sumz + z
+ }
+# call eprintf ("\t%10g %10g %10g\n")
+# call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz)
+
+ # Solve for the coefficients of the fitted line.
+ z0 = sumz / npix
+ dz = sumxz / sumxsqr
+
+# call eprintf ("fit: z0=%g, dz=%g\n")
+# call pargr(z0); call pargr(dz)
+
+ # Iterate, fitting a new line in each iteration. Compute the flattened
+ # data vector and the sigma of the flat vector. Compute the lower and
+ # upper k-sigma pixel rejection thresholds. Run down the flat array
+ # and detect pixels to be rejected from the fit. Reject pixels from
+ # the fit by subtracting their contributions from the matrix sums and
+ # marking the pixel as rejected.
+
+ ngoodpix = npix
+ minpix = max (MIN_NPIXELS, int (npix * MAX_REJECT))
+
+ for (niter=1; niter <= maxiter; niter=niter+1) {
+ last_ngoodpix = ngoodpix
+
+ # Subtract the fitted line from the data array.
+ call zsc_flatten_data (data, Memr[flat], Memr[normx], npix, z0, dz)
+
+ # Compute the k-sigma rejection threshold. In principle this
+ # could be more efficiently computed using the matrix sums
+ # accumulated when the line was fitted, but there are problems with
+ # numerical stability with that approach.
+
+ ngoodpix = zsc_compute_sigma (Memr[flat], Mems[badpix], npix,
+ mean, sigma)
+ threshold = sigma * krej
+
+ # Detect and reject pixels further than ksigma from the fitted
+ # line.
+ ngoodpix = zsc_reject_pixels (data, Memr[flat], Memr[normx],
+ Mems[badpix], npix, sumxsqr, sumxz, sumx, sumz, threshold,
+ ngrow)
+
+ # Solve for the coefficients of the fitted line. Note that after
+ # pixel rejection the sum of the X values need no longer be zero.
+
+ if (ngoodpix > 0) {
+ rowrat = sumx / sumxsqr
+ z0 = (sumz - rowrat * sumxz) / (ngoodpix - rowrat * sumx)
+ dz = (sumxz - z0 * sumx) / sumxsqr
+ }
+
+# call eprintf ("fit: z0=%g, dz=%g, threshold=%g, npix=%d\n")
+# call pargr(z0); call pargr(dz); call pargr(threshold); call pargi(ngoodpix)
+
+ if (ngoodpix >= last_ngoodpix || ngoodpix < minpix)
+ break
+ }
+
+ # Transform the line coefficients back to the X range [1:npix].
+ zstart = z0 - dz
+ zslope = dz * xscale
+
+ call sfree (sp)
+ return (ngoodpix)
+end
+
+
+# ZSC_FLATTEN_DATA -- Compute and subtract the fitted line from the data array,
+# returned the flattened data in FLAT.
+
+procedure zsc_flatten_data (data, flat, x, npix, z0, dz)
+
+real data[npix] # raw data array
+real flat[npix] # flattened data (output)
+real x[npix] # x value of each pixel
+int npix # number of pixels
+real z0, dz # z-intercept, dz/dx of fitted line
+int i
+
+begin
+ do i = 1, npix
+ flat[i] = data[i] - (x[i] * dz + z0)
+end
+
+
+# ZSC_COMPUTE_SIGMA -- Compute the root mean square deviation from the
+# mean of a flattened array. Ignore rejected pixels.
+
+int procedure zsc_compute_sigma (a, badpix, npix, mean, sigma)
+
+real a[npix] # flattened data array
+short badpix[npix] # bad pixel flags (!= 0 if bad pixel)
+int npix
+real mean, sigma # (output)
+
+real pixval
+int i, ngoodpix
+double sum, sumsq, temp
+
+begin
+ sum = 0
+ sumsq = 0
+ ngoodpix = 0
+
+ # Accumulate sum and sum of squares.
+ do i = 1, npix
+ if (badpix[i] == GOOD_PIXEL) {
+ pixval = a[i]
+ ngoodpix = ngoodpix + 1
+ sum = sum + pixval
+ sumsq = sumsq + pixval ** 2
+ }
+
+ # Compute mean and sigma.
+ switch (ngoodpix) {
+ case 0:
+ mean = INDEF
+ sigma = INDEF
+ case 1:
+ mean = sum
+ sigma = INDEF
+ default:
+ mean = sum / ngoodpix
+ temp = sumsq / (ngoodpix - 1) - sum**2 / (ngoodpix * (ngoodpix - 1))
+ if (temp < 0) # possible with roundoff error
+ sigma = 0.0
+ else
+ sigma = sqrt (temp)
+ }
+
+ return (ngoodpix)
+end
+
+
+# ZSC_REJECT_PIXELS -- Detect and reject pixels more than "threshold" greyscale
+# units from the fitted line. The residuals about the fitted line are given
+# by the "flat" array, while the raw data is in "data". Each time a pixel
+# is rejected subtract its contributions from the matrix sums and flag the
+# pixel as rejected. When a pixel is rejected reject its neighbors out to
+# a specified radius as well. This speeds up convergence considerably and
+# produces a more stringent rejection criteria which takes advantage of the
+# fact that bad pixels tend to be clumped. The number of pixels left in the
+# fit is returned as the function value.
+
+int procedure zsc_reject_pixels (data, flat, normx, badpix, npix,
+ sumxsqr, sumxz, sumx, sumz, threshold, ngrow)
+
+real data[npix] # raw data array
+real flat[npix] # flattened data array
+real normx[npix] # normalized x values of pixels
+short badpix[npix] # bad pixel flags (!= 0 if bad pixel)
+int npix
+double sumxsqr,sumxz,sumx,sumz # matrix sums
+real threshold # threshold for pixel rejection
+int ngrow # number of pixels of growing
+
+int ngoodpix, i, j
+real residual, lcut, hcut
+double x, z
+
+begin
+ ngoodpix = npix
+ lcut = -threshold
+ hcut = threshold
+
+ do i = 1, npix
+ if (badpix[i] == BAD_PIXEL)
+ ngoodpix = ngoodpix - 1
+ else {
+ residual = flat[i]
+ if (residual < lcut || residual > hcut) {
+ # Reject the pixel and its neighbors out to the growing
+ # radius. We must be careful how we do this to avoid
+ # directional effects. Do not turn off thresholding on
+ # pixels in the forward direction; mark them for rejection
+ # but do not reject until they have been thresholded.
+ # If this is not done growing will not be symmetric.
+
+ do j = max(1,i-ngrow), min(npix,i+ngrow) {
+#call eprintf ("\t\t%d->%d\tcheck\n");call pargi(j); call pargs(badpix[j])
+ if (badpix[j] != BAD_PIXEL) {
+ if (j <= i) {
+ x = normx[j]
+ z = data[j]
+#call eprintf ("\treject [%d:%6g]=%6g sum[xsqr,xz,z]\n")
+#call pargi(j); call pargd(x); call pargd(z)
+#call eprintf ("\t%10g %10g %10g\n")
+#call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz)
+ sumxsqr = sumxsqr - (x ** 2)
+ sumxz = sumxz - z * x
+ sumx = sumx - x
+ sumz = sumz - z
+#call eprintf ("\t%10g %10g %10g\n")
+#call pargd(sumxsqr); call pargd(sumxz); call pargd(sumz)
+ badpix[j] = BAD_PIXEL
+ ngoodpix = ngoodpix - 1
+ } else
+ badpix[j] = REJECT_PIXEL
+#call eprintf ("\t\t%d->%d\tset\n");call pargi(j); call pargs(badpix[j])
+ }
+ }
+ }
+ }
+
+ return (ngoodpix)
+end
diff --git a/pkg/images/tv/iis/window.cl b/pkg/images/tv/iis/window.cl
new file mode 100644
index 00000000..25f00c65
--- /dev/null
+++ b/pkg/images/tv/iis/window.cl
@@ -0,0 +1,5 @@
+#{ WINDOW -- Adjust the lookup tables for the current frame.
+
+{
+ _dcontrol (type="frame", window+)
+}
diff --git a/pkg/images/tv/iis/x_iis.x b/pkg/images/tv/iis/x_iis.x
new file mode 100644
index 00000000..06813f75
--- /dev/null
+++ b/pkg/images/tv/iis/x_iis.x
@@ -0,0 +1,7 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# Driver for image control
+
+task cv = t_cv,
+ cvl = t_load
+ #giis = t_giis
diff --git a/pkg/images/tv/iis/zoom.cl b/pkg/images/tv/iis/zoom.cl
new file mode 100644
index 00000000..9aa48959
--- /dev/null
+++ b/pkg/images/tv/iis/zoom.cl
@@ -0,0 +1,11 @@
+#{ ZOOM -- Zoom in on a portion of the display.
+
+# zoom_factor,i,a,2,1,4,factor by which image scale is to be expanded
+# window,b,h,no,,,window enlarged image
+
+{
+ if (window)
+ _dcontrol (zoom=zoom_factor, roam=yes, window=yes)
+ else
+ _dcontrol (zoom=zoom_factor, roam=yes)
+}
diff --git a/pkg/images/tv/iis/zoom.par b/pkg/images/tv/iis/zoom.par
new file mode 100644
index 00000000..849c3439
--- /dev/null
+++ b/pkg/images/tv/iis/zoom.par
@@ -0,0 +1,2 @@
+zoom_factor,i,a,2,1,4,factor by which image scale is to be expanded
+window,b,h,no,,,window enlarged image