aboutsummaryrefslogtreecommitdiff
path: root/sys/gio/stdgraph
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 /sys/gio/stdgraph
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'sys/gio/stdgraph')
-rw-r--r--sys/gio/stdgraph/README77
-rw-r--r--sys/gio/stdgraph/font.com207
-rw-r--r--sys/gio/stdgraph/font.h29
-rw-r--r--sys/gio/stdgraph/mkpkg80
-rw-r--r--sys/gio/stdgraph/stdgraph.com46
-rw-r--r--sys/gio/stdgraph/stdgraph.h98
-rw-r--r--sys/gio/stdgraph/stgcancel.x16
-rw-r--r--sys/gio/stdgraph/stgclear.x16
-rw-r--r--sys/gio/stdgraph/stgclose.x47
-rw-r--r--sys/gio/stdgraph/stgclws.x28
-rw-r--r--sys/gio/stdgraph/stgctrl.x82
-rw-r--r--sys/gio/stdgraph/stgdeact.x54
-rw-r--r--sys/gio/stdgraph/stgdraw.x27
-rw-r--r--sys/gio/stdgraph/stgdrawch.x144
-rw-r--r--sys/gio/stdgraph/stgencode.x539
-rw-r--r--sys/gio/stdgraph/stgescape.x99
-rw-r--r--sys/gio/stdgraph/stgfa.x115
-rw-r--r--sys/gio/stdgraph/stgfaset.x18
-rw-r--r--sys/gio/stdgraph/stgfilter.x165
-rw-r--r--sys/gio/stdgraph/stgflush.x14
-rw-r--r--sys/gio/stdgraph/stggcell.x15
-rw-r--r--sys/gio/stdgraph/stggcur.x52
-rw-r--r--sys/gio/stdgraph/stggdisab.x17
-rw-r--r--sys/gio/stdgraph/stggenab.x17
-rw-r--r--sys/gio/stdgraph/stggim.x919
-rw-r--r--sys/gio/stdgraph/stggrstr.x16
-rw-r--r--sys/gio/stdgraph/stginit.x193
-rw-r--r--sys/gio/stdgraph/stglkcur.x18
-rw-r--r--sys/gio/stdgraph/stgmove.x27
-rw-r--r--sys/gio/stdgraph/stgonerr.x17
-rw-r--r--sys/gio/stdgraph/stgonint.x21
-rw-r--r--sys/gio/stdgraph/stgopen.x103
-rw-r--r--sys/gio/stdgraph/stgopenws.x220
-rw-r--r--sys/gio/stdgraph/stgoutput.x28
-rw-r--r--sys/gio/stdgraph/stgoutstr.x30
-rw-r--r--sys/gio/stdgraph/stgpcell.x85
-rw-r--r--sys/gio/stdgraph/stgpl.x126
-rw-r--r--sys/gio/stdgraph/stgplset.x20
-rw-r--r--sys/gio/stdgraph/stgpm.x118
-rw-r--r--sys/gio/stdgraph/stgpmset.x19
-rw-r--r--sys/gio/stdgraph/stgrcur.x425
-rw-r--r--sys/gio/stdgraph/stgreact.x41
-rw-r--r--sys/gio/stdgraph/stgres.x85
-rw-r--r--sys/gio/stdgraph/stgreset.x54
-rw-r--r--sys/gio/stdgraph/stgrtty.x137
-rw-r--r--sys/gio/stdgraph/stgscur.x36
-rw-r--r--sys/gio/stdgraph/stgtx.x528
-rw-r--r--sys/gio/stdgraph/stgtxqual.x17
-rw-r--r--sys/gio/stdgraph/stgtxset.x34
-rw-r--r--sys/gio/stdgraph/stgtxsize.x31
-rw-r--r--sys/gio/stdgraph/stgunkown.x14
-rw-r--r--sys/gio/stdgraph/stgwtty.x118
-rw-r--r--sys/gio/stdgraph/t_gkideco.x63
-rw-r--r--sys/gio/stdgraph/t_showcap.x210
-rw-r--r--sys/gio/stdgraph/t_stdgraph.x110
-rw-r--r--sys/gio/stdgraph/x_stdgraph.x5
-rw-r--r--sys/gio/stdgraph/zzdebug.x37
57 files changed, 5907 insertions, 0 deletions
diff --git a/sys/gio/stdgraph/README b/sys/gio/stdgraph/README
new file mode 100644
index 00000000..6007b9b1
--- /dev/null
+++ b/sys/gio/stdgraph/README
@@ -0,0 +1,77 @@
+gio$stdgraph
+
+ This directory contains the source and executables for the STDGRAPH and
+GKIDECODE graphics kernels. The two kernels are implemented both as libraries
+and as executable tasks.
+
+ gkidecode This kernel is used standalone to examine GKI
+ metafiles. The real work is done by the GKIPRINT
+ library module in the GIO package.
+
+ stdgraph A graphics kernel for graphics terminals. Implemented
+ both as the library "libstdg.a" and as the kernel task
+ STDGRAPH. The library is required for this kernel to
+ permit inclusion of the stdgraph kernel in the CL
+ process.
+
+Both kernels are available as CL callable tasks in the executable file
+x_kernel.e.
+
+
+GKIPRINT -- Graphics kernel for decoding metacode. This graphics kernel
+formats metacode instructions into readable form and prints them on the output
+file. The gkiprint kernel is useful for examining metafiles and for
+debugging kernels which drive specific devices. The driver consists of the
+following procedures:
+
+ gkp_openws (devname, n, mode)
+ gkp_closews (devname, n)
+ gkp_mftitle (title, n) **
+ gkp_clear (dummy)
+ gkp_cancel (dummy)
+ gkp_flush (dummy)
+ gkp_polyline (p, npts)
+ gkp_polymarker (p, npts)
+ gkp_text (x, y, text, n)
+ gkp_fillarea (p, npts)
+ gkp_getcellarray (m, nx, ny, x1,y1, x2,y2)
+ gkp_putcellarray (m, nx, ny, x1,y1, x2,y2)
+ gkp_setcursor (x, y, cursor)
+ gkp_plset (gki)
+ gkp_pmset (gki)
+ gkp_txset (gki)
+ gkp_faset (gki)
+ gkp_getcursor (cursor)
+ gkp_escape (fn, instruction, nwords) **
+ gkp_setwcs (wcs, nwords) **
+ gkp_getwcs (wcs, nwords) **
+ gkp_unknown (gki) **
+
+A GKI driven device driver may implement any subset of these procedures.
+The starred procedures should be omitted by most drivers. In particular,
+the SETWCS and GETWCS instructions are internal instructions which should
+be ignored by ordinary device drivers. The procedure names may be anything,
+but the arguments lists must be as shown. All coordinates are in GKI units,
+0 to 32767. Character strings are passed in ASCII, one character per metacode
+word. Whenever a GKI character string appears as an array argument in the
+argument list of a procedure, the count N of the number of characters in the
+string follows as the next argument. GKI character strings are not EOS
+delimited. Polyline, polymarker, and fillarea data is passed as an array
+of (x,y) points P, in GKI coordinates, defining the polyline or polygon to
+be plotted.
+
+One additional procedure, GKP_INSTALL, is called by the main program of the
+graphics kernel task to install the debugging driver, i.e., to fill the DD
+array with the entry point addresses of the driver procedures. For a normal
+driver this function is performed by a user supplied procedure named
+GKOPEN (graphics kernel open). The user supplied kernel procedures will
+be called to execute each instruction as the instructions are decoded by the
+main routine. The user supplied procedure GKCLOSE will be called when
+interpretation ends and the task is about to exit.
+
+ gkopen (dd)
+ gkclose ()
+
+Do not confuse GKOPEN and GKCLOSE, which open and close the graphics kernel,
+with GKI_OPENWS and GKI_CLOSEWS, the metacode instructions used to direct
+an opened kernel to open and close workstations.
diff --git a/sys/gio/stdgraph/font.com b/sys/gio/stdgraph/font.com
new file mode 100644
index 00000000..ec1b0ec9
--- /dev/null
+++ b/sys/gio/stdgraph/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/stdgraph/font.h b/sys/gio/stdgraph/font.h
new file mode 100644
index 00000000..c33dc6ee
--- /dev/null
+++ b/sys/gio/stdgraph/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/sys/gio/stdgraph/mkpkg b/sys/gio/stdgraph/mkpkg
new file mode 100644
index 00000000..8530f2c9
--- /dev/null
+++ b/sys/gio/stdgraph/mkpkg
@@ -0,0 +1,80 @@
+# Make the STDGRAPH GIO graphics kernel.
+
+$checkout libstg.a lib$
+$update libstg.a
+$checkin libstg.a lib$
+$exit
+
+update: # update lib$x_stdgraph.e
+ $call relink
+ $call install
+ ;
+
+relink: # make x_stdgraph.e in local directory
+ $omake x_stdgraph.x
+ $link x_stdgraph.o -lstg
+ ;
+
+install: # install in system library
+ $move x_stdgraph.e bin$
+ ;
+
+libstg.a:
+ # $set xflags = "$(xflags) -qfx"
+
+ stgcancel.x stdgraph.com stdgraph.h <fset.h>
+ stgclear.x stdgraph.com stdgraph.h
+ stgclose.x stdgraph.com stdgraph.h
+ stgclws.x stdgraph.h <ttset.h> stdgraph.com
+ stgctrl.x stdgraph.com stdgraph.h
+ stgdeact.x stdgraph.com stdgraph.h <gset.h> <ttset.h>
+ stgdraw.x stdgraph.com stdgraph.h
+ stgdrawch.x font.com font.h stdgraph.com stdgraph.h <gki.h>\
+ <gset.h> <math.h>
+ stgencode.x stdgraph.com stdgraph.h <ctype.h>
+ stgescape.x
+ stgfa.x stdgraph.com stdgraph.h
+ stgfaset.x stdgraph.com stdgraph.h <gki.h>
+ stgfilter.x stdgraph.com stdgraph.h <ttset.h> <chars.h> <fset.h>
+ stgflush.x stdgraph.com stdgraph.h
+ stggcell.x
+ stggcur.x stdgraph.com stdgraph.h
+ stggdisab.x stdgraph.com stdgraph.h
+ stggim.x stdgraph.com stdgraph.h <chars.h> <ctype.h> <fset.h>\
+ <mach.h> <gescape.h> <gki.h> <gim.h>
+ stggenab.x stdgraph.com stdgraph.h
+ stggrstr.x stdgraph.com stdgraph.h
+ stginit.x stdgraph.com stdgraph.h <ctype.h> <gki.h> <gset.h>\
+ <mach.h>
+ stglkcur.x stdgraph.com stdgraph.h <gset.h>
+ stgmove.x stdgraph.com stdgraph.h
+ stgonerr.x stdgraph.com stdgraph.h
+ stgonint.x stdgraph.h <config.h> <xwhen.h>
+ stgopen.x stdgraph.com stdgraph.h <gki.h> <gset.h>
+ stgopenws.x stdgraph.com stdgraph.h <error.h> <gki.h> <ttset.h>\
+ <chars.h> <finfo.h>
+ stgoutput.x stdgraph.com stdgraph.h
+ stgoutstr.x stdgraph.com stdgraph.h
+ stgpcell.x stdgraph.com stdgraph.h <gki.h>
+ stgpl.x stdgraph.com stdgraph.h
+ stgplset.x stdgraph.com stdgraph.h <gki.h>
+ stgpm.x stdgraph.com stdgraph.h
+ stgpmset.x stdgraph.com stdgraph.h <gki.h>
+ stgrcur.x stdgraph.com stdgraph.h <chars.h> <config.h> <error.h>\
+ <fset.h> <gki.h> <gset.h> <ttset.h>
+ stgreact.x stdgraph.com stdgraph.h <gset.h> <ttset.h>
+ stgres.x stdgraph.com stdgraph.h <gki.h>
+ stgreset.x stdgraph.com stdgraph.h <gset.h>
+ stgrtty.x stdgraph.com stdgraph.h <chars.h> <fset.h>
+ stgscur.x stdgraph.com stdgraph.h
+ stgtx.x stdgraph.com stdgraph.h <gki.h> <gset.h> <mach.h>\
+ <math.h>
+ stgtxqual.x stdgraph.com stdgraph.h <gset.h>
+ stgtxset.x stdgraph.com stdgraph.h <gki.h> <gset.h>
+ stgtxsize.x stdgraph.com stdgraph.h <gki.h>
+ stgunkown.x
+ stgwtty.x stdgraph.com stdgraph.h <ctype.h> <chars.h>
+ t_gkideco.x <error.h> <gki.h>
+ t_showcap.x stdgraph.h <ctype.h>
+ t_stdgraph.x <error.h> <gki.h> <gset.h>
+ ;
diff --git a/sys/gio/stdgraph/stdgraph.com b/sys/gio/stdgraph/stdgraph.com
new file mode 100644
index 00000000..3d3c43c5
--- /dev/null
+++ b/sys/gio/stdgraph/stdgraph.com
@@ -0,0 +1,46 @@
+# STDGRAPH 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. For maximum efficiency the polyline generation and
+# coordinate transformation datums are kept in the common.
+
+pointer g_sg # stdgraph graphics descriptor
+pointer g_tty # graphcap descriptor
+pointer g_term # termcap descriptor for terminal
+pointer g_pbtty # script graphcap, playback mode
+int g_nopen # open count for the kernel
+int g_active # workstation is open for graphics i/o
+int g_enable # graphics is enabled
+int g_message # message mode (output text)
+pointer g_msgbuf # message buffer (input text)
+int g_msgbuflen # allocated size of message buffer
+int g_msglen # amount of data in message
+int g_keycol # used to show keys in playback mode
+int g_keyline # used to show keys in playback mode
+pointer g_xy # pointer to coord encoding string
+int g_stream # graphics stream (metacode)
+int g_in, g_out # input, output streams to device
+int g_ucaseout # stty ucaseout status flag
+int g_xres, g_yres # desired device resolution
+int g_dxres, g_dyres # scale down to resolution coords
+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
+int g_lastx, g_lasty # used to clip unresolved points
+int g_hardchar # controls use of hardware character gen
+int g_cursor # user override of logical cursor
+int g_reg[NREGISTERS] # encoder registers
+char g_mem[SZ_MEMORY] # encoder memory
+char g_device[SZ_GDEVICE] # device name for forced device output
+char g_pbdevice[SZ_GDEVICE] # device name of playback script
+char g_hixy[TEK_XRES] # lookup tables for tek encoding
+char g_lox[TEK_XRES] # " "
+char g_loy[TEK_YRES] # " "
+
+common /stgcom/ g_sg, g_tty, g_term, g_pbtty, g_nopen, g_active, g_enable,
+ g_message, g_msgbuf, g_msgbuflen, g_msglen,
+ g_keycol, g_keyline, g_xy, g_stream, g_in, g_out,
+ g_ucaseout, g_xres, g_yres, g_dxres, g_dyres, g_dx, g_dy, g_x1,
+ g_y1, g_x2, g_y2, g_lastx, g_lasty, g_hardchar, g_cursor, g_reg,
+ g_mem, g_device, g_pbdevice, g_hixy, g_lox, g_loy
diff --git a/sys/gio/stdgraph/stdgraph.h b/sys/gio/stdgraph/stdgraph.h
new file mode 100644
index 00000000..de216065
--- /dev/null
+++ b/sys/gio/stdgraph/stdgraph.h
@@ -0,0 +1,98 @@
+# STDGRAPH definitions.
+
+define MAX_CHARSIZES 10 # max discreet device char sizes
+define SZ_SBUF 2048 # initial string buffer size
+define SZ_MEMORY 1024 # encoder memory size
+define SZ_GDEVICE 256 # force output to named device
+define SZ_UIFNAME 199 # user interface file name
+define SZ_MSGBUF 4096 # default size message buffer
+define FLUSH_MEMORY 117 # time to flush encoded polyline
+define LEN_STACK 20 # encoder stack size
+define NREGISTERS 12 # number of encoder registers
+define E_IOP 11 # encoder i/o pointer register
+define E_TOP 12 # encoder top memory register
+define LONG_POLYLINE 50 # big enough to post X_INT
+define PADCHAR 0 # used to gen. delays
+
+# The user can have private copies of UI specifications in GUIDIR.
+define GUIDIR "guidir"
+
+# The STDGRAPH state/device descriptor.
+
+define LEN_SG 91
+
+define SG_SBUF Memi[$1] # string buffer
+define SG_SZSBUF Memi[$1+1] # size of string buffer
+define SG_NEXTCH Memi[$1+2] # next char pos in string buf
+define SG_NCHARSIZES Memi[$1+3] # number of character sizes
+define SG_POLYLINE Memi[$1+4] # polyline output permitted
+define SG_POLYMARKER Memi[$1+5] # device supports polymarker
+define SG_FILLAREA Memi[$1+6] # device supports fillarea
+define SG_ENCODEXY Memi[$1+7] # format for encoding coords
+define SG_STARTDRAW Memi[$1+8] # pointer to DS string
+define SG_ENDDRAW Memi[$1+9] # pointer to DE string
+define SG_STARTMOVE Memi[$1+10] # pointer to VS string
+define SG_ENDMOVE Memi[$1+11] # pointer to VE string
+define SG_STARTMARK Memi[$1+12] # pointer to MS string
+define SG_ENDMARK Memi[$1+13] # pointer to ME string
+define SG_STARTFILL Memi[$1+14] # pointer to FS string
+define SG_ENDFILL Memi[$1+15] # pointer to FE string
+define SG_STARTTEXT Memi[$1+16] # start text draw
+define SG_ENDTEXT Memi[$1+17] # end text draw
+define SG_CURSOR Memi[$1+18] # last cursor accessed
+define SG_UPDCURSOR Memi[$1+19] # update cursor pos before read
+define SG_CURSOR_X Memi[$1+20] # current cursor X position
+define SG_CURSOR_Y Memi[$1+21] # current cursor Y position
+define SG_COLOR Memi[$1+22] # last color set
+define SG_TXSIZE Memi[$1+23] # last text size set
+define SG_TXFONT Memi[$1+24] # last text font set
+define SG_PLTYPE Memi[$1+25] # last line type set
+define SG_FASTYLE Memi[$1+26] # last fill area style set
+define SG_PLWIDTH Memi[$1+27] # last line width set
+define SG_DEVNAME Memi[$1+28] # name of open device
+define SG_UIFNAME Memi[$1+29] # user interface file name
+define SG_UIFDATE Memi[$1+30] # UI file date
+ # empty
+define SG_CHARHEIGHT Memi[$1+40+$2-1] # character height
+define SG_CHARWIDTH Memi[$1+50+$2-1] # character width
+define SG_CHARSIZE Memr[P2R($1+60+$2-1)] # text sizes permitted
+define SG_PLAP ($1+70) # polyline attributes
+define SG_PMAP ($1+74) # polymarker attributes
+define SG_FAAP ($1+78) # fill area attributes
+define SG_TXAP ($1+81) # 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]
+
+# TEK 4012 definitions for optimized tek coordinate encoding.
+
+define TEK_XRES 1024
+define TEK_YRES 780
diff --git a/sys/gio/stdgraph/stgcancel.x b/sys/gio/stdgraph/stgcancel.x
new file mode 100644
index 00000000..d47e24df
--- /dev/null
+++ b/sys/gio/stdgraph/stgcancel.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include "stdgraph.h"
+
+# STG_CANCEL -- Cancel any buffered output.
+
+procedure stg_cancel (dummy)
+
+int dummy # not used at present
+include "stdgraph.com"
+
+begin
+ call fseti (g_out, F_CANCEL, YES)
+ call stg_reset()
+end
diff --git a/sys/gio/stdgraph/stgclear.x b/sys/gio/stdgraph/stgclear.x
new file mode 100644
index 00000000..9573c972
--- /dev/null
+++ b/sys/gio/stdgraph/stgclear.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_CLEAR -- Clear the workstation screen. All attribute packets are
+# initialized to their default values when the screen is cleared.
+
+procedure stg_clear (dummy)
+
+int dummy # not used at present
+include "stdgraph.com"
+
+begin
+ call stg_ctrl ("CL")
+ call stg_reset()
+end
diff --git a/sys/gio/stdgraph/stgclose.x b/sys/gio/stdgraph/stgclose.x
new file mode 100644
index 00000000..3d7eb70b
--- /dev/null
+++ b/sys/gio/stdgraph/stgclose.x
@@ -0,0 +1,47 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_CLOSE -- Close the STDGRAPH kernel. Free all storage associated with the
+# stdgraph descriptor. Note that the stdgraph kernel may be multiply opened
+# (connected to two or more graphics steams, e.g., both STDGRAPH and STDIMAGE),
+# hence we do not physically close down until the last stream is closed.
+
+procedure stg_close()
+
+include "stdgraph.com"
+
+begin
+ g_nopen = g_nopen - 1
+
+ if (g_nopen <= 0) {
+ call stg_deactivatews (0)
+ call flush (g_out)
+ call mfree (SG_SBUF(g_sg), TY_CHAR)
+ call mfree (g_sg, TY_STRUCT)
+
+ if (g_tty != NULL) {
+ call ttycdes (g_tty)
+ g_tty = NULL
+ }
+
+ if (g_term != NULL) {
+ call ttycdes (g_term)
+ g_term = NULL
+ }
+
+ if (g_pbtty != NULL) {
+ call ttycdes (g_pbtty)
+ g_pbtty = NULL
+ }
+
+ if (g_msgbuf != NULL) {
+ call mfree (g_msgbuf, TY_CHAR)
+ g_msgbuf = NULL
+ g_msgbuflen = 0
+ g_msglen = 0
+ }
+
+ g_nopen = 0
+ }
+end
diff --git a/sys/gio/stdgraph/stgclws.x b/sys/gio/stdgraph/stgclws.x
new file mode 100644
index 00000000..137784cd
--- /dev/null
+++ b/sys/gio/stdgraph/stgclws.x
@@ -0,0 +1,28 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ttset.h>
+include "stdgraph.h"
+
+# STG_CLOSEWS -- Close the named workstation. Output the termination string,
+# if any, and flush the output. Buffer deallocation is handled by STGCLOSE.
+
+procedure stg_closews (devname, n)
+
+short devname[ARB] # device name (not used)
+int n # length of device name
+
+include "stdgraph.com"
+
+begin
+ call stg_ctrl ("CW")
+ call flush (g_out)
+
+ g_active = NO
+ g_enable = NO
+
+ # Reenable stty ucaseout mode if it was set when the workstation
+ # was activated.
+
+ if (g_ucaseout == YES)
+ call ttseti (g_out, TT_UCASEOUT, YES)
+end
diff --git a/sys/gio/stdgraph/stgctrl.x b/sys/gio/stdgraph/stgctrl.x
new file mode 100644
index 00000000..6689de8a
--- /dev/null
+++ b/sys/gio/stdgraph/stgctrl.x
@@ -0,0 +1,82 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+define SZ_PROGRAM 256
+
+# STG_CTRL -- Fetch an encoder format string from the graphcap entry and
+# use it to encode zero, one, or two integer arguments into a control string.
+# Put the control string to the output device.
+
+procedure stg_ctrl (cap)
+
+char cap[ARB] # name of device capability to be encoded
+pointer sp, prog
+int stg_encode(), ttygets()
+include "stdgraph.com"
+
+begin
+ call smark (sp)
+ call salloc (prog, SZ_PROGRAM, TY_CHAR)
+
+ # Fetch the program from the graphcap file. Zero is returned if the
+ # device does not have the named capability, in which case the function
+ # is inapplicable and should be ignored.
+
+ if (ttygets (g_tty, cap, Memc[prog], SZ_PROGRAM) > 0) {
+ # Encode the output string and write the encoded string to the
+ # output file.
+ g_reg[E_IOP] = 1
+ if (stg_encode (Memc[prog], g_mem, g_reg) == OK) {
+ g_mem[g_reg[E_IOP]] = EOS
+ call ttyputs (g_out, g_tty, g_mem, 1)
+ }
+ }
+
+ call sfree (sp)
+end
+
+
+# STG_CTRL1 -- Encode one integer argument.
+
+procedure stg_ctrl1 (cap, arg1)
+
+char cap[ARB] # device capability
+int arg1
+include "stdgraph.com"
+
+begin
+ g_reg[1] = arg1
+ call stg_ctrl (cap)
+end
+
+
+# STG_CTRL2 -- Encode two integer arguments.
+
+procedure stg_ctrl2 (cap, arg1, arg2)
+
+char cap[ARB] # device capability
+int arg1, arg2
+include "stdgraph.com"
+
+begin
+ g_reg[1] = arg1
+ g_reg[2] = arg2
+ call stg_ctrl (cap)
+end
+
+
+# STG_CTRL3 -- Encode three integer arguments.
+
+procedure stg_ctrl3 (cap, arg1, arg2, arg3)
+
+char cap[ARB] # device capability
+int arg1, arg2, arg3
+include "stdgraph.com"
+
+begin
+ g_reg[1] = arg1
+ g_reg[2] = arg2
+ g_reg[3] = arg3
+ call stg_ctrl (cap)
+end
diff --git a/sys/gio/stdgraph/stgdeact.x b/sys/gio/stdgraph/stgdeact.x
new file mode 100644
index 00000000..b11e4a07
--- /dev/null
+++ b/sys/gio/stdgraph/stgdeact.x
@@ -0,0 +1,54 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ttset.h>
+include <gset.h>
+include "stdgraph.h"
+
+# STG_DEACTIVATEWS -- Deactivate the workstation, i.e., disable graphics,
+# leaving the terminal in text mode. Note that it is the CW (close
+# workstation) sequence which is actually output, since the GD sequence is
+# used only to write single lines of text to the status line.
+
+procedure stg_deactivatews (flags)
+
+int flags # action modifier flags
+
+char buf[1]
+int stg_readtty(), and()
+include "stdgraph.com"
+
+begin
+ if (g_out <= 0)
+ return
+
+ # The g_active and g_out test permits us to be called before the
+ # kernel is opened and causes redundant calls to be ignored.
+
+ if (g_active == YES) {
+ # Pause before deactivating?
+ if (and (flags, AW_PAUSE) != 0) {
+ call stg_putline (g_out, "\n[Hit return to continue]\n")
+ while (stg_readtty (STDIN, buf, 1) != EOF)
+ if (buf[1] == '\r' || buf[1] == '\n')
+ break
+ }
+
+ # Deactivate the workstation.
+ call stgctrl ("CW")
+
+ g_active = NO
+ g_enable = NO
+
+ # Reenable stty ucaseout mode if it was set when the workstation
+ # was activated.
+
+ if (g_ucaseout == YES)
+ call ttseti (g_out, TT_UCASEOUT, YES)
+ }
+
+ # Clear the text screen?
+ if (and (flags, AW_CLEAR) != 0 && g_term != NULL)
+ call ttyclear (g_out, g_term)
+
+ call flush (g_out)
+end
diff --git a/sys/gio/stdgraph/stgdraw.x b/sys/gio/stdgraph/stgdraw.x
new file mode 100644
index 00000000..ae5a4ace
--- /dev/null
+++ b/sys/gio/stdgraph/stgdraw.x
@@ -0,0 +1,27 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_DRAW -- Output a device draw line-segment instruction to draw from the
+# current position to the position (x,y) in GKI coordinates.
+
+procedure stg_draw (x, y)
+
+int x, y # destination
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ # Transform the first point from GKI coords to device coords and
+ # draw to the transformed point.
+
+ call ttyputs (g_out, g_tty, Memc[SG_STARTDRAW(g_sg)], 1)
+
+ g_reg[1] = x * g_dx + g_x1
+ g_reg[2] = y * g_dy + g_y1
+ g_reg[E_IOP] = 1
+ if (stg_encode (Memc[g_xy], g_mem, g_reg) == OK)
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+
+ call ttyputs (g_out, g_tty, Memc[SG_ENDDRAW(g_sg)], 1)
+end
diff --git a/sys/gio/stdgraph/stgdrawch.x b/sys/gio/stdgraph/stgdrawch.x
new file mode 100644
index 00000000..fd317d2b
--- /dev/null
+++ b/sys/gio/stdgraph/stgdrawch.x
@@ -0,0 +1,144 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <gset.h>
+include <gki.h>
+include "stdgraph.h"
+include "font.h"
+
+define ITALIC_TILT 0.30 # fraction of xsize to tilt italics at top
+define MAXPTS 40 # max points in a char drawing polyline
+
+
+# STG_DRAWCHAR -- Draw a character of the given size and orientation at the
+# given position.
+
+procedure stg_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
+
+pointer pl, tx
+real px, py, coso, sino, theta
+int stroke, tab1, tab2, i, pen, mx, my
+int save_ltype, save_lwidth, save_color
+int bitupk()
+include "font.com"
+include "stdgraph.com"
+
+begin
+ if (ch < CHARACTER_START || ch > CHARACTER_END)
+ i = '?' - CHARACTER_START + 1
+ else
+ i = ch - CHARACTER_START + 1
+
+ # Set the font.
+ if (SG_TXFONT(g_sg) != font) {
+ call stg_ctrl1 ("TF", font - GT_ROMAN + 1)
+ SG_TXFONT(g_sg) = font
+ }
+
+ # Since we will be using the polyline generator, set the polyline
+ # linetype to solid and save the current linetype for later restoration.
+
+ pl = SG_PLAP(g_sg)
+ tx = SG_TXAP(g_sg)
+ save_color = PL_COLOR(pl)
+ save_ltype = PL_LTYPE(pl)
+ save_lwidth = PL_WIDTH(pl)
+ PL_COLOR(pl) = TX_COLOR(tx)
+ PL_LTYPE(pl) = GL_SOLID
+ PL_WIDTH(pl) = 1
+
+ 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 sgch_move (mx, my)
+ else
+ call sgch_draw (mx, my)
+ }
+
+ # Flush any remaining points.
+ call sgch_flush()
+
+ # Restore polyline linetype and color.
+ PL_LTYPE(pl) = save_ltype
+ PL_WIDTH(pl) = save_lwidth
+ PL_COLOR(pl) = save_color
+end
+
+
+# SGCH_MOVE -- Start accumulating a new polyline.
+
+procedure sgch_move (mx, my)
+
+int mx, my
+short pl[MAXPTS], op
+common /sgchcm/ pl, op
+
+begin
+ call sgch_flush()
+
+ pl[1] = mx
+ pl[2] = my
+ op = 3
+end
+
+
+# SGCH_DRAW -- Add a point to the polyline.
+
+procedure sgch_draw (mx, my)
+
+int mx, my
+short pl[MAXPTS], op
+common /sgchcm/ pl, op
+
+begin
+ pl[op] = mx
+ pl[op+1] = my
+ op = min (MAXPTS, op + 2)
+end
+
+
+# SGCH_FLUSH -- Flush the polyline to the output device.
+
+procedure sgch_flush()
+
+int npts
+short pl[MAXPTS], op
+common /sgchcm/ pl, op
+
+begin
+ if (op > 2) {
+ npts = op / 2
+ call stg_polyline (pl, npts)
+ }
+ op = 1
+end
diff --git a/sys/gio/stdgraph/stgencode.x b/sys/gio/stdgraph/stgencode.x
new file mode 100644
index 00000000..3c7a6ffb
--- /dev/null
+++ b/sys/gio/stdgraph/stgencode.x
@@ -0,0 +1,539 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctype.h>
+include "stdgraph.h"
+
+.help stg_encode
+.nf _________________________________________________________________________
+STG_ENCODE -- Table driven binary encoder/decoder. The encoder (which can
+also decode) processes a format string, also referred to as a program, to
+either encode an output string or decode an input string. Internally the
+encoder operates in two modes, copy mode and execute mode. In copy mode
+all format characters are copied to the output except the following special
+characters:
+
+ ' escape next character (literal)
+ % begin a formatted output string
+ ( switch to execute mode (stack driven, RPN interpreter)
+
+An ( appearing in the format string causes a mode switch to execute mode.
+In execute mode characters are metacode instructions to be executed. An
+unescaped ) causes reversion to copy mode. Parens may not be nested; an
+( in execute mode is an instruction to push the binary value of ( on the
+stack, and an ) in copy mode is copied to the output as a character. In
+execute mode the following characters are recognized as special instructions.
+All other characters are instructions too, telling the encoder to push the
+ASCII value of the character on the stack.
+
+ ' escape next character (recognized everywhere)
+ % formatted output
+ ) revert to copy mode
+ #nnn push signed decimal integer number nnn
+ $ switch case construct
+ . pop number from stack and place in output string
+ , get next character from input string and push on stack
+ & modulus (similar to AND of low bits)
+ + add (similar to OR)
+ - subtract (similar to AND)
+ * multiply (shift left if pwr of 2)
+ / divide (shift right if pwr of 2)
+ < less than (0=false, 1=true)
+ > greater than (0=false, 1=true)
+ = equals (0=false, 1=true)
+ ; branch if: <bool> <offset> ;. The ; is at offset zero.
+ 0-9 push register
+ !N pop stack into register N
+ !! pop N from stack and output an N millisecond delay
+
+The encoder communicates with the outside world via three general purpose
+data structures.
+
+ registers 0-9 (integer only)
+ memory char array
+ program char array
+
+The registers are used for parameter input and output as well as for storing
+intermediate results. R 1-3 are used for input and output arguments. R 4-9
+and R0 (R10) are reserved for use by the program. R11 is the i/o pointer into
+encoder memory, used for character input and output. R12 should contain the
+maximum memory address upon input. Memory may be used for anything but is
+normally used only for the input string or output string. The program is the
+format string.
+
+Further documentation is given in the GIO reference manual.
+.endhelp _____________________________________________________________________
+
+define SZ_FORMAT 10 # max length printf format
+define SZ_NUMSTR 10 # encoded numeric string
+
+define R1 registers[1] # argument
+define R2 registers[2] # argument
+define R3 registers[3] # argument
+define R4 registers[4] # scratch
+define R5 registers[5] # scratch
+define R6 registers[6] # scratch
+define R7 registers[7] # scratch
+define R8 registers[8] # scratch
+define R9 registers[9] # scratch
+define R0 registers[10] # scratch
+define IOP registers[11] # i/o pointer into encoder memory
+define TOP registers[12] # max memory location
+
+# Inline macros.
+
+define memory_overflow_ 1
+define stack_underflow_ 2
+define stack_overflow_ 3
+
+define input {$1=memory[iop];iop=iop+1}
+define output {memory[iop]=($1);iop=iop+1;if(iop>top)goto memory_overflow_}
+define push {stack[sp]=($1);sp=sp+1}
+define pop {sp=sp-1;$1=stack[sp]}
+
+
+# STG_ENCODE -- Interpret a program, encoding values passed in registers into
+# memory, or decoding memory into registers.
+
+int procedure stg_encode (program, memory, registers)
+
+char program[ARB] # program to be executed
+char memory[ARB] # data space
+int registers[NREGISTERS] # general purpose registers
+
+int x, y, num, ch, status
+int stack[LEN_STACK]
+int sp, pc, iop, top, incase
+common /sgecom/ pc, sp, iop, top, incase, stack
+int sge_execute()
+include "stdgraph.com"
+
+begin
+ # TEK format, %t. This format deserves special treatment due to the
+ # prevalence of tektronix compatible graphics terminals.
+
+ if (program[1] == '%' && program[2] == 't') {
+ x = R1
+ y = R2
+ iop = IOP + 4
+ if (iop > top)
+ goto memory_overflow_
+
+ memory[iop-4] = g_hixy[y+1]
+ memory[iop-3] = g_loy[y+1]
+ memory[iop-2] = g_hixy[x+1]
+ memory[iop-1] = g_lox[x+1]
+
+ IOP = iop
+ if (program[3] == EOS)
+ return (OK)
+ }
+
+ # Process a general format string (as well as any chars following the
+ # %t format).
+
+ incase = NO
+ iop = IOP
+ top = TOP
+ pc = 1
+ sp = 1
+
+ for (ch=program[pc]; ch != EOS; ch=program[pc]) {
+ pc = pc + 1
+ if (ch == '%' && program[pc] != EOS) {
+ if (program[pc] == 't') {
+ # Tek format again.
+ pc = pc + 1
+ x = R1
+ y = R2
+ iop = iop + 4
+ if (iop > top)
+ goto memory_overflow_
+
+ memory[iop-4] = g_hixy[y+1]
+ memory[iop-3] = g_loy[y+1]
+ memory[iop-2] = g_hixy[x+1]
+ memory[iop-1] = g_lox[x+1]
+
+ } else {
+ # Extract a general format specification and use it to
+ # encode the number on top of the stack.
+ pop (num)
+ if (sp < 1) {
+ IOP = iop
+ return (stack_underflow_)
+ } else
+ call sge_printf (num, memory, iop, top, program, pc)
+ }
+
+ } else if (ch == '(' && program[pc] != EOS) {
+ # Switch to execute mode.
+ status = sge_execute (program, memory, registers)
+ if (status != OK)
+ return (status)
+
+ } else if (ch == '\'' && program[pc] != EOS) {
+ # Escape next character.
+ output (program[pc])
+ pc = pc + 1
+
+ } else {
+ # Copy an ordinary character to the output string.
+ output (ch)
+ }
+ }
+
+ IOP = iop
+ return (OK)
+
+memory_overflow_
+ IOP = iop
+ return (memory_overflow_)
+end
+
+
+# SGE_EXECUTE -- Execute a metacode program stored in encoder memory starting
+# at the location of the PC. The stack, program counter, i/o pointer, and
+# registers are shared by the copy and execute mode procedures via common.
+
+int procedure sge_execute (program, memory, registers)
+
+char program[ARB] # program to be executed
+char memory[ARB] # data space
+int registers[NREGISTERS] # general purpose registers
+
+int num, ch, a, b, neg, x, y
+int stack[LEN_STACK]
+int sp, pc, iop, top, incase, msec, npad, baud, envgeti(), btoi()
+common /sgecom/ pc, sp, iop, top, incase, stack
+include "stdgraph.com"
+errchk envgeti
+
+begin
+ # Execute successive single character instructions until either ) or
+ # EOS is seen. On a good host machine this case will be compiled as
+ # a vectored goto with a loop overhead of only a dozen or so machine
+ # instructions per loop.
+
+ for (ch=program[pc]; ch != EOS; ch=program[pc]) {
+ pc = pc + 1
+
+ switch (ch) {
+ case '\'':
+ # Escape next character (recognized everywhere).
+ ch = program[pc]
+ if (ch != EOS) {
+ # Push ASCII value of character.
+ push (ch)
+ pc = pc + 1
+ }
+
+ case '%':
+ if (program[pc] == 't') {
+ # Tek format again.
+ pc = pc + 1
+ x = R1
+ y = R2
+ iop = iop + 4
+ if (iop > top)
+ goto memory_overflow_
+
+ memory[iop-4] = g_hixy[y+1]
+ memory[iop-3] = g_loy[y+1]
+ memory[iop-2] = g_hixy[x+1]
+ memory[iop-1] = g_lox[x+1]
+
+ } else {
+ # Formatted output.
+ if (program[pc] != EOS) {
+ pop (num)
+ call sge_printf (num, memory, iop, top, program, pc)
+ } else
+ output (ch)
+ }
+
+ case ')':
+ # End interpreter mode.
+ return (OK)
+
+ case '#':
+ # Push signed decimal integer number.
+ neg = NO
+ if (program[pc] == '-') {
+ neg = YES
+ pc = pc + 1
+ }
+
+ num = 0
+ while (IS_DIGIT (program[pc])) {
+ num = num * 10 + TO_INTEG (program[pc])
+ pc = pc + 1
+ }
+
+ if (neg == YES)
+ push (-num)
+ else
+ push (num)
+
+ case '$':
+ # Switch case instruction.
+
+ if (incase == NO) {
+ # Pop the switch off the stack.
+ pop (num)
+
+ # Search for case number 'num'.
+ for (ch=program[pc]; ch != EOS; ch=program[pc]) {
+ if (ch == '$') {
+ # End of switch statement.
+ pc = pc + 1
+ incase = NO
+ break
+
+ } else if (program[pc+1] == '-') {
+ # Range of cases.
+ a = TO_INTEG (ch)
+ b = TO_INTEG (program[pc+2])
+ pc = pc + 3
+ if (a <= num && num <= b) {
+ incase = YES
+ break
+ }
+ } else if (ch == 'D' || TO_INTEG(ch) == num) {
+ # Default or requested case.
+ pc = pc + 1
+ incase = YES
+ break
+
+ }
+
+ # Advance to the next case. Leave pc pointing to the
+ # N of case $N.
+
+ if (ch != '$' && incase == NO) {
+ while (program[pc] != EOS && program[pc] != '$')
+ pc = pc + 1
+ if (program[pc] == '$')
+ pc = pc + 1
+ }
+ }
+
+ } else {
+ # $ encountered delimiting a case. Search forward for
+ # $$ or EOS.
+
+ if (program[pc] != '$')
+ for (ch=program[pc]; ch != EOS; ch=program[pc]) {
+ pc = pc + 1
+ if (ch == '$' && program[pc] == '$')
+ break
+ }
+
+ if (program[pc] == '$')
+ pc = pc + 1
+
+ incase = NO
+ }
+
+ case '.':
+ # Pop number from stack and place in output string as a
+ # binary character.
+ pop (num)
+ output (num)
+
+ case ',':
+ # Get next character from input string and push on stack.
+ input (num)
+ push (num)
+
+ case '&':
+ # Modulus (similar to AND of low bits).
+ pop (b)
+ pop (a)
+ push (mod (a, b))
+
+ case '+':
+ # Add (similar to OR).
+ pop (b)
+ pop (a)
+ push (a + b)
+
+ case '-':
+ # Subtract (similar to AND).
+ pop (b)
+ pop (a)
+ push (a - b)
+
+ case '*':
+ # Multiply (shift left if pwr of 2).
+ pop (b)
+ pop (a)
+ push (a * b)
+
+ case '/':
+ # Divide (shift right if pwr of 2).
+ pop (b)
+ pop (a)
+ push (a / b)
+
+ case '<':
+ # Less than (0=false, 1=true).
+ pop (b)
+ pop (a)
+ push (btoi (a < b))
+
+ case '>':
+ # Greater than (0=false, 1=true).
+ pop (b)
+ pop (a)
+ push (btoi (a > b))
+
+ case '=':
+ # Equals (0=false, 1=true).
+ pop (b)
+ pop (a)
+ push (btoi (a == b))
+
+ case ';':
+ # If 2nd value on stack is true add 1st value on stack to PC.
+ # Example: "12<#-8;". The ; is at offset zero.
+ pop (a)
+ pop (b)
+ if (b != 0)
+ pc = pc - 1 + a
+
+ case '0':
+ # Push contents of register 0 (10).
+ push (R0)
+ case '1':
+ # Push contents of register 1.
+ push (R1)
+ case '2':
+ # Push contents of register 2.
+ push (R2)
+ case '3':
+ # Push contents of register 3.
+ push (R3)
+ case '4':
+ # Push contents of register 4.
+ push (R4)
+ case '5':
+ # Push contents of register 5.
+ push (R5)
+ case '6':
+ # Push contents of register 6.
+ push (R6)
+ case '7':
+ # Push contents of register 7.
+ push (R7)
+ case '8':
+ # Push contents of register 8.
+ push (R8)
+ case '9':
+ # Push contents of register 9.
+ push (R9)
+
+ case '!':
+ if (program[pc] == '!') {
+ # !!: Pop stack and generate delay.
+ pc = pc + 1
+ pop (msec)
+ iferr (baud = envgeti ("ttybaud"))
+ baud = 9600
+ npad = real(msec) * (real(baud) / 8. / 1000.)
+ while (npad > 0) {
+ output (PADCHAR)
+ npad = npad - 1
+ }
+ } else {
+ # !N: Pop stack into register N.
+ num = TO_INTEG (program[pc])
+ if (num >= 0 && num <= 9) {
+ if (num == 0)
+ num = 10
+ pop (registers[num])
+ pc = pc + 1
+ } else
+ output (ch)
+ }
+
+ default:
+ # Push ASCII value of character.
+ push (ch)
+ }
+
+ if (sp <= 0)
+ return (stack_underflow_)
+ if (sp > LEN_STACK)
+ return (stack_overflow_)
+ }
+
+ return (OK)
+
+memory_overflow_
+ return (memory_overflow_)
+end
+
+
+# SGE_PRINTF -- Process a %.. format specification. The number to be encoded
+# has already been popped from the stack into the first argument. The encoded
+# number is returned in memory at IOP, leaving IOP positioned to the first
+# char following the encoded number. The format used to encode the number is
+# extracted from the program starting at PC. PC is left pointing to the first
+# character following the format.
+
+procedure sge_printf (number, memory, iop, top, program, pc)
+
+int number # number to be encoded
+char memory[top] # output buffer
+int iop # index of first char to be written (in/out)
+int top # size of output buffer
+char program[ARB] # contains printf format string
+int pc # index of first char of format string (in/out)
+
+char format[SZ_FORMAT]
+char numstr[SZ_NUMSTR]
+int op, ch, junk
+int gstrcpy(), itoc()
+
+begin
+ # Extract format %w.dC, a string of digits, -, or ., delimited by a
+ # letter. The format %w.dr is followed by a single character which
+ # must also be included in the format string.
+
+ format[1] = '%'
+ op = 2
+ for (ch=program[pc]; ch != EOS; ch=program[pc]) {
+ pc = pc + 1
+ format[op] = ch
+ op = op + 1
+ if (IS_LOWER(ch)) {
+ if (ch == 'r' && program[pc] != EOS) {
+ # Radix digit follows %r.
+ format[op] = program[pc]
+ op = op + 1
+ pc = pc + 1
+ }
+ break
+ }
+ }
+ format[op] = EOS
+
+ # Encode the number using the extracted format string. The case of
+ # a simple decimal encoding is optimized.
+
+ if (format[2] == 'd')
+ junk = itoc (number, numstr, SZ_NUMSTR)
+ else {
+ iferr {
+ call sprintf (numstr, SZ_NUMSTR, format)
+ call pargi (number)
+ } then
+ numstr[1] = EOS
+ }
+
+ # Move the encoded number to encoder memory, advancing the i/o
+ # pointer and taking care not to overrun memory. Leave the iop
+ # pointing AT, not after, the EOS output by gstrcpy.
+
+ iop = iop + gstrcpy (numstr, memory[iop], top - iop + 1)
+end
diff --git a/sys/gio/stdgraph/stgescape.x b/sys/gio/stdgraph/stgescape.x
new file mode 100644
index 00000000..b52ffd0c
--- /dev/null
+++ b/sys/gio/stdgraph/stgescape.x
@@ -0,0 +1,99 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# STGESCAPE.X -- Stdgraph kernel escape handing code. This is the interface
+# between the stdgraph kernel and any supported escape packages. These driver
+# routines return TRUE if they recognize the escape and it is private to the
+# package, FALSE if the other escape packages may also be interested in the
+# routine.
+#
+# stg_escape standard GKI escape entry point
+#
+# sge_wstran transform and output escape
+# sge_spoolesc process and escape into frame buffer
+#
+# To add support for a new package of escapes, and entry for the driver routine
+# for each family of escapes must be added to each of these procedures.
+
+
+# STG_ESCAPE -- Pass a device dependent instruction on to the kernel.
+# The stdgraph kernel does not have any escape functions at present.
+
+procedure stg_escape (fn, instruction, nwords)
+
+int fn #I function code
+short instruction[ARB] #I instruction data words
+int nwords #I length of instruction
+
+bool sgm_execute() # GIM (Gterm) imaging excapes
+
+begin
+ if (sgm_execute (fn, instruction, nwords))
+ return
+end
+
+
+# SGE_WSTRAN -- Stdgraph escape handling routine called by an interactive
+# client (e.g the CL in cursor mode) to apply the workstation transformation
+# to a escape and execute the escape. This routine is called for all
+# escapes regardless of whether any transformation is necessary, leaving
+# it up to the escape code to decide what to do.
+
+procedure sge_wstran (fn, instruction, x1,y1, x2,y2)
+
+int fn #I escape sequence function opcode
+short instruction[ARB] #I escape instruction data
+real x1, y1 #I NDC coords of display rect
+real x2, y2 #I NDC coords of display rect
+
+bool sgm_wstran() # GIM (Gterm) imaging excapes
+
+begin
+ if (sgm_wstran (fn, instruction, x1,y1, x2,y2))
+ return
+end
+
+
+# SGE_WSENABLE -- Stdgraph escape handling routine called by an
+# interactive client (e.g the CL in cursor mode) to test whether cursor mode
+# scaling of graphics instructions is enabled when cursor mode zoom/pan is
+# done. Cursor mode scaling may be disabled if the kernel or graphics device
+# does the scaling itself.
+
+bool procedure sge_wsenable ()
+
+bool enable
+bool sgm_wsenable()
+
+begin
+ if (sgm_wsenable (enable))
+ return (enable)
+end
+
+
+# SGE_SPOOLESC -- Stdgraph escape handling routine called by an interactive
+# client (e.g the CL in cursor mode) to retain, delete, or edit an escape
+# instruction stored in a frame buffer. Ordinary drawing instructions are
+# normally retained. If the instruction should only be executed when issued
+# it should be deleted. Sometimes an instruction is edited or replaced by
+# a different one to be executed the next time the buffered graphics is drawn.
+# Sometimes when an instruction is seen earlier instructions must be edited
+# or deleted. This routine is called for all escapes, it is up to the escape
+# code to decide what to do. The delete instruction callback is called as
+# delete_fcn(tr,gki) to delete the instruction pointed to by GKI.
+
+procedure sge_spoolesc (tr, gki, fn, instruction, bp, buftop, delete_fcn)
+
+pointer tr #I arg to delete_fcn
+pointer gki #I pointer to escape instruction
+int fn #U escape sequence function opcode
+short instruction[ARB] #U escape instruction data
+pointer bp #I frame buffer pointer
+pointer buftop #I top+1 of buffered data
+int delete_fcn #I function called to delete an instruction
+
+bool sgm_spoolesc() # GIM (Gterm) imaging excapes
+
+begin
+ if (sgm_spoolesc (tr, gki, fn, instruction, bp, buftop, delete_fcn))
+ return
+end
diff --git a/sys/gio/stdgraph/stgfa.x b/sys/gio/stdgraph/stgfa.x
new file mode 100644
index 00000000..10cf4d61
--- /dev/null
+++ b/sys/gio/stdgraph/stgfa.x
@@ -0,0 +1,115 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_FILLAREA -- Fill a closed area. The area is defined by the array of
+# points P, consisting of successive (x,y) coordinate pairs outlining the
+# area to be filled.
+
+procedure stg_fillarea (p, npts)
+
+short p[ARB] #I points defining area outline
+int npts #I number of points, i.e., (x,y) pairs
+
+pointer fa
+bool tek_encoding
+int lowres_x, lowres_y
+int ip, n, sx, sy, len_p, iop, i
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ if (g_enable == NO)
+ call stg_genab()
+
+ len_p = npts * 2
+
+ # Update fillarea attributes if necessary.
+
+ fa = SG_FAAP(g_sg)
+ if (SG_COLOR(g_sg) != FA_COLOR(fa)) {
+ call stg_ctrl1 ("FC", FA_COLOR(fa))
+ SG_COLOR(g_sg) = FA_COLOR(fa)
+ }
+ if (SG_FASTYLE(g_sg) != FA_STYLE(fa)) {
+ call stg_ctrl1 ("FT", FA_STYLE(fa))
+ SG_FASTYLE(g_sg) = FA_STYLE(fa)
+ }
+
+ # Tektronix encoding is treated as a special case for max efficiency.
+ tek_encoding =
+ (Memc[g_xy] == '%' && Memc[g_xy+1] == 't' && Memc[g_xy+2] == EOS)
+
+ # Draw the fillarea. If the startfill sequence is defined we assume
+ # that the device can draw a multipoint fillarea.
+
+ if (Memc[SG_STARTFILL(g_sg)] != EOS) {
+ for (ip=1; ip <= len_p; ip=ip+2) {
+ # Output start fillarea sequence.
+ call ttyputs (g_out, g_tty, Memc[SG_STARTFILL(g_sg)], 1)
+ n = len_p
+
+ # Encode the points of the fillarea outline (or move to the
+ # single point to be drawn).
+
+ g_lastx = -1 # clip unresolved points only in the interior
+ g_lasty = -1 # of the area being drawn.
+
+ g_reg[E_IOP] = 1
+ do i = ip, n, 2 {
+ sx = p[i]
+ sy = p[i+1]
+
+ # Discard the point if it is not resolved.
+ lowres_x = sx / g_dxres
+ lowres_y = sy / g_dyres
+ if (lowres_x == g_lastx && lowres_y == g_lasty)
+ next
+
+ g_lastx = lowres_x
+ g_lasty = lowres_y
+
+ # Transform point into the device window.
+ sx = int (sx * g_dx) + g_x1
+ sy = int (sy * g_dy) + g_y1
+
+ # Encode the point, appending encoded bytes to g_mem.
+ # Tek encoding is treated as a special case since it is
+ # so common; the encoder is used for non-Tek encodings.
+
+ if (tek_encoding) {
+ iop = g_reg[E_IOP] + 4
+ g_mem[iop-4] = g_hixy[sy+1]
+ g_mem[iop-3] = g_loy[sy+1]
+ g_mem[iop-2] = g_hixy[sx+1]
+ g_mem[iop-1] = g_lox[sx+1]
+ g_reg[E_IOP] = iop
+ } else {
+ g_reg[1] = sx
+ g_reg[2] = sy
+ if (stg_encode (Memc[g_xy], g_mem, g_reg) != OK)
+ break
+ }
+
+ # Flush buffer if nearly full.
+ if (g_reg[E_IOP] > FLUSH_MEMORY) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+ }
+ ip = n
+
+ # Flush any output remaining in encoder memory.
+ if (g_reg[E_IOP] > 1) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+
+ # Output end polymarker sequence, or draw the point.
+ call ttyputs (g_out, g_tty, Memc[SG_ENDFILL(g_sg)], 1)
+ }
+ } else {
+ # If can't do a fill area, just draw the area outline.
+ call stg_polyline (p, npts)
+ }
+end
diff --git a/sys/gio/stdgraph/stgfaset.x b/sys/gio/stdgraph/stgfaset.x
new file mode 100644
index 00000000..d5b4c4e7
--- /dev/null
+++ b/sys/gio/stdgraph/stgfaset.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+# STG_FASET -- Set the fillarea attributes.
+
+procedure stg_faset (gki)
+
+short gki[ARB] # attribute structure
+pointer fa
+include "stdgraph.com"
+
+begin
+ fa = SG_FAAP(g_sg)
+ FA_STYLE(fa) = gki[GKI_FASET_FS]
+ FA_COLOR(fa) = gki[GKI_FASET_CI]
+end
diff --git a/sys/gio/stdgraph/stgfilter.x b/sys/gio/stdgraph/stgfilter.x
new file mode 100644
index 00000000..674f190f
--- /dev/null
+++ b/sys/gio/stdgraph/stgfilter.x
@@ -0,0 +1,165 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ttset.h>
+include <chars.h>
+include <fset.h>
+include "stdgraph.h"
+
+define MAXCH 16
+define RESET "reset"
+
+
+# SGF_POST_FILTER -- Post the stdgraph tty input filter to the VOS tty driver.
+# This input filter is used to intercept and process escape sequences sent by
+# the terminal to the IRAF client, to notify the client of events such as a
+# terminal reset.
+
+procedure sgf_post_filter (fd)
+
+int fd #I terminal file
+
+int locpr()
+extern sgf_ttyfilter()
+
+begin
+ # Install stdgraph filter in terminal driver.
+ call ttseti (fd, TT_FILTER, locpr(sgf_ttyfilter))
+ call ttseti (fd, TT_FILTERKEY, ESC)
+
+ # Register escapes with terminal.
+ call stg_outstr ("EZ", RESET)
+ call stg_outstr ("ER", "R")
+end
+
+
+# SGF_TTYFILTER -- Terminal input filter.
+
+procedure sgf_ttyfilter (fd, buf, maxch, status)
+
+int fd #I input file
+char buf[ARB] #U input buffer
+int maxch #I max chars in buffer
+int status #U number of chars in buffer
+
+char escape[MAXCH]
+char svbuf[MAXCH+4]
+int ip, op, sp, ch, iomode
+
+bool streq()
+int sgf_getchar(), fstati()
+include "stdgraph.com"
+define failed_ 91
+
+begin
+ # Disable the filter if reading from the terminal in nonblocking
+ # raw mode. We shouldn't receive a stdgraph escape at such a time,
+ # and this code isn't prepared to deal with nonblocking i/o. This
+ # case occurs, e.g., during a screen size query, where the terminal
+ # returns an escape sequence to the client (in nonblocking raw mode).
+
+ iomode = fstati (STDIN, F_IOMODE)
+ if (and (iomode, IO_NDELAY) != 0)
+ return
+
+ # The escape sequence is of the form "ESC P <text> ESC \", the ANSI
+ # device control string (DCS). This escape sequence is recognized by
+ # the vt100 terminal emulator in xgterm, which will accumulate and
+ # ignore the sequence. This is important because when a terminal
+ # (xgterm) reset occurs when IRAF is not reading from the terminal in
+ # raw mode, the character are echoed to the terminal and would be
+ # printed on the screen if not recognized by the terminal as an
+ # escape. By using a known escape which xgterm ignores the escape is
+ # transmitted without being seen by (and probably confusing) the
+ # user. If the reset occurs while in graphics mode and a cursor read
+ # is in progress, the terminal will be in raw mode and the sequence
+ # will not be echoed, hence the problem does not occur.
+
+ ip = 1
+ sp = 1
+ ch = sgf_getchar (fd, svbuf, sp, buf, ip, maxch, status)
+ if (ch != ESC)
+ goto failed_
+ ch = sgf_getchar (fd, svbuf, sp, buf, ip, maxch, status)
+ if (ch != 'P')
+ goto failed_
+
+ # Accumulate escape data string.
+ op = 1
+ repeat {
+ ch = sgf_getchar (fd, svbuf, sp, buf, ip, maxch, status)
+ if (ch < 0 || op > MAXCH)
+ goto failed_
+ if (ch == ESC) {
+ escape[op] = EOS
+ ch = sgf_getchar (fd, svbuf, sp, buf, ip, maxch, status)
+ break
+ } else {
+ escape[op] = ch
+ op = op + 1
+ }
+ }
+
+ # Process the escape.
+ if (streq (escape, RESET)) {
+ call stg_reset()
+ call ttseti (fd, TT_FILTER, NULL)
+ if (g_sg != NULL)
+ SG_UIFDATE(g_sg) = 0
+ } else # add additional escapes here
+ goto failed_
+
+ # Edit the input buffer to remove the escape.
+ op = 1
+ for ( ; ip <= status && op <= maxch; ip=ip+1) {
+ buf[op] = buf[ip]
+ op = op + 1
+ }
+ status = op - 1
+ return
+
+failed_
+ # Unrecognized escape. Append any newly read data to the input
+ # buffer and return all the data.
+
+ if (sp > 1) {
+ call amovc (svbuf, buf[status+1], sp - 1)
+ status = status + sp - 1
+ }
+end
+
+
+# SGF_GETCHAR -- Get a character from the input terminal. ERR or EOF is
+# returned if the input is exhausted. If reading in raw mode additional
+# reads will be performed as necessary.
+
+int procedure sgf_getchar (fd, svbuf, sp, buf, ip, maxch, nchars)
+
+int fd #I input file
+char svbuf[ARB] #O save chars as they are read
+int sp #U pointer into save buffer
+char buf[ARB] #U input buffer
+int ip #I input index
+int maxch #I max chars in buffer
+int nchars #U number of chars in buffer
+
+int ch
+int status
+
+begin
+ if (ip > nchars) {
+ if (maxch == 1) {
+ call zgetty (fd, svbuf[sp], maxch, status)
+ if (status <= 0)
+ return (ERR)
+ ch = svbuf[sp]
+ sp = sp + 1
+ return (ch)
+ } else
+ return (EOF)
+ }
+
+ ch = buf[ip]
+ ip = ip + 1
+
+ return (ch)
+end
diff --git a/sys/gio/stdgraph/stgflush.x b/sys/gio/stdgraph/stgflush.x
new file mode 100644
index 00000000..aada3927
--- /dev/null
+++ b/sys/gio/stdgraph/stgflush.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_FLUSH -- Flush output.
+
+procedure stg_flush (dummy)
+
+int dummy # not used at present
+include "stdgraph.com"
+
+begin
+ call flush (g_out)
+end
diff --git a/sys/gio/stdgraph/stggcell.x b/sys/gio/stdgraph/stggcell.x
new file mode 100644
index 00000000..2a9aea8c
--- /dev/null
+++ b/sys/gio/stdgraph/stggcell.x
@@ -0,0 +1,15 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# STG_GETCELLARRAY -- Input a cell array, i.e., two dimensional array of pixels
+# (greylevels or colors).
+
+procedure stg_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. Won't do much for a graphics terminal,
+ # but should be functionional.
+end
diff --git a/sys/gio/stdgraph/stggcur.x b/sys/gio/stdgraph/stggcur.x
new file mode 100644
index 00000000..08f2b8b7
--- /dev/null
+++ b/sys/gio/stdgraph/stggcur.x
@@ -0,0 +1,52 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_GETCURSOR -- Get the position of a cursor. The cursor value is returned
+# as a GKI structure on the graphics metacode stream.
+
+procedure stg_getcursor (cursor)
+
+int cursor #I cursor to be read or 0
+
+int cur, cn
+int key, sx, sy, raster, rx, ry
+include "stdgraph.com"
+
+begin
+ # If cursor=0 read the last cursor referenced, e.g., in a write.
+ if (cursor > 0) {
+ SG_CURSOR(g_sg) = cursor
+ cur = cursor
+ } else
+ cur = max (1, SG_CURSOR(g_sg))
+
+ # Restore graphics mode in case the user has forgotten the \n while
+ # writing to the status line.
+
+ if (g_enable == NO)
+ call stg_genab()
+
+ # If the user has locked the logical cursor override runtime selection.
+ if (g_cursor > 0)
+ cur = g_cursor
+
+ # Restore the software cursor position before reading?
+ if (SG_UPDCURSOR(g_sg) == YES) {
+ sx = SG_CURSOR_X(g_sg)
+ sy = SG_CURSOR_Y(g_sg)
+ if (sx != 0 && sy != 0)
+ call stg_setcursor (sx, sy, cur)
+ }
+
+ # Physically read the cursor and return value to caller.
+ call stg_readcursor (cur, cn, key, sx, sy, raster, rx, ry)
+ call gki_retcursorvalue (g_stream, cn, key, sx, sy, raster, rx, ry)
+ call flush (g_stream)
+
+ # Save the new position of the cursor for next time.
+ if (SG_UPDCURSOR(g_sg) == YES) {
+ SG_CURSOR_X(g_sg) = sx
+ SG_CURSOR_Y(g_sg) = sy
+ }
+end
diff --git a/sys/gio/stdgraph/stggdisab.x b/sys/gio/stdgraph/stggdisab.x
new file mode 100644
index 00000000..42ddec62
--- /dev/null
+++ b/sys/gio/stdgraph/stggdisab.x
@@ -0,0 +1,17 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_GDISAB -- Disable graphics, i.e., issue the GD control sequence.
+
+procedure stg_gdisab()
+
+include "stdgraph.com"
+
+begin
+ if (g_active == YES && g_out > 0) {
+ call stgctrl ("GD")
+ call flush (g_out)
+ g_enable = NO
+ }
+end
diff --git a/sys/gio/stdgraph/stggenab.x b/sys/gio/stdgraph/stggenab.x
new file mode 100644
index 00000000..5e350e33
--- /dev/null
+++ b/sys/gio/stdgraph/stggenab.x
@@ -0,0 +1,17 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_GENAB -- Enable graphics, i.e., issue the GE control sequence.
+
+procedure stg_genab()
+
+include "stdgraph.com"
+
+begin
+ if (g_active == YES && g_out > 0) {
+ call stgctrl ("GE")
+ call flush (g_out)
+ g_enable = YES
+ }
+end
diff --git a/sys/gio/stdgraph/stggim.x b/sys/gio/stdgraph/stggim.x
new file mode 100644
index 00000000..a71cd448
--- /dev/null
+++ b/sys/gio/stdgraph/stggim.x
@@ -0,0 +1,919 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <chars.h>
+include <ctype.h>
+include <fset.h>
+include <gescape.h>
+include <gki.h>
+include <gim.h>
+include "stdgraph.h"
+
+# STGGIM.X -- GIO.GIM gterm imaging escapes for the stdgraph kernel. The
+# routines in this file decode GKI escape instructions and encode serial
+# byte sequences which are sent to the server to execute the instruction.
+# In some cases the server returns a response which is decoded here and
+# encoded as a GKI return value which is returned to the client.
+
+define SZ_PATBUF 512
+define MAX_ARGS 32
+define TIMEOUT 10000
+
+
+# SGM_EXECUTE -- Test whether the given instruction is a GIM escape, and
+# if so execute it. Return true if the instruction was recognized and
+# executed.
+
+bool procedure sgm_execute (fn, gim, nwords)
+
+int fn #I function code
+short gim[ARB] #I instruction data words
+int nwords #I length of gim
+
+int raster
+common /sgmcom/ raster
+
+begin
+ switch (fn) {
+ case GKI_OPENWS, GKI_CLEAR:
+ call sgm_output ("RI", gim, GIM_RASTERINIT_LEN)
+ return (false)
+
+ case GIM_RASTERINIT:
+ call sgm_output ("RI", gim, GIM_RASTERINIT_LEN)
+ case GIM_CREATERASTER:
+ call sgm_output ("CR", gim, GIM_CREATERASTER_LEN)
+ case GIM_DESTROYRASTER:
+ call sgm_output ("DR", gim, GIM_DESTROYRASTER_LEN)
+ case GIM_QUERYRASTER:
+ call sgm_queryraster (gim)
+ case GIM_SETRASTER:
+ raster = gim[GIM_SETRASTER_RN]
+ call sgm_output ("SR", gim, GIM_SETRASTER_LEN)
+ case GIM_WRITEPIXELS:
+ call sgm_writepixels (gim)
+ case GIM_READPIXELS:
+ call sgm_readpixels (gim)
+ case GIM_REFRESHPIXELS:
+ call sgm_output ("RX", gim, GIM_REFRESHPIXELS_LEN)
+ case GIM_SETPIXELS:
+ call sgm_output ("SP", gim, GIM_SETPIXELS_LEN)
+ case GIM_WRITECMAP:
+ call sgm_writecmap (gim)
+ case GIM_READCMAP:
+ call sgm_readcmap (gim)
+ case GIM_LOADCMAP:
+ call sgm_output ("LM", gim, GIM_LOADCMAP_LEN)
+ case GIM_FREECMAP:
+ call sgm_output ("FL", gim, GIM_FREECMAP_LEN)
+ case GIM_WRITEIOMAP:
+ call sgm_iomapwrite (gim)
+ case GIM_READIOMAP:
+ call sgm_iomapread (gim)
+ case GIM_INITMAPPINGS:
+ call sgm_output ("IM", gim, GIM_INITMAPPINGS_LEN)
+ case GIM_FREEMAPPING:
+ call sgm_output ("FM", gim, GIM_FREEMAPPING_LEN)
+ case GIM_COPYRASTER:
+ call sgm_output ("CP", gim, GIM_COPYRASTER_LEN)
+ case GIM_SETMAPPING:
+ call sgm_output ("SM", gim, GIM_SETMAPPING_LEN)
+ case GIM_GETMAPPING:
+ call sgm_getmapping (gim)
+ case GIM_ENABLEMAPPING:
+ call sgm_output ("MN", gim, GIM_ENABLEMAPPING_LEN)
+ case GIM_DISABLEMAPPING:
+ call sgm_output ("MD", gim, GIM_DISABLEMAPPING_LEN)
+ case GIM_REFRESHMAPPING:
+ call sgm_output ("RF", gim, GIM_REFRESHMAPPING_LEN)
+
+ default:
+ return (false)
+ }
+
+ return (true)
+end
+
+
+# SGM_WSTRAN -- Transform and output a GIM escape. Ignore escapes we
+# know nothing about. TRUE is returned if the escape is one which is private
+# to the GIM interface.
+
+bool procedure sgm_wstran (fn, gim, rx1,ry1, rx2,ry2)
+
+int fn #I escape sequence function opcode
+short gim[ARB] #I escape instruction data
+real rx1,ry1 #I NDC coords of display rect
+real rx2,ry2 #I NDC coords of display rect
+
+real scale
+pointer sp, n_gim
+bool status, xflip, yflip
+int width, height, dst, src, dt
+int wx1, wy1, wx2, wy2, p1, p2
+int sx1, sy1, sx2, sy2, snx, sny
+int dx1, dy1, dx2, dy2, dnx, dny
+int n_dx1, n_dy1, n_dx2, n_dy2, n_dnx, n_dny
+int n_sx1, n_sy1, n_sx2, n_sy2
+int w_dx1, w_dy1, w_dx2, w_dy2
+bool sgm_execute()
+define exe_ 91
+
+begin
+ switch (fn) {
+ case GIM_RASTERINIT, GIM_INITMAPPINGS,
+ GIM_CREATERASTER, GIM_DESTROYRASTER, GIM_QUERYRASTER,
+ GIM_GETMAPPING, GIM_ENABLEMAPPING, GIM_DISABLEMAPPING,
+ GIM_REFRESHMAPPING, GIM_FREEMAPPING,
+ GIM_READPIXELS, GIM_WRITEPIXELS, GIM_REFRESHPIXELS, GIM_SETPIXELS,
+ GIM_WRITECMAP, GIM_READCMAP, GIM_LOADCMAP, GIM_FREECMAP,
+ GIM_WRITEIOMAP, GIM_READIOMAP,
+ GIM_COPYRASTER, GIM_SETRASTER:
+
+ # These instructions do not require any transformation.
+ status = sgm_execute (fn, gim, 0)
+
+ case GIM_SETMAPPING:
+ # Edit setmapping instructions which write to the display window.
+ # Raster 0 is the display window; only display window coordinates
+ # are affected by the workstation transformation.
+
+ src = gim[GIM_SETMAPPING_SR]
+ dst = gim[GIM_SETMAPPING_DR]
+ dt = gim[GIM_SETMAPPING_DT]
+
+ if (dst == 0 && src != dst) {
+ call smark (sp)
+ call salloc (n_gim, GIM_SETMAPPING_LEN, TY_SHORT)
+
+ xflip = false
+ yflip = false
+
+ # Convert the display rect NDC coordinates to window pixels
+ # or GKI units, depending upon which coordinate system is
+ # in use. Note that for NDC the Y axis is flipped relative
+ # to display window pixel coordinates.
+
+ if (dt == CT_PIXEL) {
+ call sgm_winsize (width, height)
+ wx1 = rx1 * (width - 1); wy1 = (1.0 - ry2) * (height - 1)
+ wx2 = rx2 * (width - 1); wy2 = (1.0 - ry1) * (height - 1)
+ } else {
+ width = GKI_MAXNDC + 1; height = GKI_MAXNDC + 1
+ wx1 = rx1 * (width - 1); wy1 = ry1 * (height - 1)
+ wx2 = rx2 * (width - 1); wy2 = ry2 * (height - 1)
+ }
+
+ sx1 = gim[GIM_SETMAPPING_SX]
+ snx = gim[GIM_SETMAPPING_SW]
+ sy1 = gim[GIM_SETMAPPING_SY]
+ sny = gim[GIM_SETMAPPING_SH]
+ sx2 = sx1 + snx - 1; sy2 = sy1 + sny - 1
+
+ dx1 = gim[GIM_SETMAPPING_DX]
+ dnx = gim[GIM_SETMAPPING_DW]
+ if (dnx < 0) {
+ dnx = -dnx
+ xflip = !xflip
+ }
+ dy1 = gim[GIM_SETMAPPING_DY]
+ dny = gim[GIM_SETMAPPING_DH]
+ if (dny < 0) {
+ dny = -dny
+ yflip = !yflip
+ }
+ dx2 = dx1 + dnx - 1; dy2 = dy1 + dny - 1
+
+ # Compute the intersection of the destination (screen) rect
+ # of the mapping with the region of the screen WS mapped by
+ # the workstation transformation.
+
+ n_dx1 = max (wx1, dx1); n_dy1 = max (wy1, dy1)
+ n_dx2 = min (wx2, dx2); n_dy2 = min (wy2, dy2)
+
+ # If the rectangles do not intersect set up a null mapping
+ # to temporarily disable the mapping.
+
+ n_dnx = n_dx2 - n_dx1 + 1; n_dny = n_dy2 - n_dy1 + 1
+ if (n_dnx <= 0 || n_dny <= 0) {
+ call amovs (gim, Mems[n_gim], GIM_SETMAPPING_LEN)
+ Mems[n_gim+GIM_SETMAPPING_SX-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_SW-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_SY-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_SH-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_DX-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_DW-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_DY-1] = 0
+ Mems[n_gim+GIM_SETMAPPING_DH-1] = 0
+ goto exe_
+ }
+
+ # Compute the source rect which maps to the new (intersection)
+ # destination rect.
+
+ if (snx == 1 || dnx == 1) {
+ n_sx1 = sx1
+ n_sx2 = sx2
+ } else {
+ scale = real(snx - 1) / real(dnx - 1)
+ n_sx1 = max(0, min(GKI_MAXNDC,
+ nint((n_dx1 - dx1) * scale + sx1)))
+ n_sx2 = max(0, min(GKI_MAXNDC,
+ nint((n_dx2 - dx2) * scale + sx2)))
+ if (xflip) {
+ p1 = sx1 + (sx2 - n_sx2)
+ p2 = sx2 - (n_sx1 - sx1)
+ n_sx1 = p1; n_sx2 = p2
+ }
+ }
+
+ if (sny == 1 || dny == 1) {
+ n_sy1 = sy1
+ n_sy2 = sy2
+ } else {
+ scale = real(sny - 1) / real(dny - 1)
+ n_sy1 = max(0, min(GKI_MAXNDC,
+ nint((n_dy1 - dy1) * scale + sy1)))
+ n_sy2 = max(0, min(GKI_MAXNDC,
+ nint((n_dy2 - dy2) * scale + sy2)))
+ if (yflip) {
+ p1 = sy1 + (sy2 - n_sy2)
+ p2 = sy2 - (n_sy1 - sy1)
+ n_sy1 = p1; n_sy2 = p2
+ }
+ }
+
+ # Scale the destination rect by the amount needed to make the
+ # WS rect fill the full display window.
+
+ if (wx1 == wx2) {
+ w_dx1 = 0
+ w_dx1 = width - 1
+ } else {
+ scale = real(width - 1) / real(wx2 - wx1)
+ w_dx1 = max(0, min(GKI_MAXNDC,
+ nint((n_dx1 - wx1) * scale)))
+ w_dx2 = max(0, min(GKI_MAXNDC,
+ nint((n_dx2 - wx1) * scale)))
+ }
+
+ if (wy1 == wy2) {
+ w_dy1 = 0
+ w_dy1 = height - 1
+ } else {
+ scale = real(height - 1) / real(wy2 - wy1)
+ w_dy1 = max(0, min(GKI_MAXNDC,
+ nint((n_dy1 - wy1) * scale)))
+ w_dy2 = max(0, min(GKI_MAXNDC,
+ nint((n_dy2 - wy1) * scale)))
+ }
+
+ # Construct the edited instruction.
+ call amovs (gim, Mems[n_gim], GIM_SETMAPPING_LEN)
+ Mems[n_gim+GIM_SETMAPPING_SX-1] = n_sx1
+ Mems[n_gim+GIM_SETMAPPING_SW-1] = n_sx2 - n_sx1 + 1
+ Mems[n_gim+GIM_SETMAPPING_SY-1] = n_sy1
+ Mems[n_gim+GIM_SETMAPPING_SH-1] = n_sy2 - n_sy1 + 1
+ Mems[n_gim+GIM_SETMAPPING_DX-1] = w_dx1
+ Mems[n_gim+GIM_SETMAPPING_DY-1] = w_dy1
+
+ n_dnx = max(0, min(GKI_MAXNDC, w_dx2 - w_dx1 + 1))
+ if (gim[GIM_SETMAPPING_DW] < 0)
+ n_dnx = -n_dnx
+ Mems[n_gim+GIM_SETMAPPING_DW-1] = n_dnx
+
+ n_dny = max(0, min(GKI_MAXNDC, w_dy2 - w_dy1 + 1))
+ if (gim[GIM_SETMAPPING_DH] < 0)
+ n_dny = -n_dny
+ Mems[n_gim+GIM_SETMAPPING_DH-1] = n_dny
+
+exe_
+ # Execute the edited instruction.
+ status = sgm_execute (fn, Mems[n_gim], 0)
+ call sfree (sp)
+
+ } else
+ status = sgm_execute (fn, gim, 0)
+
+ default:
+ status = false
+ }
+
+ return (status)
+end
+
+
+# SGM_WSENABLE -- Test if client scaling of graphics drawing instructions is
+# enabled. For the stdgraph kernel, these transformations are disabled if
+# the raster is other than zero, in which case the graphics server does the
+# scaling.
+
+bool procedure sgm_wsenable (enable)
+
+bool enable
+int raster
+common /sgmcom/ raster
+
+begin
+ enable = (raster == 0)
+ return (true)
+end
+
+
+# SGM_SPOOLESC -- Process a GIM escape into a frame buffer. All GIM escapes
+# are executed when first issued; we just determine whether the escapes are
+# preserved in the frame buffer to be executed when the frame is redrawn.
+# Ignore escapes we know nothing about. TRUE is returned if the escape is
+# one which is private to the GIM interface, i.e., if the escape has been
+# processed fully by sgm_spoolesc.
+
+bool procedure sgm_spoolesc (tr, gki, fn, gim, bp, buftop, delete_fcn)
+
+pointer tr #I arg to delete_fcn
+pointer gki #I pointer to escape instruction
+int fn #U escape sequence function opcode
+short gim[ARB] #U escape instruction data
+pointer bp #I frame buffer pointer
+pointer buftop #I top+1 of buffered data
+int delete_fcn #I function called to delete an instruction
+
+pointer ip, itop, esc
+int nleft, length, opcode, escape, mp
+
+begin
+ switch (fn) {
+ case GIM_RASTERINIT, GIM_INITMAPPINGS, GIM_FREEMAPPING,
+ GIM_CREATERASTER, GIM_DESTROYRASTER, GIM_QUERYRASTER,
+ GIM_GETMAPPING, GIM_ENABLEMAPPING, GIM_DISABLEMAPPING,
+ GIM_REFRESHMAPPING, GIM_WRITEPIXELS, GIM_READPIXELS,
+ GIM_REFRESHPIXELS, GIM_SETPIXELS, GIM_COPYRASTER,
+ GIM_WRITEIOMAP, GIM_READIOMAP, GIM_WRITECMAP, GIM_READCMAP,
+ GIM_LOADCMAP, GIM_FREECMAP:
+
+ # These escapes are only executed once.
+ call zcall2 (delete_fcn, tr, gki)
+
+ case GIM_SETRASTER:
+ ; # Preserve this instruction.
+
+ case GIM_SETMAPPING:
+ # This escape is saved in the frame buffer and rexecuted when
+ # the frame is redrawn. This allows the server to buffer the
+ # image data, but still allows the graphics to be redrawn and
+ # possibly rescaled in cursor mode. Rexecution of copyraster
+ # after a screen clear will cause any rasters created and written
+ # to with createraster/writepixels to be redrawn on the screen.
+
+ ip = bp
+ itop = gki
+
+ while (ip < itop) {
+ # Search for the beginning of the next instruction.
+ while (Mems[ip] != BOI && ip < itop)
+ ip = ip + 1
+
+ nleft = itop - ip
+ if (nleft < 3)
+ break
+ else {
+ length = Mems[ip+GKI_HDR_LENGTH-1]
+ if (length > nleft)
+ break
+
+ opcode = Mems[ip+GKI_HDR_OPCODE-1]
+ escape = Mems[ip+GKI_ESCAPE_FN-1]
+
+ # Disable instruction if same mapping number.
+ if (opcode == GKI_ESCAPE && escape == GIM_SETMAPPING) {
+ esc = ip + GKI_ESCAPE_DC - 1
+ mp = Mems[esc+GIM_SETMAPPING_MP-1]
+ if (mp == gim[GIM_SETMAPPING_MP])
+ Mems[ip+GKI_HDR_OPCODE-1] = GKI_UNKNOWN
+ }
+
+ ip = ip + length
+ }
+ }
+
+ default:
+ return (false)
+ }
+
+ return (true)
+end
+
+
+# SGM_WINSIZE -- Get the graphics window size in display pixels.
+
+procedure sgm_winsize (width, height)
+
+int width, height #O window size
+
+short gim_query[GIM_QUERYRASTER_LEN]
+short retval[GIM_RET_QRAS_LEN]
+
+begin
+ gim_query[GIM_QUERYRASTER_RN] = 0
+ call sgm_query ("QR", gim_query, GIM_QUERYRASTER_LEN,
+ "Qr", retval, GIM_RET_QRAS_LEN)
+ width = retval[GIM_RET_QRAS_NX]
+ height = retval[GIM_RET_QRAS_NY]
+end
+
+
+# SGM Private Functions.
+# ---------------------------
+
+# SGM_QUERYRASTER -- Return the attributes of a raster.
+
+procedure sgm_queryraster (gim)
+
+short gim[ARB] #I encoded instruction
+short retval[GIM_RET_QRAS_LEN]
+include "stdgraph.com"
+
+begin
+ call sgm_query ("QR", gim, GIM_QUERYRASTER_LEN,
+ "Qr", retval, GIM_RET_QRAS_LEN)
+ call write (g_stream, retval, GIM_RET_QRAS_LEN * SZ_SHORT)
+ call flush (g_stream)
+end
+
+
+# SGM_WRITEPIXELS -- Write a block of pixels to a raster.
+
+procedure sgm_writepixels (gim)
+
+short gim[ARB] #I encoded instruction
+
+char bias
+pointer sp, bp
+int nx, ny, npix, i
+include "stdgraph.com"
+
+begin
+ # Send the write-pixels escape sequence.
+ call sgm_output ("WP", gim, GIM_WRITEPIXELS_LEN)
+
+ # For the moment this code assumes 8 bit pixels.
+ nx = gim[GIM_WRITEPIXELS_NX]
+ ny = gim[GIM_WRITEPIXELS_NY]
+ npix = nx * ny
+
+ call smark (sp)
+ call salloc (bp, npix, TY_CHAR)
+ bias = 040B
+
+ # Send the pixel data encoded in printable ASCII.
+ call achtbc (gim[GIM_WRITEPIXELS_DATA], Memc[bp], npix)
+ do i = 1, npix
+ Memc[bp+i-1] = Memc[bp+i-1] + bias
+ call write (g_out, Memc[bp], npix)
+ call putci (g_out, GS)
+
+ call sfree (sp)
+end
+
+
+# SGM_READPIXELS -- Read a block of pixels from a raster and return it
+# to the client.
+
+procedure sgm_readpixels (gim)
+
+short gim[ARB] #I encoded instruction
+
+pointer sp, bp
+int sv_iomode, ch
+int npix, nx, ny, i
+short retval[GIM_RET_RPIX_LEN]
+int fstati(), getci()
+include "stdgraph.com"
+
+begin
+ sv_iomode = fstati (g_in, F_IOMODE)
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, IO_RAW)
+
+ # Send the read-pixels escape sequence.
+ call sgm_output ("RP", gim, GIM_READPIXELS_LEN)
+ call flush (g_out)
+
+ # For the moment this code assumes 8 bit pixels.
+ nx = gim[GIM_READPIXELS_NX]
+ ny = gim[GIM_READPIXELS_NY]
+ npix = nx * ny
+
+ call smark (sp)
+ call salloc (bp, npix, TY_CHAR)
+
+ # Get the pixel data. This is a block of pixel data encoded as for
+ # writepixels (040 bias), bracked by ESC at the front and a single
+ # control character such as \r or \n at the end.
+
+ while (getci (g_in, ch) != EOF)
+ if (ch == ESC)
+ break
+ for (i=0; getci (g_in, ch) >= 040B; )
+ if (i < npix) {
+ Memc[bp+i] = ch - 040B
+ i = i + 1
+ }
+ npix = i
+
+ # Send the RPIX header to the client.
+ retval[GIM_RET_RPIX_NP] = npix
+ call write (g_stream, retval, GIM_RET_RPIX_LEN * SZ_SHORT)
+
+ # Return the data to the client.
+ call achtcb (Memc[bp], Memc[bp], npix)
+ call write (g_stream, Memc[bp], (npix + SZB_CHAR-1) / SZB_CHAR)
+ call flush (g_stream)
+
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+ call sfree (sp)
+end
+
+
+# SGM_WRITECMAP -- Write to a segment of the colormap.
+
+procedure sgm_writecmap (gim)
+
+short gim[ARB] #I encoded instruction
+
+short mask
+pointer sp, bp, op
+int ncells, nchars, ip, i
+include "stdgraph.com"
+
+begin
+ call smark (sp)
+
+ # Send the write-colormap escape sequence.
+ call sgm_output ("WM", gim, GIM_WRITECMAP_LEN)
+
+ # Each cell consists of a RGB triplet encoded 2 chars per color.
+ ncells = gim[GIM_WRITECMAP_NC]
+ nchars = ncells * 3 * 2
+
+ call salloc (bp, nchars, TY_CHAR)
+ ip = GIM_WRITECMAP_DATA
+ op = bp
+
+ mask = 017B
+ do i = 1, ncells*3 {
+ Memc[op] = gim[ip] / 16 + 040B; op = op + 1
+ Memc[op] = and (gim[ip], mask) + 040B; op = op + 1
+ ip = ip + 1
+ }
+
+ call write (g_out, Memc[bp], nchars)
+ call putci (g_out, GS)
+
+ call sfree (sp)
+end
+
+
+# SGM_READCMAP -- Read a segment of the colormap.
+
+procedure sgm_readcmap (gim)
+
+short gim[ARB] #I encoded instruction
+
+pointer sp, bp, cm, ip
+int sv_iomode, ncells, nchars, ch, i
+short retval[GIM_RET_RCMAP_LEN]
+int fstati(), getci()
+include "stdgraph.com"
+
+begin
+ sv_iomode = fstati (g_in, F_IOMODE)
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, IO_RAW)
+
+ # Send the read-cmap escape sequence.
+ call sgm_output ("RM", gim, GIM_READCMAP_LEN)
+ call flush (g_out)
+
+ # Each cell consists of a RGB triplet encoded 2 chars per color.
+ ncells = gim[GIM_READCMAP_NC]
+ nchars = ncells * 3 * 2
+
+ call smark (sp)
+ call salloc (bp, nchars, TY_CHAR)
+ call salloc (cm, ncells * 3, TY_SHORT)
+
+ # Get the colormap data. This is a block of RGB colormap triplets
+ # encoded 2 bytes per color, bracked by a ESC at the front and a
+ # single control character such as \r or \n at the end.
+
+ while (getci (g_in, ch) != EOF)
+ if (ch == ESC)
+ break
+ for (i=0; getci (g_in, ch) >= 040B; )
+ if (i < nchars) {
+ Memc[bp+i] = ch - 040B
+ i = i + 1
+ }
+ ncells = i / (3 * 2)
+
+ # Decode the packed colormap data.
+ ip = bp
+ do i = 1, ncells * 3 {
+ Mems[cm+i-1] = (Memc[ip] - 040B) * 16 + (Memc[ip+1] - 040B)
+ ip = ip + 2
+ }
+
+ # Send the read-cmap header to the client.
+ retval[GIM_RET_RCMAP_NC] = ncells
+ call write (g_stream, retval, GIM_RET_RCMAP_LEN * SZ_SHORT)
+
+ # Return the colormap data to the client.
+ call write (g_stream, Mems[cm], (ncells * 3) * SZ_SHORT)
+ call flush (g_stream)
+
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+ call sfree (sp)
+end
+
+
+# SGM_IOMAPWRITE -- Write to the iomap.
+
+procedure sgm_iomapwrite (gim)
+
+short gim[ARB] #I encoded instruction
+
+short mask
+pointer sp, bp, op
+int ncells, nchars, ip, i
+include "stdgraph.com"
+
+begin
+ call smark (sp)
+
+ # Send the write-iomap escape sequence.
+ call sgm_output ("WO", gim, GIM_WRITEIOMAP_LEN)
+
+ # Each cell consists of a single short integer colormap index
+ # encoded 2 chars per cell.
+
+ ncells = gim[GIM_WRITEIOMAP_NC]
+ nchars = ncells * 2
+
+ call salloc (bp, nchars, TY_CHAR)
+ ip = GIM_WRITEIOMAP_DATA
+ op = bp
+
+ mask = 017B
+ do i = 1, ncells {
+ Memc[op] = gim[ip] / 16 + 040B; op = op + 1
+ Memc[op] = and (gim[ip], mask) + 040B; op = op + 1
+ ip = ip + 1
+ }
+
+ call write (g_out, Memc[bp], nchars)
+ call putci (g_out, GS)
+
+ call sfree (sp)
+end
+
+
+# SGM_IOMAPREAD -- Read a segment of the iomap.
+
+procedure sgm_iomapread (gim)
+
+short gim[ARB] #I encoded instruction
+
+pointer sp, bp, data, ip
+int sv_iomode, ncells, nchars, ch, i
+short retval[GIM_RET_RIOMAP_LEN]
+int fstati(), getci()
+include "stdgraph.com"
+
+begin
+ sv_iomode = fstati (g_in, F_IOMODE)
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, IO_RAW)
+
+ # Send the read-iomap escape sequence.
+ call sgm_output ("RO", gim, GIM_READIOMAP_LEN)
+ call flush (g_out)
+
+ # The data is encoded two bytes per short integer value.
+ ncells = gim[GIM_READIOMAP_NC]
+ nchars = ncells * 2
+
+ call smark (sp)
+ call salloc (bp, nchars, TY_CHAR)
+ call salloc (data, ncells, TY_SHORT)
+
+ # Get the iomap data. This is a block of iomap values encoded
+ # 2 bytes per value, bracked by a ESC at the front and a single
+ # control character such as \r or \n at the end.
+
+ while (getci (g_in, ch) != EOF)
+ if (ch == ESC)
+ break
+ for (i=0; getci (g_in, ch) >= 040B; )
+ if (i < nchars) {
+ Memc[bp+i] = ch - 040B
+ i = i + 1
+ }
+ ncells = i / 2
+
+ # Decode the packed iomap data.
+ ip = bp
+ do i = 1, ncells {
+ Mems[data+i-1] = (Memc[ip] - 040B) * 16 + (Memc[ip+1] - 040B)
+ ip = ip + 2
+ }
+
+ # Send the read-iomap header to the client.
+ retval[GIM_RET_RIOMAP_NC] = ncells
+ call write (g_stream, retval, GIM_RET_RIOMAP_LEN * SZ_SHORT)
+
+ # Return the iomap data to the client.
+ call write (g_stream, Mems[data], ncells * SZ_SHORT)
+ call flush (g_stream)
+
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+ call sfree (sp)
+end
+
+
+# SGM_GETMAPPING -- Return the attributes of a mapping.
+
+procedure sgm_getmapping (gim)
+
+short gim[ARB] #I encoded instruction
+short retval[GIM_RET_GMAP_LEN]
+include "stdgraph.com"
+
+begin
+ call sgm_query ("GM", gim, GIM_GETMAPPING_LEN,
+ "Gm", retval, GIM_RET_GMAP_LEN)
+ call write (g_stream, retval, GIM_RET_GMAP_LEN * SZ_SHORT)
+ call flush (g_stream)
+end
+
+
+# SGM_OUTPUT -- Format and output a control sequence to the graphics server
+# device.
+
+procedure sgm_output (cap, gim, nargs)
+
+char cap[ARB] #I graphcap capability name
+short gim[ARB] #I instruction (array of int args)
+int nargs #I number of arguments
+
+int ival, i
+pointer sp, fmt, ctrl
+include "stdgraph.com"
+int ttygets()
+errchk ttygets
+
+begin
+ call smark (sp)
+ call salloc (fmt, SZ_LINE, TY_CHAR)
+ call salloc (ctrl, SZ_LINE, TY_CHAR)
+
+ if (ttygets (g_tty, cap, Memc[fmt], SZ_LINE) > 0) {
+ call sprintf (Memc[ctrl], SZ_LINE, Memc[fmt])
+ do i = 1, nargs {
+ # Pass the argument as an integer to avoid INDEF
+ # processing of -32767, a valid GKI value.
+ ival = gim[i]
+ iferr (call pargi (ival))
+ ;
+ }
+ call ttyputs (g_out, g_tty, Memc[ctrl], 1)
+ }
+
+ call sfree (sp)
+end
+
+
+# SGM_QUERY -- Output an inquiry control sequence to the server and read and
+# decode the server's response.
+
+procedure sgm_query (query_cap, gim, nargs, retval_cap, retval, nout)
+
+char query_cap[ARB] #I server query cap name
+short gim[ARB] #I query instruction (args)
+int nargs #I number of args for server query
+char retval_cap[ARB] #I cap name for return value format
+short retval[ARB] #O decoded output arguments
+int nout #I number of output arguments
+
+int index[MAX_ARGS]
+pointer sp, ctrl, patbuf, pat, buf, ip, op
+int sv_iomode, arg, ch, nchars, start, value, ival, i
+int patmake(), patindex(), ttyread(), ctoi()
+int ttygets(), fstati(), gstrcpy()
+include "stdgraph.com"
+define done_ 91
+errchk ttygets
+
+begin
+ call smark (sp)
+ call salloc (ctrl, SZ_LINE, TY_CHAR)
+ call salloc (buf, SZ_LINE, TY_CHAR)
+ call salloc (pat, SZ_LINE, TY_CHAR)
+ call salloc (patbuf, SZ_PATBUF, TY_CHAR)
+
+ call aclrs (retval, nout)
+
+ # Set raw mode i/o.
+ sv_iomode = fstati (g_in, F_IOMODE)
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, IO_RAW)
+
+ # Pass the query on to the server.
+ if (ttygets (g_tty, query_cap, Memc[pat], SZ_LINE) > 0) {
+ call sprintf (Memc[ctrl], SZ_LINE, Memc[pat])
+ do i = 1, nargs {
+ # Pass the argument as an integer to avoid INDEF
+ # processing of -32767, a valid GKI value.
+ ival = gim[i]
+ iferr (call pargi (ival))
+ ;
+ }
+ call ttyputs (g_out, g_tty, Memc[ctrl], 1)
+ call flush (g_out)
+
+ } else
+ goto done_
+
+ # Encode a pattern to match the server's response as given by the
+ # pattern in retval_cap.
+
+ if (ttygets (g_tty, retval_cap, Memc[pat], SZ_LINE) <= 0)
+ goto done_
+
+ # Process the retval_cap string, used to specify the format of the
+ # string returned by the server, to map the %N fields therein into
+ # the pattern strings "%[0-9]*", noting the index positions of the
+ # pattern substrings for later decoding.
+
+ call aclri (index, MAX_ARGS)
+ arg = 0
+
+ op = buf
+ for (ip=pat; Memc[ip] != EOS; ip=ip+1) {
+ if (Memc[ip] == '%') {
+ if (Memc[ip+1] == '%') {
+ Memc[op] = Memc[ip]
+ op = op + 1
+ ip = ip + 1
+ } else {
+ op = op + gstrcpy ("%[0-9]*", Memc[op], ARB)
+ ip = ip + 1
+
+ # Arguments are %1 ... %9, %a, %b, etc.
+ ch = Memc[ip]
+ if (IS_DIGIT(ch))
+ i = TO_INTEG(ch)
+ else if (IS_UPPER(ch))
+ i = ch - 'A' + 10
+ else
+ i = ch - 'a' + 10
+
+ arg = arg + 1
+ i = min(MAX_ARGS, max(1, i))
+ index[i] = arg
+ }
+ } else if (Memc[ip] == '[') {
+ Memc[op] = '\\'; op = op + 1
+ Memc[op] = '[' ; op = op + 1
+ } else {
+ Memc[op] = Memc[ip]
+ op = op + 1
+ }
+ }
+
+ Memc[op] = EOS
+ if (patmake (Memc[buf], Memc[patbuf], SZ_PATBUF) >= SZ_PATBUF)
+ goto done_
+
+ # Scan the input stream from the server until data matching the
+ # response pattern is received, or a timeout occurs.
+
+ nchars = ttyread (g_in, g_tty,Memc[buf],SZ_LINE,Memc[patbuf], TIMEOUT)
+ if (nchars > 0) {
+ do i = 1, nout {
+ value = 0
+ if (index[i] > 0) {
+ start = patindex (Memc[patbuf], index[i])
+ if (ctoi (Memc[buf], start, value) <= 0)
+ value = 0
+ }
+ retval[i] = value
+ }
+ }
+done_
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/stggrstr.x b/sys/gio/stdgraph/stggrstr.x
new file mode 100644
index 00000000..946b52d9
--- /dev/null
+++ b/sys/gio/stdgraph/stggrstr.x
@@ -0,0 +1,16 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_GRSTREAM -- Set the FD of the graphics stream, from which we shall read
+# metacode instructions and to which we shall return cell arrays and cursor
+# values.
+
+procedure stg_grstream (stream)
+
+int stream # FD of the new graphics stream
+include "stdgraph.com"
+
+begin
+ g_stream = stream
+end
diff --git a/sys/gio/stdgraph/stginit.x b/sys/gio/stdgraph/stginit.x
new file mode 100644
index 00000000..3e393be4
--- /dev/null
+++ b/sys/gio/stdgraph/stginit.x
@@ -0,0 +1,193 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <mach.h>
+include <ctype.h>
+include <gki.h>
+include <gset.h>
+include "stdgraph.h"
+
+# STG_INIT -- Initialize the stdgraph 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 STG_RESET initializes the attribute
+# packets when the screen is cleared.
+
+procedure stg_init (tty, devname)
+
+pointer tty # graphcap descriptor
+char devname[ARB] # device name
+
+pointer nextch
+bool first_time
+int maxch, i, junk
+real char_height, char_width, char_size
+
+bool ttygetb()
+real ttygetr()
+pointer stg_gstring()
+int ttygets(), ttygeti(), btoi(), stg_encode(), gstrcpy()
+include "stdgraph.com"
+data first_time /true/
+
+begin
+ # One time initialization.
+ if (first_time) {
+ # Initialize the Tek 4012 coordinate encoding lookup tables.
+ do i = 1, TEK_XRES {
+ g_hixy[i] = (i-1) / 40B + 40B
+ g_lox[i] = mod ((i-1), 40B) + 100B
+ }
+ do i = 1, TEK_YRES
+ g_loy[i] = mod ((i-1), 40B) + 140B
+
+ first_time = false
+ }
+
+ # Allocate the stdgraph descriptor and the string buffer.
+ call calloc (g_sg, LEN_SG, TY_STRUCT)
+ call malloc (SG_SBUF(g_sg), SZ_SBUF, TY_CHAR)
+
+ # 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.
+
+ SG_SZSBUF(g_sg) = SZ_SBUF
+ SG_NEXTCH(g_sg) = SG_SBUF(g_sg) + 1
+ Memc[SG_SBUF(g_sg)] = EOS
+
+ # Set the software device resolution and the coordinate transformations
+ # to the resolution space and from GKI to device coords. The values
+ # g_[xy]res were initialized when the kernel was opened by the main
+ # program.
+
+ call stg_resolution (g_xres, g_yres)
+
+ # Initialize the encoder. The graphcap parameter LR contains encoder
+ # instructions to perform any device dependent initialization required.
+
+ call aclri (g_reg, NREGISTERS)
+ nextch = SG_NEXTCH(g_sg)
+
+ g_reg[E_IOP] = 1
+ g_reg[E_TOP] = SZ_MEMORY
+ if (ttygets (tty, "LR", Memc[nextch], SZ_SBUF-1) > 0)
+ junk = stg_encode (Memc[nextch], g_mem, g_reg)
+
+ # If the device does not support hardware character generation, set
+ # txquality to high to get software character generation.
+
+ if (!ttygetb (tty, "tx"))
+ g_hardchar = GT_HIGH
+
+ # 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 discrete 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.
+
+ SG_NCHARSIZES(g_sg) = min (MAX_CHARSIZES, ttygeti (tty, "th"))
+ nextch = SG_NEXTCH(g_sg)
+
+ if (SG_NCHARSIZES(g_sg) <= 0) {
+ SG_NCHARSIZES(g_sg) = 1
+ SG_CHARSIZE(g_sg,1) = 1.0
+ } else {
+ Memc[nextch+2] = EOS
+ for (i=1; i <= SG_NCHARSIZES(g_sg); i=i+1) {
+ Memc[nextch] = 't'
+ Memc[nextch+1] = TO_DIGIT(i)
+ char_size = ttygetr (tty, Memc[nextch])
+ SG_CHARSIZE(g_sg,i) = char_size
+ SG_CHARHEIGHT(g_sg,i) = char_height * char_size
+ SG_CHARWIDTH(g_sg,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 stdgraph
+ # descriptor. If the capability does not exist the pointer is set to
+ # point to the null string at the beginning of the string buffer.
+
+ SG_POLYLINE(g_sg) = btoi (ttygetb (tty, "PL"))
+ SG_POLYMARKER(g_sg) = btoi (ttygetb (tty, "pm"))
+ SG_FILLAREA(g_sg) = btoi (ttygetb (tty, "fa"))
+
+ SG_ENCODEXY(g_sg) = stg_gstring ("XY")
+ g_xy = SG_ENCODEXY(g_sg)
+
+ SG_STARTDRAW(g_sg) = stg_gstring ("DS")
+ SG_ENDDRAW(g_sg) = stg_gstring ("DE")
+ SG_STARTMOVE(g_sg) = stg_gstring ("VS")
+ SG_ENDMOVE(g_sg) = stg_gstring ("VE")
+ SG_STARTMARK(g_sg) = stg_gstring ("MS")
+ SG_ENDMARK(g_sg) = stg_gstring ("ME")
+ SG_STARTFILL(g_sg) = stg_gstring ("FS")
+ SG_ENDFILL(g_sg) = stg_gstring ("FE")
+ SG_STARTTEXT(g_sg) = stg_gstring ("TS")
+ SG_ENDTEXT(g_sg) = stg_gstring ("TE")
+
+ # Initialize the input parameters.
+ SG_CURSOR(g_sg) = 0
+ SG_UPDCURSOR(g_sg) = btoi (ttygetb (tty, "UC"))
+ SG_CURSOR_X(g_sg) = 0
+ SG_CURSOR_Y(g_sg) = 0
+
+ # Save the device string in the descriptor.
+ nextch = SG_NEXTCH(g_sg)
+ SG_DEVNAME(g_sg) = nextch
+ maxch = SG_SBUF(g_sg) + SZ_SBUF - nextch + 1
+ nextch = nextch + gstrcpy (devname, Memc[nextch], maxch) + 1
+
+ # Initialize the UIFNAME field.
+ SG_UIFNAME(g_sg) = nextch
+ Memc[nextch] = EOS
+ nextch = nextch + SZ_UIFNAME + 1
+ SG_NEXTCH(g_sg) = nextch
+end
+
+
+# STG_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 stg_gstring (cap)
+
+char cap[ARB] # device capability to be fetched
+pointer strp, nextch
+int maxch, nchars
+int ttygets()
+include "stdgraph.com"
+
+begin
+ nextch = SG_NEXTCH(g_sg)
+ maxch = SG_SBUF(g_sg) + SZ_SBUF - nextch + 1
+
+ nchars = ttygets (g_tty, cap, Memc[nextch], maxch)
+ if (nchars > 0) {
+ strp = nextch
+ nextch = nextch + nchars + 1
+ } else
+ strp = SG_SBUF(g_sg)
+
+ SG_NEXTCH(g_sg) = nextch
+ return (strp)
+end
diff --git a/sys/gio/stdgraph/stglkcur.x b/sys/gio/stdgraph/stglkcur.x
new file mode 100644
index 00000000..6152534b
--- /dev/null
+++ b/sys/gio/stdgraph/stglkcur.x
@@ -0,0 +1,18 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include "stdgraph.h"
+
+# STG_LOCKCURSOR -- Lock the logical cursor number. Called interactively by
+# cursor mode in response to a ":.cursor N" command by the user. When the
+# cursor is not locked the logical cursor may be selected under program
+# control.
+
+procedure stg_lockcursor (new_cursor)
+
+int new_cursor # desired new logical cursor
+include "stdgraph.com"
+
+begin
+ g_cursor = new_cursor
+end
diff --git a/sys/gio/stdgraph/stgmove.x b/sys/gio/stdgraph/stgmove.x
new file mode 100644
index 00000000..5f7396a3
--- /dev/null
+++ b/sys/gio/stdgraph/stgmove.x
@@ -0,0 +1,27 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_MOVE -- Output a device move instruction to move to the position (x,y)
+# in GKI coordinates.
+
+procedure stg_move (x, y)
+
+int x, y # destination
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ # Transform the first point from GKI coords to device coords and
+ # move to the transformed point.
+
+ call ttyputs (g_out, g_tty, Memc[SG_STARTMOVE(g_sg)], 1)
+
+ g_reg[1] = x * g_dx + g_x1
+ g_reg[2] = y * g_dy + g_y1
+ g_reg[E_IOP] = 1
+ if (stg_encode (Memc[g_xy], g_mem, g_reg) == OK)
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+
+ call ttyputs (g_out, g_tty, Memc[SG_ENDMOVE(g_sg)], 1)
+end
diff --git a/sys/gio/stdgraph/stgonerr.x b/sys/gio/stdgraph/stgonerr.x
new file mode 100644
index 00000000..047c6152
--- /dev/null
+++ b/sys/gio/stdgraph/stgonerr.x
@@ -0,0 +1,17 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_ONERROR -- Called when error recovery takes place to deactivate the
+# stdgraph workstation, i.e., take the terminal out of graphics mode. If
+# this is not done error messages will be written as vectors.
+
+procedure stg_onerror (errcode)
+
+int errcode
+include "stdgraph.com"
+
+begin
+ if (g_active == YES)
+ call stg_deactivatews (0)
+end
diff --git a/sys/gio/stdgraph/stgonint.x b/sys/gio/stdgraph/stgonint.x
new file mode 100644
index 00000000..2aed03ee
--- /dev/null
+++ b/sys/gio/stdgraph/stgonint.x
@@ -0,0 +1,21 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <config.h>
+include <xwhen.h>
+include "stdgraph.h"
+
+# STG_ONINT -- Interrupt handler for the stdgraph kernel. If an interrupt
+# occurs while we are posted to an exception, branch to the last ZSVJMP.
+# (This library procedure is not currently used by the kernel).
+
+procedure stg_onint (vex, next_handler)
+
+int vex # virtual exception
+int next_handler # next exception handler in chain
+int jmpbuf[LEN_JUMPBUF]
+common /stgxin/ jmpbuf
+
+begin
+ call xer_reset()
+ call zdojmp (jmpbuf, vex)
+end
diff --git a/sys/gio/stdgraph/stgopen.x b/sys/gio/stdgraph/stgopen.x
new file mode 100644
index 00000000..47fb2b61
--- /dev/null
+++ b/sys/gio/stdgraph/stgopen.x
@@ -0,0 +1,103 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <gki.h>
+include "stdgraph.h"
+
+# STG_OPEN -- Install the STDGRAPH 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 stg_open (devname, dd, in, out, xres, yres, hardchar)
+
+char devname[ARB] # if nonnull, force output to device
+int dd[ARB] # device table to be initialized
+int in # input file
+int out # output file
+int xres # number of resolved pixels in X
+int yres # number of resolved pixels in Y
+int hardchar # use hardware character generator
+
+bool first_time
+pointer sp, devns
+int len_devname
+int locpr(), strlen()
+
+extern stg_openws(), stg_closews(), stg_clear(), stg_cancel()
+extern stg_flush(), stg_polyline(), stg_polymarker(), stg_text()
+extern stg_fillarea(), stg_putcellarray(), stg_setcursor(), stg_plset()
+extern stg_pmset(), stg_txset(), stg_faset(), stg_getcursor()
+extern stg_getcellarray(), stg_escape()
+extern stg_reactivatews(), stg_deactivatews()
+include "stdgraph.com"
+data first_time /true/
+
+begin
+ call smark (sp)
+ call salloc (devns, SZ_FNAME, TY_SHORT)
+
+ if (first_time) {
+ g_nopen = 0
+ g_sg = NULL
+ g_tty = NULL
+ g_term = NULL
+ g_pbtty = NULL
+ g_cursor = 0
+ first_time = false
+ }
+
+ g_in = in
+ g_out = out
+ g_xres = xres
+ g_yres = yres
+ g_nopen = g_nopen + 1
+ g_stream = STDGRAPH
+ g_hardchar = hardchar
+ g_active = NO
+ g_enable = NO
+ g_message = NO
+ g_msgbuf = NULL
+ g_msgbuflen = 0
+ g_msglen = 0
+ call strcpy (devname, g_device, SZ_GDEVICE)
+
+ # Install the device driver.
+ dd[GKI_OPENWS] = locpr (stg_openws)
+ dd[GKI_CLOSEWS] = locpr (stg_closews)
+ dd[GKI_REACTIVATEWS] = locpr (stg_reactivatews)
+ dd[GKI_DEACTIVATEWS] = locpr (stg_deactivatews)
+ dd[GKI_MFTITLE] = 0
+ dd[GKI_CLEAR] = locpr (stg_clear)
+ dd[GKI_CANCEL] = locpr (stg_cancel)
+ dd[GKI_FLUSH] = locpr (stg_flush)
+ dd[GKI_POLYLINE] = locpr (stg_polyline)
+ dd[GKI_POLYMARKER] = locpr (stg_polymarker)
+ dd[GKI_TEXT] = locpr (stg_text)
+ dd[GKI_FILLAREA] = locpr (stg_fillarea)
+ dd[GKI_PUTCELLARRAY] = locpr (stg_putcellarray)
+ dd[GKI_SETCURSOR] = locpr (stg_setcursor)
+ dd[GKI_PLSET] = locpr (stg_plset)
+ dd[GKI_PMSET] = locpr (stg_pmset)
+ dd[GKI_TXSET] = locpr (stg_txset)
+ dd[GKI_FASET] = locpr (stg_faset)
+ dd[GKI_GETCURSOR] = locpr (stg_getcursor)
+ dd[GKI_GETCELLARRAY] = locpr (stg_getcellarray)
+ dd[GKI_ESCAPE] = locpr (stg_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 stg_openws (Mems[devns], len_devname, NEW_FILE)
+ }
+
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/stgopenws.x b/sys/gio/stdgraph/stgopenws.x
new file mode 100644
index 00000000..a70a51f7
--- /dev/null
+++ b/sys/gio/stdgraph/stgopenws.x
@@ -0,0 +1,220 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include <ttset.h>
+include <error.h>
+include <chars.h>
+include <finfo.h>
+include "stdgraph.h"
+
+# STG_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, followed by initialization of the device itself.
+
+procedure stg_openws (devname, n, mode)
+
+short devname[ARB] #I device name (actually device[,uifname])
+int n #I length of device name
+int mode #I access mode
+
+bool reinit
+long fi[LEN_FINFO]
+int dummy, init_file
+pointer sp, ip, op, buf, device, uifname, fname
+
+pointer ttygdes(), ttyodes()
+bool ttygetb(), strne(), streq()
+int ttygets(), open(), ttstati(), finfo(), gstrcpy()
+int nowhite(), envfind(), strlen(), fnroot(), access()
+extern stg_onerror()
+include "stdgraph.com"
+define ow_ 91
+
+begin
+ call smark (sp)
+ call salloc (buf, max (SZ_PATHNAME, n), TY_CHAR)
+ call salloc (fname, SZ_PATHNAME, TY_CHAR)
+
+ # Open a termcap descriptor for the terminal too, in case we need
+ # to talk to the terminal as a terminal.
+
+ if (g_term == NULL)
+ iferr (g_term = ttyodes ("terminal"))
+ g_term = NULL
+
+ # If we are appending merely reactivate the device without performing
+ # any initialization.
+
+ if (g_sg != NULL && mode == APPEND) {
+ if (g_active == NO) {
+ g_ucaseout = ttstati (g_out, TT_UCASEOUT)
+ if (g_ucaseout == YES)
+ call ttseti (g_out, TT_UCASEOUT, NO)
+
+ g_active = YES
+ g_enable = YES
+ }
+ goto ow_
+ }
+
+ # 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)
+
+ # Parse the "device,uifname" specification into the two fields.
+ device = buf
+ uifname = NULL
+ for (ip=buf; Memc[ip] != EOS; ip=ip+1)
+ if (Memc[ip] == ',') {
+ Memc[ip] = EOS
+ if (Memc[ip+1] != EOS)
+ uifname = ip + 1
+ if (nowhite (Memc[uifname], Memc[uifname], ARB) == 0)
+ uifname = NULL
+ break
+ }
+
+ # If the kernel is already open for this device skip most of the
+ # initialization. If already open for a different device free
+ # storage before reinitialization.
+
+ reinit = true
+ if (g_sg != NULL)
+ if (strne (Memc[device], Memc[SG_DEVNAME(g_sg)])) {
+ call mfree (SG_SBUF(g_sg), TY_CHAR)
+ call mfree (g_sg, TY_STRUCT)
+ reinit = true
+ } else
+ reinit = false
+
+ # Reinitialize the kernel datastructures. Open graphcap descriptor
+ # for the named device, allocate and initialize descriptor and common.
+
+ if (reinit) {
+ if (g_tty != NULL) {
+ call ttycdes (g_tty)
+ g_tty = NULL
+ }
+
+ iferr (g_tty = ttygdes (Memc[device])) {
+ g_tty = ttygdes ("4012")
+ call erract (EA_WARN)
+ }
+
+ # Initialize data structures.
+ call stg_init (g_tty, Memc[device])
+ }
+
+ call stg_reset()
+
+ if (g_active == NO) {
+ # Must disable stty ucaseout mode when in graphics mode, else
+ # plotting commands may be modified by the terminal driver.
+
+ g_ucaseout = ttstati (g_out, TT_UCASEOUT)
+ if (g_ucaseout == YES)
+ call ttseti (g_out, TT_UCASEOUT, NO)
+
+ # Post ONERROR cleanup routine.
+ call onerror (stg_onerror)
+ g_active = YES
+ g_enable = YES
+ }
+
+ # If no UI file was specified but the device has the EM capability,
+ # use the default UI if any specified in the graphcap entry. If the
+ # EM capability is missing, ignore any uifname specified when the
+ # device was opened.
+
+ if (ttygetb (g_tty, "EM")) {
+ if (uifname == NULL) {
+ uifname = buf + strlen(Memc[device]) + 1
+ if (ttygets (g_tty, "ED", Memc[uifname], ARB) <= 0)
+ uifname = NULL
+ }
+
+ # If the user has a version of the named UI file in their GUIDIR,
+ # use that instead.
+
+ if (envfind (GUIDIR, Memc[fname], SZ_PATHNAME) > 0) {
+ op = fname + strlen (Memc[fname])
+ op = op + fnroot (Memc[uifname], Memc[op],
+ fname + SZ_PATHNAME - op)
+ op = op + gstrcpy (".gui", Memc[op], fname + SZ_PATHNAME - op)
+ if (access (Memc[fname], 0, 0) == YES)
+ uifname = fname
+ }
+
+ # If the UI is already running and has not been modified there
+ # is no need to download it again.
+
+ if (g_sg != NULL)
+ if (streq (Memc[uifname], Memc[SG_UIFNAME(g_sg)]))
+ if (finfo (Memc[uifname], fi) != ERR)
+ if (SG_UIFDATE(g_sg) == FI_MTIME(fi))
+ uifname = NULL
+ } else {
+ # Ignore UI file if no EM capability.
+ Memc[SG_UIFNAME(g_sg)] = EOS
+ SG_UIFDATE(g_sg) = 0
+ uifname = NULL
+ }
+
+ # Open and Initialize the device. Output contents of UI definition
+ # file if any, followed by graphics device initialization file,
+ # if any.
+
+ if (mode == NEW_FILE) {
+ # Output UI definition file.
+ if (uifname != NULL) {
+ iferr (init_file = open (Memc[uifname], READ_ONLY, TEXT_FILE)) {
+ call erract (EA_WARN)
+ call stg_ctrl ("OW")
+ } else {
+ call flush (g_out)
+ call stg_ctrl ("EM")
+
+ # Download the UI.
+ call putline (g_out, "server ")
+ iferr (call fcopyo (init_file, g_out))
+ call erract (EA_WARN)
+ call close (init_file)
+
+ # Record particulars of active UI file.
+ call strcpy (Memc[uifname], Memc[SG_UIFNAME(g_sg)],
+ SZ_UIFNAME)
+ if (finfo (Memc[uifname], fi) != ERR)
+ SG_UIFDATE(g_sg) = FI_MTIME(fi)
+ call sgf_post_filter (g_out)
+
+ call putci (g_out, US)
+ call flush (g_out)
+ }
+ } else
+ call stg_ctrl ("OW")
+
+ # Output device graphics initialization file if any.
+ if (ttygets (g_tty, "IF", Memc[buf], SZ_FNAME) > 0) {
+ iferr (init_file = open (Memc[buf], READ_ONLY, TEXT_FILE))
+ call erract (EA_WARN)
+ iferr (call fcopyo (init_file, g_out))
+ call erract (EA_WARN)
+ call close (init_file)
+ }
+
+ # Clear the screen if device is being opened in new_file mode.
+ call stg_clear (dummy)
+
+ } else
+ow_ call stg_ctrl ("OW")
+
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/stgoutput.x b/sys/gio/stdgraph/stgoutput.x
new file mode 100644
index 00000000..098af6e7
--- /dev/null
+++ b/sys/gio/stdgraph/stgoutput.x
@@ -0,0 +1,28 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_OUTPUT2 -- Encode two arguments using the program given and write the
+# encoded character string to the output file.
+
+procedure stg_output2 (fd, program, arg1, arg2)
+
+int fd # output file
+char program[ARB] # encoder program defining encoding
+int arg1 # argument to be placed in register 1
+int arg2 # argument to be placed in register 2
+
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ # Set up encoder.
+ g_reg[1] = arg1
+ g_reg[2] = arg2
+ g_reg[E_IOP] = 1
+
+ # Encode the output string and write the encoded string to the output
+ # file.
+ if (stg_encode (g_xy, g_mem, g_reg) == OK)
+ call write (fd, g_mem, g_reg[E_IOP] - 1)
+end
diff --git a/sys/gio/stdgraph/stgoutstr.x b/sys/gio/stdgraph/stgoutstr.x
new file mode 100644
index 00000000..2d854e75
--- /dev/null
+++ b/sys/gio/stdgraph/stgoutstr.x
@@ -0,0 +1,30 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_OUTSTR -- Format and output a control sequence containing a string
+# string argument to the output device.
+
+procedure stg_outstr (cap, strval)
+
+char cap[ARB] #I graphcap capability name
+char strval[ARB] #I string data
+
+pointer sp, fmt, ctrl
+include "stdgraph.com"
+int ttygets()
+errchk ttygets
+
+begin
+ call smark (sp)
+ call salloc (fmt, SZ_LINE, TY_CHAR)
+ call salloc (ctrl, SZ_LINE, TY_CHAR)
+
+ if (ttygets (g_tty, cap, Memc[fmt], SZ_LINE) > 0) {
+ call sprintf (Memc[ctrl], SZ_LINE, Memc[fmt])
+ call pargstr (strval)
+ call ttyputs (g_out, g_tty, Memc[ctrl], 1)
+ }
+
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/stgpcell.x b/sys/gio/stdgraph/stgpcell.x
new file mode 100644
index 00000000..476d90cf
--- /dev/null
+++ b/sys/gio/stdgraph/stgpcell.x
@@ -0,0 +1,85 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+define ZSTEP 4 # bit to be tested (step function width)
+
+
+# STG_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 stg_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
+
+real dx, dy
+int my, i1, i2, v, i, j, k
+include "stdgraph.com"
+int and()
+
+begin
+ # Set polyline width to 1 for max y-res.
+ call stg_ctrl1 ("LW", 1)
+ SG_PLWIDTH(g_sg) = 1
+
+ # 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.
+ dy = max (1.0, real(GKI_MAXNDC) / real(g_yres))
+
+ # 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 stg_move (int ((i1-1) * dx + ax1), my)
+ call stg_draw (int (i2 * dx + ax1), my)
+
+ if (i2 >= nx)
+ i = nx + 1
+ }
+ }
+
+ k = k + 1
+ }
+end
diff --git a/sys/gio/stdgraph/stgpl.x b/sys/gio/stdgraph/stgpl.x
new file mode 100644
index 00000000..894a92c3
--- /dev/null
+++ b/sys/gio/stdgraph/stgpl.x
@@ -0,0 +1,126 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_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 stg_polyline (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+
+pointer pl
+bool tek_encoding
+int lowres_x, lowres_y
+int ip, n, sx, sy, len_p, iop, i
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ if (g_enable == NO)
+ call stg_genab()
+
+ len_p = npts * 2
+
+ # Update polyline attributes if necessary.
+
+ pl = SG_PLAP(g_sg)
+ if (SG_PLTYPE(g_sg) != PL_LTYPE(pl)) {
+ call stg_ctrl1 ("LT", PL_LTYPE(pl))
+ SG_PLTYPE(g_sg) = PL_LTYPE(pl)
+ }
+ if (SG_PLWIDTH(g_sg) != PL_WIDTH(pl)) {
+ call stg_ctrl1 ("LW", PL_WIDTH(pl))
+ SG_PLWIDTH(g_sg) = PL_WIDTH(pl)
+ }
+ if (SG_COLOR(g_sg) != PL_COLOR(pl)) {
+ call stg_ctrl1 ("LC", PL_COLOR(pl))
+ SG_COLOR(g_sg) = PL_COLOR(pl)
+ }
+
+ # Transform the first point from GKI coords to device coords and
+ # move to the transformed point.
+
+ sx = p[1]; sy = p[2]
+ call stg_move (sx, sy)
+
+ # Tektronix encoding is treated as a special case for max efficiency.
+ tek_encoding =
+ (Memc[g_xy] == '%' && Memc[g_xy+1] == 't' && Memc[g_xy+2] == EOS)
+
+ # Draw the polyline. If the device has the "polyline" capability
+ # we can encode and output successive points without enclosing each
+ # individual point in the startdraw and enddraw strings.
+
+ for (ip=3; ip <= len_p; ip=ip+2) {
+ # Output start draw sequence.
+ call ttyputs (g_out, g_tty, Memc[SG_STARTDRAW(g_sg)], 1)
+
+ # Determine number of points to output.
+ if (SG_POLYLINE(g_sg) == YES)
+ n = len_p
+ else
+ n = ip + 2
+
+ # Encode the points of the polyline.
+
+ g_lastx = -1 # clip unresolved points only in the interior
+ g_lasty = -1 # of the polyline being drawn.
+
+ g_reg[E_IOP] = 1
+ do i = ip, n, 2 {
+ sx = p[i]
+ sy = p[i+1]
+
+ # Discard the point if it is not resolved.
+ lowres_x = sx / g_dxres
+ lowres_y = sy / g_dyres
+ if (lowres_x == g_lastx && lowres_y == g_lasty)
+ next
+
+ g_lastx = lowres_x
+ g_lasty = lowres_y
+
+ # Transform point into the device window.
+ sx = int (sx * g_dx) + g_x1
+ sy = int (sy * g_dy) + g_y1
+
+ # Encode the point, appending encoded bytes to g_mem. Tek
+ # encoding is treated as a special case since it is so common;
+ # the encoder is used for non-Tek encodings.
+
+ if (tek_encoding) {
+ iop = g_reg[E_IOP] + 4
+ g_mem[iop-4] = g_hixy[sy+1]
+ g_mem[iop-3] = g_loy[sy+1]
+ g_mem[iop-2] = g_hixy[sx+1]
+ g_mem[iop-1] = g_lox[sx+1]
+ g_reg[E_IOP] = iop
+ } else {
+ g_reg[1] = sx
+ g_reg[2] = sy
+ if (stg_encode (Memc[g_xy], g_mem, g_reg) != OK)
+ break
+ }
+
+ # Flush buffer if nearly full.
+ if (g_reg[E_IOP] > FLUSH_MEMORY) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+ }
+ ip = n
+
+ # Flush any output remaining in encoder memory.
+ if (g_reg[E_IOP] > 1) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+
+ # Output end draw sequence.
+ call ttyputs (g_out, g_tty, Memc[SG_ENDDRAW(g_sg)], 1)
+ }
+end
diff --git a/sys/gio/stdgraph/stgplset.x b/sys/gio/stdgraph/stgplset.x
new file mode 100644
index 00000000..c435feb5
--- /dev/null
+++ b/sys/gio/stdgraph/stgplset.x
@@ -0,0 +1,20 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+# STG_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 stg_plset (gki)
+
+short gki[ARB] # attribute structure
+pointer pl
+include "stdgraph.com"
+
+begin
+ pl = SG_PLAP(g_sg)
+ PL_LTYPE(pl) = gki[GKI_PLSET_LT]
+ PL_WIDTH(pl) = max (1, nint (GKI_UNPACKREAL (gki[GKI_PLSET_LW])))
+ PL_COLOR(pl) = gki[GKI_PLSET_CI]
+end
diff --git a/sys/gio/stdgraph/stgpm.x b/sys/gio/stdgraph/stgpm.x
new file mode 100644
index 00000000..3808d63b
--- /dev/null
+++ b/sys/gio/stdgraph/stgpm.x
@@ -0,0 +1,118 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_POLYMARKER -- Draw a polymarker. The polymarker is defined by the array
+# of points P, consisting of successive (x,y) coordinate pairs, each of which
+# is to be plotted as a point. If the marker start sequence MS is defined the
+# polymarker will be drawn as <markstart> <p1> ... <pN> <markend>, otherwise
+# ther marker is draw using the polyline move and draw commands to draw each
+# individual point.
+
+procedure stg_polymarker (p, npts)
+
+short p[ARB] # points defining line
+int npts # number of points, i.e., (x,y) pairs
+
+pointer pm
+bool tek_encoding
+int lowres_x, lowres_y
+int ip, n, sx, sy, len_p, iop, i
+int stg_encode()
+include "stdgraph.com"
+
+begin
+ if (g_enable == NO)
+ call stg_genab()
+
+ len_p = npts * 2
+
+ # Update polymarker attributes if necessary.
+
+ pm = SG_PMAP(g_sg)
+ if (SG_COLOR(g_sg) != PM_COLOR(pm)) {
+ call stg_ctrl1 ("MC", PM_COLOR(pm))
+ SG_COLOR(g_sg) = PM_COLOR(pm)
+ }
+
+ # Tektronix encoding is treated as a special case for max efficiency.
+ tek_encoding =
+ (Memc[g_xy] == '%' && Memc[g_xy+1] == 't' && Memc[g_xy+2] == EOS)
+
+ # Draw the polymarker. If the startmark sequence is defined we assume
+ # that the device can draw a multipoint polymarker, else low level move
+ # and draw sequences are used.
+
+ if (Memc[SG_STARTMARK(g_sg)] != EOS) {
+ for (ip=1; ip <= len_p; ip=ip+2) {
+ # Output start marker sequence [revised to use the encoder].
+ call ttyputs (g_out, g_tty, Memc[SG_STARTMARK(g_sg)], 1)
+ n = len_p
+
+ # Encode the points of the polymarker (or move to the single
+ # point to be drawn).
+
+ g_lastx = -1 # clip unresolved points only in the interior
+ g_lasty = -1 # of the polymarker being drawn.
+
+ g_reg[E_IOP] = 1
+ do i = ip, n, 2 {
+ sx = p[i]
+ sy = p[i+1]
+
+ # Discard the point if it is not resolved.
+ lowres_x = sx / g_dxres
+ lowres_y = sy / g_dyres
+ if (lowres_x == g_lastx && lowres_y == g_lasty)
+ next
+
+ g_lastx = lowres_x
+ g_lasty = lowres_y
+
+ # Transform point into the device window.
+ sx = int (sx * g_dx) + g_x1
+ sy = int (sy * g_dy) + g_y1
+
+ # Encode the point, appending encoded bytes to g_mem.
+ # Tek encoding is treated as a special case since it is
+ # so common; the encoder is used for non-Tek encodings.
+
+ if (tek_encoding) {
+ iop = g_reg[E_IOP] + 4
+ g_mem[iop-4] = g_hixy[sy+1]
+ g_mem[iop-3] = g_loy[sy+1]
+ g_mem[iop-2] = g_hixy[sx+1]
+ g_mem[iop-1] = g_lox[sx+1]
+ g_reg[E_IOP] = iop
+ } else {
+ g_reg[1] = sx
+ g_reg[2] = sy
+ if (stg_encode (Memc[g_xy], g_mem, g_reg) != OK)
+ break
+ }
+
+ # Flush buffer if nearly full.
+ if (g_reg[E_IOP] > FLUSH_MEMORY) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+ }
+ ip = n
+
+ # Flush any output remaining in encoder memory.
+ if (g_reg[E_IOP] > 1) {
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ g_reg[E_IOP] = 1
+ }
+
+ # Output end polymarker sequence, or draw the point.
+ call ttyputs (g_out, g_tty, Memc[SG_ENDMARK(g_sg)], 1)
+ }
+ } else {
+ for (ip=1; ip <= len_p; ip=ip+2) {
+ sx = p[ip]; sy = p[ip+1]
+ call stg_move (sx, sy)
+ call stg_draw (sx, sy)
+ }
+ }
+end
diff --git a/sys/gio/stdgraph/stgpmset.x b/sys/gio/stdgraph/stgpmset.x
new file mode 100644
index 00000000..6651564f
--- /dev/null
+++ b/sys/gio/stdgraph/stgpmset.x
@@ -0,0 +1,19 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+# STG_PMSET -- Set the polymarker attributes.
+
+procedure stg_pmset (gki)
+
+short gki[ARB] # attribute structure
+pointer pm
+include "stdgraph.com"
+
+begin
+ pm = SG_PMAP(g_sg)
+ PM_LTYPE(pm) = gki[GKI_PMSET_MT]
+ PM_WIDTH(pm) = max (1, nint (GKI_UNPACKREAL (gki[GKI_PMSET_MW])))
+ PM_COLOR(pm) = gki[GKI_PMSET_CI]
+end
diff --git a/sys/gio/stdgraph/stgrcur.x b/sys/gio/stdgraph/stgrcur.x
new file mode 100644
index 00000000..e0ab890a
--- /dev/null
+++ b/sys/gio/stdgraph/stgrcur.x
@@ -0,0 +1,425 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <syserr.h>
+include <config.h>
+include <error.h>
+include <chars.h>
+include <ttset.h>
+include <gset.h>
+include <fset.h>
+include <gki.h>
+include "stdgraph.h"
+
+define MAX_LENCUR 17
+define MAX_KEYLINES 30
+define KEYSIZE 1
+define QUIT 'q'
+define GO 'g'
+
+# STG_READCURSOR -- Physically read the cursor, returning the cursor position
+# in GKI coordinates and the keystroke value as output arguments. The cursor
+# value string is read in raw mode with interrupts disabled. Receipt of the
+# EOF character or CR causes EOF to be returned as the key value.
+#
+# The cursor is described by two parameters, a pattern string (CD) and a string
+# length parameter (CN).
+#
+# CD A pattern specifying either the delimiter sequence if
+# len_curval > 0, or the entire cursor value string if
+# len_curval <= 0.
+#
+# CN If no pattern is given, CN is the number of characters to be
+# read and automatic error detection is not possible. If a
+# pattern is given, a negative CN specifies the minimum number
+# of characters in the cursor value string, with the pattern
+# being used to match the characters in the actual cursor value
+# string. A positive CN specifies a fixed length cursor value
+# string, which which case the pattern is used only to determine
+# when a valid cursor value string has been received.
+#
+# The cursor read algorithm tries to ignore unsolicited input and recover from
+# bad cursor reads, or loss of hardware cursor mode during a cursor read, e.g.,
+# if the screen is accidentally cleared or the terminal otherwise initialized.
+#
+# The physical cursor read sequence is implemented by the stg_rdcursor routine.
+# The purpose of the higher level routine is to support STTY playback mode.
+# In playback mode, terminal input is taken from a logfile rather than from
+# the physical terminal; this is used to prepare automatic scripts to test
+# software and for demos. If playback mode is enabled and `verify' is enabled,
+# the logged cursor position will be read, a WC will be issued to move the
+# cursor to that position, and then the physical cursor will be read and the
+# return value discard, returning the logged position to the calling program.
+# In playback mode with `verify' disabled, we need only disable the RC
+# instruction and read the logged cursor position; the physical cursor is
+# never turned on.
+
+procedure stg_readcursor (cursor, cn, key, sx, sy, raster, rx, ry)
+
+int cursor #I cursor to be read
+int cn #O cursor which was read
+int key #O keystroke which terminated cursor read
+int sx, sy #O screen coordinates of cursor in GKI units
+int raster #O raster number
+int rx, ry #O raster coordinates of cursor in GKI units
+
+short texts[4]
+char textc[4], ch
+pointer sp, pbdevice, tx, o_tx
+int delay, nchars, mx, my, i, j, k
+bool playback_mode, pbverify_mode
+
+bool strne()
+pointer ttygdes()
+int ttstati(), ttstats(), ctocc()
+errchk ttygdes, syserr
+include "stdgraph.com"
+define samedev_ 91
+
+begin
+ playback_mode = (ttstati (STDIN, TT_PLAYBACK) == YES)
+
+ if (!playback_mode) {
+ call stg_rdcursor (g_tty, cursor, YES,
+ cn, key, sx, sy, raster, rx, ry)
+ return
+ }
+
+ call smark (sp)
+ call salloc (pbdevice, SZ_GDEVICE, TY_CHAR)
+ call salloc (o_tx, LEN_TX, TY_STRUCT)
+
+ # The playback script may have been generated on a different graphics
+ # terminal than the one we are playing it back on. Open the graphcap
+ # descriptor for the device used when the script was recorded. This
+ # must be used when decoding cursor input from the logfile. If device
+ # name not recorded in logfile, try to make do with the descriptor for
+ # the current stdgraph device.
+
+ if (ttstats (STDIN, TT_GDEVICE, Memc[pbdevice], SZ_GDEVICE) <= 0) {
+ # Device name not recorded in logfile.
+ call syserr (SYS_STTYNOGDEV)
+
+ } else if (g_pbtty == NULL || strne (g_pbdevice, Memc[pbdevice])) {
+ # Device name was recorded; try to load graphcap for it if not
+ # already loaded.
+
+ if (g_pbtty != NULL)
+ call ttycdes (g_pbtty)
+ iferr (g_pbtty = ttygdes (Memc[pbdevice])) {
+ g_pbtty = NULL
+ call erract (EA_ERROR)
+ }
+
+ call strcpy (Memc[pbdevice], g_pbdevice, SZ_GDEVICE)
+ }
+
+ # Set the playback delay to 0 msec while reading the cursor, else
+ # the multicharacter cursor read will take forever. We issue the
+ # delay below, ourselves, one per cursor read.
+
+ delay = ttstati (STDIN, TT_PBDELAY)
+ call ttseti (STDIN, TT_PBDELAY, 0)
+
+ # Read the logged cursor position with RC disabled.
+ call stg_rdcursor (g_pbtty, cursor, NO,
+ cn, key, sx, sy, raster, rx, ry)
+
+ # Determine if verify mode is set for this cursor read. This must
+ # be done after the call to stg_rdcursor to permit processing of
+ # any \{ .. \} in the logfile.
+
+ pbverify_mode = (ttstati (STDIN, TT_PBVERIFY) == YES)
+
+ # Set passthru mode to read/write the device directly.
+ call ttseti (STDIN, TT_PASSTHRU, YES)
+
+ # Encode the logged keystroke as a character string.
+ if (key == EOF) {
+ call strcpy ("EOF", textc, 4)
+ nchars = 3
+ } else if (key <= ' ') {
+ ch = key
+ nchars = ctocc (ch, textc, 4)
+ } else {
+ nchars = 1
+ textc[1] = key
+ }
+
+ # Pack the string in a short array for the GKI operator.
+ call achtcs (textc, texts, nchars)
+
+ # Set the text drawing attributes.
+ tx = SG_TXAP(g_sg)
+ call amovi (Memi[tx], Memi[o_tx], LEN_TX)
+ TX_SIZE(tx) = KEYSIZE
+ TX_HJUSTIFY(tx) = GT_LEFT
+ TX_VJUSTIFY(tx) = GT_BOTTOM
+
+ # Echo the key character in graphics mode on the top line of the screen,
+ # duplicating the text drawn at the cursor position.
+
+ mx = nint ((g_keycol + 0.5) * SG_CHARWIDTH(g_sg,1))
+ my = GKI_MAXNDC - nint ((g_keyline + 0.2) * SG_CHARHEIGHT(g_sg,KEYSIZE))
+
+ call stg_text (mx, my, texts, nchars)
+ g_keyline = g_keyline + 1
+ if (g_keyline > MAX_KEYLINES) {
+ g_keycol = g_keycol + 1
+ g_keyline = 1
+ }
+
+ # Echo the logged keystroke at the position of the cursor. This may
+ # not always be readable, but at least it marks the cursor position.
+
+ call stg_text (sx, sy, texts, nchars)
+
+ if (pbverify_mode) {
+ # Issue a WC to set the cursor position, and perform a normal
+ # cursor read in passthru mode, discarding the return value.
+
+ call stg_setcursor (sx, sy, cursor)
+ call stg_rdcursor (g_tty, cursor, YES, i, i, j, k, i, j, k)
+
+ # User wants to terminate playback mode?
+ if (k == QUIT || k == INTCHAR) {
+ call ttseti (STDIN, TT_PLAYBACK, NO)
+ call stg_ctrl ("GD")
+ call putline (STDOUT, "[playback mode terminated]")
+ call stg_ctrl ("GE")
+ call flush (STDOUT)
+ call zwmsec (500)
+ if (k == INTCHAR)
+ key = EOF
+ } else if (k == GO)
+ call ttseti (STDIN, TT_PBVERIFY, NO)
+ } else
+ call zwmsec (delay)
+
+ # Restore everything modified earlier.
+ call ttseti (STDIN, TT_PASSTHRU, NO)
+ call ttseti (STDIN, TT_PBDELAY, delay)
+ call amovi (Memi[o_tx], Memi[tx], LEN_TX)
+
+ call sfree (sp)
+end
+
+
+# STG_RDCURSOR -- Physically read the cursor; an internal routine called only
+# by the stg_readcursor procedure. A lower level routine is needed since
+# two cursor reads may be required in STTY playback mode, one to read the
+# logged cursor position and another to read the physical cursor to synch
+# with the user. This is the real cursor read routine; the only concession
+# to playback mode is the `output_rc' switch, to disable output of the RC
+# instruction to the terminal, so that the routine does only input from the
+# logical device.
+
+procedure stg_rdcursor (tty, cursor, output_rc, cn, key, sx,sy, raster, rx,ry)
+
+pointer tty #I graphcap descriptor
+int cursor #I cursor to be read
+int output_rc #I flag to output the RC instruction
+int cn #O cursor which was read
+int key #O keystroke which terminated cursor read
+int sx, sy #O cursor screen position in GKI coords
+int raster #O raster number
+int rx, ry #O cursor raster position in GKI coords
+
+pointer decodecur, delimcur, pattern, patbuf, sp, otop
+int len_pattern, len_curval, sv_iomode, nchars, ip, op, i1, i2, ch
+
+bool ttygetb()
+int getci(), stg_encode()
+int ttygets(), ttygeti(), gstrcpy(), gpatmatch(), patmake(), fstati()
+include "stdgraph.com"
+define quit_ 91
+
+begin
+ call smark (sp)
+ call salloc (pattern, SZ_LINE, TY_CHAR)
+ call salloc (patbuf, SZ_LINE, TY_CHAR)
+ call salloc (decodecur, SZ_LINE, TY_CHAR)
+ call salloc (delimcur, SZ_FNAME, TY_CHAR)
+
+ key = EOF
+
+ # Make sure there is a cursor before going any further.
+ if (!ttygetb (g_tty, "RC"))
+ goto quit_
+
+ len_curval = ttygeti (tty, "CN")
+ if (ttygets (tty, "SC", Memc[decodecur], SZ_LINE) <= 0)
+ goto quit_
+
+ len_pattern = 0
+ if (ttygets (tty, "CD", Memc[delimcur], SZ_FNAME) > 0)
+ len_pattern = gstrcpy (Memc[delimcur], Memc[pattern], SZ_LINE)
+
+ # Either len_curval or pattern must be given, preferably both.
+ if (len_curval == 0 && len_pattern == 0)
+ goto quit_
+
+ # Encode the cursor value pattern, which may be either a pattern
+ # matching the entire cursor value, or just the delimiter. The value
+ # of len_curval may be negative if a pattern is given, but must be
+ # positive otherwise. If the pattern is a delimiter string, append
+ # the $ metacharacter to match only at the end of the string.
+
+ if (len_pattern > 0) {
+ if (len_curval > 0) {
+ Memc[pattern+len_pattern] = '$'
+ len_pattern = len_pattern + 1
+ Memc[pattern+len_pattern] = EOS
+ }
+ if (patmake (Memc[pattern], Memc[patbuf], SZ_LINE) == ERR)
+ goto quit_
+ } else if (len_curval < 0)
+ len_curval = -len_curval
+
+ # Set raw mode on the input file (the graphics terminal).
+ call flush (STDOUT); call flush (STDERR)
+ sv_iomode = fstati (g_in, F_IOMODE)
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, IO_RAW)
+
+ repeat {
+ # Initiate a cursor read.
+ if (output_rc == YES) {
+ call stg_ctrl1 ("RC", cursor)
+ call flush (g_out)
+ }
+
+ # Read the cursor value string. If a pattern is given accumulate
+ # at least abs(len_curval) characters and stop when the pattern
+ # is matched, returning the last len_curval characters if
+ # len_curval > 0, else the matched substring. If no pattern is
+ # given simply accumulate len_curval characters. The number of
+ # characters we will accumulate in one iteration is limited to
+ # MAX_LENCUR to permit retransmission of the RC control sequence
+ # in the event that hardware cursor mode is accidentally cleared.
+
+ for (op=1; op <= MAX_LENCUR; op=op+1) {
+ g_mem[op] = getci (g_in, key)
+ g_mem[op+1] = EOS
+
+ if (key == EOF) {
+ # Turn off raw input mode and return EOF.
+ key = EOF
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+ goto quit_
+
+ } else if (len_pattern > 0) {
+ # A pattern string was given. Once the minimum number of
+ # chars have been accumulated, try to match the pattern,
+ # which may match either the cursor string delimiter (in
+ # the case of a fixed length cursor value), or the entire
+ # cursor string (which may then be variable length).
+
+ if (op < abs(len_curval))
+ next
+ else if (gpatmatch (g_mem[1], Memc[patbuf], i1,i2) > 0) {
+ if (len_curval > 0)
+ ip = op - len_curval + 1 # fixed length cur
+ else
+ ip = i1 # variable length cur
+ break
+ }
+
+ } else if (op >= len_curval) {
+ # No pattern was given. Terminate the cursor read once
+ # the len_curval characters have been accumulated.
+
+ ip = 1
+ break
+ }
+ }
+
+ # We have received too many characters, indicating that cursor
+ # mode was lost and the user has been pounding on the keyboard
+ # trying to get the cursor back. Discard the chars, restart
+ # the cursor and try again.
+
+ if (op > MAX_LENCUR)
+ op = -1
+
+ } until (op >= abs(len_curval) || len_curval == 0)
+
+ # Decode the cursor value string and return the position and key
+ # as output values. Return the cursor position in GKI coordinates.
+ # If extra characters were typed, e.g., before the cursor was turned
+ # on, and the cursor has a delimiter string, the extra characters will
+ # have been read into low memory and we should be able to ignore them
+ # and still get a valid read.
+
+ g_reg[E_IOP] = ip
+ call aclri (g_reg, 7)
+ if (stg_encode (Memc[decodecur], g_mem, g_reg) != OK)
+ call syserr (SYS_GGCUR)
+
+ # Multiple cursors are not implemented yet so just echo input.
+ cn = cursor
+
+ # Standard cursor value.
+ sx = nint ((g_reg[1] - g_x1) / g_dx)
+ sy = nint ((g_reg[2] - g_y1) / g_dy)
+ key = g_reg[3]
+
+ # Only some devices return the following fields. Note that FX,FY
+ # are returned by stg_encode in GKI coordinates.
+
+ nchars = g_reg[4]
+ raster = g_reg[5]
+ if (raster == 0) {
+ rx = sx
+ ry = sy
+ } else {
+ rx = g_reg[6]
+ ry = g_reg[7]
+ }
+
+ # If the NCHARS field is nonzero then a data block of length nchars
+ # follows the cursor value struct returned by the terminal. Read this
+ # into the g_msgbuf message buffer. The client makes a subsequent
+ # call to stg_readtty to access this data, otherwise it is discarded
+ # in the next cursor read.
+
+ if (nchars > 0) {
+ if (nchars > g_msgbuflen) {
+ g_msgbuflen = (nchars + SZ_MSGBUF - 1) / SZ_MSGBUF * SZ_MSGBUF
+ call realloc (g_msgbuf, g_msgbuflen, TY_CHAR)
+ }
+
+ # We should encode this data transfer in a way that permits
+ # detection and recovery from lost data. For the moment, the
+ # following assumes that nchars of data will actually be received.
+
+ op = g_msgbuf
+ otop = g_msgbuf + nchars
+ while (op < otop && getci (g_in, ch) != EOF) {
+ Memc[op] = ch
+ op = op + 1
+ }
+ g_msglen = op - g_msgbuf
+ Memc[op] = EOS
+
+ } else
+ g_msglen = 0
+
+ # Turn off raw input mode.
+ if (sv_iomode != IO_RAW)
+ call fseti (g_in, F_IOMODE, sv_iomode)
+
+ # Return EOF if any EOF character (e.g., <ctrl/z> or <ctrl/d>) or the
+ # interrupt character is typed.
+
+ if (key == EOFCHAR || key == INTCHAR || key == '\004' || key == '\032')
+ key = EOF
+quit_
+ # Terminate the cursor read.
+ if (output_rc == YES) {
+ call stg_ctrl1 ("RE", cursor)
+ call flush (g_out)
+ }
+
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/stgreact.x b/sys/gio/stdgraph/stgreact.x
new file mode 100644
index 00000000..21c2a821
--- /dev/null
+++ b/sys/gio/stdgraph/stgreact.x
@@ -0,0 +1,41 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <ttset.h>
+include "stdgraph.h"
+
+# STG_REACTIVATEWS -- Reactivate the workstation, i.e., enable graphics.
+
+procedure stg_reactivatews (flags)
+
+int flags # action flags (handled by cursor mode)
+
+int junk
+int ttstati(), ttyctrl(), and()
+extern stg_onerror()
+include "stdgraph.com"
+
+begin
+ if (g_active == NO) {
+ junk = ttyctrl (g_out, g_tty, "OW", 1)
+
+ # Post error handler to be called if we abort.
+ call onerror (stg_onerror)
+
+ g_active = YES
+ g_enable = YES
+
+ # Must disable stty ucaseout mode when in graphics mode, else
+ # plotting commands may be modified by the terminal driver.
+
+ g_ucaseout = ttstati (g_out, TT_UCASEOUT)
+ if (g_ucaseout == YES)
+ call ttseti (g_out, TT_UCASEOUT, NO)
+
+ # Clear the graphics screen?
+ if (and (flags, AW_CLEAR) != 0)
+ call stg_clear (0)
+
+ call flush (g_out)
+ }
+end
diff --git a/sys/gio/stdgraph/stgres.x b/sys/gio/stdgraph/stgres.x
new file mode 100644
index 00000000..d6355bd9
--- /dev/null
+++ b/sys/gio/stdgraph/stgres.x
@@ -0,0 +1,85 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+# STG_RESOLUTION -- Set the "soft" device resolution. When plotting GKI
+# coordinates are transformed into a space with the indicated resolution and
+# unresolved points are discarded, before transforming to device coordinates.
+# We must set up both the transformation to resolution space and the
+# transformation to device space.
+
+procedure stg_resolution (xres, yres)
+
+int xres # device X resolution
+int yres # device Y resolution
+int nx, ny
+int ttygeti()
+include "stdgraph.com"
+
+begin
+ if (g_tty == NULL) {
+ g_xres = xres
+ g_yres = yres
+ return
+ }
+
+ # Set the resolution value in the stdgraph common only if a nonzero
+ # value is given. A value of zero does not change the resolution.
+
+ if (xres > 0)
+ g_xres = xres
+ if (yres > 0)
+ g_yres = yres
+
+
+ # If we still have a zero resolution then we use the full resolution
+ # of the device. The 3/4 reduction in resolution is needed to clip
+ # points that would be unresolved due to integer truncation effects.
+
+ if (g_xres <= 0) {
+ g_xres = ttygeti (g_tty, "xr")
+ if (g_xres <= 0)
+ g_xres = 1024
+ g_xres = max (2, g_xres * 3 / 4)
+ }
+ if (g_yres <= 0) {
+ g_yres = ttygeti (g_tty, "yr")
+ if (g_yres <= 0)
+ g_yres = 1024
+ g_yres = max (2, g_yres * 3 / 4)
+ }
+
+ # Set up coordinate transformations. The first transformation is from
+ # GKI coordinates to device resolution coordinates (0:xres-1,0:yres-1)
+ # and is defined by xres, yres, and GKI_MAXNDC. Clipping of unresolved
+ # points is performed after this first transformation. The second
+ # transformation maps resolved points into the device window.
+
+ # GKI -> resolution coords.
+ g_dxres = max (1, (GKI_MAXNDC + 1) / g_xres)
+ g_dyres = max (1, (GKI_MAXNDC + 1) / g_yres)
+
+ g_x1 = ttygeti (g_tty, "X1")
+ g_y1 = ttygeti (g_tty, "Y1")
+ g_x2 = ttygeti (g_tty, "X2")
+ g_y2 = ttygeti (g_tty, "Y2")
+ nx = g_x2 - g_x1 + 1
+ ny = g_y2 - g_y1 + 1
+
+ if (nx <= 1 || ny <= 1) {
+ call eprintf ("openws: illegal graphics device window\n")
+ nx = g_xres
+ ny = g_yres
+ }
+
+ # GKI -> window coords.
+ g_dx = real (nx - 1) / GKI_MAXNDC
+ g_dy = real (ny - 1) / GKI_MAXNDC
+
+ # The last point in resolution coords is used to clip unresolved
+ # points when drawing polylines.
+
+ g_lastx = -1
+ g_lasty = -1
+end
diff --git a/sys/gio/stdgraph/stgreset.x b/sys/gio/stdgraph/stgreset.x
new file mode 100644
index 00000000..0f2fd1e2
--- /dev/null
+++ b/sys/gio/stdgraph/stgreset.x
@@ -0,0 +1,54 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include "stdgraph.h"
+
+# STG_RESET -- Reset the state of the stdgraph 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 stg_reset()
+
+pointer pl, pm, fa, tx
+include "stdgraph.com"
+
+begin
+ # Set pointers to attribute substructures.
+ pl = SG_PLAP(g_sg)
+ pm = SG_PMAP(g_sg)
+ fa = SG_FAAP(g_sg)
+ tx = SG_TXAP(g_sg)
+
+ # Initialize the attribute packets.
+ PL_LTYPE(pl) = 1
+ PL_WIDTH(pl) = 1
+ PL_COLOR(pl) = 1
+ PM_COLOR(pm) = 1
+ FA_STYLE(fa) = 1
+ FA_COLOR(fa) = 1
+ TX_UP(tx) = 90
+ TX_SIZE(tx) = 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.
+
+ SG_COLOR(g_sg) = -1
+ SG_TXSIZE(g_sg) = -1
+ SG_TXFONT(g_sg) = -1
+ SG_PLTYPE(g_sg) = -1
+ SG_FASTYLE(g_sg) = -1
+ SG_PLWIDTH(g_sg) = -1
+ g_lastx = -1
+ g_lasty = -1
+ g_keycol = 1
+ g_keyline = 1
+ g_message = NO
+ g_msglen = 0
+end
diff --git a/sys/gio/stdgraph/stgrtty.x b/sys/gio/stdgraph/stgrtty.x
new file mode 100644
index 00000000..237a7c7b
--- /dev/null
+++ b/sys/gio/stdgraph/stgrtty.x
@@ -0,0 +1,137 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <fset.h>
+include <chars.h>
+include "stdgraph.h"
+
+# STG_READTTY -- Read a line of text from the graphics terminal.
+# If the workstation is currently activated the read is performed in raw mode,
+# presumably with the cursor positioned to the end of a prompt string on the
+# status line. The workstation will have been put into text mode and the
+# cursor positioned to the status line by an immediately preceding call to
+# stg_writetty, which is called by pseudofile i/o when the user task writes
+# to STDOUT or STDERR while the workstation is activated. The input sequence
+# terminates when the user types return or newline, causing exit with
+# transmission of the GE sequence to restore the terminal to graphics mode.
+
+int procedure stg_readtty (fd, obuf, maxch)
+
+int fd #I input stream [NOT USED]
+char obuf[ARB] #O output buffer
+int maxch #I max chars to read
+
+int nchars, op, ch
+int read(), getci(), fstati()
+include "stdgraph.com"
+errchk read, getci, ttyctrl
+string delstr "\010 \010"
+
+begin
+ call flush (STDERR)
+ call flush (STDOUT)
+
+ if (g_active == NO) {
+ # Workstation in normal text mode; normal text input.
+ return (read (STDIN, obuf, maxch))
+
+ } else if (g_msglen > 0) {
+ # The message data has already been transmitted and resides in
+ # the message buffer.
+
+ nchars = min (maxch, g_msglen)
+ call amovc (Memc[g_msgbuf], obuf, nchars)
+ obuf[nchars+1] = EOS
+ g_msglen = 0
+ return (nchars)
+
+ } else {
+ # Workstation is activated; read status line in raw mode.
+ # If already in rew mode, read a single char with no echo.
+ # Note that genable is not automatic in raw input mode.
+
+ if (g_enable == YES)
+ call stg_gdisab()
+
+ if (fstati (g_in, F_RAW) == YES) {
+ if (getci (g_in, ch) == EOF) {
+ obuf[1] = EOS
+ return (EOF)
+ } else if (ch == '\004' || ch == '\032') {
+ obuf[1] = EOS
+ return (EOF)
+ } else {
+ obuf[1] = ch
+ obuf[2] = EOS
+ return (1)
+ }
+ } else
+ call fseti (g_in, F_RAW, YES)
+
+ for (op=1; getci (g_in, ch) != EOF; op=min(maxch,op)) {
+ switch (ch) {
+ case EOF, '\004', '\032': # EOF
+ call stg_genab()
+ break
+ case '\n', '\r':
+ obuf[op] = '\n'
+ op = op + 1
+ call putline (g_out, "\r\n")
+ call stg_genab()
+ break
+ case INTCHAR, '\025': # <ctrl/u>
+ for (; op > 1; op=op-1)
+ call putline (g_out, delstr)
+ case BS, '\177':
+ if (op > 1) {
+ call putline (g_out, delstr)
+ op = op - 1
+ } else {
+ call stg_genab()
+ break # exit
+ }
+ default:
+ call putci (g_out, ch)
+ obuf[op] = ch
+ op = op + 1
+ }
+ call flush (g_out)
+ }
+
+ obuf[op] = EOS
+ call fseti (g_in, F_RAW, NO)
+
+ if (op > 1)
+ return (op - 1)
+ else
+ return (EOF)
+ }
+end
+
+
+# STG_GETLINE -- Get a line of text from the graphics terminal, reading from
+# the status line if the workstation is activated, and doing a normal text
+# read otherwise.
+
+int procedure stg_getline (fd, obuf)
+
+int fd #I input file
+char obuf[SZ_LINE] #O output buffer
+
+int stg_readtty()
+
+begin
+ return (stg_readtty (fd, obuf, SZ_LINE))
+end
+
+
+# STG_MSGLEN -- This routine is called to determine if there is any message
+# data buffered in the kernel, to be returned in the next call to stg_readtty.
+
+int procedure stg_msglen (fd)
+
+int fd #I input file
+include "stdgraph.com"
+
+begin
+ return (g_msglen)
+end
diff --git a/sys/gio/stdgraph/stgscur.x b/sys/gio/stdgraph/stgscur.x
new file mode 100644
index 00000000..e40d4a3d
--- /dev/null
+++ b/sys/gio/stdgraph/stgscur.x
@@ -0,0 +1,36 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include "stdgraph.h"
+
+# STG_SETCURSOR -- Set the position of a cursor.
+
+procedure stg_setcursor (x, y, cursor)
+
+int x, y # new position of cursor
+int cursor # cursor to be set
+int mx, my, cur
+include "stdgraph.com"
+
+begin
+ # If cursor=0, write the cursor last referenced.
+ if (cursor > 0) {
+ SG_CURSOR(g_sg) = cursor
+ cur = cursor
+ } else
+ cur = max (1, SG_CURSOR(g_sg))
+
+ # If the user has locked the logical cursor override runtime selection.
+ if (g_cursor > 0)
+ cur = g_cursor
+
+ # Restore the software cursor position before reading?
+ if (SG_UPDCURSOR(g_sg) == YES) {
+ SG_CURSOR_X(g_sg) = x
+ SG_CURSOR_Y(g_sg) = y
+ }
+
+ mx = max(g_x1, min(g_x2, nint (x * g_dx) + g_x1))
+ my = max(g_y1, min(g_y2, nint (y * g_dy) + g_y1))
+
+ call stg_ctrl3 ("WC", mx, my, cur)
+end
diff --git a/sys/gio/stdgraph/stgtx.x b/sys/gio/stdgraph/stgtx.x
new file mode 100644
index 00000000..ff5abae2
--- /dev/null
+++ b/sys/gio/stdgraph/stgtx.x
@@ -0,0 +1,528 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <math.h>
+include <mach.h>
+include <gki.h>
+include <gset.h>
+include "stdgraph.h"
+
+# STG_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. Two levels of character quality are implemented: MEDIUM and HIGH,
+# wherein characters are generated in software, and everything else, wherein
+# the characters are generated by the hardware.
+
+procedure stg_text (xc, yc, text, n)
+
+int xc, yc # where to draw text string
+short text[ARB] # text string
+int n # number of characters
+
+bool hard
+real x, y
+int x1, x2, y1, y2, mx, my
+int x0, y0, dx, dy, ch, cw, sz
+int xstart, ystart, newx, newy
+int totlen, polytext, font, seglen, orien, hwsz
+pointer sp, seg, ip, op, tx, first
+int stx_segment(), stg_encode()
+include "stdgraph.com"
+
+begin
+ call smark (sp)
+ call salloc (seg, n + 2, TY_CHAR)
+
+ if (g_enable == NO)
+ call stg_genab()
+
+ # Set pointer to the text attribute structure.
+ tx = SG_TXAP(g_sg)
+
+ # 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, dx,dy, polytext, orien)
+
+ # 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. If software (!hard)
+ # character generation is indicated then size 1 is simply scaled by
+ # the indicated factor, otherwise the text size is converted to a
+ # hardware size index by stg_txsize.
+
+ call stx_chars (tx, ch, cw, hwsz, hard, orien)
+ sz = TX_SIZE(tx)
+
+ if (hard)
+ if (SG_TXSIZE(g_sg) != sz) {
+ call stg_ctrl1 ("TH", hwsz)
+ SG_TXSIZE(g_sg) = sz
+ }
+
+ if (TX_COLOR(tx) != SG_COLOR(g_sg)) {
+ call stg_ctrl1 ("TC", TX_COLOR(tx))
+ SG_COLOR(g_sg) = TX_COLOR(tx)
+ }
+
+ # 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.
+ # All computations are in GKI coordinates.
+
+ x = x0
+ y = y0
+
+ for (ip=seg; Memc[ip] != EOS; ip=ip+1) {
+ # Process the font control character heading the next segment.
+ font = Memc[ip]
+ ip = ip + 1
+ if (hard)
+ if (SG_TXFONT(g_sg) != font) {
+ call stg_ctrl1 ("TF", font - GT_ROMAN + 1)
+ SG_TXFONT(g_sg) = font
+ }
+
+ # 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 >= 0 && x2 <= GKI_MAXNDC &&
+ y1 >= 0 && y2 <= GKI_MAXNDC) {
+
+ 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 <= 0 || x2 >= GKI_MAXNDC ||
+ y1 <= 0 || y2 >= GKI_MAXNDC) {
+
+ 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.
+ if (hard) {
+ g_reg[1] = xstart * g_dx + g_x1
+ g_reg[2] = ystart * g_dy + g_y1
+ g_reg[E_IOP] = 1
+ if (stg_encode (Memc[SG_STARTTEXT(g_sg)],g_mem,g_reg) == OK)
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ }
+
+ first = ip
+ x = xstart
+ y = ystart
+
+ # Draw the characters.
+ while (seglen > 0 && (polytext == YES || ip == first)) {
+ if (hard)
+ call putc (g_out, Memc[ip])
+ else {
+ mx = nint(x)
+ my = nint(y)
+ call stg_drawchar (Memc[ip], mx,my, cw, ch, orien, font)
+ x = x + dx
+ y = y + dy
+ }
+
+ ip = ip + 1
+ seglen = seglen - 1
+ }
+
+ x = newx
+ y = newy
+ ip = op
+
+ if (hard) {
+ g_reg[E_IOP] = 1
+ if (stg_encode (Memc[SG_ENDTEXT(g_sg)], g_mem, g_reg) == OK)
+ call write (g_out, g_mem, g_reg[E_IOP] - 1)
+ }
+ }
+ }
+
+ 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
+bool hard
+int up, path, hwsz, ch, cw, i
+real dir, cosv, sinv, space
+real xsize, ysize, xvlen, yvlen, xu, yu, xv, yv, p, q
+include "stdgraph.com"
+
+begin
+ tx = SG_TXAP(g_sg)
+
+ # 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
+
+ # Get character sizes in GKI(NSPP) coords.
+ call stx_chars (tx, ch, cw, hwsz, hard, orien)
+
+ # 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
+ }
+
+ # If hardware character generation is enabled the character up vector
+ # is constrained to 90 degrees. Flip the direction in which characters
+ # will be drawn if necessary to draw from left to right or from top
+ # down, the readable directions.
+
+ if (hard) {
+ # Constrain the up vector.
+ orien = 0
+
+ # Flip direction vector if in 2nd or 3rd quadrant.
+ i = nint(dir)
+ if (i < 0)
+ i = i + 360
+ if (i >= 90 && i < 180)
+ i = i + 180
+ if (i >= 360)
+ i = i - 360
+ dir = real(i)
+ }
+
+ # ------- 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) ||
+ (hard && abs(cosv) < .9)) {
+ 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
+
+
+# STX_CHARS -- Get the character drawing parameters, i.e., the size of a
+# character in X and Y and whether or not to use the hardware character
+# generator. The decision whether or not to use the hardware character
+# generator is based on the text attribute QUALITY, unless overridden by
+# the g_hardchar switch in common (set explicitly in cursor mode or by a
+# stdgraph task parameter).
+
+procedure stx_chars (tx, ch, cw, hwsz, hard, orien)
+
+pointer tx # pointer to text attribute structure
+int ch, cw # character height, width, GKI coords
+int hwsz # size index if hardware character
+bool hard # use/dontuse hardware character generation
+int orien # rotation angle of character (0=normal)
+
+int sz, quality
+real txsize, aspect, q
+int stg_txsize()
+real ttygetr()
+include "stdgraph.com"
+
+begin
+ sz = TX_SIZE(tx)
+ if (g_hardchar == 0)
+ quality = TX_QUALITY(tx)
+ else
+ quality = g_hardchar
+ hard = (quality != GT_MEDIUM && quality != GT_HIGH)
+
+ # Get character size in GKI units.
+ if (hard) {
+ hwsz = stg_txsize (sz)
+ ch = SG_CHARHEIGHT(g_sg,hwsz)
+ cw = SG_CHARWIDTH (g_sg,hwsz)
+
+ } else {
+ # If character generation is in software scale character sizes
+ # by the size of the size 1 hardware character. If the character
+ # is rotated correct for the device aspect ratio so that the
+ # character comes out the same size regardless of the orientation.
+
+ txsize = GKI_UNPACKREAL(sz)
+ cw = SG_CHARWIDTH (g_sg,1) * txsize
+ ch = SG_CHARHEIGHT(g_sg,1) * txsize
+
+ if (orien != 0) {
+ aspect = ttygetr (g_tty, "ar")
+ if (aspect > EPSILON && abs (aspect - 1.0) > .01) {
+ q = 1.0 + abs(sin(real(orien))) * (aspect - 1.0)
+ cw = cw / q
+ ch = ch * q
+ }
+ }
+ }
+end
diff --git a/sys/gio/stdgraph/stgtxqual.x b/sys/gio/stdgraph/stgtxqual.x
new file mode 100644
index 00000000..122cf303
--- /dev/null
+++ b/sys/gio/stdgraph/stgtxqual.x
@@ -0,0 +1,17 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include "stdgraph.h"
+
+# STG_TXQUALITY -- Select the type of character generator to be used. If the
+# selected flag value is 0 this decision will be deferred to the set text
+# attribute instruction at runtime (default).
+
+procedure stg_txquality (quality)
+
+int quality # text generation quality flag
+include "stdgraph.com"
+
+begin
+ g_hardchar = quality
+end
diff --git a/sys/gio/stdgraph/stgtxset.x b/sys/gio/stdgraph/stgtxset.x
new file mode 100644
index 00000000..8db3e8c3
--- /dev/null
+++ b/sys/gio/stdgraph/stgtxset.x
@@ -0,0 +1,34 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gset.h>
+include <gki.h>
+include "stdgraph.h"
+
+# STG_TXSET -- Set the text drawing attributes.
+
+procedure stg_txset (gki)
+
+short gki[ARB] # attribute structure
+pointer tx
+include "stdgraph.com"
+
+begin
+ tx = SG_TXAP(g_sg)
+
+ 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]
+
+ # Unpack the packed-real character spacing parameter.
+ TX_SPACING(tx) = GKI_UNPACKREAL (gki[GKI_TXSET_SP])
+
+ # The character size is left as a packed real as we must defer the
+ # decision to use a discreet hardware character size or to draw
+ # characters in software.
+
+ TX_SIZE(tx) = gki[GKI_TXSET_SZ]
+end
diff --git a/sys/gio/stdgraph/stgtxsize.x b/sys/gio/stdgraph/stgtxsize.x
new file mode 100644
index 00000000..71829e04
--- /dev/null
+++ b/sys/gio/stdgraph/stgtxsize.x
@@ -0,0 +1,31 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <gki.h>
+include "stdgraph.h"
+
+# STG_TXSIZE -- Given the relative character size as a packed real, select
+# the discreet closest device character size.
+
+int procedure stg_txsize (pksize)
+
+int pksize # packed real relative character size
+int i, best_size
+real txsize, diff, least_diff
+include "stdgraph.com"
+
+begin
+ txsize = GKI_UNPACKREAL (pksize)
+
+ best_size = 1
+ least_diff = abs (txsize - SG_CHARSIZE(g_sg,1))
+
+ do i = 2, SG_NCHARSIZES(g_sg) {
+ diff = abs (txsize - SG_CHARSIZE(g_sg,i))
+ if (diff < least_diff) {
+ best_size = i
+ least_diff = diff
+ }
+ }
+
+ return (best_size)
+end
diff --git a/sys/gio/stdgraph/stgunkown.x b/sys/gio/stdgraph/stgunkown.x
new file mode 100644
index 00000000..55327b62
--- /dev/null
+++ b/sys/gio/stdgraph/stgunkown.x
@@ -0,0 +1,14 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+# STG_UNKNOWN -- The unknown instruction. Called by the interpreter whenever
+# an unrecognized opcode is encountered. Should never be called.
+
+procedure stg_unknown (gki)
+
+short gki[ARB] # the GKI instruction
+int fd, verbose
+common /stgcom/ fd, verbose
+
+begin
+ call fprintf (fd, "unknown\n")
+end
diff --git a/sys/gio/stdgraph/stgwtty.x b/sys/gio/stdgraph/stgwtty.x
new file mode 100644
index 00000000..c01bd93c
--- /dev/null
+++ b/sys/gio/stdgraph/stgwtty.x
@@ -0,0 +1,118 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctype.h>
+include <chars.h>
+include "stdgraph.h"
+
+# STG_WRITETTY -- Write one or more lines of text to the terminal in text
+# mode. If the workstation is currently activated normal output is to the
+# status line, otherwise output is to the indicated stream (STDOUT or
+# STDERR). If the worstation is activated and the text to be output is
+# preceded by the EM code, the text is a message being sent by GIO to a user
+# interface parameter, and the text is passed on as is without formatting for
+# the status line.
+#
+# Terminal output is directed to the status line by the GD sequence, and
+# graphics output is reenabled by the GE sequence. The output text should
+# consist of only a single line, but if multiple lines are present they are
+# output line by line, without the trailing newline, since the status line
+# can display only a single line of text.
+#
+# NOTE - If output occurs while in graphics mode and the output text is newline
+# terminated, the GE (graphics enable) sequence is output to restore the
+# terminal to graphics mode before exiting. If the text is not newline
+# terminated, e.g., if it is a prompt, the workstation is left in alpha mode,
+# ready for a read from STDIN. Thus one can write a prompt to STDOUT and read
+# the user response from STDIN, while in graphics mode.
+#
+# This procedure is called by pseudofile i/o (gio/cursor/prpsio) whenever a
+# task writes to STDOUT or STDERR.
+
+procedure stg_writetty (fd, text, nchars)
+
+int fd #I output stream
+char text[ARB] #I text to be output
+int nchars #I nchars to be written
+
+int ip, delim
+pointer sp, lbuf, op
+include "stdgraph.com"
+bool ttygetb()
+errchk write
+
+begin
+ if (g_active == NO) {
+ # Workstation not activated (normal text mode); normal text output.
+ call write (fd, text, nchars)
+ call flush (fd)
+
+ } else if (text[1] == EM || g_message == YES) {
+ # Workstation is activated; the output text is a message to be
+ # sent to a UI parameter. The output stream is assumed to be
+ # flushed before and after a UI message, so we assume that the
+ # control codes used to bracket the message are the first and
+ # last characters in the output write packets. Multiple writes
+ # may be used to write output text, and messages can be any
+ # length. If the output device does not support messaging (no
+ # "EM" capability) the messages are discarded.
+
+ g_message = YES
+ if (ttygetb (g_tty, "EM"))
+ call write (g_out, text, nchars)
+ delim = text[nchars]
+ if (delim == GS || delim == US)
+ g_message = NO
+
+ } else {
+ # Workstation is activated; write to status line. Writing
+ # anything when graphics is enabled causes the status line to be
+ # cleared; newline causes a graphics enable; the string "\n\n"
+ # will always clear the status line and leave the terminal in
+ # graphics mode, regardless of the state of g_enable when issued.
+
+ call smark (sp)
+ call salloc (lbuf, SZ_LINE, TY_CHAR)
+
+ if (g_enable == YES)
+ call stg_gdisab()
+
+ op = lbuf
+ for (ip=1; ip <= nchars; ip=ip+1) {
+ if (text[ip] == '\n') {
+ if (g_enable == YES)
+ call stg_gdisab()
+ if (op > lbuf)
+ call write (g_out, Memc[lbuf], op-lbuf)
+ call stg_genab()
+ op = lbuf
+ } else {
+ Memc[op] = text[ip]
+ op = min (lbuf+SZ_LINE, op+1)
+ }
+ }
+
+ # Output a partial line, leaving graphics disabled.
+ if (op > lbuf) {
+ if (g_enable == YES)
+ call stg_gdisab()
+ call write (g_out, Memc[lbuf], op-lbuf)
+ }
+
+ call flush (g_out)
+ call sfree (sp)
+ }
+end
+
+
+# STG_PUTLINE -- Output an EOS delimited line of text to the graphics terminal
+# with stg_writetty.
+
+procedure stg_putline (fd, text)
+
+int fd # output file
+char text[ARB] # EOS delimited line of text
+int strlen()
+
+begin
+ call stg_writetty (fd, text, strlen(text))
+end
diff --git a/sys/gio/stdgraph/t_gkideco.x b/sys/gio/stdgraph/t_gkideco.x
new file mode 100644
index 00000000..200cf33a
--- /dev/null
+++ b/sys/gio/stdgraph/t_gkideco.x
@@ -0,0 +1,63 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <gki.h>
+
+# GKIDECODE -- Decode the contents of one or more metacode files, printing
+# the decoded metacode instructions in readable form on the standard output.
+
+procedure t_gkidecode()
+
+int fd, list, verbose, gkiunits
+pointer gki, sp, fname
+int dd[LEN_GKIDD]
+
+bool clgetb()
+int clpopni(), clgfil(), clplen(), open(), btoi()
+int gki_fetch_next_instruction()
+
+begin
+ call smark (sp)
+ call salloc (fname, SZ_FNAME, TY_CHAR)
+
+ # Open list of metafiles to be decoded.
+ list = clpopni ("input")
+
+ if (clgetb ("generic")) {
+ verbose = NO
+ gkiunits = NO
+ } else {
+ verbose = btoi (clgetb ("verbose"))
+ gkiunits = btoi (clgetb ("gkiunits"))
+ }
+
+ # Set up the decoding graphics kernel.
+ call gkp_install (dd, STDOUT, 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) {
+ # Print header if new file.
+ if (clplen (list) > 1) {
+ call printf ("\n# METAFILE '%s':\n")
+ call pargstr (Memc[fname])
+ }
+
+ # Open input file.
+ iferr (fd = open (Memc[fname], READ_ONLY, BINARY_FILE)) {
+ call erract (EA_WARN)
+ next
+ } else
+ call gkp_grstream (fd)
+
+ # Process the metacode.
+ while (gki_fetch_next_instruction (fd, gki) != EOF)
+ call gki_execute (Mems[gki], dd)
+
+ call close (fd)
+ }
+
+ call clpcls (list)
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/t_showcap.x b/sys/gio/stdgraph/t_showcap.x
new file mode 100644
index 00000000..ddb8407c
--- /dev/null
+++ b/sys/gio/stdgraph/t_showcap.x
@@ -0,0 +1,210 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <ctype.h>
+include "stdgraph.h"
+
+define SZ_PROGRAM 256
+define MAXARGSTR 15
+
+
+# SHOWCAP - Show the ascii control string sent to a device to implement a
+# control function. Useful for testing graphcap entries.
+
+procedure t_showcap()
+
+char cap[2]
+int g_reg[NREGISTERS]
+char g_mem[SZ_MEMORY]
+char argstr[MAXARGSTR]
+int arg1, arg2, arg3, op, len_prog, status, nchars
+pointer tty, sp, prog, ip, cmd
+pointer ttygdes(), ttycaps()
+int stg_encode(), ctoi(), getline(), strncmp()
+int ttygets(), ctowrd(), strlen()
+bool ttygetb(), streq()
+define getargs_ 91
+
+begin
+ call smark (sp)
+ call salloc (cmd, SZ_LINE, TY_CHAR)
+ call salloc (prog, SZ_PROGRAM, TY_CHAR)
+
+ # Print instructions.
+ call printf ("cmd : `set' device\n")
+ call printf (" | `*' (to dump full graphcap entry\n")
+ call printf (" | cc [arg1 [arg2 [arg3]]]\n")
+ call printf (" ;\n")
+ call printf ("\n")
+ call printf ("cc : a two chararacter capcode (e.g., 'cm')\n")
+ call printf (" | an encoder program (non alpha first char)\n")
+ call printf (" ;\n")
+ call printf ("\n")
+
+ # Interpret and translate control commands until EOF or "bye"
+ # is typed.
+
+ tty = NULL
+
+ repeat {
+ # Prompt for input.
+ call printf ("* ")
+ call flush (STDOUT)
+
+ if (getline (STDIN, Memc[cmd]) == EOF) {
+ call printf ("\n")
+ break
+ }
+
+ for (ip=cmd; IS_WHITE (Memc[ip]); ip=ip+1)
+ ;
+
+ if (Memc[ip] == '\n') {
+ next
+ } else if (strncmp (Memc[ip], "set", 3) == 0) {
+ ip = ip + 3
+ len_prog = ctowrd (Memc, ip, Memc[prog], SZ_PROGRAM)
+ if (tty != NULL)
+ call ttycdes (tty)
+ tty = ttygdes (Memc[prog])
+ call sgc_dump (STDOUT, Memc[ttycaps(tty)],
+ strlen (Memc[ttycaps(tty)]))
+ next
+ } else if (Memc[ip] == '*') {
+ call sgc_dump (STDOUT, Memc[ttycaps(tty)],
+ strlen (Memc[ttycaps(tty)]))
+ next
+ } else if (!IS_ALPHA (Memc[ip])) {
+ len_prog = ctowrd (Memc, ip, Memc[prog], SZ_PROGRAM)
+ cap[1] = EOS
+ goto getargs_
+ } else if (strncmp (Memc[ip], "bye", 3) == 0)
+ break
+
+ # Parse command with optional arguments, e.g., "RC 1".
+ # Extract 2 character capability name (required).
+
+ op = 1
+ while (IS_ALNUM(Memc[ip])) {
+ cap[op] = Memc[ip]
+ ip = ip + 1
+ op = min (2, op + 1)
+ }
+ cap[3] = EOS
+getargs_
+ # Argument type depends on whether encoding or decoding.
+ if (streq ("SC", cap)) {
+ nchars = ctowrd (Memc, ip, argstr, MAXARGSTR)
+ if (nchars == 0) {
+ call printf ("SC must have 1 contiguous string argument\n")
+ next
+ }
+
+ } else {
+ # Extract up to three arguments (optional).
+ if (ctoi (Memc, ip, arg1) <= 0)
+ arg1 = 0
+ if (ctoi (Memc, ip, arg2) <= 0)
+ arg2 = 0
+ if (ctoi (Memc, ip, arg3) <= 0)
+ arg3 = 0
+ }
+
+ # Fetch the program from the graphcap file. Zero is returned if
+ # the device does not have the named capability, in which case
+ # the function is inapplicable and should be ignored.
+
+ if (cap[1] != EOS)
+ if (tty == NULL) {
+ call printf ("use `set' to specify device name\n")
+ next
+ } else
+ len_prog = ttygets (tty, cap, Memc[prog], SZ_PROGRAM)
+
+ if (len_prog > 0) {
+ if (Memc[prog] == '#')
+ call sgc_dump (STDOUT, Memc[prog+1], len_prog - 1)
+ else {
+ # Dump the program on the standard output.
+ if (cap[1] != EOS) {
+ call printf ("program: ")
+ call sgc_dump (STDOUT, Memc[prog], len_prog)
+ }
+
+ # Set memory or registers depending on whether encoding or
+ # decoding.
+ if (streq ("SC", cap))
+ call strcpy (argstr, g_mem, nchars)
+
+ else {
+ g_reg[1] = arg1
+ g_reg[2] = arg2
+ g_reg[3] = arg3
+ }
+ g_reg[E_IOP] = 1
+ g_reg[E_TOP] = SZ_MEMORY
+
+ # If scan_cursor, decode the input string and write the
+ # registers to the output file. Else, encode the output
+ # string and write the encoded string to the output file.
+
+ status = stg_encode (Memc[prog], g_mem, g_reg)
+ if (status == OK) {
+ nchars = g_reg[E_IOP] - 1
+
+ if (streq ("SC", cap)) {
+ call printf ("X(R1)=%d, Y(R2)=%d, key=%c\n")
+ call pargi (g_reg[1])
+ call pargi (g_reg[2])
+ call pargi (g_reg[3])
+ } else {
+ call printf ("encoding: ")
+ call sgc_dump (STDOUT, g_mem, nchars)
+ }
+
+ } else
+ call printf ("error encoding control string\n")
+ call printf (" status = %d\n")
+ call pargi (status)
+ }
+
+ } else if (len_prog == 0)
+ if (ttygetb (tty, cap))
+ call printf ("boolean capability is true\n")
+
+ else {
+ call printf ("device capability `%s' not found\n")
+ call pargstr (cap)
+ }
+ }
+
+ if (tty != NULL)
+ call ttycdes (tty)
+ call sfree (sp)
+end
+
+
+# SGC_DUMP -- Dump a sequence of ascii characters in printable form.
+
+procedure sgc_dump (fd, data, nchars)
+
+int fd # output file
+char data[ARB] # chars to be dumped
+int nchars
+
+int ip
+int col
+
+begin
+ col = 1
+ for (ip=1; ip <= nchars; ip=ip+1) {
+ call putcc (fd, data[ip])
+ if (data[ip] == ':' && col > 60) {
+ call putci (fd, '\\')
+ call putci (fd, '\n')
+ col = 1
+ } else
+ col = col + 1
+ }
+
+ call putci (fd, '\n')
+end
diff --git a/sys/gio/stdgraph/t_stdgraph.x b/sys/gio/stdgraph/t_stdgraph.x
new file mode 100644
index 00000000..8d6856fc
--- /dev/null
+++ b/sys/gio/stdgraph/t_stdgraph.x
@@ -0,0 +1,110 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <error.h>
+include <gset.h>
+include <gki.h>
+
+define SZ_TXQUALITY 1
+
+# STDGRAPH -- Graphics kernel for the standard graphics output (interactive
+# graphics terminal).
+
+procedure t_stdgraph()
+
+int fd, list
+char txquality[SZ_TXQUALITY]
+pointer gki, sp, fname, devname
+int dev[LEN_GKIDD], deb[LEN_GKIDD]
+int debug, verbose, gkiunits, xres, yres, quality
+bool clgetb()
+int clpopni(), clgfil(), open(), btoi(), clgeti()
+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
+ quality = 0
+ xres = 0
+ yres = 0
+
+ } else {
+ debug = btoi (clgetb ("debug"))
+ if (debug == YES) {
+ verbose = btoi (clgetb ("verbose"))
+ gkiunits = btoi (clgetb ("gkiunits"))
+ }
+
+ # Get the quality parameter for the text generator.
+ call clgstr ("txquality", txquality, SZ_TXQUALITY)
+ switch (txquality[1]) {
+ case 'l':
+ quality = GT_LOW
+ case 'm':
+ quality = GT_MEDIUM
+ case 'h':
+ quality = GT_HIGH
+ default:
+ quality = 0
+ }
+
+ xres = clgeti ("xres")
+ yres = clgeti ("yres")
+ }
+
+ # Open the graphics kernel.
+
+ call stg_open (Memc[devname], dev, STDIN, STDOUT, xres, yres, quality)
+ 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
+ } else
+ call stg_grstream (fd)
+
+ # Process the metacode instruction stream.
+ while (gki_fetch_next_instruction (fd, gki) != EOF)
+ switch (Mems[gki+GKI_HDR_OPCODE-1]) {
+ case GKI_CLOSEWS, GKI_DEACTIVATEWS, GKI_REACTIVATEWS:
+ # These instructions are passed directly to the kernel via
+ # the PSIOCTRL stream at runtime, but are ignored in
+ # metacode to avoid unnecessary mode switching of the
+ # terminal.
+ ;
+ default:
+ if (debug == YES)
+ call gki_execute (Mems[gki], deb)
+ call gki_execute (Mems[gki], dev)
+ }
+
+ call close (fd)
+ }
+
+ # Make sure we finish with CLOSEWS so that the terminal is left in
+ # text mode.
+
+ call stg_closews (NULL, NULL)
+
+ # Finish up.
+ call gkp_close()
+ call stg_close()
+ call clpcls (list)
+ call sfree (sp)
+end
diff --git a/sys/gio/stdgraph/x_stdgraph.x b/sys/gio/stdgraph/x_stdgraph.x
new file mode 100644
index 00000000..37c5a055
--- /dev/null
+++ b/sys/gio/stdgraph/x_stdgraph.x
@@ -0,0 +1,5 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+task gkidecode = t_gkidecode,
+ stdgraph = t_stdgraph,
+ showcap = t_showcap
diff --git a/sys/gio/stdgraph/zzdebug.x b/sys/gio/stdgraph/zzdebug.x
new file mode 100644
index 00000000..ce11d4ea
--- /dev/null
+++ b/sys/gio/stdgraph/zzdebug.x
@@ -0,0 +1,37 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+task slio = t_slio
+
+procedure t_slio()
+
+pointer gp
+char lbuf[SZ_LINE]
+real x[5], y[5]
+
+pointer gopen()
+int getline()
+
+begin
+ x[1] = .25; y[1] = .25
+ x[2] = .75; y[2] = .25
+ x[3] = .75; y[3] = .75
+ x[4] = .25; y[4] = .75
+ x[5] = .25; y[5] = .25
+
+ gp = gopen ("stdgraph", NEW_FILE, STDGRAPH)
+ call gpline (gp, x, y, 5)
+ call gflush (gp)
+
+ call putline (STDOUT, "enter text: ")
+ call flush (STDOUT)
+
+ if (getline (STDIN, lbuf) != EOF) {
+ call zwmsec (3000)
+ call printf ("text = %s")
+ call pargstr (lbuf)
+ call flush (STDOUT)
+ }
+
+ call zwmsec (3000)
+ call gclose (gp)
+end