izSyntax10.Scn.Fnt0wSStyleElemsAlloc HeaderSyntax16.Scn.FntSqBalloonElemsAlloc#Syntax10.Scn.Fntright interclick to edit menu 0wS, Text1Syntax14b.Scn.Fnta8FoldElemsNewSyntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoColsLinkElemsAllocProg.Guide.Text462Prog.Guide.Text\IProg.Guide.Text\%Prog.Guide.Textb8HProg.Guide.Text 3Prog.Guide.TextNW8Prog.Guide.Text%/Prog.Guide.Text 0Prog.Guide.Textzd0~Prog.Guide.Text\Prog.Guide.Text%  Prog.Guide.Text~y1 System log text Oberon.Log Create an empty text text := TextFrames.Text(""); Create a new text and initialize it from text := TextFrames.Text(name); disk file name Write to system log  Insert buffer buf at position pos in text Texts.Insert(text, pos, buf); Append buffer buf to text Texts.Append(text, buf); Read sequential characters  Scan sequential symbols  Save stretch [beg, end) of text in NEW(buf); Texts.OpenBuf(buf); buffer buf Texts.Save(text, beg, end, buf); Create a text  Read from a text  Scan a text  80wS, Text1^8,Syntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoColsLinkElemsAllocProg.Guide.Text&`R'Prog.Guide.TextRRProg.Guide.TextjProg.Guide.Text\(Prog.Guide.TextrProg.Guide.Textf:!Prog.Guide.TextiRProg.Guide.TextK~k Prog.Guide.TextW-t/Prog.Guide.TextФ!w System parameter list Oberon.Par Viewer from which command is issued Oberon.Par.vwr Frame from which command is issued Oberon.Par.frame Text from which command is issued Oberon.Par.text Start of parameter list Oberon.Par.pos The most recent selection in the system Oberon.GetSelection(text, beg, end, time) The marked viewer Oberon.MarkedViewer() Open scanner for parameter list  Was command issued from a menu IF Oberon.Par.frame = Oberon.Par.vwr.dsc THEN frame of any viewer? Parameters in the selection  The marked viewer as parameter  Menu commands implicitly refer to the viewer  which contains the menu frame. 80wS, Text1 89 Syntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoColsb8FoldElemsNew#Syntax10.Scn.Fnt|| --------------- Most Oberon viewers have 2 frames (a menu frame and a contents frame). Such viewers are opened with MenuViewers.New instead of Viewers.Open. MenuViewers.New needs the following parameters: - a menu frame - a contents frame - the height of the menu (usually always TextFrames.menuH) - the coordinates of a point on the upper edge of the new viewer --------------- 8C8#Syntax10.Scn.Fnt== --------------- A viewer is normally closed interactively with the command System.Close. It can, however, also be closed from a program with Viewers.Close. The contents of the viewer is not saved automatically. A viewer that was closed unintentionally can be reopened with the command System.Recall. --------------- 8PMarkElemsAlloc:p&8Syntax10.Scn.Fnt8FoldElemsNew#Syntax10.Scn.FntViewers.This(x, 0)8 8#Syntax10.Scn.Fnt v.state > 18,8#Syntax10.Scn.FntViewers.Next(v)88#Syntax10.Scn.Fntx + v.W8. --------------- This can be useful for finding a specific viewer or a viewer with a certain contents. PROCEDURE TraverseAllViewers; VAR x: INTEGER; v: Viewers.Viewer; BEGIN x := 0; WHILE x < Display.Width DO v := bottom viewer in x track; WHILE v is not the filler viewer DO (*... process viewer v ...*) v := viewer above v END; x := x of next track END END TraverseAllViewers; --------------- 8(}8#Syntax10.Scn.Fntaa --------------- This message is normally forwarded to the frames of the viewer. --------------- 8 8`Syntax10.Scn.Fnt5LinkElemsAllocMyProg.Guide.Text:pa --------------- Traverse all viewers on the screen () and find the one with the smallest value of v.dsc.next(TextFrames.Frame).time. --------------- 8 Opening a viewer  v := MenuViewers.New(menuF, contF, menuH, x, y) Closing a viewer  Viewers.Close(v) Finding the viewer at position (x, y) v := Viewers.This(x, y) Traversing all viewers on the screen  Broadcasting a message to all viewers  Viewers.Broadcast(msg) Getting the focus viewer v := Oberon.FocusViewer Getting the marked viewer v := Oberon.MarkedViewer() Getting the viewer containing the most recent text selection 80wS, Text1@8WSyntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoCols6LinkElemsAllocProg.Guide.Text6CProg.Guide.TextWProg.Guide.Text/bProg.Guide.TextECProg.Guide.TextDProg.Guide.Text\Prog.Guide.TextHProg.Guide.Text}Prog.Guide.TextProg.Guide.TextOProg.Guide.Text$Wj Position of star-shaped pointer x := Oberon.Pointer.X; y := Oberon.Pointer.Y; The marked viewer Oberon.MarkedViewer() Position of the mouse x := Oberon.Mouse.X; y := Oberon.Mouse.Y; Viewer which contains mouse Viewers.This(Oberon.Mouse.X, Oberon.Mouse.Y) Focus viewer Oberon.FocusViewer Is viewer v a standard text viewer? IF (v IS MenuViewers.Viewer) & (v.dsc IS TextFrames.Frame) & (v.dsc.next IS TextFrames.Frame) THEN ... Has viewer v a text frame as menu frame? IF v.dsc IS TextFrames.Frame THEN ... Has viewer v a text frame as main frame? IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN ... The menu frame of a text viewer v v.dsc(TextFrames.Frame) The menu text of a text viewer v v.dsc(TextFrames.Frame).text The main frame of a text viewer v v.dsc.next(TextFrames.Frame) The main text of a text viewer v v.dsc.next(TextFrames.Frame).text The most recent selection Oberon.GetSelection(text, beg, end, time) Is the command executed from the menu v := Oberon.Par.vwr; frame? IF (Oberon.Par.frame IS TextFrames.Frame) & (v.dsc = Oberon.Par.frame) THEN ... Placement of the viewer in the user track Oberon.AllocateUserViewer( of the display which contains the mouse Oberon.Mouse.X, x, y) Placement of the viewer in the system track Oberon.AllocateSystemViewer( of the display which contains the mouse Oberon.Mouse.X, x, y) Open a new text viewer: x and y are text := TextFrames.Text(name); determined by AllocateUserViewer or v := MenuViewers.New( AllocateSystemViewer TextFrames.NewMenu(name, cmds), TextFrames.NewText(text, 0), TextFrames.menuH, x, y) Open a viewer 80wS, Text18,Syntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoColsLinkElemsAllocProg.Guide.Text-|Prog.Guide.Text$vProg.Guide.Text_Prog.Guide.TextD9Prog.Guide.TextNProg.Guide.Text8Prog.Guide.TextoProg.Guide.Text;@LProg.Guide.Text2h8Prog.Guide.TextKn Has viewer v a main frame? IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN ... The focus viewer Oberon.FocusViewer Text of text frame f f.text Position of first displayed character f.org A caret is set in text frame f IF f.hasCar THEN ... Position of the caret, if one is set IF f.hasCar THEN pos := f.carloc.pos END; A selection exists in text frame f IF f.hasSel THEN ... Start of the selection, if one exists IF f.hasSel THEN pos := f.selbeg.pos END; End of the selection, if one exists IF f.hasSel THEN pos := f.selend.pos END; Set the caret at pos in text frame f Oberon.PassFocus(v); installed in menu viewer v TextFrames.SetCaret(f, pos); Select stretch [beg, end) in text frame f TextFrames.SetSelection(f, beg, end); Scroll text such that line with origin at org TextFrames.RemoveSelection(f); will be displayed on top of the viewer TextFrames.RemoveCaret(f); Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); TextFrames.Show(f, org); Delete the selected text in the marked viewer  Copy the most recent selection to the caret's position  A caret is only allowed if the viewer which manages the frame is the focus viewer. If a caret is displayed (f.car > 0), it must be removed prior to using TextFrames.SetCaret. Prior to using TextFrames.Show, the caret, the selection, the mouse cursor, and the pointer must be removed. The Caret is removed either by a call of TextFrames.RemoveCaret(f) or as a consequence of Oberon.PassFocus(v).80wS, Text18Syntax10.Scn.Fnt0wSPStyleElemsAlloc   TwoCols*LinkElemsAllocProg.Guide.Text1Prog.Guide.Text$C.Prog.Guide.TextMYJProg.Guide.Text5;Prog.Guide.Text7Prog.Guide.Texta4Prog.Guide.TextpUB Open a new file name f := Files.New(name); Open an existing file name f := Files.Old(name); Write buffers to disk sectors Files.Close(f); Write buffers to disk and register file f in directory Files.Register(f); Sequential read access through rider r Files.Set(r, f, 0); Files.Read(r, ch); Files.Read(r, ch); Sequential write access through rider r Files.Set(r, f, 0); Files.Write(r, ch); Files.Write(r, ch); Random access at position pos Files.Set(r, f, pos); Files.Read(r, ch); ... Files.Write(r, ch); Read/write a record a of type T Files.ReadBytes(r, a, SIZE(T)); Files.WriteBytes(r, a, SIZE(T)); Read/write a record of type T accessed Files.ReadBytes(r, p^, SIZE(T)); with a pointer p Files.WriteBytes(r, p^, SIZE(T)); Opening another rider for the same file Files.Set(newR, Files.Base(r), Files.Pos(r))80wS, Text18-Syntax10.Scn.Fnt0wS,StyleElemsAlloc Text1 8FoldElemsNew!Syntax10.Scn.Fntr0wS"StyleElemsAlloc +ևҝϳText20wSP   TwoCols< Module In provides a set of basic routines for formatted input of characters, character sequences, numbers, and names. It assumes a standard input stream with a current position that can be reset. Usually the input stream is the text immediately following the most recently invoked command. If this text starts with the character ^ the current position is set to the beginning of the most recent selection (if no selection exists, Done is set to FALSE). If the text starts with the character * the current position is set to the beginning of the text in the marked viewer (if no viewer is marked, Done is set to FALSE). The end of the input stream is the end of the text containing the current position. Start reading process In.Open or In.OpenText(t, pos) Read a character In.Char(ch) Usually you want to skip leading blanks WHILE In.Done & (ch = " ") DO In.Char(ch) END; Read an integer number In.Int(i) or In.LongInt(li) Read a real number In.Real(r) or In.LongReal(lr) Read a name or a string In.Name(s) or In.String(s) Read next symbol IF In.Next() = In.name THEN In.char, In.int, In.name, In.string, In.Name(s) In.real, In.longReal, ELSIF In.Next() = In.string THEN and In.inval In.String(s) ELSE ... Determine success of the last operation IF In.Done THEN ...80wS, Text1 8!Syntax10.Scn.Fntr"StyleElemsAlloc +ևҝϳText2P   TwoColsB Module Out provides a set of basic routines for formatted output of characters, numbers, and strings. It assumes a standard output stream to which the symbols are written. Start writing process Usually you want to write into the system log which does not need an Out.Open call. Open a new output viewer Out.Open Redirect output to System.Log again Out.Close Write a character Out.Char(ch) Write an integer number Out.Int(i, 0) ... within 10 characters Out.Int(i, 10) Write a real number Out.Real(r, 0) or Out.LongReal(lr, 0) Write a string Out.String(s) Write a new line character Out.Ln Write a string containing one integer number Out.F("$Value of x: #", x) ... 2, 3, or 4 integer numbers Out.F2("$x=#, y=#", x, y) "$" is a new line character Out.F3("$x=#, y=#, z=#", x, y, z) Out.F4("$x=#, y=#, a=#, b=#", x, y, a, b)80wS, Text1 8Syntax10.Scn.Fntr0wS"StyleElemsAlloc +ևҝϳText2TP   TwoColsLinkElemsAllocProg.Guide.Text'Prog.Guide.Text,%V  Module Input provides facilities to access the mouse, the keyboard, and the clock. Track the mouse  Try to read a character from keyboard  Get the time elapsed since system startup seconds := Input.Time() DIV Input.TimeUnit 8+ Module In Module Out Module Input80wS, Text1tMarkElemsAlloc\Syntax10i.Scn.Fnt@28PSyntax10.Scn.Fnt)Syntax8i.Scn.Fnt/B& VAR text: Texts.Text; BEGIN NEW(text); (* create an instance and install notifier *) text.notify := TextFrames.NotifyDisplay; Texts.Open(text, name); (* initialize text from file name *) RETURN text END Text;8% B718Syntax10.Scn.Fnt>Syntax8i.Scn.Fnt#MarkElemsAlloc%/4&9 VAR r: Texts.Reader; ch: CHAR; BEGIN IF pos < text.len THEN (* position is within the text *) Texts.OpenReader(r, text, pos); Texts.Read(r, ch); (* read character at position pos *) WHILE ~r.eot DO (* process character ch *) Texts.Read(r, ch) (* read next character *) END END END ProcessText;8?8Syntax10.Scn.FntSyntax8i.Scn.FntMarkElemsAlloc 06b' VAR r: Texts.Reader; ch: CHAR; Syntax10i: Fonts.Font; BEGIN IF pos < text.len THEN Syntax10i := Fonts.This("Syntax10i.Scn.Fnt"); (* the italics font *) Texts.OpenReader(r, text, pos); Texts.Read(r, ch); (* read first character *) WHILE ~r.eot DO IF r.fnt = Syntax10i THEN RETURN Texts.Pos(r) - 1 END; Texts.Read(r, ch) (* read next character *) END END; RETURN -1 END GetItalics;8~y148Syntax10.Scn.FntdSyntax8i.Scn.Fnt#MarkElemsAlloczd0!(2- VAR s: Texts.Scanner; ch: CHAR; name: ARRAY 256 OF CHAR; i: LONGINT; BEGIN IF pos < text.len THEN (* position is within the text *) Texts.OpenScanner(s, text, pos); (* set scanner to starting position *) Texts.Scan(s); (* scan a symbol *) IF s.class = Texts.Name THEN COPY(s.s, name) (* process name *) ELSIF s.class = Texts.Int THEN i := s.i (* process integer *) END END END ScanText;8b83:8Syntax10.Scn.Fnt#Syntax8i.Scn.Fnt"-2MarkElemsAlloc46NW8   BEGIN Texts.WriteString(w, txt); (* append string txt to w.buf *) Texts.WriteInt(w, i, 1); (* convert i to text and append to w.buf *) Texts.WriteLn(w); (* append a carriage return character to w.buf *) Texts.Append(Oberon.Log, w.buf) (* display w.buf in log *) END PutInt;8_8Syntax10.Scn.Fnt8MarkElemsAllociR&`RRSSyntax8i.Scn.Fnt%& VAR s: Texts.Scanner; name: ARRAY 256 OF CHAR; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); WHILE s.class = Texts.Name DO COPY(name, s.s); (* process object with name s.s *) Texts.Scan(s) END END ProcessNames;8K~k%8Syntax10.Scn.FntSyntax8i.Scn.Fnt )-MarkElemsAllocj:6E VAR t: Texts.Text; (* the text of the selection *) beg, end: LONGINT; (* the stretch in t which is selected *) time: LONGINT; (* the time of the most recent selection *) BEGIN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN (* the selection exists *) (* process selection *) END END ProcessSelection;8s8Syntax10.Scn.FntCSyntax8i.Scn.Fnt )-MarkElemsAlloc&`RRS%S'" VAR s: Texts.Scanner; name: ARRAY 256 OF CHAR; t: Texts.Text; (* the text of the selection *) beg, end: LONGINT; (* the stretch in t which is selected *) time: LONGINT; (* the time of the most recent selection *) BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); WHILE s.class = Texts.Name DO COPY(name, s.s); (* process object with name s.s *) Texts.Scan(s) END; IF (s.class = Texts.Char) & (s.c = "^") THEN Oberon.GetSelection(t, beg, end, time); IF time > 0 THEN (* the selection exists *) Texts.OpenScanner(s, t, beg); Texts.Scan(s); IF s.class = Texts.Name THEN (* process object with name s.s *) END END END END ProcessArgs;8W-tf8uSyntax10i.Scn.FntSyntax10.Scn.FntMarkElemsAllocr="& VAR v: Viewers.Viewer; s: Texts.Scanner; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "*") THEN v := Oberon.MarkedViewer(); (* does not require the star-shaped pointer to be visible *) Viewers.Close(v) END END Close;8vW8Syntax10i.Scn.FntSyntax10.Scn.Fnt!MarkElemsAllocf:)' VAR v: Viewers.Viewer; s: Texts.Scanner; BEGIN Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); IF (s.class = Texts.Char) & (s.c = "*") & Oberon.Pointer.on THEN (* star-shaped must be visible *) v := Oberon.MarkedViewer(); Viewers.Close(v) END END CloseVisible;8[8YSyntax10.Scn.FntiSyntax8i.Scn.Fnt%)%MarkElemsAlloc\)6J,<%/b$H#%$?07V) VAR f: TextFrames.Frame; t: Texts.Text; r: Texts.Reader; v: Viewers.Viewer; beg, end, time: LONGINT; (* time and stretch of selection *) x, y: INTEGER; (* position designated by the pointer *) pos: LONGINT; (* character equivalent of x, y *) ch: CHAR; BEGIN Oberon.GetSelection(t, beg, end, time); (* most recent selection *) IF (time > 0) (* selection exists *) & Oberon.Pointer.on (* pointer is visible *) THEN x := Oberon.Pointer.X; y := Oberon.Pointer.Y; v := Viewers.This(x, y); (* the viewer which contains the pointer *) IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN (* second frame is the text frame *) f := v.dsc.next(TextFrames.Frame); (* the main frame *) IF (y >= f.X) & (x < f.X + f.W) & (y >= f.Y) & (y < f.Y + f.H) THEN (* pointer is in the main frame *) pos := TextFrames.Pos(f, x, y); (* convert x, y to text position *) IF pos >= 0 THEN (* position is valid *) Texts.OpenReader(r, f.text, pos); Texts.Read(r, ch); (* read character at pos to access its font *) Texts.ChangeLooks(t, beg, end, {0}, r.fnt, 0, 0) (* the font of the stretch [beg, end) is changed and the display is updated *) END END END END END CopyFont;8$Wg8Syntax10.Scn.Fnt9Syntax8i.Scn.Fnt1MarkElemsAlloc}2OJ VAR menuF, mainF: TextFrames.Frame; txt: Texts.Text; (* text of the main frame *) v: MenuViewers.Viewer; x, y: INTEGER; BEGIN txt := TextFrames.Text(""); (* create an empty text *) menuF := TextFrames.NewMenu("New Viewer", "System.Close System.Copy System.Grow Edit.Store"); mainF := TextFrames.NewText(txt, 0); Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); (* placement hint *) v := MenuViewers.New(menuF, mainF, TextFrames.menuH, x, y) END OpenViewer;8Фx8Syntax10.Scn.FntSyntax10i.Scn.FntSyntax8i.Scn.Fnt.MarkElemsAllocHd$>6 4>2 VAR txt: Texts.Text; (* text to be processed *) v: Viewers.Viewer; s: Texts.Scanner; BEGIN v := Oberon.Par.vwr; IF (Oberon.Par.frame IS TextFrames.Frame) & (Oberon.Par.frame = v.dsc) THEN (* command is issued from menu *) IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN txt := Oberon.Par.vwr.dsc.next(TextFrames.Frame).text (* process text *) END ELSE (* command is issued from an editable text frame *) Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s); WHILE s.class = Texts.Name DO txt := TextFrames.Text(s.s); (* open text from file with name s.s *) (* process text *) Texts.Scan(s) END END END ProcessText2;8<8Syntax10.Scn.FntVMarkElemsAlloc-SSyntax8i.Scn.Fnt=%$v%"# ,N20 VAR f: TextFrames.Frame; buf: Texts.Buffer; v: Viewers.Viewer; pos: LONGINT; BEGIN v := Oberon.FocusViewer; IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN (* Focus viewer has a main frame which is a text frame. *) f := v.dsc.next(TextFrames.Frame); (* the main frame *) IF f.hasCar THEN (* a caret is set *) Texts.Recall(buf); (* the most recently deleted text *) pos := f.carloc.pos + buf.len; (* caret position after insert *) Texts.Insert(f.text, f.carloc.pos, buf); TextFrames.SetCaret(f, pos) END END END Recall;8aw8cSyntax10.Scn.FntKMarkElemsAllocWVSyntax8i.Scn.Fnt=E$v D/";@I78' VAR v: Viewers.Viewer; pos, carPos: LONGINT; f: TextFrames.Frame; BEGIN v := Oberon.MarkedViewer(); IF (v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame) THEN (* marked viewer has a main frame which is a text frame *) f := v.dsc.next(TextFrames.Frame); (* the main frame *) IF f.hasCar THEN (* a caret is displayed *) carPos := f.carloc.pos ELSE carPos := 0 END; pos := GetItalics(f.text, carPos); IF pos < 0 THEN RETURN (* no italics font found *) ELSE Oberon.PassFocus(v); (* request focus, clear caret if one is set *) TextFrames.RemoveSelection(f); Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); TextFrames.Show(f, pos - 200); (* scroll viewer, positions the text near the top *) TextFrames.SetCaret(f, pos); (* set the caret *) END END END SearchItalics;8@,8Syntax10.Scn.FntMarkElemsAlloc$CSyntax8i.Scn.Fnt6- 5MY#Syntax10i.Scn.FntN7 VAR file: Files.File; BEGIN file := Files.Old(name); (* create file variable from directory entry name *) IF file = NIL THEN (* no entry name exists in the directory *) file := Files.New(name); (* create new file *) ELSE (* process file *) END; (* ... *) Files.Register(file) (* write buffers to disk and register file. In the case where the file is opened with Files.Old there is no need to register the file, thus Files.Close(f) would be enough. *) (* The file is still valid after Files.Close or Files.Register is called! *) END ProcessFile;828#Syntax10.Scn.Fnt VAR i, j: INTEGER; BEGIN i := 0; j := 0; LOOP WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END; IF name[i] = 0X THEN EXIT END; INC(i); WHILE j # i DO bak[j] := name[j]; INC(j) END END; bak[j] := "B"; bak[j + 1] := "a"; bak[j + 2] := "k"; bak[j + 3] := 0X END Backup;8'l8Syntax10.Scn.FntbSyntax8i.Scn.Fnt'5Z .  VAR file: Files.File; bakName: ARRAY 32 OF CHAR; res: INTEGER; BEGIN file := Files.New(name); (* create an output file *) (* ... *) Backup(name, bakName); (* create a backup name *) Files.Rename(name, bakName, res); CASE res OF 0: (* file renamed *) | 1: (* backup file already exists and is now associated with the old version of file name *) | 2: (* name is not in directory *) | 3: (* name is not well formed *) END; Files.Register(file) (* register the newly created output file *) END Save;8X8Syntax10.Scn.FntZSyntax8i.Scn.FntfMarkElemsAlloc7) a1=p2 " TYPE Person = POINTER TO PersonDesc; PersonDesc = RECORD Name: ARRAY 32 OF CHAR; (* other fields *) END; VAR customer: Person; r, w: Files.Rider; f: Files.File; BEGIN f := Files.New("customer"); Files.Set(r, f, 0); Files.Set(w, f, 0); (* ... *) Files.ReadBytes(r, customer^, SIZE(PersonDesc)); (* It is important to dereference the pointer *) (* ... *) Files.WriteBytes(w, customer^, SIZE(PersonDesc)); (* ... *) Files.Register(f) END RecordFile;882hU8QSyntax10.Scn.FntSyntax10i.Scn.Fnt(R[ VAR main: TextFrames.Frame; v: Viewers.Viewer; BEGIN v := Oberon.MarkedViewer(); IF (v.dsc # NIL) & (v.dsc.next # NIL) & (v.dsc.next IS TextFrames.Frame) THEN main := v.dsc.next(TextFrames.Frame); (* main text frame of marked viewer *) IF main.hasSel THEN Texts.Delete(main.text, main.selbeg.pos, main.selend.pos) END END END Delete;8MKn8Syntax10.Scn.FntSyntax10i.Scn.Fnt!8FoldElemsNew#Syntax10.Scn.Fnt time >= 088#Syntax10.Scn.Fnt00(v.dsc # NIL) & (v.dsc.next IS TextFrames.Frame)8K8#Syntax10.Scn.Fnt main.hasCar 8}S VAR main: TextFrames.Frame; buf: Texts.Buffer; v: Viewers.Viewer; beg, end, time: LONGINT; t: Texts.Text; BEGIN Oberon.GetSelection(t, beg, end, time); (* get most recent selection *) IF selection exists THEN NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, beg, end, buf); (* save text in buffer *) v := Oberon.FocusViewer; (* get focus viewer *) IF it is a text viewer THEN main := v.dsc.next(TextFrames.Frame); (* main text frame *) IF caret exists THEN Texts.Insert(main.text, main.carloc.pos, buf) (* insert text at caret's position *) END END END END CopyText;8E:8CSyntax10.Scn.Fnt!Syntax10i.Scn.Fnt/ VAR keys: SET; BEGIN REPEAT (* procress keysum and mouse position (x, y) *) Input.Mouse(keys, x, y); Oberon.DrawCursor(Oberon.Mouse , Oberon.Arrow, x, y); keysum := keysum + keys UNTIL keys = {} END TrackMouse;8.,%+{8#Syntax10.Scn.Fntcc BEGIN IF Input.Available() = 0 THEN RETURN FALSE END; Input.Read(ch); RETURN TRUE END ReadChar;8!E\ qPopupElemsAllocCommandos#Syntax10.Scn.FntRRSample.OpenViewer Sample.Recall Sample.SearchItalics Sample.Delete Sample.CopyTextm Programming Guide based on M. Reiser: "The Oberon System" H. Mssenbck, C. Mayrhofer, C. Steindl  Working with texts Accessing parameters Viewers Working with text viewers Working with text frames Working with files Input and Output MODULE Sample; IMPORT Texts, TextFrames, Fonts, Oberon, Viewers, MenuViewers, Files, Input; VAR w: Texts.Writer; (* The following code is what TextFrames.Text actually does. *) PROCEDURE Text* (name: ARRAY OF CHAR): Texts.Text; (* Process all characters of a text, starting at position pos. *) PROCEDURE ProcessText (text: Texts.Text; pos: LONGINT); (* Searches a text from the initial position pos for the first occurrence of an italics font. It returns this position, if it exists, otherwise -1 results. *) PROCEDURE GetItalics (text: Texts.Text; pos: LONGINT): LONGINT; (* Scan a text, starting at position pos. *) (* When scanning a whole text, you can use ~s.eot as predicate in a WHILE loop as above, but s.eot may already yield TRUE while the last valid symbol is returned, not only after an attempt to scan beyond the end of the text. In this case, a WHILE loop using the predicate ~s.eot misses the last symbol. Therefore, it is always preferable to terminate a sequence of scan operations with a definite symbol. *) PROCEDURE ScanText (text: Texts.Text; pos: LONGINT); PROCEDURE PutInt* (txt: ARRAY OF CHAR; i: LONGINT); PROCEDURE ProcessNames*; (* {name} ~ *) PROCEDURE ProcessSelection*; (* ^ *) PROCEDURE ProcessArgs*; (* {name} ~ | ^ *) PROCEDURE Close*; (* * *) PROCEDURE CloseVisible*; (* * *) (* Copies the font of the character underneath the star-shaped pointer to the selection *) PROCEDURE CopyFont*; PROCEDURE OpenViewer*; (* If the command is issued from an editable text, it admits a parameter list. All texts in the list will be processed. If, on the other hand, ProcessText2 is issued from the menu, it will work on the text contained in the main frame of the viewer which contains the menu. *) PROCEDURE ProcessText2*; (* The following code is what Edit.Recall actually does. *) PROCEDURE Recall*; (* The text of the main frame of the marked viewer is searched for the occurrence of a character in italics font Syntax10i.Scn.Fnt. The search is started at the caret position or at the beginning of the text if not caret is set. If a character is located, the text is scrolled such that it is displayed near the top line and the caret is positioned. *) PROCEDURE SearchItalics*; (* Try to open an old file, if none exists, create a new one *) PROCEDURE ProcessFile (name: ARRAY OF CHAR); PROCEDURE Backup (VAR name, bak: ARRAY OF CHAR); PROCEDURE Save (name: ARRAY OF CHAR); PROCEDURE RecordFile; (* Deletes the selected text in the marked viewer. *) PROCEDURE Delete*; (* Copies the most recently selected text part to the caret's position. *) PROCEDURE CopyText*; (* Tracks the mouse and process the mouse keys and the position *) PROCEDURE TrackMouse (VAR keysum: SET; VAR x, y: INTEGER); (* Try to read a character from keyboard *) PROCEDURE ReadChar (VAR ch: CHAR): BOOLEAN; BEGIN Texts.OpenWriter(w) (* The writer is based on the file system. In most cases, one writer per module is enough. It is, therefore, good practice to open the writer once per session in the module's body. *) END Sample. Compiler.Compile @\s ErrorElems.Mark ErrorElems.Unmark