Viewers.Mod.txt 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. MODULE Viewers; (*JG 14.9.90 / NW 15.9.2013*)
  2. IMPORT Display;
  3. CONST restore* = 0; modify* = 1; suspend* = 2; (*message ids*)
  4. inf = 65535;
  5. TYPE Viewer* = POINTER TO ViewerDesc;
  6. ViewerDesc* = RECORD (Display.FrameDesc) state*: INTEGER END;
  7. (*state > 1: displayed; state = 1: filler; state = 0: closed; state < 0: suspended*)
  8. ViewerMsg* = RECORD (Display.FrameMsg)
  9. id*: INTEGER;
  10. X*, Y*, W*, H*: INTEGER;
  11. state*: INTEGER
  12. END;
  13. Track = POINTER TO TrackDesc;
  14. TrackDesc = RECORD (ViewerDesc) under: Display.Frame END;
  15. VAR curW*, minH*, DH: INTEGER;
  16. FillerTrack: Track; FillerViewer,
  17. backup: Viewer; (*last closed viewer*)
  18. PROCEDURE Open* (V: Viewer; X, Y: INTEGER);
  19. VAR T, u, v: Display.Frame; M: ViewerMsg;
  20. BEGIN
  21. IF (V.state = 0) & (X < inf) THEN
  22. IF Y > DH THEN Y := DH END;
  23. T := FillerTrack.next;
  24. WHILE X >= T.X + T.W DO T := T.next END;
  25. u := T.dsc; v := u.next;
  26. WHILE Y > v.Y + v.H DO u := v; v := u.next END;
  27. IF Y < v.Y + minH THEN Y := v.Y + minH END;
  28. IF (v.next.Y # 0) & (Y > v.Y + v.H - minH) THEN
  29. V.X := T.X; V.W := T.W; V.Y := v.Y; V.H := v.H;
  30. M.id := suspend; M.state := 0;
  31. v.handle(v, M); v(Viewer).state := 0;
  32. V.next := v.next; u.next := V; V.state := 2
  33. ELSE V.X := T.X; V.W := T.W; V.Y := v.Y; V.H := Y - v.Y;
  34. M.id := modify; M.Y := Y; M.H := v.Y + v.H - Y;
  35. v.handle(v, M); v.Y := M.Y; v.H := M.H;
  36. V.next := v; u.next := V; V.state := 2
  37. END
  38. END
  39. END Open;
  40. PROCEDURE Change* (V: Viewer; Y: INTEGER);
  41. VAR v: Display.Frame; M: ViewerMsg;
  42. BEGIN
  43. IF V.state > 1 THEN
  44. IF Y > DH THEN Y := DH END;
  45. v := V.next;
  46. IF (v.next.Y # 0) & (Y > v.Y + v.H - minH) THEN Y := v.Y + v.H - minH END;
  47. IF Y >= V.Y + minH THEN
  48. M.id := modify; M.Y := Y; M.H := v.Y + v.H - Y;
  49. v.handle(v, M); v.Y := M.Y; v.H := M.H; V.H := Y - V.Y
  50. END
  51. END
  52. END Change;
  53. PROCEDURE RestoreTrack (S: Display.Frame);
  54. VAR T, t, v: Display.Frame; M: ViewerMsg;
  55. BEGIN t := S.next;
  56. WHILE t.next # S DO t := t.next END;
  57. T := S(Track).under;
  58. WHILE T.next # NIL DO T := T.next END;
  59. t.next := S(Track).under; T.next := S.next; M.id := restore;
  60. REPEAT t := t.next; v := t.dsc;
  61. REPEAT v := v.next; v.handle(v, M); v(Viewer).state := - v(Viewer).state
  62. UNTIL v = t.dsc
  63. UNTIL t = T
  64. END RestoreTrack;
  65. PROCEDURE Close* (V: Viewer);
  66. VAR T, U: Display.Frame; M: ViewerMsg;
  67. BEGIN
  68. IF V.state > 1 THEN
  69. U := V.next; T := FillerTrack;
  70. REPEAT T := T.next UNTIL V.X < T.X + T.W;
  71. IF (T(Track).under = NIL) OR (U.next # V) THEN
  72. M.id := suspend; M.state := 0;
  73. V.handle(V, M); V.state := 0; backup := V;
  74. M.id := modify; M.Y := V.Y; M.H := V.H + U.H;
  75. U.handle(U, M); U.Y := M.Y; U.H := M.H;
  76. WHILE U.next # V DO U := U.next END;
  77. U.next := V.next
  78. ELSE (*close track*)
  79. M.id := suspend; M.state := 0;
  80. V.handle(V, M); V.state := 0; backup := V;
  81. U.handle(U, M); U(Viewer).state := 0;
  82. RestoreTrack(T)
  83. END
  84. END
  85. END Close;
  86. PROCEDURE Recall* (VAR V: Viewer);
  87. BEGIN V := backup
  88. END Recall;
  89. PROCEDURE This* (X, Y: INTEGER): Viewer;
  90. VAR T, V: Display.Frame;
  91. BEGIN
  92. IF (X < inf) & (Y < DH) THEN
  93. T := FillerTrack;
  94. REPEAT T := T.next UNTIL X < T.X + T.W;
  95. V := T.dsc;
  96. REPEAT V := V.next UNTIL Y < V.Y + V.H
  97. ELSE V := NIL
  98. END ;
  99. RETURN V(Viewer)
  100. END This;
  101. PROCEDURE Next* (V: Viewer): Viewer;
  102. BEGIN RETURN V.next(Viewer)
  103. END Next;
  104. PROCEDURE Locate* (X, H: INTEGER; VAR fil, bot, alt, max: Display.Frame);
  105. VAR T, V: Display.Frame;
  106. BEGIN
  107. IF X < inf THEN
  108. T := FillerTrack;
  109. REPEAT T := T.next UNTIL X < T.X + T.W;
  110. fil := T.dsc; bot := fil.next;
  111. IF bot.next # fil THEN
  112. alt := bot.next; V := alt.next;
  113. WHILE (V # fil) & (alt.H < H) DO
  114. IF V.H > alt.H THEN alt := V END;
  115. V := V.next
  116. END
  117. ELSE alt := bot
  118. END;
  119. max := T.dsc; V := max.next;
  120. WHILE V # fil DO
  121. IF V.H > max.H THEN max := V END;
  122. V := V.next
  123. END
  124. END
  125. END Locate;
  126. PROCEDURE InitTrack* (W, H: INTEGER; Filler: Viewer);
  127. VAR S: Display.Frame; T: Track;
  128. BEGIN
  129. IF Filler.state = 0 THEN
  130. Filler.X := curW; Filler.W := W; Filler.Y := 0; Filler.H := H;
  131. Filler.state := 1; Filler.next := Filler;
  132. NEW(T); T.X := curW; T.W := W; T.Y := 0; T.H := H; T.dsc := Filler; T.under := NIL;
  133. FillerViewer.X := curW + W; FillerViewer.W := inf - FillerViewer.X;
  134. FillerTrack.X := FillerViewer.X; FillerTrack.W := FillerViewer.W;
  135. S := FillerTrack;
  136. WHILE S.next # FillerTrack DO S := S.next END;
  137. S.next := T; T.next := FillerTrack; curW := curW + W
  138. END
  139. END InitTrack;
  140. PROCEDURE OpenTrack* (X, W: INTEGER; Filler: Viewer);
  141. VAR newT: Track; S, T, t, v: Display.Frame; M: ViewerMsg; v0: Viewer;
  142. BEGIN
  143. IF (X < inf) & (Filler.state = 0) THEN
  144. S := FillerTrack; T := S.next;
  145. WHILE X >= T.X + T.W DO S := T; T := S.next END;
  146. WHILE X + W > T.X + T.W DO T := T.next END;
  147. M.id := suspend; t := S;
  148. REPEAT t := t.next; v := t.dsc;
  149. REPEAT v := v.next; M.state := -v(Viewer).state; v.handle(v, M); v(Viewer).state := M.state
  150. UNTIL v = t.dsc
  151. UNTIL t = T;
  152. Filler.X := S.next.X; Filler.W := T.X + T.W - S.next.X; Filler.Y := 0; Filler.H := DH;
  153. Filler.state := 1; Filler.next := Filler;
  154. NEW(newT); newT.X := Filler.X; newT.W := Filler.W; newT.Y := 0; newT.H := DH;
  155. newT.dsc := Filler; newT.under := S.next; S.next := newT;
  156. newT.next := T.next; T.next := NIL
  157. END
  158. END OpenTrack;
  159. PROCEDURE CloseTrack* (X: INTEGER);
  160. VAR T, V: Display.Frame; M: ViewerMsg;
  161. BEGIN
  162. IF X < inf THEN
  163. T := FillerTrack;
  164. REPEAT T := T.next UNTIL X < T.X + T.W;
  165. IF T(Track).under # NIL THEN
  166. M.id := suspend; M.state := 0; V := T.dsc;
  167. REPEAT V := V.next; V.handle(V, M); V(Viewer).state := 0 UNTIL V = T.dsc;
  168. RestoreTrack(T)
  169. END
  170. END
  171. END CloseTrack;
  172. PROCEDURE Broadcast* (VAR M: Display.FrameMsg);
  173. VAR T, V: Display.Frame;
  174. BEGIN T := FillerTrack.next;
  175. WHILE T # FillerTrack DO
  176. V := T.dsc;
  177. REPEAT V := V.next; V.handle(V, M) UNTIL V = T.dsc;
  178. T := T.next
  179. END
  180. END Broadcast;
  181. BEGIN backup := NIL; curW := 0; minH := 1; DH := Display.Height;
  182. NEW(FillerViewer); FillerViewer.X := 0; FillerViewer.W := inf; FillerViewer.Y := 0; FillerViewer.H := DH;
  183. FillerViewer.next := FillerViewer;
  184. NEW(FillerTrack);
  185. FillerTrack.X := 0; FillerTrack.W := inf; FillerTrack.Y := 0; FillerTrack.H := DH;
  186. FillerTrack.dsc := FillerViewer; FillerTrack.next := FillerTrack
  187. END Viewers.