Syntax10.Scn.FntHSyntax10b.Scn.Fnt !$   # 6_ D 6  LlQMODULE Boards; IMPORT TextFrames, Texts, Viewers, Display, Files; TYPE Board* = POINTER TO BoardDesc; Note* = POINTER TO NoteDesc; BoardDesc* = RECORD; list: Note END; NoteDesc* = RECORD; X*, Y*, W*, H*: INTEGER; text*: Texts.Text; next: Note END; UpdateMsg* = RECORD (Display.FrameMsg) id*: INTEGER; board*: Board; note*: Note END; Reader* = RECORD N: Note END; CONST poste* = 0; discard* = 1; move* = 2; toTop* = 3; (* message id's *) BoardFileId* = 31697; VAR minW*, minH*: INTEGER; (* minimal size of a note *) PROCEDURE Max (i, j: INTEGER): INTEGER; BEGIN IF i >= j THEN RETURN i ELSE RETURN j END END Max; PROCEDURE XYinRect(X0, Y0, X, Y, W, H: INTEGER): BOOLEAN; BEGIN RETURN (X0 >= X) & (X0 <= X + W) & (Y0 >= Y) & (Y0 <=Y + H) END XYinRect; PROCEDURE Append(B: Board; N: Note); VAR Q: Note; BEGIN (* N not in B.list *) N.next := NIL; Q := B.list; IF Q = NIL THEN B.list := N ELSE WHILE Q.next # NIL DO Q := Q.next END; Q.next := N END END Append; PROCEDURE ToListEnd(B: Board; N: Note); VAR Q: Note; BEGIN (* N in B.list *) IF N.next # NIL THEN (* N is not already at list end *) Q := B.list; IF Q = N THEN B.list := N.next END; WHILE Q.next # NIL DO IF Q.next = N THEN Q.next := N.next END; Q := Q.next END; Q.next := N; N.next := NIL END END ToListEnd; PROCEDURE Poste*(B: Board; N: Note); VAR M: UpdateMsg; BEGIN Append(B, N); M.id := poste; M.note := N; M.board := B; Viewers.Broadcast(M) (* poste message *) END Poste; PROCEDURE PosteEmpty*(B: Board; X, Y, W, H: INTEGER); VAR N: Note; BEGIN IF (W < minW) OR (H < minH) THEN RETURN END; NEW(N); N.X := X; N.Y := Y; N.W := W; N.H := H; N.text := TextFrames.Text(""); Poste(B, N) END PosteEmpty; PROCEDURE ToTop*(B: Board; N: Note); VAR M: UpdateMsg; BEGIN ToListEnd(B, N); M.id := toTop; M.note := N; M.board := B; Viewers.Broadcast(M) (* toTop message *) END ToTop; PROCEDURE Discard*(B: Board; N: Note); VAR Q: Note; M: UpdateMsg; BEGIN (* N in B.list *) Q := B.list; IF Q = N THEN B.list := N.next ELSE WHILE Q.next # N DO Q := Q.next END; Q.next := N.next END; M.id := discard; M.note := N; M.board := B; Viewers.Broadcast(M) (* discard message *) END Discard; PROCEDURE Move*(B: Board; N: Note; dX, dY: INTEGER); VAR M: UpdateMsg; BEGIN ToListEnd(B, N); N.X := N.X + dX; N.Y := N.Y + dY; M.id := move; M.note := N; M.board := B; Viewers.Broadcast(M) (* move message *) END Move; PROCEDURE Resize*(B: Board; N: Note; newW, newH: INTEGER); VAR M: UpdateMsg; BEGIN IF (newW < minW) OR (newH < minH) THEN RETURN END; N.Y := N.Y - (newH - N.H) ; N.W := newW; N.H := newH; M.id := move; M.note := N; M.board := B; Viewers.Broadcast(M) (* move message *) END Resize; PROCEDURE OpenReader*(VAR R: Reader; B: Board); BEGIN R.N := B.list END OpenReader; PROCEDURE Read*(VAR R: Reader; VAR N: Note); BEGIN N := R.N; IF N # NIL THEN R.N := R.N.next END END Read; PROCEDURE Store*(B: Board; name: ARRAY OF CHAR); VAR F: Files.File; R: Files.Rider; N: Note; BEGIN F := Files.New(name); Files.Set(R, F, 0); Files.WriteInt(R, BoardFileId); N := B.list; WHILE N # NIL DO Files.WriteInt(R, N.X); Files.WriteInt(R, N.Y); Files.WriteInt(R, N.W); Files.WriteInt(R, N.H); Texts.Store(R, N.text); N := N.next END; Files.Register(F) END Store; PROCEDURE Open*(B: Board; name: ARRAY OF CHAR); VAR F: Files.File; R: Files.Rider; N: Note; tag: INTEGER; BEGIN B.list := NIL; F := Files.Old(name); IF F# NIL THEN Files.Set(R, F, 0); Files.ReadInt(R, tag); IF tag = BoardFileId THEN NEW(N); Files.ReadInt(R, N.X); WHILE ~R.eof DO Files.ReadInt(R, N.Y); Files.ReadInt(R, N.W); Files.ReadInt(R, N.H); NEW(N.text); N.text.notify := TextFrames.NotifyDisplay; Texts.Load(R, N.text); Append(B, N); NEW(N); Files.ReadInt(R, N.X) END END END END Open; BEGIN minW := 20; minH := 15; END Boards.