window.mod 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
  1. (* Copyright (C) 1987 Jensen & Partners International *)
  2. (*$V-,R-,S-,I-,A-,O-*)
  3. IMPLEMENTATION MODULE Window;
  4. FROM SYSTEM IMPORT Registers,CurrentProcess,Seg,Ofs;
  5. FROM Storage IMPORT ALLOCATE,DEALLOCATE;
  6. FROM Str IMPORT Length,CHARSET,Copy;
  7. FROM Lib IMPORT Move,WordMove,Fill,WordFill,ScanR,FatalError;
  8. FROM AsmLib IMPORT BufferToScreen,BufferWrite,ActivePage,PalXlat,
  9. ScreenToBuffer,InitScreenType;
  10. IMPORT Lib,IO;
  11. TYPE
  12. UseListPtr = POINTER TO UseListLink;
  13. UseListLink = RECORD
  14. Next : UseListPtr;
  15. Proc : ADDRESS;
  16. Wind : WinType;
  17. END;
  18. VAR
  19. UseList : UseListPtr;
  20. WindowStack : WinType;
  21. CursorStack : WinType;
  22. MultiP : BOOLEAN;
  23. Lock,Unlock : PROC;
  24. CursorLines : CARDINAL ;
  25. CONST
  26. GuardConst = 4A4EH;
  27. PROCEDURE CheckWindow (*$N*) ( W : WinType );
  28. BEGIN
  29. IF W^.Guard-Seg(W^) <> GuardConst THEN
  30. FatalError('Window, Fatal error : Invalid window');
  31. END;
  32. END CheckWindow;
  33. PROCEDURE (*$N*) ClipFrame ( W : WinType );
  34. VAR
  35. i : CARDINAL;
  36. BEGIN
  37. WITH W^ DO
  38. IF WDef.FrameOn THEN i := 1 ELSE i := 0 END;
  39. IF XA < WDef.X1+i THEN
  40. XA := WDef.X1+i
  41. ELSIF XA > WDef.X2-i THEN
  42. XA := WDef.X2-i
  43. END;
  44. IF XB > WDef.X2-i THEN
  45. XB := WDef.X2-i
  46. ELSIF XB < WDef.X1+i THEN
  47. XB := WDef.X1+i
  48. END;
  49. IF YA < WDef.Y1+i THEN
  50. YA := WDef.Y1+i
  51. ELSIF YA > WDef.Y2-i THEN
  52. YA := WDef.Y2-i
  53. END;
  54. IF YB > WDef.Y2-i THEN
  55. YB := WDef.Y2-i
  56. ELSIF YB < WDef.Y1+i THEN
  57. YB := WDef.Y1+i
  58. END;
  59. Width := XB-XA+1; Depth := YB-YA+1;
  60. END;
  61. END ClipFrame;
  62. PROCEDURE ClipXY ( W : WinType; VAR X,Y : RelCoord );
  63. VAR
  64. mw,md : CARDINAL;
  65. BEGIN
  66. WITH W^ DO
  67. mw := Width; md := Depth;
  68. IF WDef.FrameOn AND NOT WDef.WrapOn THEN
  69. INC(md); INC(mw)
  70. ELSE
  71. IF X=0 THEN X := 1 END;
  72. IF Y=0 THEN Y := 1 END;
  73. END;
  74. IF X>mw THEN X := mw END;
  75. IF Y>md THEN Y := md END;
  76. END;
  77. END ClipXY;
  78. PROCEDURE (*$N*) BufferSpaceFill ( W : WinType; pos : CARDINAL; len : CARDINAL );
  79. BEGIN
  80. WITH W^ DO
  81. IF IsPalette THEN
  82. WordFill(ADR(Buffer^[pos]),len,32
  83. +VAL(CARDINAL,CurPalColor)*256);
  84. ELSE
  85. WordFill(ADR(Buffer^[pos]),len,32+
  86. ORD(WDef.Foreground)*256+ORD(WDef.Background)*4096);
  87. END;
  88. END;
  89. END BufferSpaceFill;
  90. PROCEDURE (*$N*) CurWin () : WinType;
  91. (*
  92. Returns The current window being used for output for this process
  93. If no window assigned by Use then returns Top
  94. NB Locks window system and leaves locked if MultiP set
  95. *)
  96. VAR
  97. u : UseListPtr;
  98. p : ADDRESS;
  99. BEGIN
  100. IF MultiP THEN
  101. Lock();
  102. p := CurrentProcess();
  103. u := UseList^.Next;
  104. LOOP
  105. IF u=NIL THEN
  106. RETURN WindowStack (* Top() *)
  107. ELSIF p=u^.Proc THEN
  108. RETURN u^.Wind;
  109. END;
  110. u := u^.Next;
  111. END;
  112. END;
  113. u := UseList^.Next;
  114. IF u = NIL THEN RETURN WindowStack (* Top() *) END;
  115. RETURN u^.Wind;
  116. END CurWin;
  117. PROCEDURE (*$N*) ResetCursor;
  118. VAR
  119. R : Registers;
  120. mode : CARDINAL;
  121. BEGIN
  122. IF (CursorStack = NIL) OR
  123. ObscuredAt(CursorStack,CursorStack^.CurrentX,CursorStack^.CurrentY) THEN
  124. mode := 2000H;
  125. ELSE
  126. WITH CursorStack^ DO
  127. WITH R DO
  128. AH := 2;
  129. BH := ActivePage();
  130. DL := SHORTCARD(XA+CurrentX-1);
  131. DH := SHORTCARD(YA+CurrentY-1);
  132. END;
  133. Lib.Intr(R,10H);
  134. END;
  135. mode := CursorLines;
  136. END;
  137. R.AH := 1;
  138. R.CX := mode;
  139. Lib.Intr(R,10H);
  140. END ResetCursor;
  141. PROCEDURE (*$N*) UnlinkCursor ( W : WinType );
  142. VAR
  143. w : WinType;
  144. BEGIN
  145. w := CursorStack;
  146. IF w = W THEN CursorStack := w^.CursorChain END;
  147. LOOP
  148. IF w = NIL THEN RETURN END;
  149. IF w^.CursorChain = W THEN
  150. w^.CursorChain := W^.CursorChain;
  151. RETURN;
  152. END;
  153. w := w^.CursorChain;
  154. END;
  155. END UnlinkCursor;
  156. (* ------------------------- *)
  157. (* Cursor Control *)
  158. (* ------------------------- *)
  159. PROCEDURE (*$F*) CursorOn;
  160. VAR
  161. w,cw : WinType;
  162. BEGIN
  163. cw := CurWin();
  164. UnlinkCursor(cw);
  165. cw^.WDef.CursorOn := TRUE;
  166. IF NOT cw^.WDef.Hidden THEN
  167. cw^.CursorChain := CursorStack;
  168. CursorStack := cw;
  169. END;
  170. ResetCursor;
  171. Unlock();
  172. END CursorOn;
  173. PROCEDURE (*$F*) CursorOff;
  174. VAR
  175. w,cw : WinType;
  176. BEGIN
  177. cw := CurWin();
  178. UnlinkCursor(cw);
  179. cw^.WDef.CursorOn := FALSE;
  180. ResetCursor;
  181. Unlock();
  182. END CursorOff;
  183. (* ------------------------- *)
  184. (* Window creation *)
  185. (* ------------------------- *)
  186. PROCEDURE (*$N*) MakeWindow ( VAR WD : WinDef ) : WinType;
  187. (*
  188. Creates a new Window descriptor
  189. The size is Inclusive of frame if needed
  190. does not allocate buffer
  191. *)
  192. VAR W : WinType; min : CARDINAL ;
  193. BEGIN
  194. NEW(W);
  195. WITH W^ DO
  196. WITH WD DO
  197. IF X2 >= ScreenWidth THEN X2:=ScreenWidth-1 END;
  198. IF Y2 >= ScreenDepth THEN Y2:=ScreenDepth-1 END;
  199. IF WD.FrameOn THEN min := 2 ELSE min := 0 END ;
  200. IF (X1+min>X2) THEN X2 := X1+min END ;
  201. IF (Y1+min>Y2) THEN Y2 := Y1+min END ;
  202. XA := X1; YA := Y1; XB := X2; YB := Y2;
  203. Width := X2-X1+1 ; Depth := Y2-Y1+1;
  204. END;
  205. WDef := WD;
  206. OWidth := Width ; ODepth := Depth;
  207. CurrentX := 1;
  208. CurrentY := 1;
  209. Next := NIL;
  210. Buffer := NIL;
  211. UserRecord := NIL;
  212. IsPalette := FALSE;
  213. CurPalColor:= NormalPaletteColor;
  214. TMode := NoTitle;
  215. Guard := GuardConst+Seg(W^);
  216. Title := NIL;
  217. END;
  218. ClipFrame(W);
  219. RETURN W;
  220. END MakeWindow;
  221. PROCEDURE (*$F*) Open ( WD : WinDef ) : WinType;
  222. (*
  223. Opens a window on the screen ready for use
  224. *)
  225. VAR
  226. W : WinType;
  227. BEGIN
  228. Lock();
  229. W := MakeWindow (WD);
  230. WITH W^ DO
  231. ALLOCATE ( Buffer,OWidth*ODepth*2);
  232. BufferSpaceFill(W,0,OWidth*ODepth);
  233. IF WD.FrameOn THEN
  234. SetFrame(W,WDef.FrameDef,WDef.FrameFore,WDef.FrameBack);
  235. END;
  236. END;
  237. IF WD.Hidden THEN
  238. Use ( W )
  239. ELSE
  240. PutOnTop ( W )
  241. END;
  242. Unlock();
  243. RETURN W;
  244. END Open;
  245. (* ------------------------- *)
  246. (* Window stack manipulation *)
  247. (* and screen redraw *)
  248. (* ------------------------- *)
  249. PROCEDURE (*$F*) Use ( W : WinType );
  250. (*
  251. Causes all subsequent output (by the current process)
  252. to appear in the specified Window
  253. NB does not have to be Top Window (or in fact on the screen at all)
  254. UseList is the MRU window
  255. *)
  256. VAR
  257. p : ADDRESS;
  258. u : UseListPtr;
  259. up : UseListPtr;
  260. BEGIN
  261. Lock();
  262. CheckWindow(W);
  263. p := CurrentProcess();
  264. up := UseList;
  265. u := up^.Next;
  266. LOOP
  267. IF u = NIL THEN NEW(u); u^.Proc := p; EXIT END;
  268. IF p = u^.Proc THEN up^.Next := u^.Next; EXIT END;
  269. up := u; u := u^.Next;
  270. END;
  271. u^.Next := UseList^.Next;
  272. UseList^.Next := u;
  273. u^.Wind := W;
  274. Unlock();
  275. END Use;
  276. PROCEDURE (*$N*) TakeOffStack ( W : WinType ); (* Private *)
  277. VAR pw : WinType;
  278. BEGIN
  279. IF W = WindowStack THEN
  280. WindowStack := W^.Next;
  281. ELSE
  282. pw := WindowStack;
  283. IF W <> pw THEN
  284. LOOP
  285. IF (pw = NIL) THEN EXIT END;
  286. IF (pw^.Next = W) THEN pw^.Next := W^.Next; EXIT END;
  287. pw := pw^.Next;
  288. END;
  289. END;
  290. END;
  291. W^.Next := NIL;
  292. END TakeOffStack;
  293. PROCEDURE (*$N*) UpdateScreen ( W : WinType; X,Y : AbsCoord; Len : CARDINAL );
  294. (* Updates the screen from the window buffer *)
  295. VAR
  296. NextLen,
  297. NextX : AbsCoord;
  298. w : WinType;
  299. oxa,oxb,ax,bx : AbsCoord;
  300. buff : ARRAY[0..ScreenWidth-1] OF CARDINAL;
  301. a : ADDRESS;
  302. BEGIN
  303. IF W^.WDef.Hidden THEN RETURN END;
  304. WHILE Len<>0 DO
  305. (* adjust co ordinates for crossing windows *)
  306. NextLen := 0;
  307. w := WindowStack;
  308. ax := X; bx := X+Len-1;
  309. LOOP
  310. IF (w = W)OR(w=NIL) THEN EXIT END;
  311. WITH w^ DO
  312. IF (Y>=WDef.Y1) AND (Y<=WDef.Y2) THEN
  313. oxa := WDef.X1; oxb := WDef.X2;
  314. IF (ax>=oxa) AND (bx<=oxb) THEN (* wiped out *)
  315. ax := bx+1; EXIT;
  316. ELSIF (ax<=oxb) AND (bx>=oxa) THEN (* some interaction *)
  317. IF (ax<oxa) AND (bx>oxb) THEN (* cut into two *)
  318. bx := oxa-1;
  319. NextX := oxb+1;
  320. NextLen := X+Len-NextX;
  321. ELSIF (bx>oxb) THEN (* left edge cut off *)
  322. ax := oxb+1;
  323. ELSIF (ax<oxa) THEN (* right edge cut off *)
  324. bx := oxa-1;
  325. END;
  326. END;
  327. END;
  328. w := Next;
  329. END;
  330. END;
  331. Len := bx-ax+1;
  332. IF Len <> 0 THEN
  333. WITH W^ DO
  334. a := ADR(Buffer^[(ax-WDef.X1)+(Y-WDef.Y1)*OWidth]);
  335. IF IsPalette THEN
  336. PalXlat(ADR(buff),a,Len,ADR(PalAttr));
  337. a := ADR(buff);
  338. END;
  339. BufferToScreen ( ax,Y,a,Len);
  340. END;
  341. END;
  342. X := NextX;
  343. Len := NextLen;
  344. END;
  345. END UpdateScreen;
  346. PROCEDURE (*$N*) RedrawSection ( W : WinType;
  347. X1,Y1,X2,Y2 : AbsCoord ); (* Private *)
  348. (* redraws rectangular portion of the window from the buffer *)
  349. VAR
  350. Y : AbsCoord;
  351. BEGIN
  352. FOR Y := Y1 TO Y2 DO
  353. UpdateScreen(W,X1,Y,X2-X1+1);
  354. END;
  355. END RedrawSection;
  356. PROCEDURE (*$N*) RedrawWindow ( W : WinType ); (* Private *)
  357. BEGIN
  358. WITH W^ DO
  359. RedrawSection ( W,WDef.X1,WDef.Y1,WDef.X2,WDef.Y2 );
  360. END;
  361. END RedrawWindow;
  362. PROCEDURE (*$N*) RedrawWindowPane ( W : WinType ); (* Private *)
  363. BEGIN
  364. WITH W^ DO
  365. RedrawSection ( W,XA,YA,XB,YB );
  366. END;
  367. END RedrawWindowPane;
  368. PROCEDURE (*$N*) DisplayBeneath ( W : WinType; NW : WinType ); (* Private *)
  369. (* Re-displays windows Obscured by W from NW *)
  370. VAR
  371. x1,x2,y1,y2 : AbsCoord;
  372. BEGIN
  373. WITH W^ DO
  374. WHILE NW<>NIL DO
  375. IF ((WDef.X2>=NW^.WDef.X1)AND(NW^.WDef.X2>=WDef.X1) AND
  376. (WDef.Y2>=NW^.WDef.Y1)AND(NW^.WDef.Y2>=WDef.Y1)) THEN (* windows cross *)
  377. (* calculate Intersection *)
  378. IF WDef.X1>NW^.WDef.X1 THEN
  379. x1 := WDef.X1
  380. ELSE
  381. x1 := NW^.WDef.X1
  382. END;
  383. IF WDef.X2<NW^.WDef.X2 THEN
  384. x2 := WDef.X2
  385. ELSE
  386. x2 := NW^.WDef.X2
  387. END;
  388. IF WDef.Y1>NW^.WDef.Y1 THEN
  389. y1 := WDef.Y1
  390. ELSE
  391. y1 := NW^.WDef.Y1
  392. END;
  393. IF WDef.Y2<NW^.WDef.Y2 THEN
  394. y2 := WDef.Y2
  395. ELSE
  396. y2 := NW^.WDef.Y2
  397. END;
  398. RedrawSection (NW, x1,y1,x2,y2 );
  399. END;
  400. NW := NW^.Next;
  401. END;
  402. END;
  403. END DisplayBeneath;
  404. PROCEDURE (*$F*) PutOnTop ( W : WinType );
  405. (*
  406. Puts the specified window on the top of the window stack
  407. Ensuring that it is fully visible.
  408. If this results in other windows becoming obscured then a buffer
  409. is allocated for each of these windows.
  410. All otherwise undirected output (ie with no Use) will appear
  411. within this window.
  412. *)
  413. BEGIN
  414. Lock();
  415. CheckWindow(W);
  416. IF W <> WindowStack THEN
  417. TakeOffStack( W );
  418. W^.Next := WindowStack;
  419. WindowStack := W;
  420. WITH W^ DO
  421. WDef.Hidden := FALSE;
  422. RedrawWindow ( W );
  423. IF WDef.CursorOn THEN
  424. Use ( W );
  425. CursorOn;
  426. END;
  427. END;
  428. END;
  429. Use ( W );
  430. ResetCursor;
  431. Unlock();
  432. END PutOnTop;
  433. PROCEDURE (*$F*) Hide ( W : WinType );
  434. (*
  435. Removes window from the Window stack and also the screen
  436. Placing the windows contents in a buffer for possible re-display later
  437. Uncovers obscured windows
  438. *)
  439. VAR
  440. p : WinType;
  441. w : WinType;
  442. BEGIN
  443. Lock();
  444. CheckWindow(W);
  445. WITH W^ DO
  446. IF NOT WDef.Hidden THEN
  447. w := W^.Next;
  448. TakeOffStack ( W );
  449. DisplayBeneath ( W, w );
  450. IF WDef.CursorOn THEN CursorOff; WDef.CursorOn := TRUE; END;
  451. WDef.Hidden := TRUE;
  452. END;
  453. END;
  454. ResetCursor;
  455. Unlock();
  456. END Hide;
  457. PROCEDURE (*$F*) PutBeneath ( W : WinType; WA : WinType );
  458. (*
  459. Puts window W beneath window WA
  460. *)
  461. VAR
  462. p : WinType;
  463. w : WinType;
  464. BEGIN
  465. Hide(W);
  466. Lock();
  467. CheckWindow(WA);
  468. WITH WA^ DO
  469. IF NOT WDef.Hidden THEN
  470. w := Next;
  471. Next := W;
  472. W^.Next := w;
  473. W^.WDef.Hidden := FALSE;
  474. RedrawWindow ( W );
  475. END;
  476. END;
  477. ResetCursor;
  478. Unlock();
  479. END PutBeneath;
  480. PROCEDURE (*$F*) SnapShot;
  481. (* Updates the Window buffer from the screen *)
  482. (* only works with non palette windows *)
  483. VAR
  484. W : WinType;
  485. y : CARDINAL;
  486. p : CARDINAL;
  487. BEGIN
  488. W := CurWin();
  489. WITH W^ DO
  490. WITH WDef DO
  491. IF NOT IsPalette THEN
  492. p := 0;
  493. FOR y := Y1 TO Y2 DO
  494. ScreenToBuffer(X1,y,ADR(Buffer^[p]),OWidth);
  495. INC(p,OWidth);
  496. END;
  497. END;
  498. END;
  499. END;
  500. Unlock();
  501. END SnapShot;
  502. (* ------------------------- *)
  503. (* Window disposal *)
  504. (* ------------------------- *)
  505. PROCEDURE (*$N*) DisposeTitle ( W : WinType );
  506. BEGIN
  507. WITH W^ DO
  508. IF TMode <> NoTitle THEN
  509. DEALLOCATE(Title,Length(Title^)+1);
  510. TMode := NoTitle;
  511. END;
  512. END;
  513. END DisposeTitle;
  514. PROCEDURE (*$F*) Close ( VAR W : WinType );
  515. (*
  516. removes the specified window from the screen
  517. deletes window descriptor and
  518. de-allocates any buffers previously allocated.
  519. *)
  520. VAR
  521. w : WinType;
  522. u,up,un : UseListPtr;
  523. BEGIN
  524. Lock();
  525. Hide ( W );
  526. TakeOffStack (W);
  527. UnlinkCursor(W);
  528. WITH W^ DO
  529. IF (Buffer <> NIL) THEN DEALLOCATE(Buffer,OWidth * ODepth * 2); END;
  530. END;
  531. up := UseList;
  532. u := up^.Next;
  533. WHILE (u<>NIL) DO
  534. un := u^.Next;
  535. IF (u^.Wind = W) THEN
  536. up^.Next := un;
  537. DISPOSE(u);
  538. ELSE
  539. up := u;
  540. END;
  541. u := un;
  542. END;
  543. DisposeTitle(W);
  544. W^.Guard := GuardConst; (* Invalidate guard *)
  545. DISPOSE(W);
  546. Unlock();
  547. END Close;
  548. PROCEDURE (*$F*) Used () : WinType;
  549. (*
  550. Returns The current window being used for output for this process
  551. If no window assigned by Use then returns Top
  552. *)
  553. VAR
  554. w : WinType;
  555. BEGIN
  556. w := CurWin();
  557. Unlock();
  558. RETURN w;
  559. END Used;
  560. PROCEDURE (*$F*) Top () : WinType;
  561. (*
  562. Returns The current top Window
  563. *)
  564. VAR w : WinType;
  565. BEGIN
  566. Lock();
  567. w := WindowStack;
  568. Unlock();
  569. RETURN w;
  570. END Top;
  571. PROCEDURE (*$F*) At (X,Y : AbsCoord) : WinType;
  572. (*
  573. Returns the window displayed at the absolute position X,Y
  574. *)
  575. VAR
  576. W : WinType;
  577. BEGIN
  578. Lock();
  579. W := WindowStack;
  580. LOOP
  581. IF W = NIL THEN EXIT END;
  582. WITH W^ DO
  583. IF (Y >= WDef.Y1) AND (Y <= WDef.Y2) AND
  584. (X >= WDef.X1) AND (X <= WDef.X2) THEN
  585. EXIT
  586. END;
  587. W := Next;
  588. END;
  589. END;
  590. Unlock();
  591. RETURN W;
  592. END At;
  593. PROCEDURE (*$F*) ObscuredAt (W : WinType; X,Y : RelCoord ) : BOOLEAN;
  594. (*
  595. Returns if the specified window is obscured at the specified position
  596. *)
  597. VAR
  598. b : BOOLEAN;
  599. w : WinType;
  600. BEGIN
  601. Lock();
  602. CheckWindow(W);
  603. WITH W^ DO
  604. IF WDef.Hidden THEN
  605. b:= TRUE;
  606. ELSE
  607. INC(X,XA-1); INC(Y,YA-1);
  608. w := WindowStack;
  609. LOOP
  610. IF w = W THEN b := FALSE; EXIT END;
  611. WITH w^ DO
  612. IF (Y>=WDef.Y1) AND (Y<=WDef.Y2) AND
  613. (X>=WDef.X1) AND (X<=WDef.X2) THEN
  614. b := TRUE;
  615. EXIT
  616. END;
  617. w := Next;
  618. END;
  619. END;
  620. END;
  621. END;
  622. Unlock();
  623. RETURN b;
  624. END ObscuredAt;
  625. PROCEDURE (*$N*) WindowWrite ( W : WinType;
  626. x,y : RelCoord;
  627. Len : CARDINAL;
  628. str : ADDRESS;
  629. frame : BOOLEAN ); (* Private *)
  630. VAR
  631. Attr : CARDINAL;
  632. X,Y : AbsCoord;
  633. BEGIN
  634. IF Len>0 THEN
  635. WITH W^ DO
  636. IF IsPalette THEN
  637. IF frame THEN
  638. Attr := VAL(CARDINAL,FramePaletteColor);
  639. ELSE
  640. Attr := VAL(CARDINAL,CurPalColor);
  641. END;
  642. ELSIF frame THEN
  643. Attr := ORD(WDef.FrameFore)+ORD(WDef.FrameBack)*16;
  644. ELSE
  645. Attr := ORD(WDef.Foreground)+ORD(WDef.Background)*16;
  646. END;
  647. X := x+XA-1; Y := y+YA-1;
  648. IF Len+X-1 > WDef.X2 THEN Len := WDef.X2+1-X END;
  649. BufferWrite (ADR(Buffer^[X-WDef.X1+(Y-WDef.Y1)*OWidth]),str,Len,Attr);
  650. UpdateScreen(W,X,Y,Len);
  651. END;
  652. END;
  653. END WindowWrite;
  654. PROCEDURE (*$N*) DrawFrame ( W : WinType );
  655. VAR
  656. s : ARRAY[0..81] OF CHAR;
  657. w,l,tl : CARDINAL;
  658. i : CARDINAL;
  659. PROCEDURE PutTitle ( mode : CARDINAL; row : CARDINAL );
  660. VAR
  661. i,j : CARDINAL;
  662. BEGIN
  663. WITH W^ DO
  664. CASE mode OF
  665. 0 : i := 1 |
  666. 1 : i := (Width-tl) DIV 2 + 1; |
  667. 2 : i := Width+1-tl |
  668. ELSE
  669. i := MAX(CARDINAL);
  670. END;
  671. j := 0;
  672. WHILE (i<=Width)AND(j<tl) DO
  673. s[i] := Title^[j]; INC(i); INC(j)
  674. END;
  675. WindowWrite (W,0,row,OWidth,ADR(s),TRUE);
  676. END;
  677. END PutTitle;
  678. BEGIN
  679. WITH W^ DO
  680. IF NOT WDef.FrameOn THEN
  681. IF (OWidth<3)OR(ODepth<3) THEN RETURN END; (* No Room *)
  682. WDef.FrameOn := TRUE;
  683. ClipFrame(W);
  684. ResetCursor;
  685. END;
  686. s[0] := WDef.FrameDef[0];
  687. Fill(ADR(s[1]),Width,WDef.FrameDef[1]);
  688. s[Width+1] := WDef.FrameDef[2];
  689. IF TMode <> NoTitle THEN
  690. tl := Length(Title^);
  691. IF tl>Width THEN tl := Width END;
  692. END;
  693. PutTitle(ORD(TMode-LeftUpperTitle),0);
  694. (* Sides *)
  695. FOR i := 1 TO Depth DO
  696. WindowWrite(W,0,i,1,ADR(WDef.FrameDef[3]),TRUE);
  697. WindowWrite(W,Width+1,i,1,ADR(WDef.FrameDef[4]),TRUE);
  698. END;
  699. s[0] := WDef.FrameDef[5];
  700. Fill(ADR(s[1]),Width,WDef.FrameDef[6]);
  701. s[Width+1] := WDef.FrameDef[7];
  702. PutTitle(ORD(TMode-LeftLowerTitle),Depth+1);
  703. END;
  704. END DrawFrame;
  705. PROCEDURE (*$F*) SetFrame ( W : WinType;
  706. Frame : FrameStr;
  707. Fore, Back : Color );
  708. (*
  709. Put a frame around the specified window
  710. With Title String and border definition (see above)
  711. having specified fore/background colours for the border
  712. *)
  713. BEGIN
  714. Lock();
  715. CheckWindow(W);
  716. WITH W^ DO
  717. WDef.FrameDef := Frame;
  718. WDef.FrameFore := Fore;
  719. WDef.FrameBack := Back;
  720. END;
  721. DrawFrame(W);
  722. Unlock();
  723. END SetFrame;
  724. PROCEDURE (*$N*) MergeWindows ( s,d : WinType );
  725. (* slightly complicated procedure to merge two windows
  726. s is new (hidden) window
  727. d is old window to be merged into
  728. *)
  729. VAR
  730. w : WinDescriptor;
  731. r,wd : CARDINAL;
  732. sw,sd,so,sp : CARDINAL;
  733. dw,dd,do,dp : CARDINAL;
  734. BEGIN
  735. s^.CurrentX := d^.CurrentX;
  736. s^.CurrentY := d^.CurrentY;
  737. s^.CursorChain := d^.CursorChain;
  738. s^.UserRecord := d^.UserRecord;
  739. s^.CurPalColor := d^.CurPalColor;
  740. s^.Title := d^.Title;
  741. s^.TMode := d^.TMode;
  742. d^.TMode := NoTitle;
  743. d^.WDef.CursorOn := FALSE;
  744. w := d^; d^ := s^; s^ := w;
  745. WITH s^ DO
  746. sw := OWidth; sd := ODepth;
  747. IF WDef.FrameOn THEN
  748. DEC(sw,2); DEC(sd,2);
  749. sp := (OWidth+1);
  750. ELSE
  751. sp := 0;
  752. END;
  753. Guard := GuardConst+Seg(s^);
  754. END;
  755. WITH d^ DO
  756. dw := OWidth; dd := ODepth;
  757. IF WDef.FrameOn THEN
  758. DEC(dw,2); DEC(dd,2);
  759. dp := OWidth+1;
  760. ELSE
  761. dp := 0;
  762. END;
  763. Guard := GuardConst+Seg(d^);
  764. END;
  765. IF sd < dd THEN wd := sd ELSE wd := dd END;
  766. FOR r := 0 TO wd-1 DO
  767. IF sw>=dw THEN
  768. WordMove(ADR(s^.Buffer^[sp]),ADR(d^.Buffer^[dp]),dw);
  769. ELSE
  770. WordMove(ADR(s^.Buffer^[sp]),ADR(d^.Buffer^[dp]),sw);
  771. BufferSpaceFill(d,dp+sw,dw-sw);
  772. END;
  773. INC(sp,s^.OWidth); INC(dp,d^.OWidth);
  774. END;
  775. (* now fill rest *)
  776. IF wd<dd THEN
  777. FOR r := wd TO dd-1 DO
  778. BufferSpaceFill(d,dp,dw);
  779. INC(dp,d^.OWidth);
  780. END
  781. END;
  782. IF d^.WDef.FrameOn THEN DrawFrame(d) END;
  783. IF NOT s^.WDef.Hidden THEN
  784. d^.Next := s;
  785. d^.WDef.Hidden := FALSE;
  786. RedrawWindow(d);
  787. END;
  788. Close(s);
  789. END MergeWindows;
  790. PROCEDURE (*$N*) IGotoXY ( W : WinType; X,Y : RelCoord );
  791. (*
  792. Sets the current X Y position of the pane currently being used
  793. *)
  794. BEGIN
  795. WITH W^ DO CurrentX := X; CurrentY := Y END;
  796. IF CursorStack = W THEN ResetCursor END;
  797. END IGotoXY;
  798. (* ------------------------- *)
  799. (* Palette procedures *)
  800. (* ------------------------- *)
  801. PROCEDURE (*$N*) GetPal ( W : WinType; VAR Pal : PaletteDef );
  802. VAR
  803. i : PaletteRange;
  804. BEGIN
  805. CheckWindow(W);
  806. WITH W^ DO
  807. FOR i := 0 TO PaletteMax DO
  808. Pal[i].Fore := Color(PalAttr[i] MOD 16);
  809. Pal[i].Back := Color(PalAttr[i] DIV 16);
  810. END;
  811. END;
  812. END GetPal;
  813. PROCEDURE (*$N*) SetPal ( W : WinType; VAR Pal : PaletteDef );
  814. VAR
  815. i : PaletteRange;
  816. BEGIN
  817. CheckWindow(W);
  818. WITH W^ DO
  819. FOR i := 0 TO PaletteMax DO
  820. PalAttr[i] := VAL(SHORTCARD,ORD(Pal[i].Fore)+ORD(Pal[i].Back)*16);
  821. END;
  822. IsPalette := TRUE;
  823. END;
  824. END SetPal;
  825. PROCEDURE (*$F*) PaletteOpen(WD: WinDef; Pal: PaletteDef) : WinType;
  826. (*
  827. Opens a window on the screen ready for use
  828. *)
  829. VAR
  830. W : WinType;
  831. BEGIN
  832. Lock();
  833. W := MakeWindow (WD);
  834. SetPal(W,Pal);
  835. WITH W^ DO
  836. ALLOCATE ( Buffer,OWidth*ODepth*2);
  837. BufferSpaceFill(W,0,OWidth*ODepth);
  838. IF WD.FrameOn THEN
  839. SetFrame(W,WDef.FrameDef,WDef.FrameFore,WDef.FrameBack);
  840. END;
  841. END;
  842. IF WD.Hidden THEN
  843. Use ( W )
  844. ELSE
  845. PutOnTop ( W )
  846. END;
  847. Unlock();
  848. RETURN W;
  849. END PaletteOpen;
  850. PROCEDURE (*$F*) SetPaletteColor ( c : PaletteRange );
  851. VAR
  852. W : WinType;
  853. BEGIN
  854. W := CurWin();
  855. W^.CurPalColor := c;
  856. Unlock();
  857. END SetPaletteColor;
  858. PROCEDURE (*$F*) PaletteColor() : PaletteRange;
  859. VAR
  860. W : WinType;
  861. BEGIN
  862. W := CurWin();
  863. Unlock();
  864. RETURN W^.CurPalColor;
  865. END PaletteColor;
  866. PROCEDURE (*$F*) SetPalette(W: WinType; Pal: PaletteDef);
  867. (*
  868. Changes the Palette of the specified window,
  869. redisplaying the changed colors
  870. *)
  871. BEGIN
  872. Lock();
  873. SetPal(W,Pal);
  874. RedrawWindow(W);
  875. Unlock();
  876. END SetPalette;
  877. PROCEDURE (*$F*) PaletteColorUsed(W: WinType; pc: PaletteRange) : BOOLEAN;
  878. (*
  879. Returns if color in use anywhere in the window
  880. *)
  881. VAR
  882. p : CARDINAL;
  883. l : CARDINAL;
  884. m : CARDINAL;
  885. ba : POINTER TO ARRAY[0..MAX(CARDINAL)] OF SHORTCARD;
  886. BEGIN
  887. CheckWindow(W);
  888. WITH W^ DO
  889. ba := ADR(Buffer^);
  890. p := 0;
  891. m := OWidth*ODepth*2;
  892. LOOP
  893. l := m-p;
  894. p := p+ScanR(ADR(ba^[p]),l,pc);
  895. IF p >= m THEN RETURN FALSE END;
  896. IF ODD(p) THEN RETURN TRUE END;
  897. INC(p);
  898. END;
  899. END;
  900. END PaletteColorUsed;
  901. (* ------------------------- *)
  902. (* Move resize procedure *)
  903. (* ------------------------- *)
  904. PROCEDURE (*$F*) Change ( W : WinType; X1,Y1,X2,Y2 : AbsCoord );
  905. (*
  906. Changes the size and/or position of the specified window
  907. The contents of the window will be moved with it
  908. *)
  909. VAR
  910. nw : WinType;
  911. wd : WinDef;
  912. pal : PaletteDef;
  913. save : WinType;
  914. min : CARDINAL ;
  915. BEGIN
  916. CheckWindow(W);
  917. save := CurWin();
  918. WITH W^ DO
  919. IF X2>=ScreenWidth THEN X2:=ScreenWidth-1 END;
  920. IF Y2>=ScreenDepth THEN Y2:=ScreenDepth-1 END;
  921. wd := WDef;
  922. IF wd.FrameOn THEN min := 2 ELSE min := 0 END ;
  923. IF (X1+min>X2)OR(Y1+min>Y2) THEN RETURN END ;
  924. wd.X1 := X1; wd.Y1 := Y1;
  925. wd.X2 := X2; wd.Y2 := Y2;
  926. wd.Hidden := TRUE;
  927. IF IsPalette THEN
  928. GetPal(W,pal);
  929. nw := PaletteOpen(wd,pal);
  930. ELSE
  931. nw := Open( wd );
  932. END;
  933. MergeWindows(nw,W);
  934. ClipFrame (W);
  935. IF CurrentX>Width THEN CurrentX := Width END;
  936. IF CurrentY>Depth THEN CurrentY := Depth END;
  937. ResetCursor;
  938. END;
  939. Use(save); (* restore used window *)
  940. Unlock();
  941. END Change;
  942. (* ------------------------- *)
  943. (* Multi process support *)
  944. (* ------------------------- *)
  945. PROCEDURE (*$F*) NullProc;
  946. BEGIN
  947. END NullProc;
  948. PROCEDURE (*$F*) SetProcessLocks ( LockProc,UnlockProc : PROC );
  949. BEGIN
  950. Lock := LockProc;
  951. Unlock := UnlockProc;
  952. MultiP := TRUE;
  953. END SetProcessLocks;
  954. (* ------------------------- *)
  955. (* Window output *)
  956. (* ------------------------- *)
  957. PROCEDURE (*$F*) DeleteLine ( W : WinType; Y : RelCoord );
  958. VAR
  959. r,p : CARDINAL;
  960. BEGIN
  961. CheckWindow(W);
  962. WITH W^ DO
  963. p := XA-WDef.X1+(YA-WDef.Y1+Y-1)*OWidth;
  964. FOR r := Y TO Depth-1 DO
  965. Move(ADR(Buffer^[p+OWidth]),ADR(Buffer^[p]),Width*2);
  966. INC(p,OWidth);
  967. END;
  968. BufferSpaceFill(W,p,Width);
  969. RedrawSection ( W,XA,Y+YA-1,XB,YB );
  970. END;
  971. END DeleteLine;
  972. PROCEDURE (*$F*) Clear;
  973. (*
  974. clears the current window
  975. *)
  976. VAR
  977. r,p : CARDINAL;
  978. W : WinType;
  979. BEGIN
  980. W := CurWin();
  981. WITH W^ DO
  982. p := XA-WDef.X1+(YA-WDef.Y1)*OWidth;
  983. FOR r := 1 TO Depth DO
  984. BufferSpaceFill(W,p,Width);
  985. INC(p,OWidth);
  986. END;
  987. RedrawWindowPane(W);
  988. END;
  989. IGotoXY(W,1,1);
  990. Unlock();
  991. END Clear;
  992. PROCEDURE (*$F*) ClrEol;
  993. (*
  994. clears from the cursor to the end of line
  995. *)
  996. VAR
  997. W : WinType;
  998. BEGIN
  999. W := CurWin();
  1000. WITH W^ DO
  1001. BufferSpaceFill(W,XA-WDef.X1+CurrentX-1+(YA-WDef.Y1+CurrentY-1)*OWidth,
  1002. Width-CurrentX+1);
  1003. RedrawSection ( W,XA-1+CurrentX,YA-1+CurrentY,XB,YA-1+CurrentY );
  1004. END;
  1005. Unlock();
  1006. END ClrEol;
  1007. PROCEDURE Bell;
  1008. VAR
  1009. R : Registers;
  1010. BEGIN
  1011. WITH R DO
  1012. AX := 0E07H;
  1013. BL := 0;
  1014. Lib.Intr(R,10H);
  1015. END;
  1016. END Bell;
  1017. PROCEDURE (*$N*) WriteC ( W : WinType; C : CHAR);
  1018. VAR
  1019. nx : CARDINAL;
  1020. BEGIN
  1021. WITH W^ DO
  1022. CASE C OF
  1023. CHR(12) : Clear;
  1024. IGotoXY(W,1,1);
  1025. | CHR(10) : IF CurrentY=Depth THEN
  1026. DeleteLine ( W, 1 );
  1027. ELSE
  1028. IGotoXY(W,CurrentX,CurrentY+1);
  1029. END;
  1030. | CHR(13) : (*ClrEol; change 1/7/88*) IGotoXY(W,1,CurrentY);
  1031. | CHR(08) : IF CurrentX>1 THEN
  1032. IGotoXY(W,CurrentX-1,CurrentY); WriteC(W,' ');
  1033. IGotoXY(W,CurrentX-1,CurrentY);
  1034. END;
  1035. | CHR(7) : Bell;
  1036. ELSE
  1037. IF CurrentX > Width THEN RETURN END;
  1038. WindowWrite(W,CurrentX,CurrentY,1,ADR(C),FALSE);
  1039. IF (CurrentX<>Width)OR NOT WDef.WrapOn THEN
  1040. IGotoXY(W,CurrentX+1,CurrentY);
  1041. ELSE
  1042. IF CurrentY=Depth THEN
  1043. DeleteLine ( W, 1 );
  1044. IGotoXY(W,1,CurrentY);
  1045. ELSE
  1046. IGotoXY(W,1,CurrentY+1);
  1047. END;
  1048. END;
  1049. END;
  1050. END;
  1051. END WriteC;
  1052. PROCEDURE (*$F*) WriteOut (S : ARRAY OF CHAR);
  1053. VAR
  1054. W : WinType;
  1055. p,q,m : CARDINAL;
  1056. ss : CARDINAL;
  1057. BEGIN
  1058. W := CurWin();
  1059. WITH W^ DO
  1060. ss := HIGH(S)+1;
  1061. p := 0;
  1062. q := 0;
  1063. LOOP
  1064. (* first accumulate normal chars on same line *)
  1065. m := Width+p-CurrentX;
  1066. IF NOT W^.WDef.WrapOn THEN INC(m) END; (* can fit another char in *)
  1067. IF m > ss THEN m := ss END;
  1068. WHILE (q<m)AND(S[q]>=' ') DO INC(q) END;
  1069. (* now output the line *)
  1070. IF q > p THEN
  1071. WindowWrite(W,CurrentX,CurrentY,q-p,ADR(S[p]),FALSE);
  1072. IGotoXY(W,CurrentX+q-p,CurrentY);
  1073. END;
  1074. (* now output the special char *)
  1075. IF (S[q] = CHR(0)) OR (q > HIGH(S)) THEN EXIT ELSE WriteC(W,S[q]);
  1076. END;
  1077. INC(q);
  1078. p := q;
  1079. END;
  1080. END;
  1081. Unlock();
  1082. END WriteOut;
  1083. PROCEDURE (*$F*) DirectWrite ( X,Y : RelCoord; (* start co-ords *)
  1084. A : ADDRESS; (* address of char array *)
  1085. Len : CARDINAL ); (* length to be written *)
  1086. (*
  1087. writes directly to current window at the specified X,Y coordinates
  1088. with no check for special (ie control) chars or eol wrap
  1089. *)
  1090. VAR
  1091. W : WinType;
  1092. BEGIN
  1093. W := CurWin();
  1094. ClipXY(W,X,Y);
  1095. WindowWrite(W,X,Y,Len,A,FALSE);
  1096. Unlock();
  1097. END DirectWrite;
  1098. PROCEDURE (*$F*) GotoXY ( X,Y : RelCoord );
  1099. VAR
  1100. W : WinType;
  1101. BEGIN
  1102. W := CurWin();
  1103. ClipXY(W,X,Y);
  1104. IGotoXY(W,X,Y);
  1105. Unlock();
  1106. END GotoXY;
  1107. PROCEDURE (*$F*) WhereX ( ) : RelCoord;
  1108. VAR
  1109. W : WinType;
  1110. BEGIN
  1111. W := CurWin();
  1112. Unlock();
  1113. RETURN W^.CurrentX;
  1114. END WhereX;
  1115. PROCEDURE (*$F*) WhereY ( ) : RelCoord;
  1116. VAR
  1117. W : WinType;
  1118. BEGIN
  1119. W := CurWin();
  1120. Unlock();
  1121. RETURN W^.CurrentY;
  1122. END WhereY;
  1123. PROCEDURE (*$F*) ConvertCoords ( W : WinType ;
  1124. X,Y : RelCoord;
  1125. VAR XO,YO : AbsCoord );
  1126. BEGIN
  1127. CheckWindow(W);
  1128. XO := X+W^.XA-1; YO := Y+W^.YA-1;
  1129. END ConvertCoords;
  1130. PROCEDURE (*$F*) InsLine;
  1131. VAR
  1132. W : WinType;
  1133. r,p,p1 : CARDINAL;
  1134. BEGIN
  1135. W := CurWin();
  1136. WITH W^ DO
  1137. p := XA-WDef.X1+(YA-WDef.Y1+Depth-1)*OWidth;
  1138. FOR r := CurrentY TO Depth-1 DO
  1139. DEC(p,OWidth);
  1140. Move(ADR(Buffer^[p]),ADR(Buffer^[p+OWidth]),Width*2);
  1141. END;
  1142. BufferSpaceFill(W,p,Width);
  1143. RedrawSection ( W,XA,CurrentY+YA-1,XB,YB );
  1144. END;
  1145. Unlock();
  1146. END InsLine;
  1147. PROCEDURE (*$F*) DelLine;
  1148. VAR
  1149. W : WinType;
  1150. BEGIN
  1151. W := CurWin();
  1152. DeleteLine(W,W^.CurrentY);
  1153. Unlock();
  1154. END DelLine;
  1155. PROCEDURE (*$F*) TextColor ( c : Color );
  1156. VAR
  1157. W : WinType;
  1158. BEGIN
  1159. W := CurWin();
  1160. W^.WDef.Foreground := c;
  1161. Unlock();
  1162. END TextColor;
  1163. PROCEDURE (*$F*) TextBackground ( c : Color );
  1164. VAR
  1165. W : WinType;
  1166. BEGIN
  1167. W := CurWin();
  1168. W^.WDef.Background := c;
  1169. Unlock();
  1170. END TextBackground;
  1171. PROCEDURE (*$F*) SetWrap ( on : BOOLEAN );
  1172. VAR
  1173. W : WinType;
  1174. BEGIN
  1175. W := CurWin();
  1176. W^.WDef.WrapOn := on;
  1177. Unlock();
  1178. END SetWrap;
  1179. PROCEDURE Info (*$F*) ( W : WinType; VAR WD : WinDef );
  1180. (* gets information for specified window *)
  1181. BEGIN
  1182. Lock();
  1183. WD := W^.WDef ;
  1184. Unlock();
  1185. END Info;
  1186. (* ------------------------- *)
  1187. (* Title procedure *)
  1188. (* ------------------------- *)
  1189. PROCEDURE SetTitle ( W : WinType;
  1190. NewTitle : ARRAY OF CHAR;
  1191. Mode : TitleMode );
  1192. (*
  1193. updates the window title within the window frame,
  1194. positioning it in the position defined by the title mode
  1195. *)
  1196. VAR
  1197. l : CARDINAL;
  1198. BEGIN
  1199. CheckWindow(W);
  1200. Lock();
  1201. DisposeTitle(W);
  1202. WITH W^ DO
  1203. IF Mode <> NoTitle THEN
  1204. l := Length(NewTitle);
  1205. ALLOCATE(Title,l+1);
  1206. Move(ADR(NewTitle),ADR(Title^),l);
  1207. Title^[l] := CHR(0);
  1208. END;
  1209. TMode := Mode;
  1210. END;
  1211. DrawFrame(W);
  1212. Unlock;
  1213. END SetTitle;
  1214. PROCEDURE ReadString ( VAR string : ARRAY OF CHAR );
  1215. VAR
  1216. c : CHAR;
  1217. line: ARRAY[0..82] OF CHAR;
  1218. p,H : CARDINAL;
  1219. W : WinType;
  1220. con : BOOLEAN;
  1221. BEGIN
  1222. W := CurWin();
  1223. PutOnTop(W);
  1224. con := W^.WDef.CursorOn;
  1225. CursorOn;
  1226. H := HIGH(string);
  1227. IF H>79 THEN H := 79 END;
  1228. p := 0;
  1229. LOOP
  1230. c := IO.RdKey();
  1231. IF (c=CHR(8))OR(c=CHR(127)) THEN
  1232. IF p>0 THEN DEC(p); IO.WrChar(CHR(8)) END;
  1233. ELSIF (c>=' ') THEN
  1234. IF p<=H THEN
  1235. IO.WrChar(c);
  1236. line[p] := c;
  1237. INC(p);
  1238. END;
  1239. ELSIF c=CHR(13) THEN
  1240. EXIT;
  1241. END;
  1242. END;
  1243. line[p] := CHR(0);
  1244. Copy(string,line);
  1245. IF NOT con THEN CursorOff END;
  1246. Unlock;
  1247. IO.WrLn;
  1248. END ReadString;
  1249. (* Low level routines to read and write to the window buffer direct *)
  1250. PROCEDURE (*$F*) RdBufferLn ( W : WinType; (* Source window *)
  1251. X,Y : RelCoord; (* start co-ords *)
  1252. Dest : ADDRESS; (* address of buffer *)
  1253. Len : CARDINAL ); (* length in WORDs *)
  1254. VAR
  1255. AX,AY : AbsCoord;
  1256. BEGIN
  1257. WITH W^ DO
  1258. AX := X+XA-1; AY := Y+YA-1;
  1259. Lib.WordMove(ADR(Buffer^[AX-WDef.X1+(AY-WDef.Y1)*OWidth]),Dest,Len);
  1260. END ;
  1261. END RdBufferLn ;
  1262. PROCEDURE (*$F*) WrBufferLn ( W : WinType; (* Dest window *)
  1263. X,Y : RelCoord; (* start co-ords *)
  1264. Src : ADDRESS; (* address of buffer *)
  1265. Len : CARDINAL ); (* length in WORDs *)
  1266. VAR
  1267. AX,AY : AbsCoord;
  1268. BEGIN
  1269. WITH W^ DO
  1270. AX := X+XA-1; AY := Y+YA-1;
  1271. Lib.WordMove(Src,ADR(Buffer^[AX-WDef.X1+(AY-WDef.Y1)*OWidth]),Len);
  1272. UpdateScreen(W,AX,AY,Len);
  1273. END ;
  1274. END WrBufferLn ;
  1275. (* ------------------------- *)
  1276. (* Main initialization *)
  1277. (* ------------------------- *)
  1278. PROCEDURE Init ;
  1279. CONST
  1280. ClearOnEntry = TRUE ; (* Change to FALSE if automatic clear
  1281. NOT required *)
  1282. VAR
  1283. R : Registers ;
  1284. WD : WinDef ;
  1285. BEGIN
  1286. InitScreenType(FALSE); (* FALSE = no snow *)
  1287. R.AH := 3;
  1288. R.BH := ActivePage();
  1289. Lib.Intr(R,10H);
  1290. IF (R.CH<20H)AND(R.CL>0) THEN
  1291. CursorLines := R.CX ;
  1292. ELSE
  1293. CursorLines := 0607H ;
  1294. END ;
  1295. Lock := NullProc;
  1296. Unlock := NullProc;
  1297. MultiP := FALSE;
  1298. WindowStack := NIL;
  1299. NEW(UseList);
  1300. UseList^.Next := NIL; (* dummy *)
  1301. CursorStack := NIL;
  1302. IO.WrStrRedirect := WriteOut;
  1303. IO.RdStrRedirect := ReadString;
  1304. IF ClearOnEntry THEN
  1305. FullScreen := Open(FullScreenDef);
  1306. ELSE
  1307. WD := FullScreenDef ;
  1308. WD.Hidden := TRUE ;
  1309. FullScreen := Open(WD);
  1310. SnapShot ;
  1311. PutOnTop(FullScreen);
  1312. GotoXY(ORD(R.DL)+1,ORD(R.DH)+1);
  1313. END ;
  1314. END Init ;
  1315. BEGIN
  1316. Init ;
  1317. END Window.
  1318.