TD9]  PRO178 Tool Kit disk 8 mmmmmmm m m e!7F ***THIS VOLUME DOES NOT CONTAIN A HARDWARE BOOTABLE SYSTEM *** ߋtv89999 9(909t:#z xQz kzNNz*O:zt:#zt:#z kz U%pU U` `U7 0t&L mVw %  Fʇ0, 8 e    ݺS ee@ 7w Tʇ  4 R N F>et {E . kz 16MAY85134436[ByqSYNTK1\f16MAY85134436)SYNTK1 [128,128] DECFILE11A {U. NNz 16MAY851344360FE1I . *O:z 16MAY851344363Ut~M . t:#z 16MAY85134436-ie.'=yqKz16MAY8513444216MAY851344414L I . xQz 16MAY85134436 12 e.' _z20MAY8510363520MAY851036348 g .j& _r^21NOV8513384821NOV85133847 6_g!.M'K21NOV8513391421NOV85133912n7e.' }z20MAY8510365420MAY85103652eg!. O' _21NOV8513385121NOV85133850e@e. '͌z20MAY8510371520MAY85103713Ag!.O' _l^21NOV8513385321NOV85133852jg!. "' _:21NOV8515471721NOV851338385Eg!.O' _;d21NOV8513390721NOV85133855nh e . &'& _21NOV8513384521NOV85133841%9 Zg!.H' _rw21NOV8513391121NOV85133908m Xg!.M'#E&"kQ21NOV8513393021NOV85133927a5Ta." '͌:21NOV8515502920MAY85104808Jg!.D'Iq wkQ21NOV8513393321NOV85133931qVZg!.' }20MAY8510485720MAY851048300g!.N',@kQ21NOV8513391721NOV851339151qg!.O'z"@;d21NOV8513393721NOV85133935x Jg!.O##',-8;;d21NOV8513392221NOV85133918"-g!.*6' _r:21NOV8513394021NOV85133939@ g!.P',-G;f;d21NOV8513392621NOV85133923PHD g!. '͌21NOV8513132920MAY85104720٤ e .&z 21NOV8513091721NOV85130913mg!. p'z""321NOV8513092021NOV85130918 mee. 'o Wz21NOV8514263521NOV85142633ema." & }:21NOV8515490320MAY85104914 e .!j& _r^21NOV8514265721NOV85142653N Se.'rz21NOV8513085021NOV85130848ϸ m % mJHmmmm\t:#z xQz kzNNz*O:z=yqKz _z }z ͌zrz o Wzmh   m m f/   /  v f&f d W! B!W T  # %p &q 'r (s )t *u +v ,w -x .y A B !C 7K!t 69& 6 25V 6p9& 6 254 D966C3 3  ,, UEs3w8|Db6&fVD B * ͋'% ͥ!ͥE%,  K5  PBFd$Gd&GF(GF*G&$1ff8 ֭GG=G =GGff8 eR Ԭ F$GW!B fGE&GtE&GtE " W! G G  G   G  & & GF GF 6    T  G#wpTe^A F3 `A ~E`A   `A3 ^A B c L r,e2L 6%2 LB ce G   G     W!G!  "D P Q R S 1~ 2~ 3~ 4~ 5~ 6~ 13~ 14~ 15~ 17~ 18~ 19~ 20~ 21~ 23~ 24~ 25~ 26~ 28~ 29~ 31~ 32~ 33~ 34~ j 'f&t @jf '~7  &f  7j`W 5 ~f '~ ! sfj   T)f x'   4 )(UU5 @EU > pQs2 %pˋ5J J J @ EͥAA IP1 `Gp3e  r `G@ r( ]9   k&f&wf ^4 f @ AeBCDeҔ ~ * F|>T>>;7 ;7 ;7 ; w; ~ f -;;F`;|; ,@wr; ~wl;> >>V;>>9 7 97,9e|?7(9 99>>> &7`8E8>8:1"aa aa 8 ̳e (Taa1X  11a11babaaa11a11~01V0 1G8 " eRaa a *Rded)& : nt n! j a u % ±6  ĕEE=% zB1   % zJ1 ==ĕE=  Pf ,2;4;Wo3*0 w:"&.7 p?7.&.7 Z?7/&.7 D?70&.7 .?7n1&.7 ?7V2&.7 ?7>3&.7 >7&4&.7 >75>>&ff&8.E @ 9@ & & &9& & & & ew 9뇅9&.5@  zx93j9&f&fn9 7D 74  7$7 s *&  0e 0  : !6 ` Wf (6 EEp CaC a AW9W+PC C @C   e |6  J! @`    Ba +- 8e "! p   p   ` pRme ߄ گ  ¯GG G FFF  FFF&F1f8 @ ? GFF FFF FFFFF@GU ΃k. PASCAL -- No FPA context. Task Build with /FP f 2*&@ d,: ?8h JG@GU8G@GU?G@GU/G@GUG@ GU GߗF GߗF GFGFG@GGGGGGGPGGGGG GG011fN8 lW#& 0 =  eap%WpGPp%CPG Re 4G1G8 GFGFGF GFGFGFGGGGGGGGGGG GGGv8 F 1Gj8 R GG0~FGFGFGF G:"G&"1ff\8 ,W"aa a F jaa01X 楅 6 pRa e v  # eBe0~p  p  p  fe21G\8 > &a : aPa  > VC.Cm0 pCm2f4  Vf.& & f. B. & &   6A. r ` @m4gF   ` l& aI  p -&  e4 |B BaE0.646 6 t8 t: pFpe  D BgF ne  .0 ,, ,, ߕ;G,ߕ:G aGv8 j  Ҧ BҦ  ҡ   Bҡ  0 Ҷ . BҶ 0 ~ ^e( H 4肝a<1aaaG 8 ֚ -- ,%& z2 F>1aG:8 e   `e  -;G-:G e n8GG ߋ;Gɕ ;Gߋ:Gɕ:G 9G ىBWp `v< t>& & e  fe e   ` a ₕE 4% xR1. .t.tE62 %. xX1,-4 n  4"-4 \  4-2 H  2 2 6  20. "  -4% x1.2.28.t6. 2E.t6P.B @aE]. w ;G:G& & ( aGv8 > re4 ZaNaaa^a%. x2ߕ p` e) tpTe^A F `A,`A`A,`A`A ^At`bAdA ^At`fAhA ^A gG  t`C `tc` A!t`&eeL& G t`&eeN G t`&eePG zt`&e eRf G Z t`&& aanaa41X ܡ 6 pRa e l  #  eBe"0~p ( p *$F t&,, fe"61Gf\8 4  a .f  CCm pCmf # V f&  & f B & &  6 # & X ޟe@ ȟGe@~6*6 ( t  p" p  $ p  &e  a Ne  | "a ߶t`&&  "G % ! m&@@&t@@&tB@ b ! ʨ  aaaaG 8 T-G&1G8 4  G He DGG&.1f,1*1(1aa aG9 Ψ -;G-:G B"W"  "" e B l pl , l&gF& p& &gF d&gF & V& gF  F B  "킝 % : z18-*  -** *&-*  -** **e @ e@~     ;G :G6 *e 2 .aGv8  Be~f & 4e@ aNaaa^aaanaa81X  6 pRa e 4  #  eBe0~p  p    fe:1G\8    0      fe V D ! 5 & & t *&e  CCm pCmNmgFfNmgF H FfF  tB .l0 pl24  l.&gF& >& &gF 2&gF & $& gF         , f,e X u*, & & N *#f*e & C.Cm0B* pCm2Nm.f4Nm. $f4  j XaaZa aa 3 a *e  p  Wpv f  G& G& G  G  p C` veP  !! F& &   4e ee# # & & & ff  $e(  G GFe  G e   Ҷ. BҶ0 D  6a ۶,, %Y z1W ҋ ∐ n e ` D b ne : 1 Bҟ FF n F I    a T e   a  ed2 f2 h2 .  a  e( b"m8e<:8!a a m82 8 ea F (0e0 Ea e( a e- a e f  t`m r&  t 1CBz57 &   7 #7 " 7 $7 7  7  7 7  7  7         7 ~     7 n- 7 Z.7 N 7 B*&           &7-&5vRe j77 -zj8wJ5 ׭ 5t є~5w57 ` t t& R  e ) @ @ @ This application has encountered the following unexpected problem -- LB:[ZZBATON]BATONFRMS.OFF Can't open our frame file.P__((__ =    ~(6Jb""""b" """"v""""b """@"%B&B&8&%%B&%&%%  w 7  N57  6 w|xr|nxfb|Z^VZf&>@20$ w w57  v S~ W  y=$8w.@ PH8w t є~ 8w  &D`wv ewp wf   LeF`78 @a  Հ 5 5 2 Հ`7ww -  R'''L(Z(h ((h(h(h(((>( (  0 &.&.&f.E E6% e@ 6J. 2 '9 . v%9& @N"N  ` .6772%`&  `A  t33 :4H &f.f(CB A*  l%E?BE? eE`&  & &Y . Uw am D`w `w VW w w Sw 4W w wz S W w f XwpRwN SwN W wz bS  wd N w  Sw   D~  D~w xW w S ^ w  w w :Hw x "H C`Д wp PwZ HwZ 6 H  C` w4   B~ C`w.;9L;^;:"<<<=D<<6=r=R===;;"P b2 )# a %V ĕf! afa2 Jf rfe5ffa &a beV  $f*9`* %%&.% ?PASCAL -- Not enough memory. Make task checkpointable or extend .SDAT.f &@ "&.f.f& f E T~. e e  `D e &.   l!8l2B`.| <  " K K@b%3 e7h$7\  a ne a Be a e  a e  a e5  a |e)a P%)&a .%)+a %  a e)a %)a %  a' CBzC#CBzGCBz5  sPo>AA>> $ >>1 5  .5.UW   ,   wE5 E  W LJ5  ,E DBB2A>)  Thickness/The Batons are initially drawn with thin lines.1This option lets you change the pen or brush that0the lines are drawn with. The size of the brush+in X and Y can be controlled independently.%Press 32+{RESUME}32- to leave HELP.r JHELP indexo  Use the arrow keys to changethe line thickness:+   4+Short I 32+{u}32-; 4+Narrow4- 32+{l}32- 32+{d}32- 32+{r}32- 4+Wide  4+Tall)3+Press  aw 6  w , e 1 w E U &W 96 3  4 &9U &9E &9U3uE uU.5`.U & E& & f&ËeDef Ë )̋E U&ff 8[q8[qr[qr[q;d[q;d[q< M32+{EXIT}32- to accept values.PV$ This application has encountered% the following unexpected problem -- 6 .+Because your system is not running in color*right now, you cannot manipulate the color+map. If your Professional does have an EBO+option and a color monitor, and you want to3use color, tell Synergy by pressing 32+{SETUP}32-from the Synergy Main Menu.#Press 32+{RESUME}32- to continue.E2' Cannot create the application window.i.$ Something ha ̡* CrDB D5555RDF CL CB B DEE8@DDEIqM(F@DDIqM2AT>2AVD@&A,A@@AAAA AA@  s really gone wrong!Z, 3+Overview of Baton Twirler7Welcome to the Synergy demonstration application, Baton8Twirler. At any time while the Batons are twirling, you=can press 32+{F5}32- to temporarily pause Baton Twirler and4return to the Synergy Main Menu (and then change the=window size or move it around). Pressing 32+{EXIT}32- will7stop Baton Twirler and return to the Synergy Main Menu.>You can also press 32+{F11}32-, which will display a menu of9options that enable you  >@@@T>r>>>r A"A AP@AAXCXCXCXCjCjCjCjC|C Dto modify the Batons in a varietyof ways.%Press 32+{RESUME}32- to leave HELP. HELP indexN Personalize  Change BatonsfLine thickness Color maprgyRGBnj$ 3+Sample HELP Frame2This is a sample Synergy HELP frame that shows the/sorts of things that can be done in any Synergy1frame (HELP, menu, setup, etc.). First, here's a2sample use of the DEC Multinational () and+Special Graphics characters  that areavailable X 5ew &, Bv    5Bw ?X>!iETITI  >& >>>|?|?@) &ut&Press 32+{EXIT}32- to accept values. 3Choose red, green, or blue with the 32+{l}32- andB32+{r}32- keys. Use 32+{u}32- and 32+{d}32- to increase anddecrease the RGB components.0 3+Press 32+{EXIT}32- to accept values.{3+Baton Twirler HELP Indext The Flow Menu  Change Batonss Line thickness Color mapt Another Topics More Topicsn Suspending Exiting{ Window sizep.{."  3+Line [ >in the Synergy fonts.0Here is a sample use of renditions: You can useB3-Dim1+, Normal and 3+bold2- intensities plus 8+underline8-,9 4+Italic4- and 16+ Hilight 16- for emphasis, and for8keyboard function key notation the 32+{BOXED}32- font.%Press 32+{RESUME}32- to leave HELP. HELP index Baton Twirler 2&Baton Twirler (press HELP for details)Thhere's a2sample use of the DEC Multinational () and+Special Graphics characters that areavailable h $SDAT$ PSECT! This usuallymO; takes some trial and error to allocate enough space (but if you allocate lotsyH; of extra room to be on the safe side, you use up extra address space).GBLPAT = Baton:$NOEXT:240nF; Lastly, define values for some global variables used by the program.8GBLDEF = SCRLUN:5 ; Logical unit number for video output>GBLDEF = SCREFN:1 ; Event Flag Number for video output writes.>GBLDEF = IDLE$:6 ; Event Flag Number for keyboard input idles.//have allocated a large enoug GB; Task builder Command (.CMD) File for the sample Synergy program.K; The first line tells PAB to create the task image file with checkpointingN; enabled and floating point context space allocated (both of which you almostL; ALWAYS want). The details of the task structure are contained in the .ODL%; file, referenced by the /MP switch.Baton/CP/FP = Baton/MPK; We can give the eventual running task any name we want. This name can beF; used by other tasks running under P/OS to communicate wi  A; Overlay Description (.ODL) File for the sample Synergy program.H; The Pascal $ODAT$ psect (where all the outer level variables live in aH; program with the [Overlaid] attribute) and the Heap (where all dynamicN; memory comes from) are made non-disk resident to reduce the size of the task ; image file.H; This is accomplished by grouping those modules of the program into oneL; segment (called OFLINE here), and including in that segment a dummy moduleN; created with the .NAME directive (called S th our task. Task = BATONO; PRO/Pascal does not use the conventional RSX-11M-PLUS (and thus P/OS) area ofeJ; the task reserved for stack space usage. Rather, it allocates the stackO; itself in the PSECT $SDAT$. Thus it would be wasting address space for us tokF; allocate room to the P/OS default stack (PAB defaults to 256 words).H; Allocating zero words would be risky though, since Pascal DOES use theE; default stack momentarily until its run-time system is initialized.e Stack = 30N; This  AVER here) that is given the NODSKM; attribute. Any segment which has the NODSK attribute will not be allocatedoI; any space in the on-disk .TSK task image file by the Task Builder. FordO; simplicity, this whole segment (OFLINE) is placed as a co-tree off the end ofr; the main .ROOT structure. < .PSECT $ODAT$, RW, D, GBL, REL, OVR ; Pascal Overlaid data.9 .PSECT $SDAT$, RW, D, GBL, REL, OVR ; Pascal stack/heap. 9 .PSECT $SDAT0, RW, D, GBL, REL, OVR ; Top of stack/heap.e/ .NAME SAVER, NODSK + task needs the PRO/Pascal run-time system (PASRES), which in turn needsI; the Record Management Services library (RMSRES). At our option we havecO; included the DECnet extensions to RMS (DAPRES) to support remote file access.wCLSTR = PASRES,RMSRES,DAPRES:ROsK; The following line modifies a part of the PRO/Pascal run-time system. As L; described above, the Pascal Stack (containing subroutine linkage and localK; variable storage) is allocated in the $SDAT$ PSECT. Normally, the Pascal0N; Heap ( ; Dummy module for NODSK.t*; Here is the entire segment put together:.OFLINE: .FCTR $ODAT$ - $SDAT$ - $SDAT0 - SAVER1; Here are the actual code modules for this task:u1LIBS: .FCTR LB:[1,5]PasLib/LB - LB:[1,5]WinLib/LBE9MODULS: .FCTR Baton - GIDIS - GetAKey - KBServ - ReadMesgsH; We need RMS in this task. For P/OS V2.0 and greater, we might as wellK; include PRO/DECnet facilities in the task so that we could do transparent H; remote file accesses if we ever worked with files. To inclu Zcontaining dynamic memory from NEW/DISPOSE, file I/O buffers, etc.) isJ; automatically allocated at run-time by extending the task address regionM; (with EXTK$ directives). But this requires a checkpoint operation whenevereL; the task is extended, and checkpointing is slow. So we can ask PRO/PascalN; not to ever extend the task, and instead use the bottom portion of the stackJ; space (the $SDAT$ PSECT) to double as the heap. CAUTION: If you ever doO; this, MAKE SURE you have allocated a large enoug de DECnet,M; simply reference DAPRLX instead of RMSRLX, and add DAPRES to the CLSTR line #; in the task builder command file.@LB:[1,5]DAPRLXa% .ROOT MODULS - LIBS - RMSROT, OFLINET .END,PasLib/LB - LB:[1,5]WinLib/LBE9MODULS: .FCTR Baton - GIDIS - GetAKey - KBServ - ReadMesgsH; We need RMS in this task. For P/OS V2.0 and greater, we might as wellK; include PRO/DECnet facilities in the task so that we could do transparent H; remote file accesses if we ever worked with files. To inclu color map. A Synergy program } O{ has to be somewhat careful when it comes to changing the color map. In } O{ most cases, Synergy isolates each window from whatever goes on in every } O{ other window (that is, application A cannot affect application B's } O{ windows). This is made possible through separate software-maintained } O{ contexts for each window. For example, each window has its own writing }eO{ mode state, its own cursor position, etc. However, this is NOT tr  $ Green: 0..7; { values for a color. }d#  Blue: 0..7;. B END { ColorDescriptor } ; tO PackedColorType = PACKED RECORD  { Case variant that maps } O  CASE Integer OF  { RGB values into a 16- } O  1: ( W: Unsigned; ); { bit binary word for }O : 2: ( R: ColorDescriptor; ); { compact storage. }a.  END { PackedCol b[Overlaid] PROGRAM Baton;O{ This PRO/Pascal program is provided with the Synergy Tool Kit to }O{ demonstrate how a simple application interacts with the Synergy services to }O{ use the windowing facilities. Also, since this program makes extensive use }O{ of PRO/GIDIS to do its output, this serves as an illustration of to use }O{ GIDIS effectively in an application. Lastly, this program shows how to }O{ issue P/OS Executive Directives directly from a PRO/Pascal program. eue of the } O{ color map. On the Professional, the color map applies to ALL windows; thus }cO{ if application A changes the color map, application B's windows change too. }eO{ So changing the color map has to be done keeping possible "side effects" in }aO{ mind. Most importantly, which of the eight entries in the color map you }eO{ change is crucial. A program should virtually NEVER change entries 0 or 4. }tO{ Entry zero is always BLACK, and is used to display text in windows, for the }iO{ wind  }iO{& } O{ The ability to issue directives (EMT 377s) was inadvertantly omitted from }yO{ the PRO/Pascal V1.2 documentation. There is a new predefined procedure }aO{ named DIR$ which takes a single parameter. This parameter should be the }tO{ Directive Parameter Block for the directive you are issuing. The format }mO{ and contents for each directive is described in the P/OS System Reference }lO{ Manual owframe surrounding each window, etc. Entry four is always WHITE, and } O{ is used for the white background of all windows. If a program changes the }iO{ color of those entries, you will get very entertaining results! This } O{ sample program takes great care to only change entries 1, 2, 3, 5, 6 and 7. }e lO%Include 'BatonFrms/NoList' { Contains ordinal numbers for Frame IDs }nO%Include 'GIDISOps/NoList' { Contains declarations needed for GIDIS routines }nO%Include 'Synergy/NoLi  (chapter nine for Tool Kit version V2). To issue a directive, } O{ define a RECORD type for the DPB for the directive, and assign the fields }tO{ of the record appropriately (with constants, addresses of buffers, etc.). }iO{ Then simply invoke the DIR$ procedure, as in:  }rO{ DIR$( DPB_Record ); 5}nO{ To check the results of the directive, declare: ! }SO{ VAR $DSW: [External] st' { Contains declarations for Synergy services }y={ Here are the CONSTant definitions specific to this module } CONSTrM GTIM = 61; { Directive Identification Code for Get Time directive. }lA GTIM_Len = 2; { Length of GTIM Directive Parameter Block. }eK MaxPoints = 200; { Largest number of segments a single Baton may have. }dF MaxBatons = 10; { Largets number of simultaneous Batons allowed. }L MaxColor = 7; { Number of entries in the Professional-300 color o3Integer; }aO{ and then do: }sO{ IF $DSW = 1 THEN ...  } O{& } O{ This program takes advantage of color, if the system that it executes on } O{ has color enabled. Not only does the program display objects in different } O{ colors, the program changes the values in the map. }_H{ Here are the data structure TYPE definitions specific to this module }TYPEB A_Baton 1= RECORD { Data structure describing a Baton },  Newest, Hue: Integer;G 4 Sticks: ARRAY [ 0..MaxPoints, 0..3 ] OF Integer;9 & Speed: ARRAY [ 0..3 ] OF Integer; & : END { A_Baton } ;" ColorDescriptor = PACKED RECORDC 0 Red: 0..7; { Contains the RGB intensity }oC m 3 (} O GTIMdpbType = PACKED RECORD { Directive Parameter Block },O < D_CODE: [Pos(0,0)] 0..255; { for the Get Time (GTIM) }eO < D_LGTH: [Pos(1,0)] 0..255; { P/OS Executive Directive. } : & G_TIBA: [Pos(2,0),Unsafe] Unsigned;* $ END { GTIMdpbType } ;L GTIM$BUF < = PACKED RECORD { Buffer format used by GTIM directive }?  G_TIYR: [Pos(0,0)] Unsig Ts. Almost }eO { always, you will want to store the X,Y coordinates of your window(s), }lO { plus the width(s) and height(s). Beyond that, it's up to you. This }eO { sample application uses some of the remaining space to retain program }eO { variables which the end-user has control of. This way, the values of }NO { those variables are preserved one run of the application to the next, } O { without the application having to create a file on the disk and store }yO Aned; { Year } ? , G_TIMO: [Pos(2,0)] Unsigned; { Month } ? , G_TIDA: [Pos(4,0)] Unsigned; { Day }[? , G_TIHR: [Pos(6,0)] Unsigned; { Hour } ? , G_TIMI: [Pos(8,0)] Unsigned; { Minute }? , G_TISC: [Pos(10,0)] Unsigned; { Second } O < G_TICT: [Pos(12,0)] Unsigned; { Clock ticks of second }fO < G_TICP: [Pos(14,0)] Unsigned; { Number of ticks/second }s' u { the values there, etc. P} H XStatus: StatusBlock; { Array used to return success/failure status }H { from the various Synergy service calls. }I WDesc: WindowDescriptor; { 32-byte Window Descriptor Block that is }nI { used to manage the program's main window. } O KBBuf: [External,Volatile] Queue; { Special keyboard buffer GetAKey() uses }tO InputKey: FunctionKeyNames; { These  2orType } ;" PackedBytes = PACKED RECORDL 8 Low: 0..255; { Simple structure that allows easy }L 8 Hi: 0..255; { use of both bytes in a 16-bit word. }* Z END { PackedBytes } ;> ColorMapType = ARRAY [ 0..MaxColor ] OF PackedColorType;O > { A table large enough to contain RGB intensity values } O ^ { for all eight entries in the Professional's colot map. } I FunctionKeyNames = ( TextKey   END { GTIM$BUF } ;  TL{ Here are the data structure VARiable allocations specific to this module }VARs ContextBlock: RECORD! CASE Integer OF D 41: ( C: PACKED ARRAY [ 1..MaxContext ] OF Char; );  2: ( R: RECORDO 6WindowX: Integer; { Position of the window }:3 WindowY: Integer; K 2WindowWidth: Integer; { Size of the window }s3 ȃ., TabKey, Return, FindKey,EL 8 InsertHere, RemoveKey, SelectKey, PrevScreen,L 8 NextScreen, BreakKey, SetUpKey, SuspendKey,O < InterruptKey, ResumeKey, CancelKey, MainScreenKey,0E  Exit,  F11, F12, F13,eE # AddOptnsKey, HelpKey, DoKey, F17,aE  F18, F19, F20, PF1,mD g WindowHeight: Integer;eO 6CPoints: Integer; { How many and what size }O 6CBatons: Integer; { Batons the user wants. }(O 6SavedColor1: PackedColorType; { Values for the }O 6SavedColor2: PackedColorType; { entries in the }O 6SavedColor3: PackedColorType; { color map that } O SavedColor5: Packe S  PF2, PF3, PF4, Up,J  Down,  Right, Left, Delete );O > { Enumerated type for use with the GetAKey() subroutine. } O > { Note that the ordering of this list is unrelated to } O > { the 16-bit integer Termination Key values that Synergy } O > { uses. (This ordering is purely for the convenience of } O  { the sample program.) ϣ"dColorType; { the program }dO 6SavedColor6: PackedColorType; { allows the }mO 6SavedColor7: PackedColorType; { user to change.}nO 6LineThickness: PackedBytes; { Thickness of lines } . END { variant R } );& END { ContextBlock } ;O { Allocate the 32-byte Context Block that Synergy keeps for us. The }lO { application can store ANYTHING it wants in these 32 byte ls there are per Baton. }tO Batons, + { How many Batons there are in the window. }rO RndSeed: -{ Used as seed for a random number generator. } Integer;N ColorMap: ColorMapType; { The program's values for the hardware color map }/ BatonList: ARRAY [ 1..MaxBatons ] OF A_Baton;r@ { List of each of the Batons that are moving in the window }L?{ Here are the external procedure definitions for this module }a[Exter9 } O { They may be called from any PRO/Pascal program.  }SO{&---}nO{--0 Now begins the executable code for this module ---}u FUNCTION Rnd : Integer;VO { Simple random number generator. As used by this program, it returns }AO { numbers in the range 0..1400. RndSeed is a global variable. 4}n BEGIN { Rnd }a4 RndSeed := ( RndSeed *Hnal(GETMES)]7PROCEDURE GetMessage7( VAR FrameID: [ReadOnly] Integer; : & VAR Msg1: [Unsafe] StringType;: & VAR Msg2: [Unsafe] StringType;: & VAR Msg3: [Unsafe] StringType;: & VAR Msg4: [Unsafe] StringType;: & VAR Msg5: [Unsafe] StringType;: & VAR Msg6: [Unsafe] StringType;C : VAR Msg7: [Unsafe] StringType ); SEQ11; [Externa=_ 13077 + 6925 ) MOD 32768;0 Rnd := UAND( RndSeed, %O'77777' ) DIV 40 END { Rnd } ;$7 PROCEDURE ReadMessage( FrameID: Integer;-7 VAR Length: Integer;a8 VAR Message: [Unsafe] String );O { ReadMessage reads the specified message frame, returning the first line } O { of it in a text string. G }l VAR ' Offsets: ARRAY [ 1..9 ] OF Integer;e XStatus: SǁFl(GETMES)]7PROCEDURE GetMessage9( VAR FrameID: [ReadOnly] Integer;r: & VAR Msg1: [Unsafe] StringType;: & VAR Msg2: [Unsafe] StringType;: & VAR Msg3: [Unsafe] StringType;: & VAR Msg4: [Unsafe] StringType;: & VAR Msg5: [Unsafe] StringType;: & VAR Msg6: [Unsafe] StringType;: & VAR Msg7: [Unsafe] StringType;: tatusBlock;2 NumLines: Integer; BEGIN { ReadMessage }7E WIRMS( XStatus, NumLines, Offsets, Message, FrameID, StringMax );DE Length := Offsets[ 2 ]; { This is the length of the first line }I END { ReadMessage } ;  [ExternalE(GETMES)]7PROCEDURE GetMessage2( VAR FrameID: [ReadOnly] Integer;s8 $ VAR Msg1: [Unsafe] StringType;A l VAR Msg2: [Unsafe] StringType ); SEQ11;O{ This definition is needed for the following procedure.  Intro1.L, Intro1.S, { a fail-safe mechanism for getting }L >Intro2.L, Intro2.S, { some information on the screen. } 0, JunkStra read-ahead input is copied from our private buffer }aO { (KBBUF) into the Synergy type-ahead buffer (WITBF) so that it is not lost.}g VARe i: Integer; Ch: Char;E BEGIN { PVDetach }= FlushGIDIS; { Make sure any buffered output is put out } $ Detach; { Detach the terminal }8 UnlKeyboard; { Make sure the keyboard is unlocked }M WITBF.CurrentLength := KBBUF.Count; { Copy data from private to public }a FOR i := 1 TO KBBUF.Count DO BEGINeH RemoFtring,@ 2Length, Message, { Specific message goes here }  v0, JunkString ); END { then }d1 ELSE { Need to use the hard-coded strings }f WIERW( XStatus,= 240, ' This application has encountered ', = 240, ' the following unexpected problem -- ',  0, JunkString,> 2Length, Message, { Specific message goes here } D0, JunkString );* ExitStatus( 1 ); { Exit the program }  >veFromQueue( KBBUF, Ch ); { Get next character from KBBUF }H WITBF.Characters[ i ] := Ch; { Append it to Synergy WITBF } END { for } ;  END { PVDetach } ; A PROCEDURE WriteString( VAR Str: [ReadOnly,Unsafe] StringType ); O { WriteString takes a passed string. This string is then written to the }eO { screen, taking into account any rendition control sequences embedded in }pO { the string to change the font in mid-string. }O { NOTE: ZlEND { FatalError } ; [Global]D PROCEDURE Error( ErrorClass, ErrorNumber, ErrorMsgLength: Integer;(  VAR ErrorMsg: String;#  VAR XFile: Text; -  IOStatus, UserPC: Integer;i+  FileNameLength: Integer; * VAR FileName: String );O { Error is a substitute for the PRO/Pascal run-time system Error handler }cO { module. This routine is called whenever some "catastrophic" error }xO { condition is encNormally, the application does NOT have to be concerned with doing } O { the grunt-work for rendition control sequences. That is, whenever you } O { call some Synergy service to display some text Synergy will automatically }aO { "do the right thing" to invoke your desired renditions. You ONLY need to } O { do it yourself if YOU are going to do the GIDIS output of a string with }nO { rendition sequences in it to a window yourself "}  VAR Ch: Char; "  N L}  [Global(FTLERR)]. PROCEDURE FatalError( FetchHeaders: Boolean;( Length: Integer;@ VAR Message: [ReadOnly,Unsafe] String );O { FatalError is called to abort the running program whenever it encounters }sO { any surprise, serious error situation that it cannot cope with/recover }sO { from." E }1O { 'FetchHeaders' should be passed as True in the normal case;  ountered, for example failed file I/O operations that do }rO { not specify ERROR=CONTINUE; memory protect traps; odd-address traps; etc. }SO { Most applications should provide their own error handler, since the one }:O { that PRO/Pascal provides is very large (takes address space), plus the }FO { information that it displays when an error occurs is generally of little }mO { help to the user running the application (sort of a register dump). Your }pO { error handler can display a more fri {Change, Rendition, i: Integer;, PROCEDURE UseRendition( Rend: Integer );O { UseRendition is passed a rentition word (16-bits), and does the neces- }sO { sary things to cause subsequent character output to be in the specified }hO { r endition. }  VAR WritingMode: WritingModes;, Intensity, Italics, Alphabet: Integer; BEGIN { UseRendition }E Italics := 0; { To start with, assume n * i := i + 1; { Skip to next byte }> 0 Ch := S[ i ]; { Get the next character }2 ( UNTIL ( Ch < '0' ) OR ( Ch > '9' );  IF Ch = '+'N @THEN Rendition := UOR( Rendition, Change ) {Additive}D 8ELSE Rendition := UAND( Rendition, UNOT( Change ) );M B UseRendition( Rendition ); { Invoke new resulting rendition }u  END { else } ;g (END { while } ;d END { WriteString Co italics }dE Alphabet := WI$Normal; { Assume normal font ? }E WritingMode := Replace; { Assume "positive video" }eN Intensity := UAND( Rend, 3 ); { Pick out 2 low-order intensity bits } IF UAND( Rend, 8 ) = 0% THEN { Underline NOT wanted }   CASE Intensity OF#  0: Alphabet := WI$Dim;&  1,2: Alphabet := WI$Normal;$  3: Alphabet := WI$Bold; 0 END { case } $ ELSE { Underline IS wa} ;  J FUNCTION CountString( VAR Str: [ReadOnly,Unsafe] StringType ) : Integer;O { CountString is passed a string record. It returns the PRINTING length of } O { the string, once the rendition control sequences to change fonts have }oO { been accounted for. (Rendition control sequences start with an ASCII 28, },O { then have some digits, then have a "+" or "-". They are described in the }uO { Synergy programming manual.) }N VARS# *nted }  CASE Intensity OFA : 0, { Dim-underline is not supported, so use normal }d) " 1,2: Alphabet := WI$Underline; - & 3: Alphabet := WI$BoldUnderline;3 D END { case } ;e n IF UAND( Rend, 4 ) <> 0( THEN09  Italics := 2; B{ Use italics }e IF UAND( Rend, 16 ) <> 0 THEN9 b WritingMode := ReplaceNegate; { Inverse Video }l IF UAND( Rend, 32 ) <> 0 THEN9  Alphabet := WI$BoxeCh: Char; Len, i: Integer;g BEGIN { CountString }] Len := 0;n i := 0;o WITH Str DO  WHILE i < L DO- (BEGIN { Examine the next character }g i := i + 1;3 ,Ch := S[ i ]; { Get the next character }a IF Ch <> Chr( 28 )  THENr@ 6 Len := Len + 1 { Normal text character, count it }  ELSEeC : REPEAT { Start skipping over the rendition sequence } 7 i := i + 1; { Skip to next chd; { Boxed font }tA SetCellRendition( Italics ); { Now that we know what } A SetAlphabet( Alphabet ); { is wanted, do it. }h& SetWritingMode( WritingMode ); END { UseRendition } ; BEGIN { WriteString } E i := 0; L Rendition := 2; { To start with, we want plain, normal intensity text }; UseRendition( Rendition ); { Select normal rendition }e WITH Str DO( WHILE i < L DOA BEGIN { Examine (and maybe  aracter } 8 , Ch := S[ i ]; { Get the next character }0 & UNTIL ( Ch = '+' ) OR ( Ch = '-' ); END { while } ; : CountString := Len; { Pass out the resultant length } END { CountString } ; / PROCEDURE FillText( NumberOfStrings: Integer; ? VAR Msg: [ReadOnly,Unsafe] StringArray );tO { FillText simply takes an array of string records, and displays them one }rO { below the other in the current window. The strings are scanned to s  display) the next character }t i := i + 1;3 .Ch := S[ i ]; { Get the next character }  IF Ch <> Chr( 28 )  THEN ; 2 PutChr( Ch ) { A normal character, print it }   ELSE;7 . BEGIN { The start of a rendition string }   Change := 0; 1 ( Ch := '0'; { Prime the pump }s8 , REPEAT { Start scanning digit sequence }D 8 Change := ( Change * 10 ) + Ord( Ch ) - Ord( '0' );8  ee if } O { they contain rendition control sequences and are displayed appropriately. }( VAR  i: Integer;; BEGIN { FillText }$ FOR i := 1 TO NumberOfStrings DO: BEGIN { Display the next string inside the window }( "SetPosition( 2 * CharacterWidth,L :(i - 1) * CharacterHeight + ( CharacterHeight DIV 2 ) );L WriteString( Msg[ i ] ); { Draw the string in its proper position } END { for } ;n END { FillText } ; t PROCEDURE Initiali lH SavedColor6.R := ColorDescriptor( 7, 0, 0 ); { usable. }= 4 SavedColor7.R := ColorDescriptor( 0, 2, 3 ); M D LineThickness.Low := PixelWidth; { Lastly, choose to draw the } M D LineThickness.Hi := PixelHeight; { segments with thin lines. }   END { then } ;0N Batons 8:= CBatons; { Now copy permanent values to run-time }N Points 8:= CPoints; { variables for duration of this run. }O ColorMap[ 0 ].R := CPoints := Points;  { settable program values. }& SavedColor1 := ColorMap[ 1 ];& SavedColor2 := ColorMap[ 2 ];& SavedColor3 := ColorMap[ 3 ];& SavedColor5 := ColorMap[ 5 ];& SavedColor6 := ColorMap[ 6 ];& SavedColor7 := ColorMap[ 7 ]; END { with } ;< WIDSW( XStatus, WDesc.ID ); { Destroy the main window }O WIDON( XStatus, MaxContext, ContextBlock ); { Tell Synergy we're through }  END { CleanUpSyn } ;  PR >zeSyn;O { This sets up things for the rest of the program. }( VAR O GTIMdpb: GTIMdpbtype; { Directive Parameter Block for the GTIM directive }ON TimeBuffer: GTIM$BUF; { Time buffer used by the Get Time P/OS Directive } BEGIN { InitializeSyn } ? TitleID := TITLE; { Assume the normarl title string } 5 ContextLength := MaxContext; { Ask for the max } O WIINI( XStatus, 2, ActualVersion, %{ Call Synergy, telling it that }DO >8 ColorDescriptor( 0, 0, 0 ); { This index is BLACK } ' "ColorMap[ 1 ] := SavedColor1;7' "ColorMap[ 2 ] := SavedColor2; ' "ColorMap[ 3 ] := SavedColor3;hO JColorMap[ 4 ].R := ColorDescriptor( 7, 7, 7 ); { This index is WHITE };' "ColorMap[ 5 ] := SavedColor5; ' "ColorMap[ 6 ] := SavedColor6; ' ColorMap[ 7 ] := SavedColor7;u END { with } ; M OPENME( XStatus, $FCTV$, 25, 'LB:[ZZBATON]BATONFRMS.OFF' ); { Open file }  IF XStatus[ H ContextLength, ContextBlock, { this application has just } O  ScreenWidth, ScreenHeight, %{ started and will be requesting }BO 4 CharacterWidth, CharacterHeight, { other services. }t#  PixelWidth, PixelHeight,I | ColorWindows ); WITH ContextBlock.R DOG BEGIN { What's in the Context Block from the last time we ran? }o IF ContextLength = 0O B THEN { This is the first time this application has run. In t 1 ] <> 1 THEN,O FatalError( False, 32, ' Can''t open our frame file.' ); { Death } L { The frame file is stored in LB:[ZZBATON] so that, in P/OS V3 Cluster }L { configurations, the .OFF file can be shared among multiple users. m } WITH GTIMdpb DO M BEGIN { Set up the Directive Parameter Block for the GTIM$ directive }M? :D_CODE := GTIM; { Directive Identification Code. } ? .D_LGTH := GTIM_Len; { Parameter Block Length. } L G_TIBA :his }eO H BEGIN { case, there is no saved context from before, so we must }eO 3{ do a one-time initialization of the context data.  }aB  TitleID & := TITLE2; { Special intro title }N D WindowWidth := ScreenWidth DIV 2; { Make beginning size }N D WindowHeight := ScreenHeight DIV 2; { of half-screen. }H  WindowX , := -32763; { We want the window in }H  WindowY  := -327= Address( TimeBuffer ); { One Parameter (buffer address) } END { with } ;H DIR$( GTIMdpb ); { Issue the directive, find out the current time }J WITH TimeBuffer DO { Use low-order time values to init the RND seed }F RndSeed := UOR( UOR( G_TIMI * 37, G_TISC * 71 ), G_TICT * 293 ); END { InitializeSyn } ;  PROCEDURE CleanUpSyn; O { CleanUpSyn does whatever housekeeping is necessary before we leave. }L BEGIN { CleanUpSyn }' PVDetach; { Free up the :$63; { the middle of the screen. }H  CBatons := 1; { Start with one Baton,  }H  CPoints , := 17; { With a tail 17 segments long. }N D SavedColor1.R := ColorDescriptor( 0, 0, 7 ); { Set up nice }N D SavedColor2.R := ColorDescriptor( 0, 7, 0 ); { color map }N D SavedColor3.R := ColorDescriptor( 7, 7, 0 ); { in case }N L SavedColor5.R := ColorDescriptor( 7, 5, 0 ); { COLOR is }N  l keyboard }TO WIGEW( XStatus, DescriptorLength, WDesc ); { Get current size & position } ! WITH WDesc, ContextBlock.R DOnG BEGIN { Load the data that is to be saved in the context block }l@ WindowX := X; { Remember the window }@ WindowY := Y; { size and position in }@ WindowWidth := Width; { the context block. } WindowHeight := Height;lD CBatons := Batons;  { Also save the user- }D aeight := ScreenHeight; { the full screen. } END { with } ;N WISWP( XStatus, DescriptorLength, WDesc ); { Tell the values to Synergy }M ReadMessage( TitleID, TitleLength, TitleText ); { Read a message frame } M WITTL( XStatus, TitleLength, TitleText ); { Set the window title }o END { MakeOurWindow } ;  W PROCEDURE InitBaton;O { This procedure initializes the program-specific data structures. }W VARSL Segment, ThisBaton, Inner: Integer; { Somz*Rnd; { Pick starting X,Y coordinates } C 8UNTIL ( Sticks[ 0, Inner ] < ( WDesc.Width DIV 2 ) )eC 6AND ( Sticks[ 0, Inner ] < ( WDesc.Height DIV 2 ) )ID AND ( Sticks[ 0, Inner ] > ( 20  ) ); END { for } ;IM FFOR Segment := 1 TO Points DO { Propagate base stick into others } " FOR Inner := 0 TO 3 DO< 2Sticks[ Segment, Inner ] := Sticks[ 0, Inner ] *END { with } ; END { InitBaton } ;:e FOR loop counters and such } BEGIN { InitBaton }  IF ColorWindows <> 0 THENi; BEGIN { Color is in use, so initialize the colors }e  ColorMapIndex := 1;  FOR Inner := 1 TO 7 DOr9 2 IF Inner <> 4 { Leave index 4 (WHITE) alone }) THEN: .SetColorMap( Inner, ColorMap[ Inner ].R.Red,< ColorMap[ Inner ].R.Green,= 4ColorMap[ Inner ].R.Blue );n END { then } ;m<1 PROCEDURE Travel( VAR Node, Direction: Integer;N6 WhichBaton, Index, Max: Integer );O { Travel is called to move one part of a Baton one cycle along its track. }  BEGIN { Travel }# WITH BatonList[ WhichBaton ] DO BEGIN O LNode := Node + Direction; { Add position + speed to get new position }rH BIF ( Node <= 0 ) OR ( Node >= Max ) { If the Baton hits edge, }H FOR ( Abs( Sticks[ Newest, Index ] { or it gets too long. }L xOCEDURE MakeOurWindow;O { MakeOurWindow simply creates a window for the application, and gives it } O { a title.! }; VAR  Length: Integer;C Data: String; { Used to hold a possible error message string }  BEGIN { MakeOurWindow } ! WITH WDesc, ContextBlock.R DOs4 BEGIN { Fill in the window descriptor block }C WDesc + := WDescModel; { Init the bulk of it } G X  ( WITH ContextBlock.R.LineThickness DO3 SetPixelSize( Low, Hi, Low DIV 2, Hi DIV 2 ); WITH WDesc DOoO SetOutputClippingRegion( 0,0, Width - PixelWidth, Height - PixelHeight );  SetWritingMode( Replace );F SetPrimaryColor( 7 ); { Use index 7 for the window background } SetSecondaryColor( 7 );rM EraseClippingRegion; { Clear out window, fill it with background color }.< SetPrimaryColor( 4 ); { Go back to drawing in white } SetSecondaryColor( 4 );m>.:= WindowX; { Then fill in the specifics } ' Y  := WindowY;o+ Width  := WindowWidth; , Height := WindowHeight;N Flags.Color 5 := True; { We'll use color, if the user lets us }$ Flags.Titled := True;$ Flags.WhiteBorder := True;$ Flags.ClearOnChange := True; END { with } ;J WICRW( XStatus, DescriptorLength, WDesc ); { Create the main window } IF XStatus[ 1 ] <> 1 THEN rF FOR ThisBaton := 1 TO Batons DO { Initialize each of the Batons }$ WITH BatonList[ ThisBaton ] DO  BEGINe IF ColorWindows = 0   THENgL B Hue := 0 { Monochrome, draw them in the black colormap entry }  ELSEx4 * BEGIN { Color is present and enabled }G > Hue := UAND( Rnd, 7 ); { Pick a random starting color }gC 8 IF ( Hue >= MaxColor ) OR ( Hue = 0 ) OR ( Hue = 4 )w THENI  B= BEGIN { Yipes! We got an error creating the window } A < ReadMessage( NOWIND, Length, Data ); { Get error text } L FatalError( True, Length, Data ); { Display the text & kill task } END { then } ;o WITH WDesc DOsI BEGIN { Assign the minimum and maximum range for the window size }u3 .MinWidth := 100; { The minimum window } 3 .MinHeight := 100; { size is pretty tiny. }s8 2MaxWidth := ScreenWidth; { The Maximum is }8 MaxH 4@ Hue := 1; { Make sure that it is a legal color index }   END { else } ;n Newest := 0;  FOR Inner := 0 TO 3 DON DBEGIN { Init the X,Y speeds of both end-points of first segment }L BSpeed[ Inner ] := ( Rnd DIV 44 ) + 4; { Pick starting speed } IF Rnd > 450  THEN7O D Speed[ Inner ] := -Speed[ Inner ]; { Randomly flip the sign }R REPEATM Sticks[ 0, Inner ] := wing background }H@ :SetPosition( Sticks[ Newest, 0 ], Sticks[ Newest, 1 ] );@ Sticks[ Newest, Inner ] := Sticks[ PriorSegment, Inner ];{ WITH WDesc DOPJ &BEGIN { Now move X,Y coords of both eallowed to happen, as GIDIS is fully capable of clipping the }dO { "overhanging" segments; this program simply chose not to allow it). }  VARt6 WindowID, NewWidth, NewHeight, WhyChange: Integer; BEGIN { Hibernate }dJ PVDetach; { Free up the keyboard for Synergy and other applications } REPEAT: FlushGIDIS; { Force out any buffered GIDIS output }N WIINT( XStatus, WhyChange, WindowID, NewWidth, NewHeight ); { Suspend } IF WhyChange = 1 THENb@nds of the first segment }M DTravel( Sticks[ Newest, 0 ], Speed[ 0 ], WhichBaton, 0, Width ); M DTravel( Sticks[ Newest, 1 ], Speed[ 1 ], WhichBaton, 1, Height );-M DTravel( Sticks[ Newest, 2 ], Speed[ 2 ], WhichBaton, 2, Width );PM DTravel( Sticks[ Newest, 3 ], Speed[ 3 ], WhichBaton, 3, Height );t END { with } ;L FSetPrimaryColor( Hue ); { Draw the new (1st) segment in its color }@ 2SetPosition( Sticks[ Newest, 0 ], Sticks[ Newest,  : BEGIN { Window size was changed, update its contents }N F WIGEW( XStatus, DescriptorLength, WDesc ); { Get size & position }J B InitBaton; { Re-init the data structures to fit the new size } END { then } ; O UNTIL WhyChange = 0; { 0 = means the application should resume execution }E= KBASTInitialize; { Get the keyboard back for AST input }F EnableColors( ColorMap ); { Refresh the color map to our colors } END { Hibernate } ;e 1 PROCEDURE Ha1 ] );@ Points { next time, checking for wrap-around. }   THENW Newest := 0 END { with } END { TwiddleBaton } ; @ PROCEDURE EnableColors( VAR NewMap: [ReadOnly] ColorMapType );O { EnableColors simply refreshes the hardware color map with the current }sO { programmed color choices.  kndleKey;O { This (large) procedure processes all typed input (function keys) from the },O { keyboard. }-9 PROCEDURE HandleFCMKey( InputKey: FunctionkeyNames );tO { HandleFCMKey is called when either F11, F12, F13, or ADDTNL OPTIONS is }tO { pressed, with the intent being to display the proper leaf in the F}bO { application's main Flow Control Menu. As it turns out, this }tO { application only hi >- Sticks[ Newest, UAND( Index + 2, 3 ) ] ) > Max * 3 DIV 5 )   THENt3 , BEGIN { Reflect this node (bounce it) } %  Direction := -Direction;g3 * Node := Node + ( 2 * Direction );t END { then } ;  END { with } END { Travel } ; 0 PROCEDURE TwiddleBaton( WhichBaton: Integer );O { This procedure moves a complete Baton by one step. F}R VARt! PriorSegment, Inner: Integer;t BEGIN { TwiddleB }N VAR]% i: Integer; { FOR loop counter }e BEGIN { EnableColors } FOR i := 1 TO 7 DO4 IF i <> 4 { Skip index 4, leave it as WHITE } THENw  WITH NewMap[ i ].R DO. @ SetColorMap( i, Red, Green, Blue ); END { EnableColors } ; PROCEDURE Hibernate;O { Hibernate is called when the user presses F5; the WIINT Synergy service }eO { is used to suspend the application. This procedure is responsible for  t>aton }# WITH BatonList[ WhichBaton ] DO, BEGINx8 2IF ColorWindows <> 0 { I.e. on a Color system }   THENcM F BEGIN { Roll colors around, so as Baton moves the colors follow }e  Hue := Hue + 1;  IF Hue = 4  THEN+ Hue := 5; { Skip index 4 }n  IF Hue >= MaxColorh THEN Hue := 1;.  END { then } ;O 6SetPrimaryColor( 7 ); { Erase oldest segment by redra  } O { knowing what to do if the end-user ever changes the window size. Usually } O { this means refreshing the window based on its new width and height. In } O { this program, this is accomplished by merely re-initializing the data } O { structures used to contain the X,Y position of the Baton segments. This }RO { is done in case the window is reduced in size, such that part or all of a } O { Baton segment might fall outside the window (there is no reason why this }rO { cannot be  { does is to display a setup menu (sometimes called a property sheet) }hO { to solicit new program values from the user at the keyboard. }u VARt( "NumChanged, KeyPressed: Integer;7 \ChangedValues: PACKED ARRAY [ 1..2 ] OF 0..255; $ BEGIN { HandlePersonalizeKey }A 0h  THENRF 8 BEGIN { One or more were changed, so update things }   IF Batons < 1 THENO MaxBatons apart of the cursor, } O { the heavy hollow square. }  BEGIN { Draw }cL BSetPosition( (Index-1)*(CurSiz+Gap) + IndentX - ( Pixel DIV 2 ),5 IndentY - ( Pixel DIV 2 ) ); ? 6DrawRelLine( (Pixel + CurSiz + PixelWidth), 0 );l? 6DrawRelLine( 0, (Pixel + CurSiz + PixelHeight) );? 6DrawRelLine( -(Pixel + CurSiz + PixelWidth), 0 );h? DrawRelLine( 0, -(Pixel + C% THEN* Batons := MaxBatons; n   IF Points < 3 THEN" Points := 3;(  IF Points > MaxPoints THEN* Points := MaxPoints;L < InitBaton; { Re-start the new Batons (data structures) } END { then } ; $ END { HandlePersonalizeKey } ; b PROCEDURE HandleColorMap; O { HandleColorMap is called when the urSiz + PixelHeight) );  END { Draw } ; s BEGIN { PutCursor } O HSetPixelSize( Pixel, Pixel, Pixel DIV 2, Pixel DIV 2 ); { Fat line }eL FSetWritingMode( Erase ); { Prepare to erase any existing cursor } IF PriorIndex <> 0  THEN(L D Draw( PriorIndex ); { There was an existing cursor, erase it }! NewIndex := ColorIndex;  IF NewIndex > 3C  THENhI & NewIndex := NewIndex - 1; { Slide upauser chooses the "Color map" option } O { from the main Flow Control Menu. What this procedure does is to } O { create and process its own custom, special-purpose interface that }nO { allws the end user at the keyboard to chang+e the colors in the color } O { map.! } VARt& FunctionKey: FunctionKeyNames; NewMap: ColorMapType;a Ch: Char; & CurSiz, Gap, IndentX, IndentY, per part over index 4 } M HPriorIndex := NewIndex; { Remember new cursor position next time }xH @SetWritingMode( Replace ); { Prepare to draw the new cursor }G BSetOutputRubberBand( -1, 0, 0 ); { Disable the rubber band }  IF NewIndex <> 0  THEN M D BEGIN { There is a cursor wanted, draw it in its new position }   Draw( NewIndex );? 4 SetPosition( ( NewIndex - 1 ) * ( CurSiz + Gap ) <  4as one leaf, but the code doesn't know that. It is }pO { written such that if the frame file were changed to include more leaves } O { the code would work with them automatically. }u VARm MenuID,  OptionValue, KeyPressed: Integer;% PROCEDURE HandlePersonalizeKey;wO { HandlePersonalizeKey is called when the user chooses the "Change }'O { Batons" option from the main Flow Contr'ol Menu. What this procedure } O  ( "PriorIndex, ColorIndex: Integer;$ "MapWindow: WindowDescriptor; PROCEDURE PutCursor;O J{ PutCursor positions a semi-graphical cursor on the initial window } O J{ used in changing the color map. (Initial means the horizontal }rO J{ strip of six squares for the six colors that can be changed.) } O J{ The semi-graphical cursor is constructed as follows: First, a }MO :{ heavy black line is drawn around the square that the cur "Ι$ + IndentX + CurSiz + PixelWidth,= $IndentY + CurSiz + PixelHeight );tJ > SetOutputRubberBand( 2, ( NewIndex - 1 ) * ( CurSiz + Gap )>  + IndentX - PixelWidth,< IndentY - PixelHeight );  END { then } ;h END { PutCursor } ;  i0 ,PROCEDURE ModifyEntry( Entry: Integer );O J{ ModifyEntry manages the second, inner window portion of changing } O { L RGB <> 0  THEN I ? BEGIN { There is a new one, draw it in its new position }  Draw( NewRGB );I < SetPosition( (NewRGB-1)*(CurSiz+Gap) + IndentX + CurSiz,1 IndentY + CurSiz );;K > SetOutputRubberBand( 2, (NewRGB-1)*(CurSiz+Gap) + IndentX, 3  IndentY );a  END { then } ; " END { PutInnerCursor } ; a& PROCEDURE DisplayEditWindow;Hthe color map. This inner window has three black squares, one each }tO J{ for RED, GREEN, BLUE. This procedure allows the user to move } O J{ between the three color components, and increase or decrease their }iO { respective intensities.  }E  VAR4 ,FunctionKey: FunctionKeyNames; Ch: Char;O HEditWindow: WindowDescriptor; NewColor, OldColor: ColorDescriptor; J Level, NewRGB, PriorRGB, CurSiz,O H{ DisplayEditWindow creates the second, inner window used in "Color } O H{ map." This window has some instructions, followed by three black }iO ({ squares representing RED, GREEN, BLUE. }  CONST;I BEditHeight = 7; { Height of the inner window in text-lines }X  VAR 7 .Msg: ARRAY [ 1..EditHeight ] OF StringType;D RGBText: String;+ $LongestString, Len, i: Integer;i% BEGID& Gap, IndentX, IndentY: Integer;# PROCEDURE PutInnerCursor; O H{ PutInnerCursor positions a semi-graphical cursor on the second } O H{ window used in changing the color map. This cursor is produced } O H{ similarly to how the PutCursor procedure above produces the } O 4{ cursor for the first, outer window in "Color map." }i CONSTt9 4Pixel = 10; { Thickness of the square line }e- PROCEDURE FN { DisplayEditWindow }i   GetMessage7( EDIMSG,@ * Msg[ 1 ], Msg[ 2 ], Msg[ 3 ], Msg[ 4 ],8 " Msg[ 5 ], Msg[ 6 ], Msg[ 7 ] );N D{ Call GetMessage7 to read the instructional text from a message }N D{ frame in the frame file. GetMessage7 reads the entire frame }N F{ into a buffer, then returns the separate lines of the message. } LongestString := 0; ' &FOR i := 1 TO EditHeight DO N Draw( Index: Integer );  BEGIN { Draw }RN BSetPosition( (Index-1)*(CurSiz+Gap) + IndentX - ( Pixel DIV 2 ),7 IndentY - ( Pixel DIV 2 ) );nA 6DrawRelLine( (Pixel + CurSiz + PixelWidth), 0 );lA 6DrawRelLine( 0, (Pixel + CurSiz + PixelHeight) ); A 6DrawRelLine( -(Pixel + CurSiz + PixelWidth), 0 ); A 6DrawRelLine( 0, -(Pixel + CurSiz + PixelHeight) );  END { Draw } ;" BEH BEGIN { Compute longest string (controls width of the window) }N @Len := CountString( Msg[ i ] ); { Find the displayed length }& IF Len > LongestString  THENg(  LongestString := Len; END { for } ; M FLongestString := LongestString + 4; { Add spacers on each side }b WITH EditWindow DO< 0BEGIN { Fill in the window descriptor block }I EditWindow := WDescMode GIN { PutInnerCursor }N DSetPixelSize( Pixel, Pixel, Pixel DIV 2, Pixel DIV 2 ); { Thick }N DSetWritingMode( Erase ); { Prepare to erase any existing cursor } IF PriorRGB <> 0  THEN+H < Draw( PriorRGB ); { There is an existing one, erase it } PriorRGB := NewRGB; J @SetWritingMode( Replace ); { Prepare to draw the new cursor }I @SetOutputRubberBand( -1, 0, 0 ); { Disable the rubber band }} IF New l; { Init the bulk of it }eI Width + := LongestString * CharacterWidth;iJ Height *:= ( EditHeight + 1 ) * CharacterHeight;A X # := -32760; { Window centered }gD Y % := ( 8 * CharacterHeight ) - 2048;* Flags.Stackable := True;* Flags.Color := True;+ Flags.Titled := False;i* Flags.WhiteBorder := True;  { Display the RGB window } REPEATO FEnableColors( NewMap ); { Refresh color map with current choices }M FPutInnerCursor; { Draw the cursor wherever it's supposed to be }:L BFlushGIDIS; { Flush pending output prior to any keyboard wait }C :KBASTInitialize; { Attach the keyboard for AST input }x? 6FunctionKey := GetAKey( Ch ); { Read a keystroke } F FPVDetach; { Detach. This also flushes the GIDIS buffer } 6  END { then } ; M UNTIL ( FunctionKey = Exit ") { Signals that the user is }tM D OR ( FunctionKey = SuspendKey ) { done changing this color }LM 1 OR ( FunctionKey = MainScreenKey ); { index now.  }=% IF FunctionKey = SuspendKeyN F THEN SuspendRequested := True { Set flag, we'll get it next time }  ELSE + " IF FunctionKey = MainScreenKeyE/ $THEN MainScreenRequested := True; END { with } ;L DFlushGIDIS; { Flush any pending output to first, outer window }J BWICRW( XStatus, DescriptorLength, EditWindow ); { Create it }J DFillText( EditHeight, Msg ); { Write the text strings to it } E NewRGB := 1; { The cursor will start on the RED square } 9 2PriorRGB := 0; { There is no existing cursor },J BCurSiz := CharacterWidth * 4; { Compute some layout values }* "Gap := CharacterWidth * 4;@ 8IndentX := CharacterWidth * 14 - ( PixelWidth * 3 );* $IndentY := CharacterHeight * 4;: 2SetOutputRubberBand( -1, 0, 0 ); { Disable it }8 DisplayEditWindow; BctionKey = Down )   THENeL @ BEGIN { The component saturation was changed, check it out }  CASE NewRGB OFNO @ 1: NewColor.Red := Level; { Remember the new level for }EO 4 2: NewColor.Green := Level; { whichever component }oO @ 3: NewColor.Blue := Level; { (R,G,B) the cursor is on. }d  END { case } ;eM > NewMap[ Entry ].R := NewColor; { Update color map with it }n 0{ for } ;iK FLongestString := LongestString + 4; { Add spacers on each side }e WITH MapWindow DO : 0BEGIN { Fill in the window descriptor block }G MapWindow + := WDescModel; { Init the bulk of it }dI Width  := LongestString * CharacterWidth;iJ Height ,:= ( WindowHeight + 1 ) * CharacterHeight;? X # := -32763; { Screen centered }L6 Y  := S.Key := GetAKey( Ch ); { Read a keystroke }DD @PVDetach; { Detach. This also flushes the GIDIS buffer } p@ :CASE FunctionKey OF { Now process the resulting key } SuspendKey,  MainScreenKey,6 Exit: !; { Nothing to do right yet }1 (Right: IF ColorIndex = MaxColorN 6THEN SoundBell { Can't move right from 6th square } ELSE- IF ColorIndex = 3iH8creenHeight DIV 8;( Flags.Stackable := True;( Flags.Color := True;) Flags.Titled := False;F( Flags.WhiteBorder := True; END { with } ;M HFlushGIDIS; { Flush output to current window before creating new }eO JWICRW( XStatus, DescriptorLength, MapWindow ); { Create the window }hN JFillText( WindowHeight, Msg ); { Write the text strings in window } e$ SetWritingMode( Replace );= #c . THEN ColorIndex := 5 { Skip over index 4 }O 8 ELSE ColorIndex := ColorIndex + 1; { Move right }N* Left: IF ColorIndex = 1M 6THEN SoundBell { Can't move left from 1st square }t ELSE- IF ColorIndex = 5 M 4 THEN ColorIndex := 3 { Skip back over index 4 } N * ELSE ColorIndex := ColorIndex - 1; { MovgC FlushGIDIS; { Flush any remaining output to this window }B WindowHeight = 9; { Number of lines the window is tall }y  VARu7 0Msg: ARRAY [ 1..WindowHeight ] OF StringType;w i, Len,h! LongestString: Integer;n BEGIN { DisplayColors }p GetMessage9( COLMSG,4 Msg[ 1 ], Msg[ 2 ], Msg[ 3 ],4 Msg[ 4 ], Msg[ 5 ], Msg[ 6 ],6 " Msg[ 7 ], Msg[ 8 ], Msg[ 9 ] );L { Call GetMessage9 to read the "DrawRelLine( 0, -CurSiz ); EndFill; END { for } ;e SetPrimaryColor( 0 );e @END { DisplayColors } ;F BEGIN { HandleColorMap }N HNewMap := ColorMap; { Init new map values with the current ones }G BColorIndex := 1; { The cursor will start on the first square }o9 4PriorIndex := 0; { There is no existing cursor } * $CurSiz := CharacterWidth * 4;* Gap := CharacterWidth * 3;1 & instructional text from a message }L D{ frame in the frame file. GetMessage9 reads the entire frame }L F{ into a buffer, then returns the separate lines of the message. } LongestString := 0;:' FOR i := 1 TO WindowHeight DOrK BBEGIN { Compute longest string (determines the window width) } - "Len := CountString( Msg[ i ] );,$ IF Len > LongestString  THEN &  LongestString := Len; END   ,IndentX := CharacterWidth * 11 DIV 2; 1 .IndentY := CharacterHeight * 11 DIV 2;K HDisplayColors; { Create the outer colormap window with 6 squares }  REPEATI BEnableColors( NewMap ); { Make sure the color map is current }rB WindowHeight = 9; { Number of lines the window is tall }  VAR 7 0Msg: ARRAY [ 1..WindowHeight ] OF StringType;R) $i, Len, LongestString: Integer;n# BEGIN { DisplayLineWindow }i GetMessage9( LTHMSG,4 Msg[ 1 ], M@ CornerY: Integer; BEGIN { ShowLines } N FBoxSiz := CharacterWidth * 13; { Determine how large it will be }* "CornerX := CharacterWidth * 31;) $CornerY := CharacterHeight * 2; F >SetOutputClippingRegion( CornerX, CornerY, BoxSiz, BoxSiz );C >EraseClippingRegion; { Get rid of any old sample Baton }D  4OTHERWISE SoundBell; { Ignore all other keys } END { case } ;L UNTIL ( FunctionKey = Exit ") { Signals that the user is }L D OR ( FunctionKey = SuspendKey ) { done changing all color }L & OR ( FunctionKey = MainScreenKey ); sg[ 2 ], Msg[ 3 ],4 Msg[ 4 ], Msg[ 5 ], Msg[ 6 ],6 " Msg[ 7 ], Msg[ 8 ], Msg[ 9 ] );L D{ Call GetMessage9 to read the instructional text from a message }L D{ frame in the frame file. GetMessage9 reads the entire frame }L F{ into a buffer, then returns the separate lines of the message. } LongestString := 0;t' FOR i := 1 TO WindowHeight DOoJ FlushGIDIS; { Flush any remaining output to this window }? 8WIDSW( XStatus, MapWindow.ID ); { Destroy the window }  x }- "Len := CountString( Msg[ i ] ); $ IF Len > LongestString  THENg&  LongestString := Len; END { for } ;cK HLongestString := LongestString + 4; { Add spacers on each side }  d WITH LineWindow DO: 0BEGIN { Fill in the window descriptor block }G LineWindow *:= WDescModel; { Init the bulk of it }dI Width  := LongestString * CharacterWidth; J N0  THENB/ $ Col := 1; { Cycle back to 1 }C! IF ColorWindows = 0 E : THEN SetPrimaryColor( 0 ) { Black if monochrome } E < ELSE SetPrimaryColor( Col ); { Else use proper color } $ SetPosition( X1, Y1 );$ DrawLine( X2, Y2 );@ 4X1 := X1 - 28; { Move the Baton along its track } Y1 := Y1 + 10; X2 := X2 + 30; Y2 := Y2 + 35; END { for } ;  THENE *BEGIN { Reduce Y thickness (Shorter) } 7 Hi := Hi - PixelHeight;IN 0IF ( KBBuf.Count = 0 ) OR ( Hi = PixelHeight )%  THEN -  ShowLines; * END { Up } ; & Down: IF Hi < 200  THENF "BEGIN { Increase Y thickness (Tal= 8SetPrimaryColor( 0 ); { Back to drawing in black }C WITH LineWindow DOL DSetOutputClippingRegion( 0, 0, Width, Height ); { Full window } BEND { ShowLines } ;y o# BEGIN { HandleLineThickness }M JDisplayLineWindow; { Create the display and its instructional text } D >EnableColors( ColorMap ); { Refresh the hardware colormap }J FShowLines; { Draw the sample Baton using current line thickness }, WITH ContextBlock.R.7ler) }7 Hi := Hi + PixelHeight; G *IF ( KBBuf.Count = 0 ) OR ( Hi >= 200 ) %  THEN -  ShowLines;x, END { Down } ;F :CancelKey: BEGIN { Reset to original line thickness }+  Low := OldLow;n*  Hi := OldHi;J . ShowLines; { And display it that way again }LineThickness DO/ (BEGIN { Remember current thickness }C OldLow := Low; OldHi := Hi;C END { with } ;?  6CASE FunctionKey OF { Now process the keystroke } Susp.  END { CalcelKey } ;% OTHERWISE SoundBell;  END { case } ;M UNTIL ( FunctionKey = Exit $) { These keys signal that the } M F OR ( FunctionKey = SuspendKey ) { user is done changing the } M H OR ( FunctionKey = MainScreenKey ); { line thickness for now. } # IF FunctionKey = SuspendKey O J THEN SuspendRequested := True { Set flag, so we'll get it next time }A   ELSEh)  IO endKey,c MainScreenKey,2 Exit: ; { Nothing to do now }. Left: IF Low > PixelWidth  THENF *BEGIN { Reduce X thickness (Narrower) }8 Low := Low - PixelWidth;N 0IF ( KBBuf.Count = 0 ) OR ( Low = PixelWidth )%  THEN K 4 ShowLines; { Update display if needed } ,  F FunctionKey = MainScreenKeyE- &THEN MainScreenRequested := True; * &PVDetach; { Detach the keyboard }M JWIDSW( XStatus, LineWindow.ID ); { Destroy "Line thickness" window } , &WITH ContextBlock.R.LineThickness DO( BEGIN { Invoke the new line }9 2SetPixelSize( Low, Hi, Low DIV 2, Hi DIV 2 ); J @IF ( Low < OldLow ) OR ( Hi < OldHi ) { New line is smaller }  THEN B * InitBaton; { Start them over to erase ol 0 := CornerX + BoxSiz; { Init the starting }: Y1 := CornerY; { position of the }: X2 := CornerX; { sample Baton. } Y2 := CornerY + 80; Col := 0; E >FOR i := 1 TO 8 DO { The sample Baton is 8 segments long };, "BEGIN { Draw the next segment } Col := Col + 1;  IF Col = 4  THENs2 $ Col := 5; { Skip color index 4 } IF Col = MaxColor   c- END { Left } ;' Right: IF Low < 200t  THENE *BEGIN { Increase X thickness (Wider) } 8 Low := Low + PixelWidth;H *IF ( KBBuf.Count = 0 ) OR ( Low >= 200 )%  THEN0-  ShowLines; - END { Right } ; . Up: IF Hi > PixelHeight N d debris } END { with } ;# END { HandleLineThickness } ;e  BEGIN { HandleFCMKey }N PVDetach; { Detach keyboard to allow Synergy to operate the Flow Menu }B EXFLOW( XStatus, KeyPressed, MenuID, { Process the Flow }B OptionValue, QIXFCM, { Control Menu. }- Ord( InputKey ) - Ord( F11 ) );(L IF ( KeyPressed = PV$DO ) { A successfull terminator was pressed, }L OR ( KeyPressed = PV$RET ) { see which option HN AddOptnsKey: HandleFCMKey( InputKey ); { Process Flow Menu request }+ InsertHere: IF Batons < MaxBatonsu  THENiM 8 BEGIN { Not at max, increase the number of Batons } 0  Batons := Batons + 1;B * InitBaton; { Re-start the new Batons }' : END { then } ; # RemoveKey: IF Batons > 1b  THEN M  BEGIN { Not at m was chosen. } THEN;  CASE OptionValue OF)  1:  IF ColorWindows = 0A . THEN EXMESS( XStatus, KeyPressed, NOCOLR )FH 6 ELSE HandleColorMap; { Go change the color map }E  2: 5 HandlePersonalizeKey; { Go change the Batons }}M  3: = HandleLineThickness; { Go change the line thickness } &  OTHERWISE { Do Nothing } ; 2 END { case } ;e IF KeyPressed = PV$F5oJ&&in, decrease the number of Batons }y0  Batons := Batons - 1;B * InitBaton; { Re-start the new Batons }' END { then } ;o6 OTHERWISE SoundBell; { Ignore all other keys } END { case } ; END { HandleKey } ;  BEGIN { Baton }B: InitializeSyn; { Set up basic environmental things. }: MakeOurWindow; { Create the playing field. }: InitBaton; .{ Init the Baton data structures. }: KBAS\Z THEN SuspendRequested := True { Set flag, we'll get it next time } ELSE   IF KeyPressed = PV$MAI + THEN MainScreenRequested := True;e? KBASTInitialize; { Reattach the keyboard for AST input }n END { HandleFCMKey } ; 2 BEGIN { HandleKey }lE FlushGIDIS; { Flush pending output prior to any keyboard input }c IF SuspendReqguestedn THEN O BEGIN { F5 was pressed when we were in the middle of something before }F8 InputKey TInitialize; { Attach the keyboard for AST input. }1 SuspendRequested := False; { Clear a few } 1 MainScreenRequested := False; { variables. }  Done := False;  TitleCounter := 0;d+ REPEAT { This is the main program loop }}F WHILE ( KBBUF.Count <> 0 ) { If any keys have been pressed, }F OR SuspendRequested { or F5 was pressed a ways back, }F OR MainScreenRequested DO { or MAIN SCREEN a ways back, }F HandleKey; & := SuspendKey; { Fake an F5 }< z SuspendRequested := False; { Dismiss the request } END { then }A ELSE  IF MainScreenRequestede  THENN FBEGIN { MAIN SCREEN was pressed in the middle of something before }I InputKey ,:= MainScreenKey; { Fake a MAIN SCREEN }uB 8MainScreenRequested := False; { Dismiss the request } END { then }  ELSEH 8InputKey := GetAKey( InputChar ); { Read the REAL keyst { go process them. < } FOR i := 1 TO Batons DOFF TwiddleBaton( i ); { Move each Baton a cycle. } IF ColorWindows <> 0 THENK BEGIN { On a color system, rotate the colors to follow the Batons }}  FOR i := 1 TO 5 DO0( BEGIN { Roll the color map }, " Index := i + ColorMapIndex - 1;  IF Index > 3 THEN4 (Index := Index + 1; { Skip over 4 }!  I roke } CASE InputKey OF Exit, C MainScreenKey: Done := True; { Set a flag so we will exit }eN SuspendKey: Hibernate; { Give control up to the Synergy Main Menu } HelpKey: BEGINhJ 4PVDetach; { Free the keyboard for Synergy's use }A ,EXHELP( XStatus, OVERVW ); { Give HELP }FI 4KBASTInitialize; { Get the keyboard back again } $ &END { help } ; F11, F12, F13, ϓF Index >= MaxColoro THEN& BEGIN { Wrap around }4 $Index := Index - ( MaxColor - 1 ); IF Index > 3  THENEE 4 Index := Index + 1; { Skip over 4, after wrap }B END { then } ;(  WITH ColorMap[ Index ].R DO IF i <= 3; .THEN SetColorMap( i, Red, Green, Blue ) M BELSE SetColorMap( i + 1, Red, Green, Blue ); { Skip over 4 }  \P:.! Frame file for the Synergy demonstration program "Baton .! Twirler".G.!"---B.! First is the vector table containing the frames that the source7.! code refers to directly. Add new frames to the end..TABLE.COLMSG, DEFQ, EDIMSG, FERROR, LTHMSG, NOCOLR5NOWIND, OTSERR, OVERVW, QIXFCM, RGBMSG, TITLE, TITLE2G.!"--.-A.! This frame contains text strings used o`-200):\ 2 NumericString \ SkipE.Press \$32+{EXIT}\$32- to accept values.\ SkipG.!#--A.! This frame contains text strings used on the RGB color editing A.! window. This frame must have EXACTLY seven (7) lines of text.e.Frame EDIMSG Messagen5Choose red, green, or blue with the \$32+{l}\$32- andnH\$32+{r}\$32- keys. Use \$32+{u}[\$32- and \$32+{d}\$32- to increase anddecrease the RGB components.\ ! (must be blank)3  END { for } ;, & ColorMapIndex := ColorMapIndex - 1;  IF ColorMapIndex <= 0 THEN; ColorMapIndex := MaxColor - 2; { Wrap around }  END { then } ;  7 IF ( TitleID = TITLE2 ) AND ( TitleCounter < 1000 ) THEN O BEGIN { So the Welcome title is up (must be the first time we've run) } K H TitleCounter := TitleCounter + 1; { Increment a timeout counter }   IF TitleCounter = 1000r THENO BEGIqn the Color Map window. 7.! This frame must have EXACTLY nine (9) lines of text.-.Frame COLMSG Message-  \$3+Edit Colors\-AChoose the color to edit with the \$32+{l}\$32- and \$32+{r}\$32-r8keys, and press \$32+{DO}\$32- to edit the chosen color.\ ! (must be blank) \ ! (must be blank)R\ ! (must be blank)I\ ! (must be blank)I4 4\$3+Press \$32+{EXIT}\$32- to accept values.G.!"---tB.! This frame de5N { The Welcome Title's time limit (1000 cycles) has  }eO @ { expired, so change the title to the normal title. (1000 } O  { loops takes 30-40 seconds.) }D; 0ReadMessage( TITLE, TitleLength, TitleText );BC :PVDetach; { Free the terminal/keyboard for Synergy } N DWITTL( XStatus, TitleLength, TitleText ); { Set the new title }B 4KBASTInitialize; { Get the terminal/keyboard back }scribes the "Color map" option on the Flow Control5.! Menu (which is itself stored in the frame QIXFCM).g.Frame CMHELP Help&.Home Column:Window:Off Row:Window:Off* \$3+Color Map\ < INDEX\0When run on a color system, the Batons are drawn2in color. Six separate colors are used, producing0a travelling ribbon with the moving Batons. You2can control the individual 6 colors that are used.\-'Press \$32+{RESUME}*\$32- to leave HELP.-.Options Rows:1-\ Skipr\  END { then } ; END { then } ; K UNTIL Done; { Done is set to True when MAIN SCREEN or EXIT are pressed }lG CleanUpSyn; { Tidy up after ourselves, and tell Synergy we're done } O { Once all this is done, when the "END." is reached below, PRO/Pascal will } O { terminate the running of this task. Since this is the first and only } O { task in the application, when it terminates, the Synergy Window Manager } O { will be notified by P/OS. Control will thus p[ $ SkipCHELP index\ > INDEXG.!"---a9.! This frame describes "Change Batons" on the Flow Menu. .Frame CQHELP Help&.Home Column:Window:Off Row:Window:Off+ \$3+Change Batons\ < INDEXx\p/This option displays a set-up menu that enablesb.you to change how many individual Batons there,are, and to change how long their tails are.\$AYou can also press \$32+{INSERT HERE}\$32- and \$32+{REMOVE}\$32-ito add ^ass back to the Synergy }O { Main Menu (Window Manager), ready for another application to be run. } END { Baton } . G CleanUpSyn; { Tidy up after ourselves, and tell Synergy we're done } O { Once all this is done, when the "END." is reached below, PRO/Pascal will } O { terminate the running of this task. Since this is the first and only } O { task in the application, when it terminates, the Synergy Window Manager } O { will be notified by P/OS. Control will thus p W or subtract Batons.\d'Press \$32+{RESUME}\$32- to leave HELP.-.Options Rows:1-\ Skip-\ #Skip HELP index\ > INDEXG.!"---oB.! This is the setup menu that controls how many Batons there are..Frame DEFQ Setups,.Home Column:Window:Center Row:Window:Center\$3+Choose how many and of whatd\$3+size Batons you want.a.Options Columns:1+Number of Batons (1-10):\ 1# NumericStringR+Length of tails (3 Ϗ:enUse the arrow keys to changethe line thickness:aA  \ ! Space for picture.n \$4+Short V \$32+{u}\$32-D \$4+Narrow\$4- \$32+{l}\$32- \$32+{d}\$32- \$32+{r}\$32- \$4+Wide D \$4+Tallx\>,\$3+Press \$32+{EXIT}\$32- to accept values.G.!"--t-sA.! This message frame must contain two lines of text; they can benA.! at most 40 printing characters long (80 tram might give a?.! context-sensitive HELP frame about; so general introductory-p.! type HELP is given..Frame OVERVW Help&.Home Column:Window:Off Row:Window:Off- \$3+Overview of Baton Twirler.\ 7Welcome to the Synergy demonstration application, Baton-8Twirler. At any time while the Batons are twirling, you?can press \$32+{F5}\$32- to temporarily pause Baton Twirler and4return to the Synergy Main Menu (and Ethen change the?window size or move it around). Pressing \$32+{EXITJotal). The lines aree>.! displayed in an error window by the FatalError() procedure..Frame FERROR MessagefB.!34567890123456789012345678901234567890 Ruler for 40 columns.$ This application has encountered% the following unexpected proble m -- G.!#--@.! This message is displayed if the user chooses the "Color map"@.! option on the Flow Control Menu, when color is not available..Frame NOCOLR Messagea,.Home Column:W}\$32- willi7stop Baton Twirler and return to the Synergy Main Menu.n\d@You can also press \$32+{F11}\$32-, which will display a menu of9options that enable you to modify the Batons in a varietywof ways.\r'Press \$32+{RESUME}\$32- to leave HELP.a.Options Rows:1 \ Skipt\ Skip \ #Skip,HELP index\ > INDEXG.!"--P-M6.! This is the main Flow Control Menu for the program..Frame QIXFCM Flowj\ ! (must be blank)r\ ! (must be blank)r3 \$3+Press \$32+{EXIT}\$32- to accept values.-G.!"--- >.! This HELP frame is the main HELP Index for the application..Frame INDEX Helps&.Home Column:Window:Off Row:Window:Off\$3+Baton Twirler HELP Index.Options Columns:2 Rows: 6.! First column of entries:}The Flow Menu\ > SAMPLE CShange Batons\ > CQHELPr Line thickness\ > LTHELP Color map\ > CMHELP\ ! indow:Center Row:Window:Center.Keys RESUME, RETURN, DO, ENTERF+Because your system is not running in colorf*right now, you cannot manipulate the color+map. If your Professional does have an EBOi+option and a color monitor, and you want tod5use color, tell Synergy by pressing \$32+{SETUP}\$32--from the Synergy Main Menu.-\-%Press \$32+{RESUME}\$32- to continue.sG.!"--:- B.! This message frame must contain one line of text; tEmpty spacer.eAnother Topic\ > SAMPLE.! Second column of entries:More Topics\ > SAMPLE Suspending\ > SAMPLE- Exiting\ > SAMPLE Window size\ > SAMPLE\ ! Empty spacer.a\ ! Empty spacer.nG.!"---i:.! This frame describes "Line thickness" on the Flow Menu..Frame LTHELP Help&.Home Column:Window:Off Row:Window:Off, L \$3+Line Thickness\ < INDEX\e/The Batons are initially drawn with thin lhis line canB.! be at most 40 printing characters long (80 total). The line is@.! displayed in an error window if the program cannot create its .! main window (for any reason)..Frame NOWIND MessagepB.!34567890123456789012345678901234567890 GRuler for 40 columns.' Cannot create the application window.nG.!#--tB.! This message frame must contain one line of text; this line canB.! be at most 40 printing characters long (80  6ines. 1This option lets you change the pen or brush thatu0the lines are drawn with. The size of the brush+in X and Y can be controlled independently.d\s'Press \$32+{RESUME}\$32- to leave HELP. .Options Rows:1\ Skip-\ #Skip-HELP index\ > INDEXG.!"--->.! This frame contains text strings used on the Line Thickness@.! window. This frame must have EXACTLY nine (9) lines of text..Frame LTHMSG Messag  total). The line isA.! displayed in an error window if the program ever blows up withs.! some unexpected error fault.p.Frame OTSERR MessageB.!34567890123456789012345678901234567890 Ruler for 40 columns.$ Something has really gone wrong !G.!#--B.! This HELP frame is displayed if the user presses HELP while the@.! program is in "free-running" mode. In this case, there is no:.! specific state or context that the prog jareavailable in the Synergy fonts.\-0Here is a sample use of renditions: You can useH\$3-Dim\$1+, Normal and \$3+bold\$2- intensities plus \$8+underline\$8-,= \$4+Italic\$4- and \$16+ Hilight \$16- for emphasis, and for :keyboard function key notation the \$32+{BOXED}\$32- font.\L'Press \$32+{RESUME}\$32- to leave HELP.h.Options Rows:1 \ Skipg\ Skip HELP index\ > INDEX.G.!"--&-c>.! This message line is the title ascal form of the function header is:s ;7 ; FUNCTION GetAKey( VAR Ch: Char ) : FunctionKeyNames; ;B ; The FunctionKeyNames type is an enumerated list of the possible! ; recognized function key names.;% ; Save all needed scratch registers:t# MOV R1, -(SP) ; Pointer to KEYTAB $ MOV R2, -(SP) ; Character counter., MOV R3, -(SP) ; String comparison results.' MOV R4, -(SP) ; Input buffer pointer. 2 CLR 14(SP) ; Set function return value to text.% CLR R2 ; No characters parsed yet.e.Lfor the main program window..Frame TITLE MessageBaton Twirler\G.!"---u@.! This message line is the secondary title for the main program;.! window. This title is only used the VERY first time theBA.! application is run, and then ONLY for the first thirty secondstB.! or so that the program runs; after that time is up, qthe program<.! changes the title to use the text in frame TITLE (above)..Frame TITLE2 Messagee'Baton TwirleU MOV #INBUF-1,R4 ; Point at the input buffer..K.LOOP: ; Check the next byte in the sequence.& MOV #KEYTAB,R1 ; Point to Key Table.: CMPB (R4)+, (R2)+ ; Advance to next free byte; count it.6 MOV R4, -(SP) ; Addr of next free byte in input buf.+ JSR PC, ReadKB ; Read the next character.-510$: JSR PC, K.CMP ; Compare INBUF to table element.m, ; R3 is set: 0-no match 1-abbr. 2-equal TST R3 ; Complete non-match?e- BNE 30$ ; No, either abbreviated or exact.o8 ADD #ElSize,R1 ; Non-mZLr (press HELP for details)\..Frame TITLE MessageBaton Twirler\G.!"---u@.! This message line is the secondary title for the main program;.! window. This title is only used the VERY first time theBA.! application is run, and then ONLY for the first thirty secondstB.! or so that the program runs; after that time is up, qthe program<.! changes the title to use the text in frame TITLE (above)..Frame TITLE2 Messagee'Baton Twirleatch. Check next table element.$ TSTB (R1) ; End of table reached? BPL 10$ ; No, so continue.M2 CMP R2, #1 ; So non-match. This the first char?( BNE 20$ ; No, so it's an invalid key.< MOVB (R4), @12(SP) ; First byte means text key, return it. BR K.DONE ; Exit.?20$: MOV #KYINVL,14(SP) ; Invalid keystroke, return that type.b BR K.DONE ; Exit.30$: CMP R3, #1 ; Abbreviated?l2 BEQ K.LOOP ; Yes, continue checking characters.9 MOVB (R1), 14(SP) ; Exact! Return the FunctionKeyNa'.Home Column:Screen:Left Row:Screen:Topr.Options Rows:1i Personalize%.Options Columns:1 ! Personalize Menu Change Batons\ 2 ?CQHELPiLine thickness\ 3 ?LTHELPColor map\ 1 ?CMHELPtG.!"---;.! This message contains exactly one line, of exactly threeEB.! characters. The characters are the labels to apply to the RED,A.! GREEN, BLUE color component squares that the editing window of #.! the "Color map" option displays.w<! Indirect Command File to build the sample Synergy program.J! This command file assumes that the frame file BATONFRMS.SFF has been runM! through the Frame Compiler Tool to produce BATONFRMS.PAS and BATONFRMS.OFF.J! (To do this, invoke FCT and specify "BATONFRMS" as the file to compile.)!F! You invoke this command file by typing @BUILD from PRO/Tool Kit DCL.!PASCAL Baton/NoDebug/NoCheckPASCAL GIDIS/NoDebug/NoCheck MACRO GetAKey MACRO KBServMACRO ReadMesg! LINK @Baton g(.Frame RGBMSG MessagetRGB\G.!"--j-i$.! This HELP frame is just a sample..Frame SAMPLE Help&.Home Column:Window:Off Row:Window:Off. \$3+Sample HELP Frame\ < INDEX\-2This is a sample Synergy HELP frame that shows the/sorts of things that can be done in any Synergyc1frame (HELP, menu, setup, etc.). First, here's a 2sample use of the DEC Multinational () and+Special Graphics characters that  6 .ENABL LC, GBL ; Enable lower case, default global.$ .TITLE GETKEY Get Keystroke from TT=GETAKE::; GetAKey reads the next keystroke from the keyboard.' ; The calling sequence for GetAKey is: ;2 ; CLR -(SP) ; Allocate space for function value.4 ; MOV #Ch, -(SP) ; Address of the text key pressed.' ; JSR PC, GETAKEY ; Call the function. ;D ; On return, the Ch parameter will be poped from the stack, but theA ; function return value will still be the top word on the stack. ;- ; The P  ; R3 0: No match at all. 1 ; 1: User's string abbreviates Table element.V1 ; 2: User's string is exact match of element.o2 MOV R1, -(SP) ; Save the original Table pointer.+ MOV R4, -(SP) ; Pointer to user's string.  MOV R5, -(SP) ; Loop counter.r CLR R5 ; Clear loop counter.n0 INC R1 ; Skip over the FunctionKeyName value.* MOV #INBUF, R4 ; Start of user's string. CLR R3 ; Assume no match.310$: INC R5 ; Increment the bytes compared count.r4 CMP R5, #ElSize ; Run thHASCII <233>/2~ / ; Insert Here.% .ASCII <233>/3~ / ; Remove.A% .ASCII <233>/4~ / ; Select.K. .ASCII <233>/5~ / ; Previous Screen.* .ASCII <233>/6~ / ; Next screen.$ .ASCII <233>/13~ / ; Break.% .ASCII <233>/14~ / ; Set-up.I! .ASCII <233>/15~ / ; F5.1( .ASCII <233>/17~ / ; Interrupt.% .ASCII <233>/18~ / ; Resume. % .ASCII <233>/19~ / ; Cancel.P* .ASCII <233>/20~ / ; Main Screen.# .ASCII <24rough whole table element? BLO 30$ ; Not yet.t'20$: MOV #2, R3 ; Yes, so exact match.  BR 50$ ; Done.x030$: CMP R5, R2 ; Has the input string run out? BLOS 40$ ; No, not yet.. CMPB (R1), #40 ; Yes. End of table element?* BEQ 20$ ; Yes! That means exact match.* MOV #1, R3 ; No, so abbreviation so far. BR 50$ ; Exit. 540$: CMPB (R1)+, (R4)+ ; Compare the next two bytes.R/ BEQ 10$ ; They match, go check the next two.n(50$: MOV (SP)+, R5 ; Restore registers. MOV (SP)+33>/21~ / ; Exit.3" .ASCII <233>/23~ / ; F11." .ASCII <233>/24~ / ; F12." .ASCII <233>/25~ / ; F13.1 .ASCII <233>/26~ / ; Additional Options. # .ASCII <233>/28~ / ; Help..! .ASCII <233>/29~ / ; Do." .ASCII <233>/31~ / ; F17." .ASCII <233>/32~ / ; F18." .ASCII <233>/33~ / ; F19." .ASCII <233>/34~ / ; F20. .BYTE 200 ; End of table.;ElSize = 6 ; Six bytes per table element (five data bytes).e  .ASECTK$. = 0 , R4 MOV (SP)+, R1 RTS PC ; Done.N yNKEYTAB: ; This is the table for the function key list. The first byte of eachE ; element is the FunctionKeyNames value for the keystroke. The nextPD ; five bytes are the character sequence generated by the keystroke.G ; The order of the elements in the table is not important. Leading or G ; embedded spaces are illegal. The string must be padded with spaces.$: ; The FunctionKeyNames values must be [ 0..127 ] decimal.H ; Currently, the keyboard table o; Define the key token values..KYTEXT: .BLKB ; ASCII text key (must be zero).KYTAB: .BLKB ; Tab.K KYRETN: .BLKB ; Carriage return.KYFIND: .BLKB ; Find.dKYINHE: .BLKB ; Insert Here.KYREMV: .BLKB ; Remove..KYSELC: .BLKB ; Select.9 KYPREV: .BLKB ; Previous screen.KYNEXT: .BLKB ; Next screen.KYBRK: .BLKB ; Break keyKYSETU: .BLKB ; Set-Up.1 KYSUSP: .BLKB ; Suspend key (F5)KYINTR: .BLKB ; Interrupt keyaKYRESM: .BLKB ; Resume.tKYCNCL: .BLKB ; Cancel.eKYMAIN: .BLKB ; Main ScreenKYEX/nly contains 8-bit definitions for the8 ; keys; one could add the 7-bit equivalents if desired.& .ASCII <11>/ / ; Tab Key.6 .ASCII <15>/ / ; The Carriage Return key.- .ASCII <177>/ / ; The delete key.g' .ASCII <217>/p / ; Keypad 0. ' .ASCII <217>/q / ; Keypad 1.t& .ASCII <217>/r / ; Keypad 2' .ASCII <217>/s / ; Keypad 3.p' .ASCII <217>/t / ; Keypad 4.s' .ASCII <217>/u / ; Keypad 5.h' .ASCII xIT: .BLKB ; Exit.tKYF11: .BLKB ; F11.TKYF12: .BLKB ; F12.kKYF13: .BLKB ; F13.Y#KYADOP: .BLKB ; Additional Options.aKYHELP: .BLKB ; Help. KYDO: .BLKB ; DO.NKYF17: .BLKB ; F17.rKYF18: .BLKB ; F18.eKYF19: .BLKB ; F19. KYF20: .BLKB ; F20.BKYPF1: .BLKB ; PF1..KYPF2: .BLKB ; PF2.tKYPF3: .BLKB ; PF3.BKYPF4: .BLKB ; PF4. KYUP: .BLKB ; Up arrow. KYDOWN: .BLKB ; Down arrow.NKYRGHT: .BLKB ; Right arrow.KYLEFT: .BLKB ; Left arrow.LKYDELT: .BLKB ; Delete.NKYREFR: .BLKB ; Screen ref me.h3K.DONE: MOV (SP)+, R4 ; Restore scratch registers.l MOV (SP)+, R3 MOV (SP)+, R2 MOV (SP)+, R17 MOV (SP)+, (SP) ; Pop the VAR Ch parameter off stack.; RTS PC ; Return.i eIK.CMP: ; K.CMP compares the string of bytes that has been read in so far,E- ; to the Key Table element pointed to by R1.k ; ; Data Passed: / ; R1 Address of a Key Table element to match.;1 ; R2 Length of the bytes string so far read in.i, ; INBUF Address of the user's byte string. ; ; Data returned:a :<217>/v / ; Keypad 6.n' .ASCII <217>/w / ; Keypad 7.e' .ASCII <217>/x / ; Keypad 8. ' .ASCII <217>/y / ; Keypad 9.K' .ASCII <233>/A / ; Up arrow..) .ASCII <233>/B / ; Down arrow.k* .ASCII <233>/C / ; Right arrow.) .ASCII <233>/D / ; Left arrow.1" .ASCII <217>/P / ; PF1." .ASCII <217>/Q / ; PF2." .ASCII <217>/R / ; PF3." .ASCII <217>/S / ; PF4.# .ASCII <233>/1~ / ; Find.A* . xresh.BKYAP0: .BLKB ; Keypad 0.KYAP1: .BLKB ; Keypad 1.KYAP2: .BLKB ; Keypad 2.KYAP3: .BLKB ; Keypad 3.KYAP4: .BLKB ; Keypad 4.KYAP5: .BLKB ; Keypad 5.KYAP6: .BLKB ; Keypad 6.KYAP7: .BLKB ; Keypad 7.KYAP8: .BLKB ; Keypad 8.KYAP9: .BLKB ; Keypad 9.KYINVL: .BLKB ; Invalid key.B .PSECT ED$DAT, D, RW, GBL, CON ; Separate Psect to hold the data.+INBUF: .BLKB ElSize-1 ; Mini-input buffer.K .EVEN .END ; End of GETAKEY.MACwKYDELT: .BLKB ; Delete.NKYREFR: .BLKB ; Screen ref#the rest of this module depends on. }t BEGIN { InitializeSyn } F State.CursorOn := False; { The graphics cursor is initially off }J ASCIIQIOdpb := QIOdpbModel; { Initialize the Directive Parameter }J QIOdpb ^ := QIOdpbModel; { Blocks for the output QIOWs. } WITH QIOdpb DO BEGINu< 6Q_IOPL[ 1 ] := ( Address( GIDISBuffer ) )::Unsigned;A XQ_IOPL[ 2 ] := 0; { Set the length of the data to zero }  END { with } ;  MODULE GIDIS;O%Include 'GIDISOps/NoList' { Contains declarations needed for GIDIS routines }O%Include 'Synergy/NoList' { Contains declarations for Synergy services }CONST { Structured constants }B QIOdpbModel = QIOdpbType( QIOW,# QIOW_Len, IO_WSD, 5, 1, 0, 0, 0,8 ( 0, 0, 0, SD_GDS, 0, 0 ) );VARE XCharacterHeight: [Global(CHARHI)] Unsigned; { Returned by WIINI }E XCharacterWidth: [Global(CHARWI)] Unsigned; { Returned by WIINI }= ASCI|$WITH ASCIIQIOdpb DOd BEGINn Q_IOFN := IO_WAL;< 6Q_IOPL[ 1 ] := ( Address( ASCIIBuffer ) )::Unsigned;A 0 THEN - BEGIN { Ther$IBuffer: [Global] PACKED ARRAY [ 1..MaxASCII ] OF Char;i= GIDISBuffer: [Global] PACKED ARRAY [ 1..MaxGIDIS ] OF Char;/O { The two output buffers used by the routines in this module to do their }cO { stuff. The output is buffered (QIOs done whe_n buffer fills, buffer }0O { then emptied) in order to get increased video performance. }a, ASCIIQIOdpb: [Global,Volatile] QIOdpbType;, QIOdpb: [Global,Volatile] QIOdpbType;O { Directive Parameter Blocks used by these roue is data in the buffer } I D DIR$( ASCIIQIOdpb ); { Issue the directive to write text-mode } K F ASCIIQIOdpb.Q_IOPL[ 2 ] := 0; { Reset the buffer length to zero }eC State.CursorOn := False; { This has disables the cursor } END { then } ;; END { FlushA } ; [Global] PROCEDURE FlushASCII; BEGIN { FlushASCII }> FlushG; { Make sure any buffered GIDIS is put out first }. FlushA; { ThenC flush any text-mode data } END { FlushASCII } ;0 [Globatines to issue QIOW }YO { Executive Directives, to actually cause output data to be sent from the }OO { application task, to the P/OS Terminal Subsystem for subsequent display.}tD State: [Global] PACKED RECORD  { Some miscellaneous flags }& CursorOn: Boolean;! |END { State } ;f# KBBuf: [External,Volatile] Queue;pO { The private AST-driven type-ahead buffer used solely by this 2} O { application. Note that it is DIFFERENT ɭ*l] PROCEDURE StoreASCII( Count: Integer;F VAR Data: [ReadOnly,Unsafe] String );O { StoreASCII takes the passed byte data, and appends it to the current }eO { contents of the text-mode QIOW output buffer. Whenever the buffer fills, }O { the data pending in the buffer is written out+, and the buffer is then }}O { reset." H}T VAR  i: Integer;a BEGIN { StoreASCII } i := 0;a than the WITBF buffer defined } O { above. Our private buffer (KBBUF) is circular, whereas the Synergy } O { buffer (WITBF) is linear. Due to their different structure, we cannot }O { make double-duty of the Synergy buffer; thus we create our own. }  & [Initialize] PROCEDURE InitializeIO;O { This procedure is automatically run by the PRO/Pascal run-time system }rO { when the program starts up. This routine initializes some data  }eO { structures that  \ WITH ASCIIQIOdpb DOu; WHILE i < Count DO { For each byte being output... }d  BEGINr# IF Q_IOPL[ 2 ] = MaxASCIIs  THENd5 , FlushASCII; { Buffer is full, dump it } : 2i := i + 1; { Increment to next byte to store }N FQ_IOPL[ 2 ] := Q_IOPL[ 2 ] + 1; { Increment count of stored bytes }N FASCIIBuffer[ Q_IOPL[ 2 ] ] := Data[ i ]; { Store the byte in list } @END { while } ;t END { StoreASCII } ; I PROCEDURE Flus  cter to the passed queue. ] }  BEGIN { AddToQueue } WITH Que DO} IF Count < MaxQueueE THENV2 , BEGIN { The queue is not full, proceed }  IF Last >= MaxQueue THEN8 ,Last := 0; { Circular list; wrap around }9  Last % := Last + 1; { Advance pointer } >  Count (:= Count + 1; { Count this new byte }> 6 Data[ Last ] := Ch; { Add the byte to the buffer }  END { then } ;d J y in the characters to draw }e" Text[ i ] := Chars[ i ];O JOpCode := Draw_Packed_Characters DIV 256; { Compute opcode byte } O JParamCount := ( Length + 1 ) DIV 2; { Make a word count, rounded up }dJ Di := Length + 2; { Count of text, plus Op-code and Length bytes } IF Odd( Length )   THENsK D BEGIN { String being written is odd length, must make it even } G > Text[ Length + 1 ] := Chr( 255 ); { Packed padding byte }g2 FhG;O { FlushG forces out any buffered GIDIS (graphics mode) data. X}  BEGIN { FlushG } WITH QIOdpb DO IF Q_IOPL[ 2 ] > 0 THEN / * BEGIN { There is data in the buffer } = 6 DIR$( QIOdpb ); { Issue the write QIOW to GIDIS } A : Q_IOPL[ 2 ] := 0; { Reset the buffer length to zero }t END { then } ;e END { FlushG } ; [Global] PROCEDURE FlushGIDIS; BEGIN { FlushGIDIS }I FlushA; { Make sure any buffered ASCI END { AddToQueue } ;E [Global] PROCEDURE RemoveFromQueue( VAR Que: Queue; VAR Ch: Char ); O { RemoveFromQueue pops the oldest byte from the passed queue. [ }e BEGIN { RemoveFromQueue }Q WITH Que DOH IF Count > 0 THENiA < BEGIN { There is data in the queue, get the next byte } = 6 Ch := Data[ First ]; { Pass out the oldest byte }u  IF First >= MaxQueuet THEN< .First := 0; { Circular pointer; wrap around } lI (text-mode) data is put out }n+ FlushG; { Then output any GIDIS data }  END { FlushGIDIS } ;0 [Global] PROCEDURE StoreGIDIS( Count: Integer;F VAR Data: [ReadOnly,Unsafe] String );O { StoreGIDIS takes the passed byte data, and appends it to the current } O { contents of the graphics-mode GIDIS QIOQ output buffer. Whenever the }sO { buffer fills, the data pending in the buffer Ais written out, and the }sO { buffer is then reset. @ 8 First := First + 1; { Advance pointer to next byte }9 2 Count := Count - 1; { Decrease count by one }t END { then } ;a END { RemoveFromQueue } ; E [Global] PROCEDURE SoundBell;I BEGIN { SoundBell }tK StoreASCII( 1, 7 ); { Store a single text-mode ASCII character, BELL }t/ FlushASCII; { And force it out right now }  END { SoundyBell } ;( [Global] PROCEDURE PutChr( Ch: Char );O { PutChr takes a character, and adds it to the GIDIS output ܽ }{ VARp i: Integer;  BEGIN { StoreGIDIS } i := 0;a WITH QIOdpb DO= WHILE i < Count DO { For each data byte to output... }[  BEGIN]# IF Q_IOPL[ 2 ] = MaxGIDISe  THEN,5 , FlushGIDIS; { Buffer is full, dump it } : 2i := i + 1; { Increment to next byte to store }N FQ_IOPL[ 2 ] := Q_IOPL[ 2 ] + 1; { Increment count of stored bytes }N GIDISBuffer[ Q_IOPL[ 2 ] ] : :buffer. }t VAR $ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { PutChr }I Data[ 1 ] := Draw_Characters + 1; { Op-code, plus param count of 1 }  Data[ 2 ] := Ord( Ch );GL StoreGIDIS( 4, Data ); { Send the GIDIS sequence to the output bufferC } END { PutChr } ;E [Global] PROCEDURE PutString( Length: Integer;hF nVAR Chars: [ReadOnly,Unsafe] String );O { PutString takes a sequence of characters, and adds them to the G *= Data[ i ]; { Store the byte in list } END { while } ;: END { StoreGIDIS } ; G2 [Global] PROCEDURE EmptyQueue( VAR Que: Queue );O { EmptyQueue zeroes the passed queue. A }  BEGIN { EmptyQueue } WITH Que DO BEGINF First := 1;i Last := 0;  Count := 0;{ END { with } ; END { EmptyQueue } ;< [Global] PROCEDURE AddToQueue( VAR Que: Queue; Ch: Char );O { AddToQueue adds the passed chara vIDIS } O { output buffer (this is done with a DRAW_PACKED_CHARACTERS instruction for } O { performance sake). :}  VARd i: Integer;r Data: PACKED RECORDd* ParamCount: [Pos(0,0)] 0..255;* OpCode: [Pos(1,0)] 0..255;B 8Text: [Pos(2,0)] PACKED ARRAY [ 1..82 ] OF Char; LEND { Data } ; BEGIN { PutString }  WITH Data DO BEGINnC FOR i := 1 TO Length DO { Cop !!C)] PROCEDURE DrawRelArc( X, Y, Angle: Integer );a VARe$ Data: ARRAY [ 1..4 ] OF Integer; BEGIN { DrawRelArc }# Data[ 1 ] := Draw_Rel_Arcs + 3;r Data[ 2 ] := X;  Data[ 3 ] := Y;e Data[ 4 ] := Angle;E StoreGIDIS( 8, Da_ta ); END { DrawRelArc } ;9 [Global(SORB)] PROCEDURE SetOutputRubberBand( BandType,aH rBaseX, BaseY: Integer ); VAR $ Data: ARRAY [ 1..4 ] OF Integer; BEGIN { SetOutputRubberBand }a( ! SetPixelSize( Width, Height,aH XOffset, YOffset: [Unsafe] Integer ); VARt$ Data: ARRAY [ 1..5 ] OF Integer; BEGIN { SetPixelSize } Data[ 1 ] := Set_Pixel_Size; Data[ 2 ] := Width;E Data[ 3 ] := Height; Data[ 4 ] := XOffset;  Data[ 5 ] := YOffset;e StoreGIDIS( 10, Data );y END { SetPixelSize } ;E [Global] PROCEDURE SetOutputClippingRegion( UpperLeftX, UpperLeftY,;G Width, Hei!Data[ 1 ] := Set_Output_Rubber_Band; Data[ 2 ] := BandType; Data[ 3 ] := BaseX;  Data[ 4 ] := BaseY;w StoreGIDIS( 8, Data ); END { SetOutputRubberBand } ; : [Global] PROCEDURE SetWritingMode( Mode: WritingModes ); VAR,$ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { SetWritingMode }" Data[ 1 ] := Set_Writing_Mode; Data[ 2 ] := Ord( Mode );  StoreGIDIS( 4, Data ); END { SetWritingMode } ;; [Global] PROCEDURE SetAlphabet( WhichAlphabet: Integer ); !ght: Integer );W VARe$ Data: ARRAY [ 1..5 ] OF Integer;# BEGIN { SetOutputClippingRegion } , Data[ 1 ] := Set_Output_Clipping_Region; Data[ 2 ] := UpperLeftX; Data[ 3 ] := UpperLeftY; Data[ 4 ] := Width;W Data[ 5 ] := Height; StoreGIDIS( 10, Data );s# END { SetOutputClippingRegion } ; ) [Global] PROCEDURE EraseClippingRegion;} BEGIN { EraseClippingRegion }p+ StoreGIDIS( 2, Erase_Clipping_Region );  END { EraseClippingRegion } ;  [Global] PRO!* i := i + 1; { Count the extra byte }  END { then } ;E StoreGIDIS( i, Data ); { Add it to the GIDIS output buffer }e END { with } ; END { PutString } ;  O{ The following procedures do a wide variety of individual low-level GIDIS },O{ operations. } 2 [Global] PROCEDURE SetPosition( X, Y: Integer ); VARe$ Data: ARRAY [ 1..3 ] OF Integer; BEGIN { SetPosition }d Data[ 1 ] := Set_P!b VAR $ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { SetAlphabet }a Data[ 1 ] := Set_Alphabet; Data[ 2 ] := WhichAlphabet;t StoreGIDIS( 4, Data ); END { SetAlphabet } ;] O< [Global] PROCEDURE SetCellRendition( Rendition: Integer ); VAR $ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { SetCellRendition }$ Data[ 1 ] := Set_Cell_Rendition; Data[ 2 ] := Rendition;, StoreGIDIS( 4, Data ); END { SetCellRendition } ;A [Global(SCME)] PROCEDURE SetColorMapEn!4osition; Data[ 2 ] := X;x Data[ 3 ] := Y;  StoreGIDIS( 6, Data ); END { SetPosition } ;d/ [Global] PROCEDURE DrawLine( X, Y: Integer );} VARN$ Data: ARRAY [ 1..3 ] OF Integer; BEGIN { DrawLine }O Data[ 1 ] := Draw_Lines + 2; { Op-code word plus 2 params (1 coord pair) }  Data[ 2 ] := X;  Data[ 3 ] := Y; StoreGIDIS( 6, Data ); END { DrawLine } ;2 [Global] PROCEDURE DrawRelLine( X, Y: Integer ); VAR $ Data: ARRAY [ 1..3 ] OF Integer;!try( Map, Index, R, G, B, = Mono: Integer );  VARp$ Data: ARRAY [ 1..7 ] OF Integer; BEGIN { SetColorMapEntry }% Data[ 1 ] := Set_Color_Map_Entry;] Data[ 2 ] := Ord( Map ); Data[ 3 ] := Ord( Index ); Data[ 4 ] := Ord( R ); Data[ 5 ] := Ord( G ); Data[ 6 ] := Ord( B ); Data[ 7 ] := Ord( Mono ); StoreGIDIS( 14, Data );t END { SetColorMapEntry } ;7 [Global] PROCEDURE SetPrimaryColor( Color:! @ BEGIN { DrawRelLine }XM Data[ 1 ] := Draw_Rel_Lines + 2; { Op-code word plus 2 params (1 pair) } Data[ 2 ] := X;U Data[ 3 ] := Y;t StoreGIDIS( 6, Data ); END { DrawRelLine } ;e5 [Global] PROCEDURE DrawArc( X, Y, Angle: Integer );; VARd$ Data: ARRAY [ 1..4 ] OF Integer; BEGIN { DrawArc } Data[ 1 ] := Draw_Arcs + 3;D Data[ 2 ] := X;  Data[ 3 ] := Y;  Data[ 4 ] := Angle;l StoreGIDIS( 8, Data ); END { DrawArc } ;  .? [Global(DRAR!  Integer );n VAR,$ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { SetPrimaryColor }# Data[ 1 ] := Set_Primary_Color;  Data[ 2 ] := Color;C StoreGIDIS( 4, Data ); END { SetPrimaryColor } ; 9 [Global] PROCEDURE SetSecondaryColor( Color: Integer );  VAR $ Data: ARRAY [ 1..2 ] OF Integer; BEGIN { SetSecondaryColor }d% Data[ 1 ] := Set_Secondary_Color;  Data[ 2 ] := Color;a StoreGIDIS( 4, Data ); END { SetSecondaryColor } ;U S1 [Global] PROCEDURE ""idth; > FOR i := 1 TO Height DO { Copy in the cell pattern data }# Data[ 3 + i ] := Raster[ i ];t+ StoreGIDIS( ( Height * 2 ) + 6, Data );t END { LoadCharacterCell } ;R7 [Global] PROCEDURE SetAreaTexture( Alphabet: Integer; ? Index: [Unsafe] Integer ); VAR$ Data: ARRAY [ 1..3 ] OF Integer; BEGIN { SetAreaTexture }" Data[ 1 ] := Set_Area_Texture; Data[ 2 ] := Alphabet;E Data[ 3 ] := UAND( Index, %O'377' ); { Only use l" e= 6400; { Plus length }t7 Draw_Packed_Characters = 18944; { Plus length } 7 Draw_Rel_Arcs - = 6912; { Plus length }h7 Draw_Rel_Lines 2= 6656; { Plus length } % End_Define_Character = 9216; % End_Filled_Figure  = 8192;4' End_List = -32768;6% End_Picture A = 6144;8& Erase_Clipping_Region = 12288;% Flush_Buffer = 7168; $ Initialize = 257;% Load_By_Name"ow-order byte }  StoreGIDIS( 6, Data ); END { SetAreaTexture } ; H [Global(SCDS)] PROCEDURE SetCellDisplaySize( Width, Height: Integer ); VARN$ Data: ARRAY [ 1..3 ] OF Integer; BEGIN { SetCellDisplaySize }( Data[ 1 ] := Set_Cell_Display_Size; Data[ 2 ] := Width; Data[ 3 ] := Height;  StoreGIDIS( 6, Data );e END { SetCellDisplaySize } ;G [Global(SETUNI)] PROCEDURE SetCellUnitSize( Width, Height: Integer );  VARN$ Data: ARRAY [ 1..3 ] OF Inte" = 9474; 7 Load_Character_Cell * = 8704; { Plus length };% New_Picture  = 1536; " NOP  = 0;' Print_Screen q= -29434; & Request_Cell_Standard = 13824;& Request_Current_Position = 14080;& Request_Output_Size  = 14592;& Request_Status h= 14848;& Request_Version_Number = 18176;& Scroll_Clipping_Region = 13314;% Set_Alphabet = 9729; & Set_Area_Cell_Size "rger; BEGIN { SetCellUnitSize },% Data[ 1 ] := Set_Cell_Unit_Size;  Data[ 2 ] := Width; Data[ 3 ] := Height;h StoreGIDIS( 6, Data );N END { SetCellUnitSize } ; < PROCEDURE SetColorMap( Index, Red, Green, Blue: Integer );O { SetColorMap provides a easy interface to setting the Professional's color }eO { map. The RED, GREEN, BLUE intensity values range from 0 (nothing) to 7 }UO { (full on). }] VA"= 17666;% Set_Area_Texture = 3586; $ Set_Area_Texture_Size = 770;& Set_Cell_Display_Size = 10242;& Set_Cell_Explicit_Movement = 10498;& Set_Cell_Movement_Mode = 10753; s& Set_Cell_Oblique = 16641;& Set_Cell_Rendition = 11009;& Set_Cell_Rotation  = 11265;& Set_Cell_Unit_Size = 11522;% Set_Color_Map_Entry E = 4102;l% Set_GIDIS_Output_Space = 2308;l% Set_Line_Texture = 4355;r% Set_Output_Clippin"CEDURE BeginFill; BEGIN { BeginFill } ) StoreGIDIS( 2, Begin_Filled_Figure );i END { BeginFill } ;a [Global] PROCEDURE EndFill;; BEGIN { EndFill }r' StoreGIDIS( 2, End_Filled_Figure ); END { Set_Current_Position } ; =C E [Global(CREALP)] PROCEDURE CreateAlphabet( Width, Height, Extent,oB WidthType: Integer ); VARp$ Data: ARRAY [ 1..5 ] OF Integer; BEGIN { CreateAlphabet }! Data[ 1 ] := Create_Alphabet;o Da"2Re Mono: Unsigned;l BEGIN { SetColorMap }]O Mono := ( Red*2 + Green*4 + Blue ) DIV 7; { NTSC conversion approximation} N SetColorMapEntry( 0, Index, Red * 8192, Green * 8192, Blue * 8192, Mono ); END { SetColorMap } ; { End of module GIDIS.PAS } ;ves a easy interface to setting the Professional's color }eO { map. The RED, GREEN, BLUE intensity values range from 0 (nothing) to 7 }UO { (full on). }] VA" bta[ 2 ] := Width; Data[ 3 ] := Height; Data[ 4 ] := Extent; Data[ 5 ] := WidthType;e StoreGIDIS( 10, Data );P END { CreateAlphabet } ; [Global]= PROCEDURE LoadCharacterCell( Index, Width, Height: Integer;oH VAR Raster: [ReadOnly,Unsafe] CharCell ); VARo i: Integer; % Data: ARRAY [ 1..19 ] OF Integer;  BEGIN { LoadCharacterCell }R2 Data[ 1 ] := Load_Character_Cell + Height + 2; Data[ 2 ] := Index;t Data[ 3 ] := W" GO{ GIDISOPS.PAS Pascal %Include file that defines PRO/GIDIS things. U }CONSTO { First, define all of the PRO/GIDIS instruction op-codes that are )}O { implemented in V2.0 of PRO/GIDIS. D }% Begin_Define_Character = 8452;% Begin_Filled_Figure  = 7936;& Create_Alphabet  = 11780;7 Draw_Arcs . = 5888; { Plus length }7 Draw_Characters + = 8960; { Plus length }7 Draw_Lines ##0re are a bunch of miscellaneous constant values. }CM IO_WAL F = %O'410'; { I/O function code, ASCII (text-mode) QIOs }bL IO_WSD F = %O'5410'; { I/O function code, GIDIS (graphics) QIOs }O MaxASCII J = 100; { Size of the ASCII (text-mode) QIO buffer (bytes) } N MaxGIDIS H = 100; { Size of the GIDIS (graphics) QIO buffer (bytes) }J MaxQueue @ = 80; { Size of the private AST-driven input buffer }O QIOW  = 3; { Directive# } O  Q_IOPR: [Pos(7,0)] ! 0..255; { Directives. } ; ( Q_IOSB: [Pos(8,0),Unsafe] Unsigned;); ( Q_IOAE: [Pos(10,0),Unsafe] Unsigned; M : Q_IOPL: [Pos(12,0),Unsafe] ARRAY [ 1..6 ] OF Unsigned; ) END { QIOdpbType } ;  O{ Here are definitions for a large number of general-purpose procedures, most }OO{ of which are related to doing video output using the PRO/GIDIS interpreter. }c*#@6 Identification Code for QIOW directive }vF QIOW_Len > = 12; { Length of QIO Directive Parameter Block }L SD_GDS G = 1; { Special data type for IO.WSD signifying GIDIS }@ StringMax E= 80; { Used to allocate character arrays } TYPEL CharCell E = ARRAY [ 1..16 ] OF Integer; { Holds GIDIS char cells }J Queue 9= RECORD { Structure of the private, AST-driven }J > First, { input buffer that modules KBSERV.MAC }J #[^[External] PROCEDURE FlushASCII; EXTERNAL;0[External] PROCEDURE StoreASCII( Count: Integer;P VAR Data: [ReadOnly,Unsafe] String ); EXTERNAL;*[External] PROCEDURE FlushGIDIS; EXTERNAL;0[External] PROCEDURE StoreGIDIS( Count: Integer;P VAR Data: [ReadOnly,Unsafe] String ); EXTERNAL;)[External] PROCEDURE SoundBell; EXTERNAL;r2[External] PROCEDURE PutChr( Ch: Char ); EXTERNAL;E[External] PROCEDURE PutString( Length: Int# % Last, { and GETAKEY.MAC manage. }&  Count: Integer;C 0 Data: PACKED ARRAY [ 1..MaxQueue ] OF Char;i$  END { Queue } ;; String I = PACKED ARRAY [ 1..StringMax ] OF Char;rE StringType = RECORD  { Structure that contains }E L: Integer; { a string with a counted }nE S: String; { length.  }V) #4eger;rP VAR Chars: [ReadOnly,Unsafe] String ); EXTERNAL;<[External] PROCEDURE SetPosition( X, Y: Integer ); EXTERNAL;9[External] PROCEDURE DrawLine( X, Y: Integer ); EXTERNAL;E<[External] PROCEDURE DrawRelLine( X, Y: Integer ); EXTERNAL;9[External(SORB)] PROC'EDURE SetOutputRubberBand( BandType,SO BaseX, BaseY: Integer ); EXTERNAL;UD[External] PROCEDURE SetWritingMode( Mode: WritingModes ); EXTERNAL;A[External(SCME)] PROCEDURE#  END { StringType } ; 3 StringArray = ARRAY [ 1..99 ] OF StringType; O { Array of arbitrary length used to declare some [Unsafe] parameters. }]K WritingModes = ( Transparent, TransparentNegate, { List of the } K 8 Complement, ComplementNegate, { supported GIDIS } K 8 Overlay, OverlayNegate, { writing modes. }t2  Replace, ReplaceNegate,0 " Erase, EraseNegate, #* SetColorMapEntry( Map, Index, R, G, B, G Mono: Integer ); EXTERNAL;tE[External] PROCEDURE SetAlphabet( WhichAlphabet: Integer ); EXTERNAL; F[External] PROCEDURE SetCellRendition( Rendition: Integer ); EXTERNAL;A[External] PROCEDURE SetPrimaryColor( Color: Integer ); EXTERNAL;dC[External] PRuOCEDURE SetSecondaryColor( Color: Integer ); EXTERNAL;t:[External] PROCEDURE SetPixelSize( Width, Height, XOffset,I  YOffset: [Unsafe] I# l'g_Region = 1028;r% Set_Output_Cursor C = 1286;r& Set_Output_Cursor_Rendition = 18433;% Set_Output_IDS G= 3074;l& Set_Output_Rubber_Band = 13571;% Set_Output_Viewport  = 3332;_% Set_Pixel_Size = 4868;_% Set_Plane_Mask = 5121;_% Set_Position = 7426;_% Set_Primary_Color  = 5377;_% Set_Rel_Position = 7682;_% Set_Secondary_Color  = 3841;_% Set_Writing_Mode = 5633;_O { He#  0 NoMode );O QIOdpbType = PACKED RECORD { Directive }yO  D_CODE: [Pos(0,0)] ! 0..255; { Parameter block }(O  D_LGTH: [Pos(1,0)] ! 0..255; { for the Queue }mO  Q_IOFN: [Pos(2,0)] ! Unsigned; { I/O Request }yO  Q_IOLU: [Pos(4,0)] ! Unsigned; { (QIO/QIOW) P/OS } O  Q_IOEF: [Pos(6,0)]  0..255; { Executive $5$ydnteger ); EXTERNAL;ML[External] PROCEDURE SetOutputClippingRegion( UpperLeftX, UpperLeftY, Width,J Height: Integer ); EXTERNAL;3[External] PROCEDURE EraseClippingRegion; EXTERNAL;R)[External] PROCEDURE BeginFill; EXTERNAL;P'[External] PROCEDURE EndFill; EXTERNAL;)C[External(CreAlp)] PROCEDURE CreateAlphabet( Width, Height, Extent,)L R WidthType: Integer ); EXTERNAL;F[External] PROCEDURE LoadCharacterCell( Index, W$nput buffer KBBUF.# SOB R0, 20$ ; Loop for each byte.-' CLR WITBF+2 ; Clear length of WITBF.-99$: MOV (SP)+, R0 ; Restore temp registers.. MOV (SP)+, R15 JSR PC, KBGET ; Get characters in system typeahead.B7 JSR PC, DETACH ; Ask Pascal OTS to free the terminal.10 DIR$ #REAT ; Re-attach, for AST notification. RTS PC ; Done.n oMKBGET: ; This routine asks the P/OS terminal driver how many bytes are in the)A ; type-ahead buffer, and then reads that many bytes into our ownt ; private$idth, Height: Integer;O pVAR Raster: [ReadOnly,Unsafe] CharCell ); EXTERNAL; 7[External] PROCEDURE SetAreaTexture( Alphabet: Integer; I ` Index: [Unsafe] Integer ); EXTERNAL;a5[External(SCDS)] PROCEDURE SetCellDisplaySize( Width,EK V Height: Integer ); EXTERNAL;g4[External(SetUni)] PROCEDURE SetCellUnitSize( Width,J &Height: Integer ); EXTERNAL;?[Externa$ buffer KBBUF.- MOV R0, -(SP) ; Save needed temp registers.W MOV R1, -(SP) MOV R2, -(SP)5 DIR$ #GETCNT ; Find out how many bytes are in buf.V, CLR R0 ; Zero a scratch register, then...9 BISB TYPCNT, R0 ; Put the number of bytes read into it.f- BEQ 100$ ; If zero, nothing there so exit.f4 CMP R0, #TBUFL ; Would adding this overflow KBBUF?$ BLOS 5$ ; No, it's within bounds.7 MOV #TBUFL, R0 ; Too much at once, just get part now.n=5$: MOV R0, GETEM+Q.IOPL+2 ; Set the byte count for $Wl] PROCEDURE DrawArc( X, Y, Angle: Integer ); EXTERNAL; I[External(DRARC)] PROCEDURE DrawRelArc( X, Y, Angle: Integer ); EXTERNAL;rO[External] PROCEDURE SetColorMap( Index, Red, Green, Blue: Integer ); EXTERNAL;f<[External] PROCEDURE EmptyQueue( VAR Que: Queue ); EXTERNAL;F[External] PROCEDURE AddToQueue( VAR Que: Queue; Ch: Char ); EXTERNAL;O[External] PROCEDURE RemoveFromQueue( VAR Que: Queue; VAR Ch: Char ); EXTERNAL;  &Height: Integer ); EXTERNAL;?[Externa$Zthe read.B5 DIR$ #GETEM ; Read type-ahead into temporary TBUF.? ; So, now there are 'R0' bytes at TBUF, which need to be movedn ; into the private queue KBBUF.8 MOV #KBBUF, R2 ; Get the address of the private queue.9 MOV Q.CNT(R2),R1 ; Get current count of bytes in queue.t4 ADD R0, R1 ; Plus the new bytes that just came in.4 CMP R1, #HiMark ; Would the queue become too full? BLO 10$ ; Nope, fine.7 JSR PC, LockKe ; Yes, throw the bytes away & lock KB.. BR 100$ ; Exit./10$: MOV$r6 .ENABL LC, GBL ; Enable lower case, default global. .TITLE KBSERV Keyboard Services; .MCALL DIR$, QIOW$, ASTX$S, SETF$S ; Needed P/OS services.# .MCALL CLEF$S, WTSE$S, QIO$, SRDA$$KBASTI::; PROCEDURE KBASTInitialize;F ; This routine attaches the keyboard for AST input notification, plusH ; initializes the private type-ahead buffer KBBUF. This initializationF ; consists of copying anything from the Synergy buffer WITBF into ourA ; buffer, followed by appending anything currently in the$ #TBUF, R1 ; Get address of the bytes.a620$: MOV R2, -(SP) ; Pass address of the input queue,% MOVB (R1)+, -(SP) ; Pass each byte,4 JSR PC, ADDTOQ ; Add next byte to the input queue.# SOB R0, 20$ ; Loop for each byte...100$: MOV (SP)+, R2 ; Restore temp registers. MOV (SP)+, R1 MOV (SP)+, R0 returny GKBNOT:: ; This routine is the routine actually notified by the AST that> ; character input has occurred. It calls KBGET to handle the? ; character packet, wakes READKB, clears the st$  actualB ; Terminal Driver's buffer.6 MOV #KBBUF, -(SP) ; Get address of the input buffer.2 JSR PC, EMPTYQ ; Clear the private input buffer.' MOV R1, -(SP) ; Save temp registers. MOV R0, -(SP)9 MOV #WITBF+2,R1 ; R1 points to length of Synergy buffery0 MOV (R1)+, R0 ; Put length in R0. Is it zero?& BLE 99$ ; Yes - so nothing to copy.:20$: MOV #KBBUF, -(SP) ; Pass address of the input queue,2 MOVB (R1)+, -(SP) ; Pass each byte from WITBF...8 JSR PC, ADDTOQ ; ...to the private i$ ack, and exits.e, JSR PC, KBGET ; Get the packet into KBBUF.2 SETF$S #IDLE$ ; Set idle flag, to start READKB.1 CLR (SP)+ ; Pop the extra word from the stack.y ASTX$S ; Exit the AST state.IREADKB::; This reads the next byte from the input queue. If the queue isM9 ; empty, this routine waits till some input is received.rB ; To call this routine, the caller pushes the address of the byteD ; that will hold the returned character on the stack, then JSR's to ; this entry point.% MOV R %%  the structure of a queue.,Q.FRST::.BLKW ; Offset to the FIRST pointer.+Q.LAST::.BLKW ; Offset to the LAST pointer.A$Q.CNT:: .BLKW ; Offset to the COUNT.2Q.DATA:: ; Offset to the data in the queue itself.'. = 1 ; Define bits in the word FLAGS: 0B.KBLk::.BLKB . ; Set => the keyboard is locked.BB.Curs::.BLKB . ; Set => the cursor is OFF, Clear => Cursor is ON." .PSECT ; Back to the blank Psect.9 .MACRO QUEUE QNAME ; QUEUE allocates space for a queue. 5QNAME:: .WORD 1,0,0 ; Space for Firs%5 .ENABL LC,GBL ; Allow lower case, default globals. .TITLE READMS Read Messages- .NLIST BEX ; Don't list binary expansions.?GETMES::; PROCEDURE GetMessages( VAR Frame: [ReadOnly] Integer; ; VAR Mesg1: StringType; ; VAR Mesg2: StringType; ; :% ; VAR Mesgn: StringType ); SEQ11;D ; This routine reads multiple message strings from a single message ; frame. ;= ; The frame id is the frame file ID for the message to read. ;A ; Each string parameter passed to this ro%k5, -(SP) ; Save temp register.G610$: MOV #KBBUF, R5 ; Get address of the input queue., TST Q.CNT(R5) ; Is the input buffer empty?( BNE 20$ ; No, some data is available.8 CLEF$S #IDLE$ ; Buffer is empty. Clear the idle flag,6 JSR PC, UNLKEY ; make sure the keyboard is unlocked,8 WTSE$S #IDLE$ ; and wait till input data is received.0 BR 10$ ; Then loop back to get the next byte.920$: MOV R5, -(SP) ; Set up call to REMOVE: buffer addr,c: MOV 6(SP), -(SP) ; address of where to retur%t, Last, Count.o* .BLKB MAXQUE ; The buffer space itself." .EVEN ; Round up to next word.$ .ENDM QUEUE ; End of QUEUE macro.B .PSECT ED$DAT, D, RW, GBL, CON ; Separate Psect to hold the data.3 QUEUE KBBUF ; Allocate the private input buffer.:6FLAGS:: .WORD 0 ; Allocate space for misc bit-flags.-TBUFL = 30. ; Max number of bytes per AST.s6TBUF:: .BLKB TBUFL ; Intermediate temp input buffer.% .PSECT ; Back to the blank Psect.q7; This QIOW attaches the keyboard for AST %n next byte.8 JSR PC, RemoveFromQueue ; Get the next input character.E ; In Synergy, if the character we just got is a 377, we need to call2: ; the Synergy Window Manager back to get more type ahead.7 CMPB @4(SP), #377 ; Call-back continuation character? " BNE 30$ ; No - get out of here.8 JSR PC, PVDetach ; Detach terminal and copy input queue) ; to Synergy typeahead buffer WITBF.+ MOV #PBLK, R5 ; Set up for call to MGTCB.:* JSR PC, MGTCB ; Get new typeahead stuff.= JSR PC, KBASTIn%notification.t;>REAT: QIOW$ IO.ATA!TF.NOT!TF.XCC, SCRLUN, SCREFN, , , ,L; This QIOW returns the count of bytes in the type-ahead buffer into TYPCNT.; 7GETCNT: QIOW$ SF.GMC, SCRLUN, SCREFN, , , ,;;GMCC: .BYTE TC.TBF ; Ask TTDRV for type-ahead buffer cnt.o.TYPCNT: .BLKB ; Buffer count returned here.0GMCL = . - GMCC ; Length of params for SF.GMC.H; This QIOW reads the next N bytes from the type-ahead buffer into TBUF.;AGETEM: QIOW$ IO.RLB!TF.RAL!TF.RNE, SCRLUN,%itialize ; Reattach terminal, copy typeahead.t BR 10$n,30$: MOV (SP)+, R5 ; Restore temp register.6 MOV (SP)+, (SP) ; Clean the char address from stack. RTS PC ; Done.t eHLOCKKE::; This routine locks the keyboard, preventing further input from ; being generated. 8 WTSE$S #SCREFN ; Make sure the terminal is quiescent.! DIR$ #LCK ; Lock the keyboard.g2 BIS #B.KBLK,FLAGS ; Keep track that it's locked.; BIS #B.CURS,FLAGS ; This turns cursor off, remember this.f RTS PC ; Done% SCREFN, , , ,T; This QIO locks the keyboard.;C3LCK: QIO$ IO.WAL, SCRLUN, SCREFN, , , , ; This QIO unlocks the keyboard.;T6ULCK: QIO$ IO.WAL, SCRLUN, SCREFN, , , ,7 .PSECT ESCDAT, D, RO, GBL, CON ; Misc literal strings. LCKA: .ASCII <23> ; XOFF.;+LCKL = . - LCKA ; Length of the sequence. 9ULCKA: .ASCII <21><233>/?8h/ ; XON, plus Set Autorepeat.e-ULCKL = . - ULCKA ; Length of the sequence.. .EVEN0PBLK: .WORD 1 ; Param block for ca% .tIUNLKEY::; This routine unlocks the keyboard, allowing further input to be ; generated.g- BIT #B.KBLK,FLAGS ; Is it currently locked?s( BEQ 10$ ; Nope, so needn't unlock it.$ DIR$ #ULCK ; Unlock the keyboard.8 BIC #B.KBLK,FLAGS ; Keep track that it's now unlocked.; BIS #B.CURS,FLAGS ; This turns cursor off, remember this.R10$: RTS PC ; Done.a g-MAXQUE == 80. ; Length of a private queue.c?HIMARK == < MAXQUE * 2 > / 3 ; Point where keyboard is locked.f* .ASECT ; Define% ll to MGTCB.) .WORD StatB ; Address of status array.o-STATB: .BLKW 2 ; Status from call to MGTCB.  .END ; Of KBSERV.MACocks the keyboard.;T6ULCK: QIO$ IO.WAL, SCRLUN, SCREFN, , , ,7 .PSECT ESCDAT, D, RO, GBL, CON ; Misc literal strings. LCKA: .ASCII <23> ; XOFF.;+LCKL = . - LCKA ; Length of the sequence. 9ULCKA: .ASCII <21><233>/?8h/ ; XON, plus Set Autorepeat.e-ULCKL = . - ULCKA ; Length of the sequence.. .EVEN0PBLK: .WORD 1 ; Param block for ca &'&nish each string040$: MOV (SP)+, R4 ; Restore scratch registers. MOV (SP)+, R3 MOV (SP)+, R2 MOV (SP)+, R1 MOV (SP)+, R0 RTS PC ; Done.V 5.MSGBSZ = 500. ; Size of the message buffer.0RDPARM: .WORD 6. ; Number of parameters to WIRMS. .WORD S$Stat ; address of status return array? .WORD NLINES ; address of number of lines in line offset arrayf! .WORD LINARY ; Line offset arrayV- .WORD MSGBUF ; Address of the message buffer,0 .WORD FRAMID ; Address of the one word frame id; .WO&& WI$BoldUnderline = 14; WI$Boxed = 15;O { These are the values for the Termination Keys that a program passes to }O { Synergy in a Termination Key List, and the values that Synergy returns as }O { KeyPressed values. } PV$RET = 269; 1 PV$FND = 513; PV$INS = 514; PV$REM = 515; 1 PV$SEL = 516; PV$PRE = 517; PV$NEX = 518; B PV$BRK = 525; PV$SET = 526; PV$F5 = 527; PV$INT = 529;B PV$RES = 530; &VRD MSGBLN ; address of the length of the message bufferc MaxLin = 40.BLINARY: .BLKW MaxLin ; array to hold pointers into message buffer.?NLINES: .BLKW ; initialized with the number of lines expected...FRAMID: .BLKW ; one word frame identificationA .ASECT ; Define the offsets to parameters in the R5 param block. . = 0 )M.CNT: .BLKB ; Count of total parameters.. .BLKB ; Unused.0M.FID: .BLKW ; Address of the one word frame ID.9M.F1: .BLKW ; Address of the first of sub string buffers. $ .PS& PV$CAN = 531; PV$MAI = 532; PV$EXI = 533;B PV$F11 = 535; PV$F12 = 536; PV$F13 = 537; PV$ADD = 538; PV$HLP = 540; PV$DO = 541;B PV$F17 = 543; PV$F18 = 544; PV$F19 = 545; PV$F20 = 546;B PV$PF1 = 547; PV$PF2 = 548; PV$PF3 = 549; PV$PF4 = 550;B PV$UP = 551; PV$DWN = 552; PV$RIT = 553; PV$LEF = 554;B PV$COM = 555; PV$MIN = 556; PV$PER = 557; PV$ENT = 558;B PV$0 = 559; PV$1 = 560; PV$2 = 561; PV$3 = 562;B PV$4 = 563; P&utine is of the format:l ; +--"-+ ; | string length | 0S ; +---+ ; | data | 2 ; +---- ----+ ; | : | 4D ; . . .) MOV R0, -(SP) ; Save scratch registers.  MOV R1, -(SP) MOV R2, -(SP) MOV R3, -(SP) MOV R4, -(SP)1 MOV #MSGBSZ,MSGBLN ; Load the length of buffer.n4 MOV @M.FID(R5),FRAMID ; Put frame ID in param block' MOV R5, -(SP) ; Save R5 for a moment.f+ MOV #RDPARM,R5 ; Pass parameters to WIRMS;4 JSR PC, WIRMS ; Call Synergy read me&ECT MSGBUF, RW, D, GBL, REL, CON.MSGBLN: .BLKW ; Size of the message buffer.(MSGBUF::.BLKB MSGBSZ ; Message buffer.!S$Stat: .BLKW 2 ; Status array.; .EVEN .END ; End of READMESG.MACed...FRAMID: .BLKW ; one word frame identificationA .ASECT ; Define the offsets to parameters in the R5 param block. . = 0 )M.CNT: .BLKB ; Count of total parameters.. .BLKB ; Unused.0M.FID: .BLKW ; Address of the one word frame ID.9M.F1: .BLKW ; Address of the first of sub string buffers. $ .PS&ssage routine. MOV (SP)+, R5 ; Restore R5.+& TST S$Stat ; Any errors from WIRMS? BLE 40$ ; Yes, ugh! Exit.;) CLR R0 ; Make sure high byte is clear..6 BISB M.CNT(R5),R0 ; Get count of parameters (<256.).% DEC R0 ; Ignore FrameID parameter.) ; Now R0 = #strings to move3 MOV R5, R1 ; Get address of first string address:R4 ADD #M.F1, R1 ; R1 = addrs of addrs of 1st return.4 MOV #LinAry,R5 ; R5=Addrs to offset to 1st string.710$: MOV (R1)+, R2 ; R1=addrs of addrs of next re&DO{ SYNERGY.PAS Pascal %Include file that defines Synergy things. }CONSTI DescriptorLength = 32; { Length of a window descriptor block (bytes) }C MaxContext = 32; { Size of Synergy Context Block (bytes) }H MaxTBFSize = 80; { Size of the Synergy typeahead buffer WITBF }O { These are t7he GIDIS alphabet numbers for the pre-loaded fonts that G}O { Synergy provides. Your application can to a GIDIS SET_ALPHABET ! }O { instruction specifying o& Hturn. ) ; R2=addrs of current string return.T2 MOV (R5)+, R3 ; R5=addrs of next offset to move., ; R3=offset to current string in MSGBUF4 MOV (R5), R4 ; R4=offset to next string in MSGBUF.+ SUB R3, R4 ; R4=length of current string.D7 MOV R4, (R2)+ ; Set length into current return string, BEQ 30$ ; If empty, skip it.g8 ADD #MSGBUF,R3 ; R3=addrs of current string in MSGBUF..20$: MOVB (R3)+, (R2)+ ; Store the characters& SOB R4, 20$ ; until we get them all.&30$: SOB R0, 10$ ; Fi& ne of these numbers, and then do DRAW_CHARACTERS }sO { and DRAW_PACKED_CHARACTERS instructions to display the normal ASCII, }oO { DIGITAL Multinational, and VT100 Special Graphics characters on the }gO { screen (the ASCII, Multinational aand Line Drawing characters are all }hO { folded together into each of the fonts 9 to 14). (}  WI$Special = 7;y WI$Dim  = 9;l WI$Normal = 10; WI$Bold = 11; WI$Underline = 13; ''|U $ WhiteBorder: [Pos( 4)] Boolean;< $ ClearOnChange: [Pos( 5)] Boolean;< $ Unused6: [Pos( 6)] Boolean;< $ VT100_Style: [Pos( 7)] Boolean;< $ Invisible: [Pos( 8)] Boolean;< $ Unused9: [Pos( 9)] Boolean;< $ ThreePlane: [Pos(10)] Boolean;< $ Unused11: [Pos(11)] Boolean;< 'I)] Unsigned; { Returned from WIINI }H CharacterWidth: [External(CHARWI)] Unsigned; { Returned from WIINI }) PixelHeight, { Returned from WIINI } ) PixelWidth, { Returned from WIINI } ) ScreenWidth, { Returned from WIINI }d) ScreenHeight: { Returned from WIINI } Unsigned;- aO{ These are some procedure definitions for a number of the Synergy services. } =PROCEDURE WIINI( VAR Status:  StatusBlock;a9 " VAR ExpectedVersion: [ReadOnly] I'wu$ Unused12: [Pos(12)] Boolean;< $ Unused13: [Pos(13)] Boolean;< $ Unused14: [Pos(14)] Boolean;< $ Unused15: [Pos(15)] Boolean;(  END { Flags } ;9 & MinWidth: [Pos(12,0)] Unsigned; 9 & MinHeight: [Pos(14,0)] Unsigned; 9 & MaxWidth: [Pos(16,0)] Unsigned; 9 . MaxHeight: [Pos(18,0)] Unsigned; 9 '[q nteger;i9  VAR ActualVersion: Integer;l9  VAR ContextLength: Integer;h8 * VAR ContextBlock: [Unsafe] String;:  VAR ScreenWidth: Unsigned;:  VAR ScreenHeight: Unsigned;:  VAR CharacterWidth: Unsigned;:  VAR CharacterHeight: Unsigned;:  VAR PixelWidth: Unsigned;:  VAR Pix'Щ & XOffset: [Pos(20,0)] Unsigned; 9 & YOffset: [Pos(22,0)] Unsigned; 9 & FrameWidth: [Pos(24,0)] Unsigned; 9 & FrameHeight: [Pos(26,0)] Unsigned; K 8 OwnerTaskID: [Pos(28,0)] ARRAY [ 1..2 ] OF Unsigned;,/ + END { WindowDescriptor } ; 0 WordArray = ARRAY [ 1..99 ] OF Integer;O { Used in miscellaneous places where arrays of indeterminant size are } O { used. This ' elHeight: Unsigned;B  VAR ColorWindows: 2 Integer ); SEQ11;BPROCEDURE WIDON( VAR Status: StatusBlock;>  VAR ContextLength: [ReadOnly] Integer;F h VAR ContextBlock: [ReadOnly,Unsafe] String ); SEQ11;,PROCEDURE WIINT( VAR Status: StatusBlock;(  VAR WhyChange: Integer;(  VAR WindowID: Integer;(  VAR NewWidth: Integer;1 VAR NewHeig'V$5 = 564; PV$6 = 565; PV$7 = 566;1 PV$8 = 567; PV$9 = 568; PV$DEL = 569;7 TYPE/ StatusBlock = ARRAY [ 1..2 ] OF Integer;7O { Two-word array that success/failure status information is returned in }$O { from "the various Synergy service calls. S } J WindowDescriptor = RECORD { This is a Synergy Window Descriptor Block }8  ID: [Pos(0,0)] Integer;9  X:  [Pos(2,0)] Un'is made possible through the PRO/Pascal [Unsafe] attribute. }  CONST { Structured constants } @ WDescModel = WindowDescriptor( 0, 0, 0, 0, 0, ( 16 OF False ),D 0, 0, 0, 0, 0, 0, 0, 0, ( 0, 0 ) );M { This may be used in an assignment statement to fill in all the fields } M { of a window descriptor block in one fell swoop. u }]HVAR { Some variables that virtually all Synergy applications will use } WITBF: [External] RECORD- ' 4c signed; 9  Y:  [Pos(4,0)] Unsigned;P9 & Width: [Pos(6,0)] Unsigned; 9 & Height: [Pos(8,0)] Unsigned; = * Flags: [Pos(10,0)] PACKED RECORDr< $ Stackable: [Pos( 0)] Boolean;<  Titled: [Pos( 1)] Boolean;<  Hidden: [Pos( 2)] Boolean;<  Color:  [Pos( 3)] Boolean;< '  MaxSize: Integer;U- CurrentLength: Integer;oL 8Characters: PACKED ARRAY [ 1..MaxTBFSize ] OF Char;# END { WITBF } ; O { Definition of the Synergy-provided type-ahead buffer that is used to }nO { pass read-ahead characters from the application to Synergy and back. }o) ActualVersion, { Returned from WIINI } ) ColorWindows: { ReturneCd from WIINI }a integer;H CharacterHeight: [External(CHARH (Y(1 :WindowDescriptor ); SEQ11;>PROCEDURE WISWP( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: :WindowDescriptor ); SEQ11;@PROCEDURE WITTL( VAR Status: StatusBlock;<  VAR TitleLength: [ReadOnly] Integer;D V VAR TitleText: [ReadOnly,Unsafe] String ); SEQ11; L9PROCEDURE WIERW( VAR Status:  StatusBlock;:5 (͕k;6 VAR KeyPressed: Integer;6 VAR MenuID: Integer;6 VAR OptionValue: Integer;6 &VAR FrameID: [ReadOnly] Integer;? OVAR InitialLeaf: [ReadOnly] Integer ); SEQ11; 6PROCEDURE EXHELP( VAR Status:  StatusBlock;; sVAR FrameID: [ReadOnly] Integer ); SEQ11; nuID: [ReadOnly] Integer ); SEQ11;:PROCEDURE EXFLOW( VAR Status: StatusBloc(Η  VAR Len1: [ReadOnly] Integer;R4 & VAR Msg1: [ReadOnly,Unsafe] String;5  VAR Len2: [ReadOnly] Integer;e4 & VAR Msg2: [ReadOnly,Unsafe] String;5  VAR Len3: [ReadOnly] Integer;a4 & VAR Msg3: [ReadOnly,Unsafe] String;5  VAR Len4: [ReadOnly] Integer; 4 & VAR Msg4: [ReadOnly,Unsafe] String;5  VAR Len5: [ReadOnly] Integer; =  VAR(= !Synergy/I2Name "Baton Twirler"!File [ZZPROVUE]SYNCHK2.TSK/DeleteFile [ZZPROVUE]SYNERR.HLP/Keep%EXECUTE [ZZPROVUE]SYNCHK2.TSK/Ins/USR!EXECUTE [ZZPROVUE]SYNCHK2.TSK/Ins!$Execute [ZZPROVUE]REMEXE.TSK/Rem/USR Execute [ZZPROVUE]REMEXE.TSK/Rem!File BATON.TSK/Delete/Network*File [ZZBATON]BATONFRMS.OFF/Delete/Cluster!$Execute [ZZPROVUE]INSAPP.TSK/Ins/USR Execute [ZZPROVUE]INSAPP.TSK/Ins!*!Install [ZZSYS]PASRES.TSK/Library/Cluster!Install BATON.TSK/Task/Network !Run BATON!)(K Msg5: [ReadOnly,Unsafe] String ); SEQ11;IGPROCEDURE OPENME( VAR Status: StatusBlock; C !VAR FileVersionNumber: [ReadOnly] Integer;:C !VAR FilenameLength: [ReadOnly] Integer; K VAR Filename: C[ReadOnly,Unsafe] String ); SEQ11; ;PROCEDURE WIRMS( VAR Status:  StatusBlock;V7  VAR LineCount: Integer;L9 $ VAR LineOffsets: [Unsafe] WordA(Install [ZZPROVUE]SYNRUN.TSK/Task/Clustere Run WI$MGRCHK2.TSK/DeleteFile [ZZPROVUE]SYNERR.HLP/Keep%EXECUTE [ZZPROVUE]SYNCHK2.TSK/Ins/USR!EXECUTE [ZZPROVUE]SYNCHK2.TSK/Ins!$Execute [ZZPROVUE]REMEXE.TSK/Rem/USR Execute [ZZPROVUE]REMEXE.TSK/Rem!File BATON.TSK/Delete/Network*File [ZZBATON]BATONFRMS.OFF/Delete/Cluster!$Execute [ZZPROVUE]INSAPP.TSK/Ins/USR Execute [ZZPROVUE]INSAPP.TSK/Ins!*!Install [ZZSYS]PASRES.TSK/Library/Cluster!Install BATON.TSK/Task/Network !Run BATON!)(rray;:6 ( VAR MessageBuffer: [Unsafe] String;7 * VAR FrameID: [ReadOnly] Integer;@ P VAR BufferSize: [ReadOnly] Integer ); SEQ11;;PROCEDURE WIXPS( VAR Status:  StatusBlock;I7  VAR KeyPressed: Integer;n7  VAR NumChanged: Integer;u9 , VAR ChangedValues: [Unsafe] WordArray;n7 * VAR FrameID: [ReadOnly] Integer;n7 VAR NumEn(! _r^( 6ht: Integer ); SEQ11; >PROCEDURE WICRW( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: :WindowDescriptor ); SEQ11;6PROCEDURE WIDSW( VAR Status: StatusBlock;; L VAR WindowID: [ReadOnly] Integer ); SEQ11;t>PROCEDURE WIGEW( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: ( ə tries: [ReadOnly] Integer;M7 * VAR Entry1Class: [ReadOnly] Integer;a7  VAR Entry1Value: Integer;f7 * VAR Entry2Class: [ReadOnly] Integer;P@  VAR Entry2Value: 2Integer ); SEQ11;9PROCEDURE EXMESS( VAR Status: StatusBlock;N5 VAR KeyPressed: Integer;R> MVAR MenuID: [ReadOnly] Integer ); SEQ11;:PROCEDURE EXFLOW( VAR Status: StatusBloc ))V0 aCOV  3+Edit Colors=Choose the color to edit with the 32+{l}32- and 32+{r}32-6keys, and press 32+{DO}32- to edit the chosen color.1 53+Press 32+{EXIT}32- to accept values.2 3+Color Map0When run on a color system, the Batons are drawn2in color. Six separate colors are used, producing0a travelling ribbon with the moving Batons. You2can control the individual 6 colors that are used.%Press 32+{RE) s really gone wrong!Z, 3+Overview of Baton Twirler7Welcome to the Synergy demonstration application, Baton8Twirler. At any time while the Batons are twirling, you=can press 32+{F5}32- to temporarily pause Baton Twirler and4return to the Synergy Main Menu (and then change the=window size or move it around). Pressing 32+{EXIT}32- will7stop Baton Twirler and return to the Synergy Main Menu.>You can also press 32+{F11}32-, which will display a menu of9options that enable you )in the Synergy fonts.0Here is a sample use of renditions: You can useB3-Dim1+, Normal and 3+bold2- intensities plus 8+underline8-,9 4+Italic4- and 16+ Hilight 16- for emphasis, and for8keyboard function key notation the 32+{BOXED}32- font.%Press 32+{RESUME}32- to leave HELP. HELP index Baton Twirler 2&Baton Twirler (press HELP for details)Thhere's a2sample use of the DEC Multinational () and+Special Graphics characters that areavailable ) Thickness/The Batons are initially drawn with thin lines.1This option lets you change the pen or brush that0the lines are drawn with. The size of the brush+in X and Y can be controlled independently.%Press 32+{RESUME}32- to leave HELP.r JHELP indexo  Use the arrow keys to changethe line thickness:+   4+Short I 32+{u}32-; 4+Narrow4- 32+{l}32- 32+{d}32- 32+{r}32- 4+Wide  4+Tall)3+Press )3U $ WhiteBorder: [Pos( 4)] Boolean;< $ ClearOnChange: [Pos( 5)] Boolean;< $ Unused6: [Pos( 6)] Boolean;< $ VT100_Style: [Pos( 7)] Boolean;< $ Unused8: [Pos( 8)] Boolean;< $ Unused9: [Pos( 9)] Boolean;< $ Unused10: [Pos(10)] Boolean;< $ Unused11: [Pos(11)] Boolean;< ) M32+{EXIT}32- to accept values.PV$ This application has encountered% the following unexpected problem -- 6 .+Because your system is not running in color*right now, you cannot manipulate the color+map. If your Professional does have an EBO+option and a color monitor, and you want to3use color, tell Synergy by pressing 32+{SETUP}32-from the Synergy Main Menu.#Press 32+{RESUME}32- to continue.E2' Cannot create the application window.i.$ Something ha) u$ Unused12: [Pos(12)] Boolean;< $ Unused13: [Pos(13)] Boolean;< $ Unused14: [Pos(14)] Boolean;< $ Unused15: [Pos(15)] Boolean;(  END { Flags } ;9 & MinWidth: [Pos(12,0)] Unsigned;n9 & MinHeight: [Pos(14,0)] Unsigned;9 & MaxWidth: [Pos(16,0)] Unsigned;N9 . MaxHeight: [Pos(18,0)] Unsigned;e9 *K*q nteger; 9  VAR ActualVersion: Integer; 9  VAR ContextLength: Integer; 8 * VAR ContextBlock: [Unsafe] String;:  VAR ScreenWidth: Unsigned;:  VAR ScreenHeight: Unsigned;:  VAR CharacterWidth: Unsigned;:  VAR CharacterHeight: Unsigned;:  VAR PixelWidth: Unsigned;:  VAR Pix*K Msg5: [ReadOnly,Unsafe] String ); SEQ11; GPROCEDURE OPENME( VAR Status: StatusBlock; C !VAR FileVersionNumber: [ReadOnly] Integer;dC !VAR FilenameLength: [ReadOnly] Integer;eK VAR Filename: C[ReadOnly,Unsafe] String ); SEQ11;u;PROCEDURE WIRMS( VAR Status:  StatusBlock;R7  VAR LineCount: Integer;k9 $ VAR LineOffsets: [Unsafe] WordA*h & XOffset: [Pos(20,0)] Unsigned;19 & YOffset: [Pos(22,0)] Unsigned;t9 & FrameWidth: [Pos(24,0)] Unsigned;y9 & FrameHeight: [Pos(26,0)] Unsigned;eK 8 OwnerTaskID: [Pos(28,0)] ARRAY [ 1..2 ] OF Unsigned;V/ + END { WindowDescriptor } ; 0 WordArray = ARRAY [ 1..99 ] OF Integer;O { Used in miscellaneous places where arrays of indeterminant size are };O { used. This * elHeight: Unsigned;B  VAR ColorWindows: 2 Integer ); SEQ11;BPROCEDURE WIDON( VAR Status: StatusBlock;>  VAR ContextLength: [ReadOnly] Integer;F h VAR ContextBlock: [ReadOnly,Unsafe] String ); SEQ11;,PROCEDURE WIINT( VAR Status: StatusBlock;(  VAR WhyChange: Integer;(  VAR WindowID: Integer;(  VAR NewWidth: Integer;1 VAR NewHeig*is made possible through the PRO/Pascal [Unsafe] attribute. }5 CONST { Structured constants } @ WDescModel = WindowDescriptor( 0, 0, 0, 0, 0, ( 16 OF False ),D 0, 0, 0, 0, 0, 0, 0, 0, ( 0, 0 ) );M { This may be used in an assignment statement to fill in all the fields }5M { of a window descriptor block in one fell swoop. u }RHVAR { Some variables that virtually all Synergy applications will use } WITBF: [External] RECORD- *6ht: Integer ); SEQ11;t>PROCEDURE WICRW( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: :WindowDescriptor ); SEQ11;6PROCEDURE WIDSW( VAR Status: StatusBlock;; L VAR WindowID: [ReadOnly] Integer ); SEQ11;s>PROCEDURE WIGEW( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: * MaxSize: Integer; - CurrentLength: Integer;LL 8Characters: PACKED ARRAY [ 1..MaxTBFSize ] OF Char;# END { WITBF } ;tO { Definition of the Synergy-provided type-ahead buffer that is used to }sO { pass read-ahead characters from the application to Synergy and back. }S) ActualVersion, { Returned from WIINI } ) ColorWindows: { ReturneCd from WIINI }; integer;H CharacterHeight: [External(CHARH* :WindowDescriptor ); SEQ11;>PROCEDURE WISWP( VAR Status: StatusBlock;: , VAR DescriptorLength: [ReadOnly] Integer;L  VAR Descriptor: :WindowDescriptor ); SEQ11;@PROCEDURE WITTL( VAR Status: StatusBlock;<  VAR TitleLength: [ReadOnly] Integer;D V VAR TitleText: [ReadOnly,Unsafe] String ); SEQ11; S9PROCEDURE WIERW( VAR Status:  StatusBlock;D5 * I)] Unsigned; { Returned from WIINI }H CharacterWidth: [External(CHARWI)] Unsigned; { Returned from WIINI }) PixelHeight, { Returned from WIINI }h) PixelWidth, { Returned from WIINI } ) ScreenWidth, { Returned from WIINI }R) ScreenHeight: { Returned from WIINI }e Unsigned;  lO{ These are some procedure definitions for a number of the Synergy services. } =PROCEDURE WIINI( VAR Status:  StatusBlock; 9 " VAR ExpectedVersion: [ReadOnly] I*   VAR Len1: [ReadOnly] Integer; 4 & VAR Msg1: [ReadOnly,Unsafe] String;5  VAR Len2: [ReadOnly] Integer; 4 & VAR Msg2: [ReadOnly,Unsafe] String;5  VAR Len3: [ReadOnly] Integer;a4 & VAR Msg3: [ReadOnly,Unsafe] String;5  VAR Len4: [ReadOnly] Integer;u4 & VAR Msg4: [ReadOnly,Unsafe] String;5  VAR Len5: [ReadOnly] Integer;H=  VAR ++s͌,99TVdx S r[q Skf[q S :  +?UU uP5`wJ&& C`  *e,u0B~  & SY&& C`  C0Cm,.u1B~ 5 %% %%4ae*45"p(3  0% w,U5@`w45` z |**U \5 * kU`cB aeR`5`O55[B4BS%)%!F%+M:SYSYSYSYSYSYSYSYSYSYSYSYTITISYOV+=%4&8u5 B" B B *A6Erff wJ f\U `  MVAR MenuID: [ReadOnly] Integer ); SEQ11;:PROCEDURE EXFLOW( VAR Status: StatusBloc+] ~w%w%,w~0wvwnDwf4w^wV(wNHwFP TX`dw&8ww<whlw w\wLw@www f&.0&*"e.30*"e + ?k;6 VAR KeyPressed: Integer;6 VAR MenuID: Integer;6 VAR OptionValue: Integer;6 &VAR FrameID: [ReadOnly] Integer;? OVAR InitialLeaf: [ReadOnly] Integer ); SEQ11; 6PROCEDURE EXHELP( VAR Status:  StatusBlock;; *VAR FrameID: [ReadOnly] Integer ); SEQ11;;2+ &.0 %0\w4 H5ae   %6U^ , p5 ^U ^bpXp[w\wN ^+5^ 5^#X f* ,0 h 5` w ##!"       ʥ  w&*"ePBe  ~PpT585p\u7   ,},eG &wpe? WtE & fYf&B f ##! B EB BH#*u &*5@U@ &*E@E &f LB:[1,2]BASIC2.ERR&f P PP P,d,vTԂ&"8,vTf&|0x,TԂ&DdlN!"\,T~&`dlN!"\,Tz&|dlN!"\,Tv&ƘdlN!"\,Tr&ƴdl|N!"\,Tn&dl`N!"\,Tj&dlHN!"\,Tb&dlN!"\,T^&$dlN!"\,TZ&@dl.N!"\,TV&\dlN!"\d,:TbFN!N!@"8,vTR&Ʀ,:TbFN!@"8,vTN&, Tӂ "`b "`d դ 2Z $ դ "F ,aqP P2BRNT&xP,V$<<<2,Z$,^ ">>@@v #,vTԂx,vTbF8H,xTbN!"Ɛ դ 0 դ 2HZ դ ,,Z,082v0$,vTԂ,vTbF8H,xTbN!"Ɛv$,vTԂ0,vTbF8H,xTbN!"ƐTZb : d8pN!V d"\ҠlN!@r"Ҡ"z҈TbFN!҈@҈v#Ն v$$HN$L|lD4 ,t ,Q ,P<P P  fb> T  $*w4 l$C3 3  ,, UEs3w$7&f7 B * ͋'% ͥ!ͥE%,  K5  P,{J D(@ ZD> P $SY:$  $<"B0B BBBAAAA@AA@C Trap, ERR=Oops, that's not a number.WIDES WIGKS WICRS  I/O error on Bad entry position in ,^62  6 A25`.6+B +(565`U`^E`U` wjA2pV Ap$w0  E@*Ue0=300 ^w Vw Nw4 Fw2 >@1f*E5@U"B"e 5 ! ZeXev sX&fV ~*, > T V ^ w` b lCf <V d R$~*& & &  r&& & & Ε ,iuB2 %pˋ5J J J @ EͥAA I*P) >49L)NFF F!V!VUE drՆ  v D$,vTԂ,vTbF>8H,xTbN!"Ɛ,^lNR!,R!NN DD:v#, b+ *mH&*Z * LB:[1,2]BASIC2.ERRRESUME w leE D` bl lrw *  B eE"s    s-  Cslw  wwB&*&e& <5 ACCl  rf*e @eEf "*p`E  B~ *U@eB B  ZB B f &~Wtu` B " b, ,vTԂ8,vTbF 8H,xTbN!"Ɛd ^8&V"ƘՂ d0 ,TԂ&Ǝd:v#",T~&ƶd:8v#",Tz&d:468v#",Tv&d:z.8v#",Tr&Nd@1f*E5@U"B"e 5 ! ZeXev sX&f ~*    $ w& ( lCf v * R$~*& & &  r&& & & Ε  4*mH&* */  ~w0w4,wD0w<w4Dw,4w$w(wHw P TX`dw8ww<whlw w\wLw@www f&.0&*"e.30*"e / LB:[1,2]BASIC2.ERRRESUME w leE D` bl lrw *  B eE"s    s-  Cslw  wwB&*&e& <5 ACCl  rf*e @eEf "*p`E  B~ *U@eB B  ZB B f &~Wtu` B " b &wpe? WtE & fYf&B f 00X> TP $SY:$  $< BEFAh3A0*n `| Bt'&1 D/ <l/ 4l/5ew , Bv    5Bw 0w0=MF1 5  .5.UW   0y PH&xPRPP0 CBzC#CBzGCBz CBz7 0 7 " 7         7     &-&lHe ` -XP`6wJ ׭0wP  ,(x>  w@ 4 lhC3 3  ,, UEs3w. &f. B * ͋'% ͥ!ͥE%,  K5  PB72 %pˋ5J J J 0z L є~w7  w   N7  6 w~zrznvhrdn\vXrPTLPf&4@(& w w7  LNS~ W  y:w.@ PH.w L є~*w  v&D`wl ewp wf   Be<`7. @a  Հ 5 50  ;@ EͥAA IP) >0  WHITE d@ < XǠ BǠ D@ F@ H@ @<>@<x@ <LHN&$L|lD4 ,t 6| N D( ZD0  2 Հ`7ww -w am D`w `w VW w w Sw 4W w wp S W w f NwpHwD SwN W wz bS  wd N w  Sw   D~  D~w xW w S ^ w  w w :Hw x "H C`Д wp PwP HwZ 6 H  C` w4   B~ C`wXvL 111) } }:11!  !SYNERGY/I2NAME "Make screen white" EXECUTE [ZZPROVUE]REMEXE.TSK/REMFILE WHITE.TSK/DELETE EXECUTE [ZZPROVUE]INSAPP.TSK/INS"!INSTALL [ZZSYS]PBFSML.TSK/LIBRARY!INSTALL WHITE.TSK/TASK !RUN WHITE!INSTALL [ZZPROVUE]SYNRUN.TSK/TASK RUN WI$MGR11m1,   wE5 E  W LJ5  ,E 6/ $#H )aw 6  w 4, e 1 w ,,#E U &W 96 3  4 &9U &9E &9U3uE uU.5`.U & E&u & f&ËDef Ë )̋E U&ff kf[q1(uX.&.  t&L&  H/0/3gJ Z/6/H/\}`80 H/l/K}L0# H/Z/q 5`0/06/r@/~//IqMt0@//IqM0@//IqM0~//U(U00/5r0/U,1 /kf[qr[qr[qVdxVdxS1 '@0~/Vdx0/0rT,`"0$#"0f$# ###.%%% & & & && 22)z z""32q7SYSDISK:[ZZPROVUE]SYNERGY.ST2SYSDISK:[ZZPROVUE]SYNERGY.STR`hdfSYSDISK:[ZZPROVUE]SYNERR.HLPCHK1CHK27 d <-V 3 Dw%0 |w7   Ap*Ap-w  7 f& e77f& ef` te T P w0 4 l \7w  w w w ,ww wP2Ps,wwU kfz(S kf[q S r[q S:2  PP  PP  P0@p r & 2!%SYSYSYSYTICLSYSY22KNE^EN219 E B r z z r2 m2 fFESYSDISK:[ZZPROVUE]WINSAPPL.DATSYSDISK:[ZZPROVUE]TEMPAPPL.DATP P P  33| r  :  wd4  xtC3 3  ,, UEs3w F,&f  B * ͋'% ͥ!ͥE%,  K5  PB 2 33vm%pˋ5J J J @ EͥAA Ih3QC33b6'&1 , $  5ew d, Bv    5Bw 1 5  .5.UW   ,   wE5O E  W LJ5  ,E n ):aw 6  w 8, e 1 w3S ~<:jvj> D ::p(r@IqM@IqM@IqMU(U*p3gJ \}`> K}R# q 5f:pkfZ (Lkf z( :ZK (prT,`}:3g    E U &W 96 3  4 &9U &9E &9U3uE uU.5`.U & E& & f&ËDef Ë C)̋E U&ff r[qr[qkf[qkf[qkfzkfzM3j 6666HHHZZ/3  3  _M6z6Bz[Bz߆!AyyjR|jRUqTUq_M@26@p(U   *   424zGY applicationTEXT02"Error in window manager interface.TEXT042Synergy window envirovment not installed properly.TEXT08* Press RESUME to continueEXITREM1 DTYPTTITL$Unable to remove SYNERGY applicationTEXT027Application is still active within SYNERGY environment.sTEXT04(Please exit application before removing.TEXT08* Press RESUME to continueEXITREM2 DTYPTTITL$Unable to remove SYNERGY applicationTEXT02$Synergy environment is still active.TEXT048Please exi4 wer version of the SynergyTEXT046Window Manager before it can be installed. To updateTEXT058the window manager you must preform the following steps:TEXT071 1. Remove the current synergy window manager.nTEXT096 2. Install the new window managers application fromTEXT10( the diskettes labled SYNERGYBL14.TEXT12" 3. Reinstall this application.TEXT15+ |Press RESUME to continue.GEXITe.EXITCHK2 DTYPFTITLSynergy installation errorTEXT038This application requires a ne4LOG1 DTYPTTITL+ERROR installing SYNERGY window applicationoTEXT022Error translating logicals for application name orTEXT03application directory.TEXT05Logicals = APPL$DST, DST$NAMEiTEXT08% Press RESUME to continueiEXITWIN1 DTYPTTITL+ERROR installing SYNERGY window applicationeTEXT02(Cannot open file [ZZPROVUE]WINSAPPL.DATTEXT042SYNERGY window environment not installed properly.TEXT07" NPress RESUME to continueEXITWIN2 DTYPTTITL+ERROR installing SYNERGY win46t SYNERGY window environtment before removing.TEXT08* Press RESUME to continueEXITLOG3 DTYPTTITL,Unable to install SYNERGY window environmentTEXT02=Error retrieving application name or directory specification.iTEXT04$Logical strings = APPL$DST, DST$NAMETEXT07& Press RESUME to continueEXITWIN3 DTYPTTITL,Unable to install SYNERGY window environmentTEXT02,Error creating window application data base:TEXT03[ZZPROVUE]WINSAPPL.DATTEXT06& Press RESUME4Bdow applicationlTEXT020File operation error in [ZZPROVUE]WINSAPPL.DATTEXT042SYNERGY window environment not installed properly.TEXT07' Press RESUME to continueEXITSVR1 DTYPTTITL+ERROR installing SYNERGY window applicationTEXT02Window Server interface error.TEXT04+Unable to read frame file [ZZPROVUE]UI.OFF.oTEXT052SYNERGY window environment not installed properly.TEXT07& ^Press RESUME to continueEXITSVR2 DTYPTTITL+ERROR installing SYNERGY window applicationg4 to continueEXIT:RAP1 DTYPTTITLWarningpTEXT024This version of the Window Manager is being removed.TEXT04>If you still wish to run your Synergy applications on the PRO,TEXT05?you must reinstall this window manager or install a new versiontTEXT06of the window manager.TEXT08* Press RESUME to continueEXITFUL1 DTYPTTITL Disk is FullTEXT02&Cannot install Synergy Window Manager.TEXT046Not enough room on disk for creating Raster Workspace.TEXT08)  Press RESUME 4XTEXT02Window Server interface error.TEXT04"Unable to activate window display.TEXT07& Press RESUME to continueEXITENV1 DTYPTTITL+ERROR installing SYNERGY window applicationrTEXT02*Window environment not installed properly.TEXT04(Cannot open frame file [ZZPROVUE]UI.OFFTEXT07& Press RESUME to continueEXITSTR1 DTYPTTITL+ERROR installing SYNERGY window applicationmTEXT03; Error in SYNERGY activation command file: SYNERGY.ST2cTEXT06& Press RESUME47to continueiEXITRDUM1 DTYPTTITLERROR Starting ApplicationTEXT02This is a Synergy Application.TEXT034It cannot be started from the P/OS application menu.TEXT052You must first start the 'Synergy Window Manager'.TEXT06FYou may then run this appli3cation from the Window Manager's main menu.TEXT08. Press RESUME to continueEXITCKP1 DTYPTTITLError Removing ApplicationTEXT02-SYNERGY still has the checkpoint file active.eTEXT041You must first reboot your system and then rem4 } to continueEXITSTR2 DTYPTTITL+ERROR installing SYNERGY window applicationoTEXT02, Cannot activate SYNERGY window environment.TEXT046 Task specified in file SYNERGY.ST2 cannot be spawned.TEXT07' Press RESUME to continue EXITMGR1 DTYPTTITL$ERROR installing SYNERGY applicationTEXT02Window manager interface error.YTEXT04<Synergy window environment not installed/activated properly.TEXT07* HPress RESUME to continueEXITMGR2 DTYPTTITL$Unable to remove SYNER4 !&oveYTEXT05this application.pTEXT08* Press RESUME to continueEXITTCHK1 DTYPTTITLSynergy installation errorTEXT014This application requires the Synergy Window ManagerTEXT02before it can be installed.rTEXT044First install the window manager application locatedTEXT05on diskette labGled SYNERGYV2.TEXT07(Then you may reinstall this application.TEXT08( t Press RESUME to continue.EXITCHK2 DTYPFTITLSynergy installation errorTEXT038This application requires a ne 55m5m5m5m5m5m5m5m5 m5 m 6 6m6m6m6m6m6m6m6m6 m6 m 77m7m7m7m7m7m7m7m7 m7 m 8^8m8m8m8m8m8m8m8m8 m8 m 99m9m9m9m9m9m9m9m9 m9 m :L:m:m:m:m:m:m:m:m: m: m ;;m;m;m;m;m;m;m;m; m; m <z<m<m<m<m<m<m<m<m< m< m ==m=m=m=m=m=m=m=m= m= m >h>m>m>m>m>m>m>m>m> m> m ??m?m?m?m?m?m?m?m? m? m @-@m@m@m@m@m@m@m@m@ m@ m AAmAmAmAmAmAmAmAmA mA m B?BmBmBmBmBmBmBmBmB mB m CCmCmCmCmCmCmCmCmC mC m D DmDmDmDmDmDmDmDmD mD m EEmEmEmEmEmEmEmEmE mE m FFmFmFmFmFmFmFmFmF mF m GGmGmGmGmGmGmGmGmG mG m HeHmHmHmHmHmHmHmHmH mH m IImImImImImImImImI mI m JwJmJmJmJmJmJmJmJmJ mJ m KKmKmKmKmKmKmKmKmK mK m LALmLmLmLmLmLmLmLmL mL m MMmMmMmMmMmMmMmMmM mM m NSNmNmNmNmNmNmNmNmN mN m OOmOmOmOmOmOmOmOmO mO mO