Syntax10.Scn.Fnt Syntax10i.Scn.Fnt Syntax10b.Scn.Fnt MODULE StatusViewer; (* MH Dec 93 / Jun 94 *) IMPORT Input, Display, Fonts, Files, Texts, TextFrames, Viewers, MenuViewers, Oberon; Time = RECORD sec, min, hour, day, month, year: SHORTINT; timeStamp, dateStamp: LONGINT END; ClockUpdateMsg = RECORD (Display.FrameMsg) t: Time; END; Months: ARRAY 12*3+1 OF CHAR; CurDir: ARRAY 256 OF CHAR; W: Texts.Writer; T: Texts.Text; Task: Oberon.Task; CurTime: Time; (* time currently displayed in status viewers *) PROCEDURE GetTime (VAR t: Time); BEGIN Oberon.GetClock(t.timeStamp, t.dateStamp); t.sec := SHORT(SHORT( t.timeStamp MOD 40H )); t.min := SHORT(SHORT( (t.timeStamp DIV 40H) MOD 40H )); t.hour := SHORT(SHORT( (t.timeStamp DIV 1000H) MOD 40H )); t.day := SHORT(SHORT( t.dateStamp MOD 20H )); t.month := SHORT(SHORT( (t.dateStamp DIV 20H) MOD 10H )); t.year := SHORT(SHORT( (t.dateStamp DIV 200H) MOD 100 )); END GetTime; PROCEDURE GenLabel (VAR t: Time; VAR label: ARRAY OF CHAR); VAR m, i: INTEGER; PROCEDURE Ch (ch: CHAR); BEGIN label[i] := ch; INC(i) END Ch; PROCEDURE Int (n: SHORTINT; lead: BOOLEAN); BEGIN IF lead OR (n DIV 10 > 0) THEN Ch(CHR(48 + (n DIV 10) MOD 10)) END; Ch(CHR(48 + n MOD 10)) END Int; BEGIN i := 0; WHILE label[i] # 0X DO INC(i) END; IF label[0] # 0X THEN Ch(" "); Ch(" ") END; Int(t.day, FALSE); m := t.month - 1; Ch(" "); Ch(Months[m * 3]); Ch(Months[m * 3 + 1]); Ch(Months[m * 3 + 2]); Ch(" "); Int(t.year, TRUE); Ch(" "); Ch(" "); Ch(" "); Int(t.hour, TRUE); Ch(":"); Int(t.min, TRUE); Ch(":"); Int(t.sec, TRUE); Ch(0X) END GenLabel; PROCEDURE StrWidth (s: ARRAY OF CHAR): INTEGER; VAR i, x, y, w, h, dx, width: INTEGER; pat: LONGINT; BEGIN i := 0; width := 0; WHILE s[i] # 0X DO Display.GetChar(Fonts.Default.raster, s[i], dx, x, y, w, h, pat); INC(width, dx); INC(i); END; RETURN width; END StrWidth; PROCEDURE DispStr (X, Y, col: INTEGER; s: ARRAY OF CHAR); VAR i, x, y, w, h, dx, width: INTEGER; pat: LONGINT; BEGIN i := 0; WHILE s[i] # 0X DO Display.GetChar(Fonts.Default.raster, s[i], dx, x, y, w, h, pat); Display.CopyPattern(col, pat, X+x, Y+y, Display.paint); INC(X, dx); INC(i); END DispStr; PROCEDURE UpdateClock (F: TextFrames.Frame; VAR t: Time); VAR s: ARRAY 32 OF CHAR; w, x, y: INTEGER; BEGIN GenLabel(t, s); w := StrWidth(s); x := F.X + F.W - 7 - w; y := F.Y + 1 + (-Fonts.Default.minY); Oberon.RemoveMarks(x, F.Y, w, Fonts.Default.height); Display.ReplConst(F.col, x, F.Y, w, Fonts.Default.height, Display.replace); DispStr(x, y, Display.white-F.col, s); END UpdateClock; PROCEDURE ClockFrameHandle (F: Display.Frame; VAR M: Display.FrameMsg); BEGIN IF M IS ClockUpdateMsg THEN UpdateClock(F(TextFrames.Frame), M(ClockUpdateMsg).t) ELSIF M IS MenuViewers.ModifyMsg THEN TextFrames.Handle(F, M); IF F.H > Fonts.Default.height THEN UpdateClock(F(TextFrames.Frame), CurTime) END; ELSIF M IS TextFrames.UpdateMsg THEN TextFrames.Handle(F, M); IF M(TextFrames.UpdateMsg).text = F(TextFrames.Frame).text THEN IF F.H > Fonts.Default.height THEN UpdateClock(F(TextFrames.Frame), CurTime) END END ELSE TextFrames.Handle(F, M); END; END ClockFrameHandle; PROCEDURE Open*; VAR V: MenuViewers.Viewer; Menu, Main: TextFrames.Frame; text: Texts.Text; x, y: INTEGER; BEGIN Menu := TextFrames.NewMenu("", ""); Menu.text := T; Menu.handle := ClockFrameHandle; text := TextFrames.Text(""); Main := TextFrames.NewText(text, 0); Oberon.AllocateSystemViewer(Oberon.Mouse.X, x, y); V := MenuViewers.New(Menu, Main, TextFrames.menuH, x, y); END Open; PROCEDURE Update; VAR cu: ClockUpdateMsg; BEGIN IF CurDir # Files.CurrentDir THEN COPY(Files.CurrentDir, CurDir); Texts.WriteString(W, CurDir); Texts.Delete(T, 0, T.len); Texts.Append(T, W.buf); END; GetTime(cu.t); IF (CurTime.hour # cu.t.hour) OR (CurTime.min # cu.t.min) OR (CurTime.sec # cu.t.sec) THEN Viewers.Broadcast(cu); CurTime := cu.t END; Oberon.CurTask.time := Oberon.Time() + 1*Input.TimeUnit; END Update; BEGIN Months := "JanFebMarAprMayJunJulAugSepOctNovDec"; GetTime(CurTime); Texts.OpenWriter(W); T := TextFrames.Text(""); NEW(Task); Task.safe := FALSE; Task.time := 0; Task.handle := Update; Oberon.Install(Task); END StatusViewer. StatusViewer.Open