aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/imdkern
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /sys/gio/imdkern
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'sys/gio/imdkern')
-rw-r--r--sys/gio/imdkern/README85
-rw-r--r--sys/gio/imdkern/font.com207
-rw-r--r--sys/gio/imdkern/font.h29
-rw-r--r--sys/gio/imdkern/idk.com50
-rw-r--r--sys/gio/imdkern/idk.x509
-rw-r--r--sys/gio/imdkern/imd.com18
-rw-r--r--sys/gio/imdkern/imd.h77
-rw-r--r--sys/gio/imdkern/imdcancel.x16
-rw-r--r--sys/gio/imdkern/imdclear.x55
-rw-r--r--sys/gio/imdkern/imdclose.x37
-rw-r--r--sys/gio/imdkern/imdclws.x22
-rw-r--r--sys/gio/imdkern/imdcolor.x20
-rw-r--r--sys/gio/imdkern/imddrawch.x70
-rw-r--r--sys/gio/imdkern/imdescape.x13
-rw-r--r--sys/gio/imdkern/imdfa.x16
-rw-r--r--sys/gio/imdkern/imdfaset.x18
-rw-r--r--sys/gio/imdkern/imdflush.x14
-rw-r--r--sys/gio/imdkern/imdfont.x32
-rw-r--r--sys/gio/imdkern/imdgcell.x14
-rw-r--r--sys/gio/imdkern/imdinit.x162
-rw-r--r--sys/gio/imdkern/imdline.x31
-rw-r--r--sys/gio/imdkern/imdopen.x81
-rw-r--r--sys/gio/imdkern/imdopenws.x98
-rw-r--r--sys/gio/imdkern/imdpcell.x195
-rw-r--r--sys/gio/imdkern/imdpl.x183
-rw-r--r--sys/gio/imdkern/imdplset.x20
-rw-r--r--sys/gio/imdkern/imdpm.x56
-rw-r--r--sys/gio/imdkern/imdpmset.x19
-rw-r--r--sys/gio/imdkern/imdreset.x50
-rw-r--r--sys/gio/imdkern/imdtx.x430
-rw-r--r--sys/gio/imdkern/imdtxset.x29
-rw-r--r--sys/gio/imdkern/ltype.dat28
-rw-r--r--sys/gio/imdkern/mkpkg50
-rw-r--r--sys/gio/imdkern/t_imdkern.x89
-rw-r--r--sys/gio/imdkern/x_imdkern.x3
35 files changed, 2826 insertions, 0 deletions
diff --git a/sys/gio/imdkern/README b/sys/gio/imdkern/README
new file mode 100644
index 00000000..da041be0
--- /dev/null
+++ b/sys/gio/imdkern/README
@@ -0,0 +1,85 @@
+IMDKERN -
+
+This directory contains the source for the simple GIO/IMD kernel, used to
+draw graphics in a display frame buffer. It uses the data stream
+interface to open the frame buffer and uses code from SGI to rasterize
+the graphics.
+
+Special graphcap entries used by this kernel:
+
+ CI Color index of graphics pixels
+ FN Display frame buffer
+ LO Width in pixels of line size 1.0
+ LS Difference in pixels between line sizes
+ DB Print debug messages?
+
+
+Revision notes...
+----------------
+IMDKERN notes 20 December 1989 Z. G. Levay, STScI
+
+
+ o Make private copy idskern of gio/sgikern.
+
+ o Change "sgi" filename and procedure prefixes to "imd" throughout
+ the code. Change sgk.x to idk.x. Changed imd_open to imd_fopen to
+ aviod conflict with a procedure in libds. The files are:
+
+ font.com, font.h, idk.com, idk.h, idk.x, imd.com, imd.h,
+ imdcancel.x, imdclear.x, imdclose.x, imdclws.x, imdcolor.x,
+ imddrawch.x, imdescape.x, imdfa.x, imdfaset.x, imdflush.x,
+ imdfont.x, imdfopen.x, imdgcell.x, imdinit.x, imdipl.x,
+ imdkern.par, imdline.x, imdopenws.x, imdpcell.x, imdpl.x,
+ imdplset.x, imdpm.x, imdpmset.x, imdreset.x, imdtx.x, imdtxset.x,
+ ltype.dat, mkpkg, t_imdkern.x, x_imdkern.x,
+
+ o Modify mkpkg to build the task locally without updating the system
+ library or install the task.
+
+ o Add global parameters "frame" and "color" to task imdkern.
+ Modified imd_fopen to read task parameters and pass as arguments to
+ imd_openws. Added these parameters to imd_openws and the call to
+ idk_open.
+
+ o In idk_open, added frame and color to the calling sequence. Added
+ a call to imd_mapframe to open the frame buffer as an image,
+ changed setting the bitmap size to use the frame buffer size (via
+ IMIO) instead of graphcap parameters. Set the bits per bitmap word
+ to 8. Set the maximum bitmap size to 2048x2048 pixels. Ripped out
+ the code for opening the SGI metacode file, DD string manipulation,
+ etc. Added ttygeti calls to read the frame and color from the
+ graphcap in case they were passed as INDEF.
+
+ In idk_frame, changed the code to map an input and output section
+ of the frame buffer (via IMIO), read the bitmap line by line,
+ testing each word for any on bits, and writing the color index
+ value to the frame buffer pixel for each on bitmap bit. Set the
+ I/O buffer sizes to 64 lines (somewhat arbitrarily).
+
+ In idk_open, Changed the code to compute the x and y max (right and
+ top edges) of the bitmap by one pixel to draw to the edge. In
+ idk_linewidth, changed the code to compute the gap at the frame
+ edges by one pixel.
+
+ Removed sections of code dealing with non-bitmap format, rotated or
+ flipped bitmaps.
+
+
+----------------
+Installation and checkout. (12/21/89 dct)
+
+Installed code in gio/imdkern.
+Put hooks for new task IMDKERN in the PLOT package.
+Moved imdkern.par to plot, moved frame,color params to after "generic".
+Deleted file imdipl.x, identical to imdpl.x.
+Renamed imdfopen.x to imdopen.x for consistency with other kernels;
+ changed procedure name to imd_opendev to avoid name collision with imdopen.
+Deleted idk.h, contains only SGI metecode defs not used in idk.x.
+In t_imdkern.x, moved the clgeti's for color,frame to after the clgeti for
+ "generic" (required by startup protocol for graphics subkernel). For the
+ generic case, added initializers to set values to -1 to flag not set.
+ Got rid of the IS_INDEFs in idk.x. Nothing wrong with these, I just try
+ to avoid using INDEF in low level system code.
+mkpkg - link xx_imdkern.e, not x_imdkern.e, rename in the install (this is
+ necessary to permit local testing of new versions, else the installed BIN
+ version is used).
diff --git a/sys/gio/imdkern/font.com b/sys/gio/imdkern/font.com
new file mode 100644
index 00000000..ec1b0ec9
--- /dev/null
+++ b/sys/gio/imdkern/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/sys/gio/imdkern/font.h b/sys/gio/imdkern/font.h
new file mode 100644
index 00000000..eb2e72f4
--- /dev/null
+++ b/sys/gio/imdkern/font.h
@@ -0,0 +1,29 @@
+# FONT.H -- 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/sys/gio/imdkern/idk.com b/sys/gio/imdkern/idk.com
new file mode 100644
index 00000000..62e4eaf7
--- /dev/null
+++ b/sys/gio/imdkern/idk.com
@@ -0,0 +1,50 @@
+# IDK.COM -- The common for the IDK kernel. A common is used here for maximum
+# efficiency (minimum indirection) when rasterizing vectors and encoding
+# metacode. The maximum bitmap size is set at compile time in idk.h.
+
+# Booleans put here to avoid possible alignment problems.
+
+bool mf_bitmap # metafile type, metacode or bitmap
+bool mf_rotate # rotate (swap x and y)
+bool mf_yflip # flip y axis end for end
+bool mf_update # update bitmap
+bool mf_delete # delete metacode file after dispose
+bool mf_debug # print kernel debugging messages
+bool mf_swap2 # swap every 2 bytes on output
+bool mf_swap4 # swap every 4 bytes on output
+bool mf_oneperfile # store each frame in a new file
+
+common /idkboo/ mf_bitmap, mf_rotate, mf_yflip, mf_update, mf_delete, mf_debug,
+ mf_swap2, mf_swap4, mf_oneperfile
+
+# Everything else goes here.
+
+int mf_fd # image descriptor of frame buffer
+int mf_frame # frame counter
+char mf_fname[SZ_PATHNAME] # metafile filename
+char mf_dispose[SZ_OSCMD] # host dispose command
+
+int mf_op # [MCODE] index into obuf
+short mf_obuf[LEN_OBUF] # metacode buffer
+
+int mf_cx, mf_cy # [BITMAPS] current pen position
+int mf_nbpb # packing factor, bits per byte
+int mf_pxsize, mf_pysize # physical x, y size of bitmap, bits
+int mf_wxsize, mf_wysize # x, y size of bitmap window, bits
+int mf_xorigin, mf_yorigin # origin of bitmap window
+real mf_xscale, mf_yscale # to convert from NDC to device coords
+int mf_xmin, mf_xmax # x clipping limits
+int mf_ymin, mf_ymax # y clipping limits
+int mf_lenframe # frame size, words
+int mf_linewidth # relative line width
+int mf_lworigin # device width of line size 1.0
+real mf_lwslope # device pixels per line size increment
+int mf_fbuf[LEN_FBUF] # frame buffer (BIG)
+int mf_bitmask[BPW] # bit mask table
+int mf_color # color index
+
+common /idkcom/ mf_fd, mf_frame, mf_op, mf_cx, mf_cy, mf_nbpb, mf_pxsize,
+ mf_pysize, mf_wxsize, mf_wysize, mf_xorigin, mf_yorigin, mf_xscale,
+ mf_yscale, mf_xmin, mf_xmax, mf_ymin, mf_ymax, mf_lenframe,
+ mf_linewidth, mf_lworigin, mf_lwslope, mf_fbuf, mf_bitmask, mf_color,
+ mf_obuf, mf_fname, mf_dispose
diff --git a/sys/gio/imdkern/idk.x b/sys/gio/imdkern/idk.x
new file mode 100644
index 00000000..4d711e12
--- /dev/null
+++ b/sys/gio/imdkern/idk.x
@@ -0,0 +1,509 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <chars.h>
+include <imhdr.h>
+include <gki.h>
+
+.help idk
+.nf ---------------------------------------------------------------------------
+IDK -- Simple image display graphics interface. The purpose of this
+interface is to provide a means of drawing into a graphics overlay in
+an image display server via the IRAF data stream interface. The
+interface works by rasterizing the GKI metacode, reading the display
+frame buffer, merging the graphics raster with the frame buffer, and
+writing back the raster to the frame buffer.
+
+ g_out = idk_open (frame, color, tty) # device open
+ idk_close (g_out) # device close
+ idk_flush (g_out) # flush output
+
+ idk_frame (g_out) # start a new frame
+ idk_move (g_out, x, y) # move to (x,y)
+ idk_draw (g_out, x, y) # draw a vector to (x,y)
+ idk_linewidth (g_out, width) # set line width (>=1)
+
+The procedures comprising the top end of the IDK interface are summarized
+above and the code is included in this file. These procedures could be
+rewritten by the user to talk directly to a graphics device if desired,
+although the metacode file interface is likely to be simpler in most cases.
+
+The size of the bitmap is taken from the size of the display frame
+buffer. Values of the frame buffer are set to the specified color index
+for each set bitmap pixel. The final displayed color depends on the
+display server.
+
+The following graphcap fields apply:
+
+ DB have the kernel print debug messages during execution
+ LO width in device pixels of a line of size 1.0
+ LS difference in device pixels between line sizes
+ CI color index, i.e., the frame buffer pixel value
+ FN display frame number
+
+.endhelp ----------------------------------------------------------------------
+
+# NOTE -- The mf_physbit lookup table, used to map logical screen bits into
+# physical bits in the bitmap (for NB != 8) is equivalenced to the mf_obuf
+# array which is not otherwise used for bitmap devices. The length of the
+# mf_obuf array must therefore be >= PX.
+
+define mf_physbit mf_obuf # union these two arrays [[[NOTE]]]
+define BPW 32 # nbits in an integer
+define LEN_FBUF (8192*8192/BPW) # max size bitmap / frame buffer
+define LEN_OBUF 8192 # max size of buffer line
+define SZ_DDSTR 256 # max size graphcap.DD
+define SZ_OSCMD 256 # OS dispose command from graphcap.DD
+define IOLINES 64 # image lines per i/o transfer
+
+
+# IDK_OPEN -- Open the metacode file. Open the frame buffer as an image.
+# Initialize the bitmap based on the size of the frame.
+
+int procedure idk_open (a_frame, a_color, tty)
+
+int a_color #I display device color index
+int a_frame #I display buffer frame number
+pointer tty #I pointer to graphcap descriptor
+
+real x, y
+char strval[1]
+int byte, off, i, j
+int wcs, key, frame, color
+
+bool ttygetb()
+real ttygetr()
+int imd_mapframe(), ttygeti(), shifti(), imdrcur()
+errchk imd_mapframe, ttygetr, ttygeti, ttygetb
+include "idk.com"
+
+begin
+ frame = a_frame
+ color = a_color
+
+ # The DB flag may be set in the graphcap entry for an IMD device to
+ # print debug messages during execution.
+
+ mf_debug = ttygetb (tty, "DB")
+ if (mf_debug) {
+ call eprintf ("idk: open frame %d, color = %d\n")
+ call pargi (frame)
+ call pargi (color)
+ }
+
+ mf_update = false
+
+ # If the frame number was not specified as a parameter see if it is
+ # specified in the graphcap, else try to query the display to determine
+ # the current display frame and plot into that.
+
+ if (frame <= 0)
+ iferr (frame = ttygeti (tty, "FN"))
+ frame = 0
+ if (frame <= 0)
+ if (imdrcur ("stdimage", x, y, wcs, key, strval, 1, 0, NO) >= 0)
+ frame = max (1, wcs / 100)
+ else
+ frame = 1
+
+ # Find the color index in graphcap?
+ if (color < 0)
+ color = max(0, ttygeti (tty, "CI"))
+
+ # Map the frame buffer as an image.
+ mf_fd = imd_mapframe (frame, READ_WRITE, YES)
+
+ # Initialize bitmap parameters.
+ mf_pxsize = IM_LEN(mf_fd, 1)
+ mf_pysize = IM_LEN(mf_fd, 2)
+ mf_xorigin = 0
+ mf_yorigin = 0
+ mf_wxsize = IM_LEN(mf_fd, 1) - 1
+ mf_wysize = IM_LEN(mf_fd, 2) - 1
+ mf_nbpb = 8
+
+ # Line width parameters.
+ mf_lworigin = max (1, ttygeti (tty, "LO"))
+ mf_lwslope = ttygetr (tty, "LS")
+
+ # Size of the frame buffer.
+ mf_lenframe = (mf_pxsize * mf_pysize + BPW-1) / BPW
+
+ mf_color = color
+ mf_linewidth = mf_lworigin
+
+ # Initial "pen" position.
+ mf_cx = 0
+ mf_cy = 0
+
+ mf_xmin = mf_xorigin
+ mf_ymin = mf_yorigin
+ mf_xmax = mf_xmin + mf_wxsize
+ mf_ymax = mf_ymin + mf_wysize
+
+ mf_xscale = real(mf_wxsize) / real(GKI_MAXNDC)
+ mf_yscale = real(mf_wysize) / real(GKI_MAXNDC)
+
+ if (mf_lenframe > LEN_FBUF)
+ call error (1, "imdkern: bitmap too large")
+
+ # Initialize the bit mask table.
+ do j = 1, (BPW/NBITS_BYTE)
+ do i = 1, NBITS_BYTE {
+ off = (j - 1) * NBITS_BYTE
+ mf_bitmask[off+i] = shifti (1, off + NBITS_BYTE - i)
+ }
+
+ # Initialize the bit offset lookup table. This gives the physical
+ # x-offset into the lookup table of each addressable x-coordinate
+ # on the device. If NB is NBITS_BYTE the mapping is one-to-one.
+ # Note that the table contains zero-indexed bit offsets.
+
+ do i = 1, mf_pxsize {
+ byte = (i - 1) / mf_nbpb
+ mf_physbit[i] = min (mf_pxsize,
+ byte * NBITS_BYTE + (i - (byte * mf_nbpb))) - 1
+ }
+
+ if (mf_debug) {
+ call eprintf ("bitmap [%d,%d] origin=[%d,%d] wsize=[%d,%d]\n")
+ call pargi (mf_pxsize); call pargi (mf_pysize)
+ call pargi (mf_xorigin); call pargi (mf_yorigin)
+ call pargi (mf_wxsize); call pargi (mf_wysize)
+ }
+
+ return (mf_fd)
+end
+
+
+# IDK_CLOSE -- Update the display frame buffer and close the display.
+
+procedure idk_close (fd)
+
+int fd # output stream [NOT USED]
+
+errchk idk_frame, imunmap
+include "idk.com"
+
+begin
+ if (mf_debug)
+ call eprintf ("close device\n")
+
+ call idk_frame (mf_fd)
+
+ if (mf_fd != NULL) {
+ call imunmap (mf_fd)
+ mf_fd = NULL
+ }
+end
+
+
+# IDK_FLUSH -- Flush any buffered metacode output.
+
+procedure idk_flush (fd)
+
+int fd # output stream [NOT USED]
+include "idk.com"
+
+begin
+ if (mf_fd != NULL)
+ call imflush (mf_fd)
+end
+
+
+# IDK_FRAME -- Output a frame. Overlay the bitmap on the frame buffer.
+# Map the display frame as an image section and process the bitmap line by
+# line.
+
+procedure idk_frame (fd)
+
+int fd # output stream [NOT USED]
+
+int x1, x2, y1, y2
+int bmw # Bitmap word offset
+int npix # Pixels in local I/O buffer
+int fbp # Frame buffer section offset
+int fbp0
+int i, j
+int line
+pointer ob, ib
+
+pointer imps2s(), imgs2s()
+include "idk.com"
+
+begin
+ # Ignore frame commands if frame is empty.
+ if (!mf_update)
+ return
+
+ if (mf_debug) {
+ call eprintf ("Write the frame, color = %d\n")
+ call pargi (mf_color)
+ }
+
+ # Write the bitmap to the output frame buffer.
+
+ y2 = 0
+ for (y1=1; y2 < mf_pysize; y1=y1+IOLINES) {
+ # For each buffer section of the frame.
+ y2 = min (y1 + IOLINES-1, mf_pysize)
+ x1 = 1
+ x2 = mf_pxsize
+
+ # Map the frame section.
+ ob = imps2s (mf_fd, x1, x2, y1, y2)
+ ib = imgs2s (mf_fd, x1, x2, y1, y2)
+
+ npix = mf_pxsize * (y2 - y1 + 1)
+
+ if (ob != ib)
+ # Copy the input buffer to the output buffer
+ call amovs (Mems[ib], Mems[ob], npix)
+
+ do line = y1, y2 {
+ # Each line in the local frame buffer section
+ fbp0 = (line - y1) * mf_pxsize
+
+ do i = 1, mf_pxsize / BPW {
+ # Each word in the bitmap line.
+ bmw = (line - 1) * mf_pxsize / BPW + i
+
+ if (mf_fbuf[bmw] != 0) {
+ do j = 1, BPW {
+ # Each bit in the bitmap word.
+
+ if (and (mf_fbuf[bmw], mf_bitmask[j]) != 0) {
+ # An ON bit.
+ fbp = fbp0 + (i-1) * BPW + j
+ Mems[ob+fbp-1] = mf_color
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mf_update = false
+end
+
+
+# IDK_MOVE -- Output a pen move instruction.
+
+procedure idk_move (fd, x, y)
+
+int fd # output stream [NOT USED]
+int x, y # point to move to
+
+include "idk.com"
+
+begin
+ mf_cx = x
+ mf_cy = y
+
+ # Convert to zero indexed coordinates and clip at boundary.
+ # Allow room for line width shift near boundary.
+
+ mf_cx = max (mf_xmin, min (mf_xmax,
+ int (mf_cx * mf_xscale) + mf_xorigin))
+ mf_cy = max (mf_ymin, min (mf_ymax,
+ int (mf_cy * mf_yscale) + mf_yorigin))
+end
+
+
+# IDK_DRAW -- Output a pen draw instruction.
+
+procedure idk_draw (fd, a_x, a_y)
+
+int fd # output stream [NOT USED]
+int a_x, a_y # point to draw to
+
+int xshift, yshift, dx, dy
+int new_x, new_y, x1, y1, x2, y2, n, i
+include "idk.com"
+
+begin
+ new_x = a_x
+ new_y = a_y
+
+ if (!mf_update) {
+ # We are called when the first drawing instruction is output for a
+ # new frame. We clear the bitmap.
+
+ # Zero out all the bits in a bitmap.
+ call aclri (mf_fbuf, mf_lenframe)
+
+ mf_update = true
+ }
+
+ # Convert to zero indexed coordinates and clip at boundary.
+ # Allow room for line width shift near boundary.
+
+ new_x = max (mf_xmin, min (mf_xmax,
+ int (new_x * mf_xscale) + mf_xorigin))
+ new_y = max (mf_ymin, min (mf_ymax,
+ int (new_y * mf_yscale) + mf_yorigin))
+
+ if (mf_linewidth <= 1)
+ call idk_vector (mf_cx, mf_cy, new_x, new_y)
+ else {
+ # Redraw the vector several times with small normal shifts to
+ # produce a wider line.
+
+ xshift = 0
+ yshift = 0
+
+ if (abs (new_x - mf_cx) > abs (new_y - mf_cy)) {
+ dx = 0
+ dy = 1
+ } else {
+ dx = 1
+ dy = 0
+ }
+
+ do i = 1, mf_linewidth {
+ x1 = mf_cx + xshift
+ y1 = mf_cy + yshift
+ x2 = new_x + xshift
+ y2 = new_y + yshift
+
+ call idk_vector (x1, y1, x2, y2)
+
+ n = (i + 1) / 2
+ if (and (i, 1) == 0) {
+ xshift = dx * n
+ yshift = dy * n
+ } else {
+ xshift = -dx * n
+ yshift = -dy * n
+ }
+ }
+ }
+
+ # Update the current pen position, and set the update flag so that
+ # the bitmap will be written to the output file.
+
+ mf_cx = new_x
+ mf_cy = new_y
+end
+
+
+# IDK_VECTOR -- Write a vector (line) of unit width into the bitmap. The line
+# endpoints are expressed in physical device coordinates.
+
+procedure idk_vector (a_x1, a_y1, a_x2, a_y2)
+
+int a_x1, a_y1 # start point of line
+int a_x2, a_y2 # end point of line
+
+real dydx, dxdy
+long fbit, wbit, word
+int wpln, mask, dx, dy, x, y, x1, y1, x2, y2, or()
+include "idk.com"
+
+begin
+ x1 = a_x1; y1 = a_y1
+ x2 = a_x2; y2 = a_y2
+
+ dx = x2 - x1
+ dy = y2 - y1
+
+ if (abs(dx) > abs(dy)) {
+ if (x1 > x2) {
+ x1 = a_x2; x2 = a_x1; dx = -dx
+ y1 = a_y2; y2 = a_y1; dy = -dy
+ }
+
+ if (dy == 0 && mf_nbpb == NBITS_BYTE) {
+ # Somewhat optimized code for the case of a horiz. vector.
+
+ fbit = y1 * mf_pxsize + x1
+ word = fbit / BPW
+ wbit = and (fbit, BPW-1)
+
+ do x = x1, x2 {
+ mf_fbuf[word+1] = or (mf_fbuf[word+1], mf_bitmask[wbit+1])
+ wbit = wbit + 1
+ if (wbit >= BPW) {
+ wbit = 0
+ word = word + 1
+ }
+ }
+
+ } else {
+ # The general case for a mostly-X vector.
+
+ dydx = real(dy) / real(dx)
+ do x = x1, x2 {
+ y = int ((x - x1) * dydx) + y1
+ fbit = y * mf_pxsize + mf_physbit[x+1]
+ word = fbit / BPW
+ wbit = and (fbit, BPW-1)
+ mf_fbuf[word+1] = or (mf_fbuf[word+1], mf_bitmask[wbit+1])
+ }
+ }
+
+ } else if (dy != 0) {
+ if (y1 > y2) {
+ x1 = a_x2; x2 = a_x1; dx = -dx
+ y1 = a_y2; y2 = a_y1; dy = -dy
+ }
+
+ if (dx == 0) {
+ # Optimized code for the case of a vertical vector.
+
+ fbit = y1 * mf_pxsize + mf_physbit[x1+1]
+ word = fbit / BPW + 1
+ wbit = and (fbit, BPW-1)
+ wpln = (mf_pxsize + BPW-1) / BPW
+ mask = mf_bitmask[wbit+1]
+
+ do y = y1, y2 {
+ mf_fbuf[word] = or (mf_fbuf[word], mask)
+ word = word + wpln
+ }
+
+ } else {
+ # The general case of a mostly-Y vector.
+
+ dxdy = real(dx) / real(dy)
+ do y = y1, y2 {
+ x = int ((y - y1) * dxdy) + x1
+ fbit = y * mf_pxsize + mf_physbit[x+1]
+ word = fbit / BPW
+ wbit = and (fbit, BPW-1)
+ mf_fbuf[word+1] = or (mf_fbuf[word+1], mf_bitmask[wbit+1])
+ }
+ }
+
+ } else {
+ # Plot a single point (dx=dy=0).
+
+ fbit = y1 * mf_pxsize + mf_physbit[x1+1]
+ word = fbit / BPW
+ wbit = and (fbit, BPW-1)
+ mf_fbuf[word+1] = or (mf_fbuf[word+1], mf_bitmask[wbit+1])
+ }
+end
+
+
+# IDK_LINEWIDTH -- Output a line width set instruction.
+
+procedure idk_linewidth (fd, width)
+
+int fd # output stream [NOT USED]
+int width # new line width
+
+int gap
+include "idk.com"
+
+begin
+ # Set the line width in device pixels.
+ mf_linewidth = max (1, mf_lworigin + int ((width-1) * mf_lwslope))
+
+ # Set the clipping limits. Allow for shifting to widen lines.
+ gap = mf_linewidth / 2
+ mf_xmin = mf_xorigin + gap
+ mf_ymin = mf_yorigin + gap
+ mf_xmax = mf_xorigin + mf_wxsize - gap
+ mf_ymax = mf_yorigin + mf_wysize - gap
+end
diff --git a/sys/gio/imdkern/imd.com b/sys/gio/imdkern/imd.com
new file mode 100644
index 00000000..12cba65e
--- /dev/null
+++ b/sys/gio/imdkern/imd.com
@@ -0,0 +1,18 @@
+# IMD common. A common is necessary since there is no graphics descriptor
+# in the argument list of the kernel procedures. The stdgraph 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 g_kt # kernel transform graphics descriptor
+pointer g_tty # graphcap descriptor
+int g_nframes # number of frames written
+int g_maxframes # max frames per device metafile
+int g_ndraw # no draw instr. in current frame
+int g_in, g_out # input, output files
+int g_xres, g_yres # desired device resolution
+int g_frame, g_color # display frame and graphics color
+char g_device[SZ_GDEVICE] # force output to named device
+
+common /gioimd/ g_kt, g_tty, g_nframes, g_maxframes, g_ndraw,
+ g_in, g_out, g_xres, g_yres, g_frame, g_color, g_device
diff --git a/sys/gio/imdkern/imd.h b/sys/gio/imdkern/imd.h
new file mode 100644
index 00000000..a0e5d2d5
--- /dev/null
+++ b/sys/gio/imdkern/imd.h
@@ -0,0 +1,77 @@
+# IMD global definitions.
+
+define MAX_CHARSIZES 10 # max discreet device char sizes
+define SZ_SBUF 1024 # initial string buffer size
+define SZ_GDEVICE 31 # maxsize forced device name
+define DEF_MAXFRAMES 16 # maximum frames/metafile
+
+# The IMD state/device descriptor.
+
+define LEN_IMD 81
+
+define IMD_SBUF Memi[$1] # string buffer
+define IMD_SZSBUF Memi[$1+1] # size of string buffer
+define IMD_NEXTCH Memi[$1+2] # next char pos in string buf
+define IMD_NCHARSIZES Memi[$1+3] # number of character sizes
+define IMD_POLYLINE Memi[$1+4] # device supports polyline
+define IMD_POLYMARKER Memi[$1+5] # device supports polymarker
+define IMD_FILLAREA Memi[$1+6] # device supports fillarea
+define IMD_CELLARRAY Memi[$1+7] # device supports cell array
+define IMD_XRES Memi[$1+8] # device resolution in X
+define IMD_YRES Memi[$1+9] # device resolution in Y
+define IMD_ZRES Memi[$1+10] # device resolution in Z
+define IMD_FILLSTYLE Memi[$1+11] # number of fill styles
+define IMD_ROAM Memi[$1+12] # device supports roam
+define IMD_ZOOM Memi[$1+13] # device supports zoom
+define IMD_SELERASE Memi[$1+14] # device has selective erase
+define IMD_PIXREP Memi[$1+15] # device supports pixel replic.
+define IMD_STARTFRAME Memi[$1+16] # frame advance at metafile BOF
+define IMD_ENDFRAME Memi[$1+17] # frame advance at metafile EOF
+ # extra space
+define IMD_CURSOR Memi[$1+20] # last cursor accessed
+define IMD_COLOR Memi[$1+21] # last color set
+define IMD_TXSIZE Memi[$1+22] # last text size set
+define IMD_TXFONT Memi[$1+23] # last text font set
+define IMD_TYPE Memi[$1+24] # last line type set
+define IMD_WIDTH Memi[$1+25] # last line width set
+define IMD_DEVNAME Memi[$1+26] # name of open device
+define IMD_FRAME Memi[$1+27] # frame buffer number
+ # extra space
+define IMD_CHARHEIGHT Memi[$1+30+$2-1] # character height
+define IMD_CHARWIDTH Memi[$1+40+$2-1] # character width
+define IMD_CHARSIZE Memr[P2R($1+50+$2-1)] # text sizes permitted
+define IMD_PLAP ($1+60) # polyline attributes
+define IMD_PMAP ($1+64) # polymarker attributes
+define IMD_FAAP ($1+68) # fill area attributes
+define IMD_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]
diff --git a/sys/gio/imdkern/imdcancel.x b/sys/gio/imdkern/imdcancel.x
new file mode 100644
index 00000000..68832ae4
--- /dev/null
+++ b/sys/gio/imdkern/imdcancel.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_CANCEL -- Cancel any buffered output.
+
+procedure imd_cancel (dummy)
+
+int dummy # not used at present
+include "imd.com"
+
+begin
+ if (g_kt == NULL)
+ return
+ call imd_reset()
+end
diff --git a/sys/gio/imdkern/imdclear.x b/sys/gio/imdkern/imdclear.x
new file mode 100644
index 00000000..bf471998
--- /dev/null
+++ b/sys/gio/imdkern/imdclear.x
@@ -0,0 +1,55 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include "imd.h"
+
+# IMD_CLEAR -- Advance a frame on the plotter. All attribute packets are
+# initialized to their default values. Redundant calls or calls immediately
+# after a workstation open (before anything has been drawn) are ignored.
+
+procedure imd_clear (dummy)
+
+int dummy # not used at present
+
+int idk_open()
+errchk idk_open
+include "imd.com"
+
+begin
+ # This is a no-op if nothing has been drawn.
+ if (g_kt == NULL || g_ndraw == 0)
+ return
+
+ # Start a new frame. This is done either by issuing the frame advance
+ # instruction or by starting a new metafile. Close the output file and
+ # start a new metafile if the maximum frame count has been reached.
+ # This disposes of the metafile to the system, causing the actual
+ # plots to be drawn. Open a new metafile ready to receive next frame.
+
+ g_nframes = g_nframes + 1
+ if (g_nframes >= g_maxframes) {
+
+ # Does this device require a frame advance at end of metafile?
+ if (IMD_ENDFRAME(g_kt) == YES)
+ call idk_frame (g_out)
+
+ g_nframes = 0
+ call idk_close (g_out)
+ #g_out = idk_open (Memc[IMD_DEVNAME(g_kt)], g_tty)
+ g_out = idk_open (g_frame, g_color, g_tty)
+
+ # Does this device require a frame advance at beginning of metafile?
+ if (IMD_STARTFRAME(g_kt) == YES)
+ call idk_frame (g_out)
+
+ } else {
+ # Merely output frame instruction to start a new frame in the same
+ # metafile.
+
+ call idk_frame (g_out)
+ }
+
+ # Init kernel data structures.
+ call imd_reset()
+ g_ndraw = 0
+end
diff --git a/sys/gio/imdkern/imdclose.x b/sys/gio/imdkern/imdclose.x
new file mode 100644
index 00000000..7283f5db
--- /dev/null
+++ b/sys/gio/imdkern/imdclose.x
@@ -0,0 +1,37 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_CLOSE -- Close the IMD translation kernel. Close the spool file so
+# the output is finally plotted. Free up storage.
+
+procedure imd_close()
+
+include "imd.com"
+
+begin
+ # Check for a redundant imd_close call.
+ if (g_kt == NULL)
+ return
+
+ # If there is anything in the metafile, flush it and add a frame
+ # advance if required for the device.
+
+ if (g_ndraw > 0 || g_nframes > 0) {
+ # Does this device require a frame advance at end of metafile?
+ if (IMD_ENDFRAME(g_kt) == YES)
+ call idk_frame (g_out)
+ }
+
+ # Close output metafile, disposing of it to the host system.
+ call idk_close (g_out)
+
+ # Return tty descriptor.
+ call ttycdes (g_tty)
+
+ # Free kernel data structures.
+ call mfree (IMD_SBUF(g_kt), TY_CHAR)
+ call mfree (g_kt, TY_STRUCT)
+
+ g_kt = NULL
+end
diff --git a/sys/gio/imdkern/imdclws.x b/sys/gio/imdkern/imdclws.x
new file mode 100644
index 00000000..45072697
--- /dev/null
+++ b/sys/gio/imdkern/imdclws.x
@@ -0,0 +1,22 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_CLOSEWS -- Close the named workstation. Flush the output.
+# The spool file is closed only on the next plot or at gktclose time.
+# If the spool file is closed here, APPEND mode would not work.
+
+procedure imd_closews (devname, n)
+
+short devname[ARB] # device name (not used)
+int n # length of device name
+include "imd.com"
+
+begin
+ # For the IMD kernel, all display graphics writes are in append mode,
+ # so we may as well shutdown completely for closews (this also ensures
+ # that the display is updated at closews time).
+
+ #call idk_flush (g_out)
+ call imd_close()
+end
diff --git a/sys/gio/imdkern/imdcolor.x b/sys/gio/imdkern/imdcolor.x
new file mode 100644
index 00000000..581af9a2
--- /dev/null
+++ b/sys/gio/imdkern/imdcolor.x
@@ -0,0 +1,20 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_COLOR -- Set line drawing color.
+
+procedure imd_color (index)
+
+int index # index for color switch statement
+include "imd.com"
+
+begin
+ # switch (index) {
+ # case WHITE:
+ # case RED:
+ # case GREEN:
+ # case BLUE:
+ # default:
+ # }
+end
diff --git a/sys/gio/imdkern/imddrawch.x b/sys/gio/imdkern/imddrawch.x
new file mode 100644
index 00000000..17327563
--- /dev/null
+++ b/sys/gio/imdkern/imddrawch.x
@@ -0,0 +1,70 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <gki.h>
+include <gset.h>
+include "imd.h"
+include "font.h"
+
+define ITALIC_TILT 0.30 # fraction of xsize to tilt italics at top
+
+
+# IMD_DRAWCHAR -- Draw a character of the given size and orientation at the
+# given position.
+
+procedure imd_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
+
+int mx, my
+real px, py, coso, sino, theta
+int stroke, tab1, tab2, i, pen
+int bitupk()
+include "font.com"
+include "imd.com"
+
+begin
+ if (ch < CHARACTER_START || ch > CHARACTER_END)
+ i = '?' - CHARACTER_START + 1
+ else
+ i = ch - CHARACTER_START + 1
+
+ # Set the font.
+ call imd_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.
+ mx = x + px * coso + py * sino
+ my = y - px * sino + py * coso
+
+ # Draw the line segment or move pen.
+ if (pen == 0)
+ call idk_move (g_out, mx, my)
+ else
+ call idk_draw (g_out, mx, my)
+ }
+end
diff --git a/sys/gio/imdkern/imdescape.x b/sys/gio/imdkern/imdescape.x
new file mode 100644
index 00000000..2c2c3a26
--- /dev/null
+++ b/sys/gio/imdkern/imdescape.x
@@ -0,0 +1,13 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# IMD_ESCAPE -- Pass a device dependent instruction on to the kernel.
+# The IDK kernel does not have any escape functions at present.
+
+procedure imd_escape (fn, instruction, nwords)
+
+int fn # function code
+short instruction[ARB] # instruction data words
+int nwords # length of instruction
+
+begin
+end
diff --git a/sys/gio/imdkern/imdfa.x b/sys/gio/imdkern/imdfa.x
new file mode 100644
index 00000000..03bf446e
--- /dev/null
+++ b/sys/gio/imdkern/imdfa.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_FILLAREA -- Fill a closed area.
+
+procedure imd_fillarea (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+include "imd.com"
+
+begin
+ # Not implemented yet.
+ call imd_polyline (p, npts)
+end
diff --git a/sys/gio/imdkern/imdfaset.x b/sys/gio/imdkern/imdfaset.x
new file mode 100644
index 00000000..b790cef9
--- /dev/null
+++ b/sys/gio/imdkern/imdfaset.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+# IMD_FASET -- Set the fillarea attributes.
+
+procedure imd_faset (gki)
+
+short gki[ARB] # attribute structure
+pointer fa
+include "imd.com"
+
+begin
+ fa = IMD_FAAP(g_kt)
+ FA_STYLE(fa) = gki[GKI_FASET_FS]
+ FA_COLOR(fa) = gki[GKI_FASET_CI]
+end
diff --git a/sys/gio/imdkern/imdflush.x b/sys/gio/imdkern/imdflush.x
new file mode 100644
index 00000000..d22f04c9
--- /dev/null
+++ b/sys/gio/imdkern/imdflush.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "imd.h"
+
+# IMD_FLUSH -- Flush output.
+
+procedure imd_flush (dummy)
+
+int dummy # not used at present
+include "imd.com"
+
+begin
+ call idk_flush (g_out)
+end
diff --git a/sys/gio/imdkern/imdfont.x b/sys/gio/imdkern/imdfont.x
new file mode 100644
index 00000000..3117258b
--- /dev/null
+++ b/sys/gio/imdkern/imdfont.x
@@ -0,0 +1,32 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "imd.h"
+
+# IMD_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 IMD_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 imd_font (font)
+
+int font # code for font to be set
+int pk2, width
+include "imd.com"
+
+begin
+ width = IMD_WIDTH(g_kt)
+ pk2 = GKI_PACKREAL(2.0)
+
+ if (font == GT_BOLD) {
+ if (width != pk2) {
+ call idk_linewidth (g_out, 2)
+ width = pk2
+ }
+ } else
+ call idk_linewidth (g_out, nint (GKI_UNPACKREAL(width)))
+
+ IMD_WIDTH(g_kt) = width
+end
diff --git a/sys/gio/imdkern/imdgcell.x b/sys/gio/imdkern/imdgcell.x
new file mode 100644
index 00000000..0c384d70
--- /dev/null
+++ b/sys/gio/imdkern/imdgcell.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# IMD_GETCELLARRAY -- Input a cell array, i.e., two dimensional array of pixels
+# (greylevels or colors).
+
+procedure imd_getcellarray (nx, ny, x1,y1, x2,y2)
+
+int nx, ny # number of pixels in X and Y
+int x1, y1 # lower left corner of input window
+int x2, y2 # lower left corner of input window
+
+begin
+ # Not implemented yet.
+end
diff --git a/sys/gio/imdkern/imdinit.x b/sys/gio/imdkern/imdinit.x
new file mode 100644
index 00000000..ceed3948
--- /dev/null
+++ b/sys/gio/imdkern/imdinit.x
@@ -0,0 +1,162 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <ctype.h>
+include <gki.h>
+include "imd.h"
+
+# IMD_INIT -- Initialize the gkt data structures from the graphcap entry
+# for the device. Called once, at OPENWS time, with the TTY pointer already
+# set in the common. The companion routine IMD_RESET initializes the attribute
+# packets when the frame is flushed.
+
+procedure imd_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 "imd.com"
+
+begin
+ # Allocate the gkt descriptor and the string buffer.
+ if (g_kt == NULL) {
+ call calloc (g_kt, LEN_IMD, TY_STRUCT)
+ call malloc (IMD_SBUF(g_kt), SZ_SBUF, TY_CHAR)
+ }
+
+ # Get the maximum frame count and the flags controlling frame advance
+ # at start and end of metafile.
+
+ g_maxframes = ttygeti (tty, "MF")
+ if (g_maxframes == 0)
+ g_maxframes = DEF_MAXFRAMES
+ IMD_STARTFRAME(g_kt) = btoi (ttygetb (tty, "FS"))
+ IMD_ENDFRAME(g_kt) = btoi (ttygetb (tty, "FE"))
+
+ # 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.
+
+ IMD_SZSBUF(g_kt) = SZ_SBUF
+ IMD_NEXTCH(g_kt) = IMD_SBUF(g_kt) + 1
+ Memc[IMD_SBUF(g_kt)] = EOS
+
+ # Get the device resolution from the graphcap entry.
+
+ g_xres = ttygeti (tty, "xr")
+ if (g_xres <= 0)
+ g_xres = 1024
+ g_yres = ttygeti (tty, "yr")
+ if (g_yres <= 0)
+ g_yres = 1024
+
+ # 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.
+
+ IMD_NCHARSIZES(g_kt) = min (MAX_CHARSIZES, ttygeti (tty, "th"))
+ nextch = IMD_NEXTCH(g_kt)
+
+ if (IMD_NCHARSIZES(g_kt) <= 0) {
+ IMD_NCHARSIZES(g_kt) = 1
+ IMD_CHARSIZE(g_kt,1) = 1.0
+ IMD_CHARHEIGHT(g_kt,1) = char_height
+ IMD_CHARWIDTH(g_kt,1) = char_width
+ } else {
+ Memc[nextch+2] = EOS
+ for (i=1; i <= IMD_NCHARSIZES(g_kt); i=i+1) {
+ Memc[nextch] = 't'
+ Memc[nextch+1] = TO_DIGIT(i)
+ char_size = ttygetr (tty, Memc[nextch])
+ IMD_CHARSIZE(g_kt,i) = char_size
+ IMD_CHARHEIGHT(g_kt,i) = char_height * char_size
+ IMD_CHARWIDTH(g_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 gkt
+ # descriptor. If the capability does not exist the pointer is set to
+ # point to the null string at the beginning of the string buffer.
+
+ IMD_POLYLINE(g_kt) = btoi (ttygetb (tty, "pl"))
+ IMD_POLYMARKER(g_kt) = btoi (ttygetb (tty, "pm"))
+ IMD_FILLAREA(g_kt) = btoi (ttygetb (tty, "fa"))
+ IMD_FILLSTYLE(g_kt) = ttygeti (tty, "fs")
+ IMD_ROAM(g_kt) = btoi (ttygetb (tty, "ro"))
+ IMD_ZOOM(g_kt) = btoi (ttygetb (tty, "zo"))
+ IMD_XRES(g_kt) = ttygeti (tty, "xr")
+ IMD_YRES(g_kt) = ttygeti (tty, "yr")
+ IMD_ZRES(g_kt) = ttygeti (tty, "zr")
+ IMD_CELLARRAY(g_kt) = btoi (ttygetb (tty, "ca"))
+ IMD_SELERASE(g_kt) = btoi (ttygetb (tty, "se"))
+ IMD_PIXREP(g_kt) = btoi (ttygetb (tty, "pr"))
+
+ # Initialize the input parameters.
+
+ IMD_CURSOR(g_kt) = 1
+
+ # Save the device string in the descriptor.
+ nextch = IMD_NEXTCH(g_kt)
+ IMD_DEVNAME(g_kt) = nextch
+ maxch = IMD_SBUF(g_kt) + SZ_SBUF - nextch + 1
+ nextch = nextch + gstrcpy (devname, Memc[nextch], maxch) + 1
+ IMD_NEXTCH(g_kt) = nextch
+end
+
+
+# IMD_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 imd_gstring (cap)
+
+char cap[ARB] # device capability to be fetched
+pointer strp, nextch
+int maxch, nchars
+int ttygets()
+include "imd.com"
+
+begin
+ nextch = IMD_NEXTCH(g_kt)
+ maxch = IMD_SBUF(g_kt) + SZ_SBUF - nextch + 1
+
+ nchars = ttygets (g_tty, cap, Memc[nextch], maxch)
+ if (nchars > 0) {
+ strp = nextch
+ nextch = nextch + nchars + 1
+ } else
+ strp = IMD_SBUF(g_kt)
+
+ IMD_NEXTCH(g_kt) = nextch
+ return (strp)
+end
diff --git a/sys/gio/imdkern/imdline.x b/sys/gio/imdkern/imdline.x
new file mode 100644
index 00000000..86f32c0a
--- /dev/null
+++ b/sys/gio/imdkern/imdline.x
@@ -0,0 +1,31 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include "imd.h"
+
+# IMD_LINETYPE -- Set the line type option.
+
+procedure imd_linetype (index)
+
+int index # index for line type switch statement
+
+int linetype
+include "imd.com"
+
+begin
+ switch (index) {
+ case GL_CLEAR:
+ linetype = 0
+ case GL_DASHED:
+ linetype = 2
+ case GL_DOTTED:
+ linetype = 3
+ case GL_DOTDASH:
+ linetype = 4
+ default:
+ linetype = 1 # solid
+ }
+
+ # This will be done in software in a future version of the IMD kernel.
+ # call idk_linetype (g_out, linetype)
+end
diff --git a/sys/gio/imdkern/imdopen.x b/sys/gio/imdkern/imdopen.x
new file mode 100644
index 00000000..2a563360
--- /dev/null
+++ b/sys/gio/imdkern/imdopen.x
@@ -0,0 +1,81 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+# IMD_OPENDEV -- Install the IMD kernel as a graphics 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 imd_opendev (devname, frame, color, dd)
+
+char devname[ARB] # nonnull for forced output to a device
+int frame # display frame buffer number
+int color # graphics overlay color index
+int dd[ARB] # device table to be initialized
+
+pointer sp, devns
+int len_devname
+int locpr(), strlen()
+extern imd_openws(), imd_closews(), imd_clear(), imd_cancel()
+extern imd_flush(), imd_polyline(), imd_polymarker(), imd_text()
+extern imd_fillarea(), imd_putcellarray(), imd_plset()
+extern imd_pmset(), imd_txset(), imd_faset()
+extern imd_escape()
+include "imd.com"
+
+begin
+ call smark (sp)
+ call salloc (devns, SZ_FNAME, TY_SHORT)
+
+ # Flag first pass. Save forced device name in common for OPENWS.
+ # Zero the frame and instruction counters.
+
+ g_kt = NULL
+ g_nframes = 0
+ g_ndraw = 0
+ g_frame = frame
+ g_color = color
+ call strcpy (devname, g_device, SZ_GDEVICE)
+
+ # Install the device driver.
+
+ dd[GKI_OPENWS] = locpr (imd_openws)
+ dd[GKI_CLOSEWS] = locpr (imd_closews)
+ dd[GKI_DEACTIVATEWS] = 0
+ dd[GKI_REACTIVATEWS] = 0
+ dd[GKI_MFTITLE] = 0
+ dd[GKI_CLEAR] = locpr (imd_clear)
+ dd[GKI_CANCEL] = locpr (imd_cancel)
+ dd[GKI_FLUSH] = locpr (imd_flush)
+ dd[GKI_POLYLINE] = locpr (imd_polyline)
+ dd[GKI_POLYMARKER] = locpr (imd_polymarker)
+ dd[GKI_TEXT] = locpr (imd_text)
+ dd[GKI_FILLAREA] = locpr (imd_fillarea)
+ dd[GKI_PUTCELLARRAY] = locpr (imd_putcellarray)
+ dd[GKI_SETCURSOR] = 0
+ dd[GKI_PLSET] = locpr (imd_plset)
+ dd[GKI_PMSET] = locpr (imd_pmset)
+ dd[GKI_TXSET] = locpr (imd_txset)
+ dd[GKI_FASET] = locpr (imd_faset)
+ dd[GKI_GETCURSOR] = 0
+ dd[GKI_GETCELLARRAY] = 0
+ dd[GKI_ESCAPE] = locpr (imd_escape)
+ dd[GKI_SETWCS] = 0
+ dd[GKI_GETWCS] = 0
+ dd[GKI_UNKNOWN] = 0
+
+ # If a device was named open the workstation as well. This is
+ # necessary to permit processing of metacode files which do not
+ # contain the open workstation instruction.
+
+ len_devname = strlen (devname)
+ if (len_devname > 0) {
+ call achtcs (devname, Mems[devns], len_devname)
+ call imd_openws (Mems[devns], len_devname, NEW_FILE)
+ }
+
+ call sfree (sp)
+end
diff --git a/sys/gio/imdkern/imdopenws.x b/sys/gio/imdkern/imdopenws.x
new file mode 100644
index 00000000..cdfaeee0
--- /dev/null
+++ b/sys/gio/imdkern/imdopenws.x
@@ -0,0 +1,98 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <gki.h>
+include <error.h>
+include "imd.h"
+
+# IMD_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, following by initialization of the device itself.
+
+procedure imd_openws (devname, n, mode)
+
+short devname[ARB] # device name
+int n # length of device name
+int mode # access mode
+
+pointer sp, buf
+pointer ttygdes()
+bool streq()
+int idk_open()
+bool need_open, same_dev
+include "imd.com"
+
+begin
+ call smark (sp)
+ call salloc (buf, max (SZ_FNAME, n), TY_CHAR)
+
+ # If a device was named when the kernel was opened then output will
+ # always go to that device (g_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 (g_device[1] == EOS) {
+ call achtsc (devname, Memc[buf], n)
+ Memc[buf+n] = EOS
+ } else
+ call strcpy (g_device, Memc[buf], SZ_FNAME)
+
+ # Find out if first time, and if not, if same device as before
+ # note that if (g_kt == NULL), then same_dev is false.
+
+ same_dev = false
+ need_open = true
+
+ if (g_kt != NULL) {
+ same_dev = (streq (Memc[IMD_DEVNAME(g_kt)], Memc[buf]))
+ if (!same_dev) {
+ # Does this device require a frame advance at end of metafile?
+ if (IMD_ENDFRAME(g_kt) == YES)
+ call idk_frame (g_out)
+ call idk_close (g_out)
+ } else
+ need_open = false
+ }
+
+ # 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 (!same_dev) {
+ if (g_kt != NULL)
+ call ttycdes (g_tty)
+ iferr (g_tty = ttygdes (Memc[buf]))
+ call erract (EA_ERROR)
+
+ # Initialize data structures if we had to open a new device.
+ call imd_init (g_tty, Memc[buf])
+ call imd_reset()
+ }
+
+ # Open the output file. Metacode output to the device will be
+ # spooled and then disposed of to the device at CLOSEWS time.
+
+ iferr (g_out = idk_open (g_frame, g_color, g_tty)) {
+ call ttycdes (g_tty)
+ call erract (EA_ERROR)
+ } else {
+ # Does this device require a frame advance at start of metafile?
+ if (IMD_STARTFRAME(g_kt) == YES)
+ call idk_frame (g_out)
+ g_nframes = 0
+ g_ndraw = 0
+ }
+ }
+
+ # Clear the screen if device is being opened in new_file mode.
+ # This is a nop if we really opened a new device, but it will clear
+ # the screen if this is just a reopen of the same device in new file
+ # mode.
+
+ if (mode == NEW_FILE)
+ call imd_clear (0)
+
+ call sfree (sp)
+end
diff --git a/sys/gio/imdkern/imdpcell.x b/sys/gio/imdkern/imdpcell.x
new file mode 100644
index 00000000..deb61d18
--- /dev/null
+++ b/sys/gio/imdkern/imdpcell.x
@@ -0,0 +1,195 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+define DEF_YRES 8192 # default height of device pixel in GKI units
+define ZSTEP 4 # bit to be tested (step function width)
+
+
+# IMD_PUTCELLARRAY -- Draw a cell array, i.e., two dimensional array of pixels
+# (greylevels or colors). The algorithm used here maps 8 bits in into 1 bit
+# out, using a step function lookup table. The result is a band-contoured
+# image, where the spacing and width of the contour bands decreases as the
+# rate of change of intensity in the input cell array increases.
+
+procedure imd_putcellarray (m, nx, ny, ax1,ay1, ax2,ay2)
+
+short m[nx,ny] # cell array
+int nx, ny # number of pixels in X and Y
+int ax1, ay1 # lower left corner of output window
+int ax2, ay2 # upper right corner of output window
+
+bool ttygetb()
+include "imd.com"
+
+begin
+ if (ttygetb (g_tty, "BI"))
+ call imd_bcell (m, nx, ny, ax1,ay1, ax2,ay2)
+ else
+ call imd_mcell (m, nx, ny, ax1,ay1, ax2,ay2)
+end
+
+
+# IMD_BCELL -- Put cell array, optimized for a bitmap device. In this case,
+# to get the maximum resolution at maximum efficiency it is desirable for the
+# main loop to be over device pixels, mapping the device pixel into the
+# nearest line of the input cell array.
+
+procedure imd_bcell (m, nx, ny, ax1,ay1, ax2,ay2)
+
+short m[nx,ny] # cell array
+int nx, ny # number of pixels in X and Y
+int ax1, ay1 # lower left corner of output window
+int ax2, ay2 # upper right corner of output window
+
+real dx, dy
+int my, i1, i2, v, i, j, k
+include "imd.com"
+int and()
+
+begin
+ # Count drawing instruction, set polyline width to 1 for max y-res.
+ g_ndraw = g_ndraw + 1
+ call idk_linewidth (g_out, 1)
+ IMD_WIDTH(g_kt) = 0
+
+ # Determine the width of a cell array pixel in GKI units.
+ dx = real (ax2 - ax1) / nx
+
+ # Determine the height of a device pixel in GKI units.
+ if (IMD_YRES(g_kt) <= 0)
+ dy = GKI_MAXNDC / DEF_YRES
+ else
+ dy = max (1.0, real(GKI_MAXNDC) / real(IMD_YRES(g_kt)))
+
+ # Process the cell array. The outer loop runs over device pixels in Y;
+ # each iteration writes one line of the output raster. The inner loop
+ # runs down a line of the cell array.
+
+ k = 0
+ for (my = ay1 + dy/2; my < ay2; my = k * dy + ay1) {
+ j = max(1, min(ny, int (real(my-ay1) / real(ay2-ay1) * (ny-1)) + 1))
+ my = min (my, int (ay2 - dy/2))
+
+ for (i=1; i <= nx; ) {
+ do i = i, nx {
+ v = m[i,j]
+ if (and (v, ZSTEP) != 0)
+ break
+ }
+
+ if (i <= nx) {
+ i1 = i
+ i2 = nx
+ do i = i1 + 1, nx {
+ v = m[i,j]
+ if (and (v, ZSTEP) == 0) {
+ i2 = i
+ break
+ }
+ }
+
+ # The following decreases the length of dark line segments
+ # to make features more visible.
+
+ if (i2 - i1 >= 2)
+ if (i1 > 1 && i2 < nx) {
+ i1 = i1 + 1
+ i2 = i2 - 1
+ }
+
+ # Draw the line segment.
+ call idk_move (g_out, int ((i1-1) * dx + ax1), my)
+ call idk_draw (g_out, int (i2 * dx + ax1), my)
+
+ if (i2 >= nx)
+ i = nx + 1
+ }
+ }
+
+ k = k + 1
+ }
+end
+
+
+# IMD_MCELL -- Put cell array, optimized for a metafile device. In this case,
+# it is prohibitively expensive to draw into each resolvable line of the
+# output device. It is better to set the linewidth to the width of a cell
+# array pixel, output the minimum number of drawing instructions, and let the
+# metafile device widen the lines.
+
+procedure imd_mcell (m, nx, ny, ax1,ay1, ax2,ay2)
+
+short m[nx,ny] # cell array
+int nx, ny # number of pixels in X and Y
+int ax1, ay1 # lower left corner of output window
+int ax2, ay2 # upper right corner of output window
+
+real dx, dy
+int yres, my, i1, i2, v, i, j
+include "imd.com"
+int and()
+
+begin
+ # Count drawing instruction, clobber saved polyline width.
+ g_ndraw = g_ndraw + 1
+ IMD_WIDTH(g_kt) = 0
+
+ # Determine the width and height of a cell array pixel in GKI units.
+ dx = real (ax2 - ax1) / nx
+ dy = real (ay2 - ay1) / ny
+
+ # Set the IDK line width to the height of a pixel in the cell array.
+ yres = IMD_YRES(g_kt)
+ if (yres <= 0)
+ yres = DEF_YRES
+ call idk_linewidth (g_out,
+ max (1, nint (dy / (real(GKI_MAXNDC) / real(yres)))))
+
+ # Process the cell array. The outer loop runs over lines of the input
+ # cell array; each iteration writes only one line of the output raster,
+ # but the width of the line is adjusted to the height of a pixel in
+ # the cell array (the resolution of the cell array should not exceed
+ # that of the device).
+
+ for (j=1; j <= ny; j=j+1) {
+ my = int ((j - 0.5) * dy) + ay1
+
+ for (i=1; i <= nx; ) {
+ do i = i, nx {
+ v = m[i,j]
+ if (and (v, ZSTEP) != 0)
+ break
+ }
+
+ if (i <= nx) {
+ i1 = i
+ i2 = nx
+ do i = i + 1, nx {
+ v = m[i,j]
+ if (and (v, ZSTEP) == 0) {
+ i2 = i
+ break
+ }
+ }
+
+ # The following decreases the length of dark line segments
+ # to make features more visible.
+
+ if (i2 - i1 >= 2)
+ if (i1 > 1 && i2 < nx) {
+ i1 = i1 + 1
+ i2 = i2 - 1
+ }
+
+ # Draw the line segment.
+ call idk_move (g_out, int ((i1-1) * dx + ax1), my)
+ call idk_draw (g_out, int (i2 * dx + ax1), my)
+
+ if (i2 >= nx)
+ i = nx + 1
+ }
+ }
+ }
+end
diff --git a/sys/gio/imdkern/imdpl.x b/sys/gio/imdkern/imdpl.x
new file mode 100644
index 00000000..7c94f7d2
--- /dev/null
+++ b/sys/gio/imdkern/imdpl.x
@@ -0,0 +1,183 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "imd.h"
+
+define MAX_LTYPES 3 # max software line type patterns (excl. solid)
+define MAX_LSEGMENTS 4 # max line segments per pattern
+define LT_OFFSET 1 # offset to be subtracted from ltype code
+
+
+# IMD_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 imd_polyline (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+
+pointer pl
+int x, y
+int len_p, i
+include "imd.com"
+
+begin
+ if (npts < 2)
+ return
+
+ len_p = npts * 2
+
+ # Keep track of the number of drawing instructions since the last frame
+ # clear.
+ g_ndraw = g_ndraw + 1
+
+ # Update polyline attributes if necessary.
+ pl = IMD_PLAP(g_kt)
+
+ if (IMD_WIDTH(g_kt) != PL_WIDTH(pl)) {
+ call idk_linewidth (g_out, nint (GKI_UNPACKREAL(PL_WIDTH(pl))))
+ IMD_WIDTH(g_kt) = PL_WIDTH(pl)
+ }
+ if (IMD_COLOR(g_kt) != PL_COLOR(pl)) {
+ call imd_color (PL_COLOR(pl))
+ IMD_COLOR(g_kt) = PL_COLOR(pl)
+ }
+
+ if (PL_LTYPE(pl) == GL_CLEAR) {
+ # Ignore clear (erase) polylines.
+ ;
+
+ } else if (PL_LTYPE(pl) != GL_SOLID) {
+ # Draw a dashed or dotted polyline of the indicated type.
+ call imd_dashline (g_out, p, npts, PL_LTYPE(pl))
+
+ } else {
+ # Draw a solid polyline (usual case, optimized).
+
+ # Move to the first point.
+ x = p[1]
+ y = p[2]
+ call idk_move (g_out, x, y)
+
+ # Draw the polyline.
+ for (i=3; i <= len_p; i=i+2) {
+ x = p[i]
+ y = p[i+1]
+ call idk_draw (g_out, x, y)
+ }
+ }
+end
+
+
+# IMD_DASHLINE -- Draw a dashed or dotted polyline using the indicated line
+# style.
+
+procedure imd_dashline (g_out, p, npts, ltype)
+
+int g_out # output file
+short p[ARB] # the polyline points
+int npts # number of points, i.e., (x,y) pairs
+int ltype # desired line type
+
+bool penup
+int len_p, i
+real vlen, vpos, seglen, dx, dy
+int oldx, oldy, newx, newy, penx, peny
+int imd_getseg()
+
+begin
+ len_p = npts * 2
+
+ oldx = p[1]; oldy = p[2]
+ call idk_move (g_out, oldx, oldy)
+
+ # Process each line segment in the polyline.
+ do i = 3, len_p, 2 {
+ newx = p[i]
+ newy = p[i+1]
+
+ # Compute VLEN, the length of the polyline line segment to be
+ # drawn, VPOS, the relative position along the line segment,
+ # and DX and DY, the scale factors to be applied to VPOS to get
+ # the x and y coordinates of a point along the line segment.
+
+ dx = newx - oldx
+ dy = newy - oldy
+ vlen = sqrt (dx*dx + dy*dy)
+ if (vlen < 1.0) # GKI units
+ next
+
+ dx = dx / vlen
+ dy = dy / vlen
+ vpos = 0.0
+
+ # For each line segment, get segments of the line type pattern
+ # until all of the current line segment has been drawn. The pattern
+ # wraps around indefinitely, following the polyline around the
+ # vertices with concern only for the total length traversed.
+
+ while (vlen - vpos >= 1.0) {
+ seglen = imd_getseg (int (vlen - vpos), penup, ltype)
+ if (seglen < 1.0)
+ break
+
+ vpos = vpos + seglen
+ penx = oldx + vpos * dx
+ peny = oldy + vpos * dy
+
+ if (penup)
+ call idk_move (g_out, penx, peny)
+ else
+ call idk_draw (g_out, penx, peny)
+ }
+
+ oldx = newx
+ oldy = newy
+ }
+end
+
+
+# IMD_GETSEG -- Get a segment of a line style pattern. The segment extends
+# from the current position in the pattern to either the next penup/pendown
+# breakpoint in the pattern, or to the point MAXLEN units further along in
+# the pattern. When the end of the pattern is reached wrap around and
+# duplicate the pattern indefinitely.
+
+int procedure imd_getseg (maxlen, penup, ltype)
+
+int maxlen # max length segment to be returned
+bool penup # [out] pen up or pen down type segment?
+int ltype # line type code
+
+int seglen, seg, lt
+int p_seg[MAX_LTYPES]
+int p_nseg[MAX_LTYPES]
+int p_segleft[MAX_LTYPES]
+bool p_penup[MAX_LTYPES,MAX_LSEGMENTS]
+int p_seglen[MAX_LTYPES,MAX_LSEGMENTS]
+include "ltype.dat"
+
+begin
+ lt = max (1, min (MAX_LTYPES, ltype - LT_OFFSET))
+ seg = p_seg[lt]
+ penup = p_penup[lt,seg]
+
+ repeat {
+ if (maxlen < p_segleft[lt]) {
+ seglen = maxlen
+ p_segleft[lt] = p_segleft[lt] - seglen
+ } else {
+ seglen = p_segleft[lt]
+ seg = seg + 1
+ if (seg > p_nseg[lt])
+ seg = 1
+ p_seg[lt] = seg
+ p_segleft[lt] = p_seglen[lt,seg]
+ }
+ } until (seglen > 0)
+
+ return (seglen)
+end
diff --git a/sys/gio/imdkern/imdplset.x b/sys/gio/imdkern/imdplset.x
new file mode 100644
index 00000000..22743178
--- /dev/null
+++ b/sys/gio/imdkern/imdplset.x
@@ -0,0 +1,20 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+# IMD_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 imd_plset (gki)
+
+short gki[ARB] # attribute structure
+pointer pl
+include "imd.com"
+
+begin
+ pl = IMD_PLAP(g_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/sys/gio/imdkern/imdpm.x b/sys/gio/imdkern/imdpm.x
new file mode 100644
index 00000000..d7bcddac
--- /dev/null
+++ b/sys/gio/imdkern/imdpm.x
@@ -0,0 +1,56 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+# IMD_POLYMARKER -- Draw a polymarker. The polymarker is defined by the array
+# of points P, consisting of successive (x,y) coordinate pairs.
+
+procedure imd_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 x, y, oldx, oldy
+include "imd.com"
+
+begin
+ if (npts <= 0)
+ return
+
+ len_p = npts * 2
+
+ # Keep track of the number of drawing instructions since the last frame
+ # clear.
+ g_ndraw = g_ndraw + 1
+
+ # Update polymarker attributes if necessary.
+
+ pm = IMD_PMAP(g_kt)
+
+ if (IMD_TYPE(g_kt) != PM_LTYPE(pm)) {
+ call imd_linetype (PM_LTYPE(pm))
+ IMD_TYPE(g_kt) = PM_LTYPE(pm)
+ }
+ if (IMD_WIDTH(g_kt) != PM_WIDTH(pm)) {
+ call idk_linewidth (g_out, nint (GKI_UNPACKREAL(PM_WIDTH(pm))))
+ IMD_WIDTH(g_kt) = PM_WIDTH(pm)
+ }
+ if (IMD_COLOR(g_kt) != PM_COLOR(pm)) {
+ call imd_color (PM_COLOR(pm))
+ IMD_COLOR(g_kt) = PM_COLOR(pm)
+ }
+
+ # Draw the polymarker.
+ oldx = 0; oldy = 0
+ for (i=1; i <= len_p; i=i+2) {
+ x = p[i]; y = p[i+1]
+ if (x != oldx || y != oldy) {
+ call idk_move (g_out, x, y)
+ call idk_draw (g_out, x, y)
+ }
+ oldx = x; oldy = y
+ }
+end
diff --git a/sys/gio/imdkern/imdpmset.x b/sys/gio/imdkern/imdpmset.x
new file mode 100644
index 00000000..6912ef97
--- /dev/null
+++ b/sys/gio/imdkern/imdpmset.x
@@ -0,0 +1,19 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "imd.h"
+
+# IMD_PMSET -- Set the polymarker attributes.
+
+procedure imd_pmset (gki)
+
+short gki[ARB] # attribute structure
+pointer pm
+include "imd.com"
+
+begin
+ pm = IMD_PMAP(g_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/sys/gio/imdkern/imdreset.x b/sys/gio/imdkern/imdreset.x
new file mode 100644
index 00000000..fa830e4d
--- /dev/null
+++ b/sys/gio/imdkern/imdreset.x
@@ -0,0 +1,50 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <gset.h>
+include "imd.h"
+
+# IMD_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.
+
+procedure imd_reset()
+
+pointer pl, pm, fa, tx
+include "imd.com"
+
+begin
+ # Set pointers to attribute substructures.
+ pl = IMD_PLAP(g_kt)
+ pm = IMD_PMAP(g_kt)
+ fa = IMD_FAAP(g_kt)
+ tx = IMD_TXAP(g_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.
+
+ IMD_TYPE(g_kt) = -1
+ IMD_WIDTH(g_kt) = -1
+ IMD_COLOR(g_kt) = -1
+ IMD_TXSIZE(g_kt) = -1
+ IMD_TXFONT(g_kt) = -1
+end
diff --git a/sys/gio/imdkern/imdtx.x b/sys/gio/imdkern/imdtx.x
new file mode 100644
index 00000000..afe6c50c
--- /dev/null
+++ b/sys/gio/imdkern/imdtx.x
@@ -0,0 +1,430 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <gset.h>
+include <gki.h>
+include "imd.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.
+
+
+# IMD_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 imd_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, gki_dx, gki_dy, ch, cw
+int xstart, ystart, newx, newy
+int totlen, polytext, font, seglen
+pointer sp, seg, ip, op, tx, first
+int stx_segment()
+include "imd.com"
+
+real g_dx, g_dy # scale GKI to window coords
+int g_x1, g_y1 # origin of device window
+int g_x2, g_y2 # upper right corner of device window
+data g_dx /1.0/, g_dy /1.0/
+data g_x1 /0/, g_y1 /0/, g_x2 /GKI_MAXNDC/, g_y2 / GKI_MAXNDC/
+
+begin
+ call smark (sp)
+ call salloc (seg, n + 2, TY_CHAR)
+
+ # Keep track of the number of drawing instructions since the last frame
+ # clear.
+ g_ndraw = g_ndraw + 1
+
+ # Set pointer to the text attribute structure.
+ tx = IMD_TXAP(g_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 imd_txset, and is just a scaling factor.
+
+ IMD_TXSIZE(g_kt) = TX_SIZE(tx)
+ if (TX_COLOR(tx) != IMD_COLOR(g_kt)) {
+ call imd_color (TX_COLOR(tx))
+ IMD_COLOR(g_kt) = TX_COLOR(tx)
+ }
+
+ # Set the linetype to a solid line.
+ if (IMD_TYPE(g_kt) != GL_SOLID) {
+ call imd_linetype (GL_SOLID)
+ IMD_TYPE(g_kt) = GL_SOLID
+ }
+
+ # 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, gki_dx,gki_dy, polytext,
+ orien)
+
+ # No discreet character sizes, so just scale the base sizes.
+ tsz = GKI_UNPACKREAL(TX_SIZE(tx)) # scale factor
+ ch = IMD_CHARHEIGHT(g_kt,1) * tsz
+ cw = IMD_CHARWIDTH(g_kt,1) * tsz
+
+ # 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 * g_dx + g_x1
+ y = y0 * g_dy + g_y1
+ dx = gki_dx * g_dx
+ dy = gki_dy * g_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 >= g_x1 && x2 <= g_x2 && y1 >= g_y1 && y2 <= g_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 <= g_x1 || x2 >= g_x2 || y1 <= g_y1 || y2 >= g_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 imd_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, sz, ch, cw, cosv, sinv, space
+real xsize, ysize, xvlen, yvlen, xu, yu, xv, yv, p, q
+include "imd.com"
+
+begin
+ tx = IMD_TXAP(g_kt)
+
+ # Get character sizes in GKI coords.
+ sz = GKI_UNPACKREAL (TX_SIZE(tx))
+ ch = IMD_CHARHEIGHT(g_kt,1) * sz
+ cw = IMD_CHARWIDTH(g_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/sys/gio/imdkern/imdtxset.x b/sys/gio/imdkern/imdtxset.x
new file mode 100644
index 00000000..9479fbdd
--- /dev/null
+++ b/sys/gio/imdkern/imdtxset.x
@@ -0,0 +1,29 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <gki.h>
+include "imd.h"
+
+# IMD_TXSET -- Set the text drawing attributes.
+
+procedure imd_txset (gki)
+
+short gki[ARB] # attribute structure
+
+pointer tx
+include "imd.com"
+
+begin
+ tx = IMD_TXAP(g_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/sys/gio/imdkern/ltype.dat b/sys/gio/imdkern/ltype.dat
new file mode 100644
index 00000000..caae0c18
--- /dev/null
+++ b/sys/gio/imdkern/ltype.dat
@@ -0,0 +1,28 @@
+# LTYPE.DAT -- Initialize the builtin line types for the IMD kernel. Data
+# is given in GKI units (1.0 = 32768 units). A segment of 32 GKI units is
+# resolved on a device with 1024 resolved pixels.
+
+data p_seg /1, 1, 1/
+data p_segleft /320, 32, 512/
+
+data p_nseg[1] /2/ # PL_DASHED
+data p_penup[1,1] /false/
+data p_penup[1,2] /true/
+data p_seglen[1,1] /320/
+data p_seglen[1,2] /128/
+
+data p_nseg[2] /2/ # PL_DOTTED
+data p_penup[2,1] /false/
+data p_penup[2,2] /true/
+data p_seglen[2,1] /32/
+data p_seglen[2,2] /128/
+
+data p_nseg[3] /4/ # PL_DOTDASH
+data p_penup[3,1] /false/
+data p_penup[3,2] /true/
+data p_penup[3,3] /false/
+data p_penup[3,4] /true/
+data p_seglen[3,1] /512/
+data p_seglen[3,2] /128/
+data p_seglen[3,3] /32/
+data p_seglen[3,4] /128/
diff --git a/sys/gio/imdkern/mkpkg b/sys/gio/imdkern/mkpkg
new file mode 100644
index 00000000..03581bff
--- /dev/null
+++ b/sys/gio/imdkern/mkpkg
@@ -0,0 +1,50 @@
+# Make the GIO/IMDKERN image display device graphics kernel.
+
+$checkout libimd.a lib$
+$update libimd.a
+$checkin libimd.a lib$
+$call relink
+$exit
+
+update:
+ $call relink
+ $call install
+ ;
+
+relink:
+ $omake x_imdkern.x
+ $link x_imdkern.o -limd -lds -lstg -o xx_imdkern.e
+ ;
+
+install:
+ $move xx_imdkern.e bin$x_imdkern.e
+ ;
+
+libimd.a:
+ idk.x idk.com <chars.h> <gki.h> <imhdr.h> <mach.h>
+ imdcancel.x imd.com imd.h
+ imdclear.x imd.com imd.h <mach.h>
+ imdclose.x imd.com imd.h
+ imdclws.x imd.h imd.com
+ imdcolor.x imd.com imd.h
+ imddrawch.x font.com font.h imd.com imd.h <gki.h> <gset.h> <math.h>
+ imdescape.x
+ imdfa.x imd.com imd.h
+ imdfaset.x imd.com imd.h <gki.h>
+ imdflush.x imd.com imd.h
+ imdfont.x imd.com imd.h <gki.h> <gset.h>
+ imdgcell.x
+ imdinit.x imd.com imd.h <ctype.h> <gki.h> <mach.h>
+ imdline.x imd.com imd.h <gset.h>
+ imdopen.x imd.com imd.h <gki.h>
+ imdopenws.x imd.com imd.h <error.h> <gki.h> <mach.h>
+ imdpcell.x imd.com imd.h <gki.h>
+ imdpl.x imd.com imd.h ltype.dat <gki.h> <gset.h>
+ imdplset.x imd.com imd.h <gki.h>
+ imdpm.x imd.com imd.h <gki.h>
+ imdpmset.x imd.com imd.h <gki.h>
+ imdreset.x imd.com imd.h <gset.h> <gki.h>
+ imdtx.x imd.com imd.h <gki.h> <gset.h> <math.h>
+ imdtxset.x imd.com imd.h <gki.h> <gset.h>
+ t_imdkern.x <error.h> <gki.h>
+ ;
diff --git a/sys/gio/imdkern/t_imdkern.x b/sys/gio/imdkern/t_imdkern.x
new file mode 100644
index 00000000..ebca44bf
--- /dev/null
+++ b/sys/gio/imdkern/t_imdkern.x
@@ -0,0 +1,89 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <gki.h>
+
+# IMDKERN -- Graphics kernel for an image display frame buffer using the
+# data stream interface. The package is based on the SGI kernel.
+
+procedure t_imdkern()
+
+int fd, list, dbfd
+pointer gki, sp, fname, devname, dbfname
+int dev[LEN_GKIDD], deb[LEN_GKIDD]
+int debug, verbose, gkiunits
+int color, frame
+
+bool clgetb()
+int clgeti(), envfind()
+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)
+ call salloc (dbfname, SZ_PATHNAME, TY_CHAR)
+
+ # Open list of metafiles to be decoded.
+ list = clpopni ("input")
+
+ # Set parameter defaults.
+ debug = NO
+ verbose = NO
+ gkiunits = NO
+ frame = -1
+ color = -1
+
+ # Check for global kernel debug flag.
+ if (envfind ("idkdebug", Memc[dbfname], SZ_PATHNAME) > 0)
+ iferr (dbfd = open (Memc[dbfname], APPEND, TEXT_FILE)) {
+ debug = NO
+ dbfd = 0
+ } else
+ debug = YES
+
+ # Get parameters.
+ call clgstr ("device", Memc[devname], SZ_FNAME)
+ if (!clgetb ("generic")) {
+ debug = btoi (clgetb ("debug"))
+ verbose = btoi (clgetb ("verbose"))
+ gkiunits = btoi (clgetb ("gkiunits"))
+ frame = clgeti ("frame")
+ color = clgeti ("color")
+ }
+
+ if (debug == YES && dbfd == 0)
+ dbfd = STDERR
+
+ # Open the graphics kernel.
+ call imd_opendev (Memc[devname], frame, color, dev)
+ call gkp_install (deb, dbfd, 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 flush (dbfd)
+ }
+ call gki_execute (Mems[gki], dev)
+ }
+
+ call close (fd)
+ }
+
+ call gkp_close()
+ call imd_close()
+ call clpcls (list)
+ call sfree (sp)
+end
diff --git a/sys/gio/imdkern/x_imdkern.x b/sys/gio/imdkern/x_imdkern.x
new file mode 100644
index 00000000..3cc14388
--- /dev/null
+++ b/sys/gio/imdkern/x_imdkern.x
@@ -0,0 +1,3 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+task imdkern = t_imdkern