ð¡.Oberon10.Scn_Fnt¬üÿÿÐûÐûInfoElemsAlloc#Syntax10.Scn.Fnt11"Title": Helps to access the arguments passed to a command. "Copyright": 1996, 1997 by Claudio Nieder . This module is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This module is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ÿÿÿÿ€8ÀÔFoldElemsNew;ÿÿÿÿ€8ÀÔÈþÿÿ€8ÀÔ1Oberon10.Scn_Fnt8Q ScannerPtr*=POINTER TO Texts.Scanner; Parameter*=RECORD name-:string.StringPtr; END; ParameterPtr*=POINTER TO Parameter; ParameterProcedure*=PROCEDURE(p:ParameterPtr); T*=RECORD type*:ArgumentType; scanner*:ScannerPtr; text*:Texts.Text; frame*:TextFrames.Frame; viewer*:Viewers.Viewer; name*:ARRAY 256 OF CHAR; END;ÿÿÿÿ€8ÀÔúÿÿ€8ÀÔ#Oberon10.Scn_FntÎÎ Initializes arg and gets the environment from which the command was executed, i.e. the name of the menu viewer in which the command was executed, the text of this viewer and a scanner setup for parsing the remaining of the commands parameter (if any). The meaning of the fields of arg are: type This field is set to menu, if the command was executed from the menu frame. It is set to marked, if the command was not excuted from a menu frame, but a mark is visible. In this case name, viewer, text and frame relate to the marked viewer. If the mark is not visible, then name, viewer, text and frame relate to the viewer from which the command was excuted... but is that the viewer to which the command should apply? Thus the type is set to unknown. If the viewer is not identified as MenuViewer, then type receives the value end, and all other fields are undefined. name The filename at the left of the menu frame. Empty, if either the name is misformed (not of scanner class name or string), or if the command does not belong to a menu. viewer Viewer from which the commands was executed, or the marked viewer. See explanation of type. frame Main frame of either the command holding, or marked viewer. See explanation of type. text Main text of either the command holding, or marked viewer. See explanation of type. scanner Scanner by which additional parameters occuring after the command can be scanned. ÿÿÿÿ€8ÀÔT÷ÿÿ€8ÀÔëOberon10.Scn_FntV”ÿÿÿ€8ÀÔFoldElemsNew#Oberon10.Scn_FntJJ Was called from the menu of a menu viewer, so use this menu viewer. ÿÿÿÿ€8ÀÔVuÿÿÿ€8ÀÔ#Oberon10.Scn_Fntii Was called from within a viewer, but there is a visible marker, so implicitely use that viewer. ÿÿÿÿ€8ÀÔF¤ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt:: Was called from within a viewer. No visible viewer. ÿÿÿÿ€8ÀÔÀiÿÿÿ€8ÀÔ#Oberon10.Scn_Fntuu arg.viewer is really a menu viewer with a valid menu (arg.viewer.dsc) and main (arg.viewer.dsc.next) text. ÿÿÿÿ€8ÀÔšÿÿÿ€8ÀÔ#Oberon10.Scn_FntDD Set up scanner to parse name in menu frame and retrieve name. ÿÿÿÿ€8ÀÔ{†ÿÿÿ€8ÀÔ#Oberon10.Scn_FntXX Open a scanner starting from the current parameter, and perform the first scan. ÿÿÿÿ€8ÀÔ‚Â BEGIN arg.viewer:=Oberon.Par.vwr; IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN (**) arg.viewer:=Oberon.Par.vwr; arg.type:=menu; ELSIF Oberon.Pointer.on THEN (**) arg.viewer:=Oberon.MarkedViewer(); arg.type:=marked; ELSE (**) arg.viewer:=Oberon.Par.vwr; arg.type:=unknown; END; IF (arg.viewer#NIL) & (arg.viewer IS MenuViewers.Viewer) & (arg.viewer.dsc#NIL) & (arg.viewer.dsc IS TextFrames.Frame) THEN (**) (**) arg.frame:=arg.viewer.dsc(TextFrames.Frame); NEW(arg.scanner); Texts.OpenScanner(arg.scanner^,arg.frame.text,0); Texts.Scan(arg.scanner^); IF (arg.scanner.class=Texts.Name) OR (arg.scanner.class=Texts.String) THEN COPY(arg.scanner.s,arg.name); ELSE arg.name[0]:=0X; END; IF (arg.viewer.dsc.next#NIL) & (arg.viewer.dsc.next IS TextFrames.Frame) THEN (**) arg.frame:=arg.frame.next(TextFrames.Frame); arg.text:=arg.frame.text; END; IF Oberon.Par.text#NIL THEN (* Note: previously, this was enclosed in above IF *) Texts.OpenScanner(arg.scanner^,Oberon.Par.text,Oberon.Par.pos); END; ELSE arg.scanner:=NIL; arg.text:=NIL; arg.viewer:=NIL; arg.frame:=NIL; arg.name[0]:=0X; arg.type:=end; END; END init;ÿÿÿÿ€8ÀÔ5œÿÿÿ€8ÀÔ#Oberon10.Scn_FntBB Retrieve the current selection, and copy it in a new text. ÿÿÿÿ€8ÀÔ–þÿÿ€8ÀÔ#Oberon10.Scn_FntHH VAR buf:Texts.Buffer; selBeg,selEnd:LONGINT; text2:Texts.Text; time:LONGINT; BEGIN Oberon.GetSelection(text2,selBeg,selEnd,time); IF time>=0 THEN text:=TextFrames.Text(""); NEW(buf); Texts.OpenBuf(buf); Texts.Save(text2,selBeg,selEnd,buf); Texts.Append(text,buf); ELSE text:=NIL; END; END getSelectionText;ÿÿÿÿ€8ÀÔ;­ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt11 Setup a scanner on the current selection. ÿÿÿÿ€8ÀÔëþÿÿ€8ÀÔ#Oberon10.Scn_Fntóó VAR selBeg,selEnd:LONGINT; text:Texts.Text; time:LONGINT; BEGIN Oberon.GetSelection(text,selBeg,selEnd,time); IF time>=0 THEN NEW(scanner); Texts.OpenScanner(scanner^,text,selBeg); ELSE scanner:=NIL; END; END getSelectionScanner;ÿÿÿÿ€8ÀÔýÿÿ€8ÀÔ#Oberon10.Scn_FntÎÎ Read the next parameter. arg.type indicates which kind of parameter was found. Depending on the parameter, some further informations are stored in arg. star arg.viewer contains the marked viewer and arg.text the corresponding text, if the viewer has a text frame. at No further information. One should either use getSelectionScanner or getSelectionText to access the last selection. arrow No further information. The scanner is replaced, so that it continues to scan at the current selection. parameter The scanner points to something, which has no special meaning. Its up to the command to decide, if this is a valid parameter. end No further information. ÿÿÿÿ€8ÀÔ©÷ÿÿ€8ÀÔ’Oberon10.Scn_FntÎ~ÿÿÿ€8ÀÔFoldElemsNew#Oberon10.Scn_Fnt`` A "star" as parameter. In this case, the text of the marked menu viewer is retrieved. ÿÿÿÿ€8ÀÔ7fÿÿÿ€8ÀÔ#Oberon10.Scn_Fntxx An "at" as parameter. In this case, the selected text is the entity on which the command should operate. ÿÿÿÿ€8ÀÔ6,ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt²² An "arrow" as parameter. In this case, the text of the last selection is located. A new scanner is set up, starting at the selection. It replaces the old scanner. ÿÿÿÿ€8ÀÔ£xÿÿÿ€8ÀÔ#Oberon10.Scn_Fntff A "tilde" as parameter. This marks the end of the parameters, so the scanner is set to NIL. ÿÿÿÿ€8ÀÔM‚ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt\\ A 0X as parameter. This is taken as end parameters, so the scanner is set to NIL. ÿÿÿÿ€8ÀÔ6…ÿÿÿ€8ÀÔ#Oberon10.Scn_FntYY None of the special parameter. In this case, the scanner is left, where it is. ÿÿÿÿ€8ÀÔYÆ BEGIN arg.text:=NIL; arg.viewer:=NIL; Texts.Scan(arg.scanner^); IF arg.scanner.eot THEN arg.type:=end; arg.scanner:=NIL; ELSE IF arg.scanner.class=Texts.Char THEN IF arg.scanner.c="*" THEN (**) arg.viewer:=Oberon.MarkedViewer(); IF (arg.viewer IS MenuViewers.Viewer) & (arg.viewer.dsc.next IS TextFrames.Frame) THEN arg.frame:=arg.viewer.dsc.next(TextFrames.Frame); arg.text:=arg.frame.text; ELSE arg.text:=NIL; END; arg.type:=star; ELSIF arg.scanner.c="@" THEN (**) arg.type:=at ELSIF arg.scanner.c="^" THEN (**) getSelectionScanner(arg.scanner); IF arg.scanner=NIL THEN arg.type:=end; ELSE arg.type:=arrow; END; ELSIF arg.scanner.c="~" THEN (**) arg.type:=end; arg.scanner:=NIL; ELSIF arg.scanner.c=0X THEN (**) arg.type:=end; arg.scanner:=NIL; ELSE (**) arg.type:=parameter; END; ELSE arg.type:=parameter; END; END; END next;ÿÿÿÿ€8ÀÔ'¨ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt66 Calls next until the argument is not an arrow. ÿÿÿÿ€8ÀÔ›ÿÿÿ€8ÀÔ#Oberon10.Scn_FntCC BEGIN REPEAT next(arg) UNTIL arg.type#arrow; END nextNonArrow;ÿÿÿÿ€8ÀÔ5=ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt¡¡ Return first argument, if it is a name. This happens so often in my programs, that I think it is useful to treat this special case in arguments itself. ÿÿÿÿ€8ÀÔâþÿÿ€8ÀÔ#Oberon10.Scn_Fntüü BEGIN init(arg); nextNonArrow(arg); IF arg.type=end THEN Log.Str("Missing name."); Log.Ln; valid:=FALSE; ELSIF arg.scanner.class#Texts.Name THEN Log.Str("Argument not a name."); Log.Ln; valid:=FALSE; ELSE valid:=TRUE; END; END oneName;ÿÿÿÿ€8ÀÔ9=ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt¡¡ Return first argument, if it is a name. This happens so often in my programs, that I think it is useful to treat this special case in arguments itself. ÿÿÿÿ€8ÀÔÿÿÿÿ€8ÀÔúÿÿÿÿ€8ÀÔ8=ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt¡¡ Return first argument, if it is a name. This happens so often in my programs, that I think it is useful to treat this special case in arguments itself. ÿÿÿÿ€8ÀÔ£ÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt;; BEGIN init(arg); nextInteger(arg,valid); END oneInteger;ÿÿÿÿ€8ÀÔMHÿÿÿ€8ÀÔ#Oberon10.Scn_Fnt–– For each occurance of a name or string call the passed procedure. The loop stops, as soon as there are no parameter of type name or string. ÿÿÿÿ€8ÀÔ2þÿÿ€8ÀÔ#Oberon10.Scn_Fnt¬¬ VAR arg:T; quit:BOOLEAN; BEGIN init(arg); quit:=FALSE; REPEAT next(arg); IF arg.type=end THEN quit:=TRUE; ELSE CASE arg.type OF | parameter: CASE arg.scanner.class OF | Texts.Name,Texts.String: string.dup(param.name,arg.scanner.s); procedure(param); ELSE quit:=TRUE; END; | arrow: (* just reenter loop *) ELSE quit:=TRUE; END; END; UNTIL quit; END forEachName;ÿÿÿÿ€8ÀÔ;šÿÿÿ€8ÀÔ#Oberon10.Scn_FntDD Remove extension .Sym, .Mod or .Obj from the passed string. ÿÿÿÿ€8ÀÔ’þÿÿ€8ÀÔ#Oberon10.Scn_FntLL VAR extension:ARRAY 4 OF CHAR; length:LONGINT; BEGIN length:=string.length(fileName); IF length>4 THEN IF fileName[length-4]='.' THEN string.copyPart(extension,fileName,length-3,3); IF (extension="Mod") OR (extension="Sym") OR (extension="Obj") THEN fileName[length-4]:=0X; END; END; END; END removeExtension;ÿÿÿÿ€8ÀÔkMODULE arguments;  IMPORT Log,MenuViewers,Oberon,TextFrames,Texts,Viewers ,string; (*enum: ArgumentType*=(end,parameter,star,at,arrow,menu,marked,unknown); *) TYPE ArgumentType*=SHORTINT; CONST end*=0; parameter*=1; star*=2; at*=3; arrow*=4; menu*=5; marked*=6; unknown*=7; TYPE PROCEDURE init*(VAR arg:T);(**) PROCEDURE getSelectionText*(VAR text:Texts.Text);(**) PROCEDURE getSelectionScanner*(VAR scanner:ScannerPtr);(**) PROCEDURE next*(VAR arg:T);(**) PROCEDURE nextNonArrow*(VAR arg:T);(**) PROCEDURE oneName*(VAR arg:T; VAR valid:BOOLEAN);(**) PROCEDURE nextInteger*(VAR arg:T; VAR valid:BOOLEAN);(**) BEGIN nextNonArrow(arg); IF arg.type=end THEN Log.Str("Missing integer."); Log.Ln; valid:=FALSE; ELSIF arg.scanner.class#Texts.Int THEN Log.Str("Argument not an integer."); Log.Ln; valid:=FALSE; ELSE valid:=TRUE; END; END nextInteger; PROCEDURE oneInteger*(VAR arg:T; VAR valid:BOOLEAN);(**) PROCEDURE forEachName*(procedure:ParameterProcedure; param:ParameterPtr);(**) PROCEDURE removeExtension*(VAR fileName:ARRAY OF CHAR);(**) END arguments.