-- TiogaExecuteImpl.mesa
-- written by Bill Paxton, May 1981
-- last edit by Bill Paxton, 14-Jul-81 10:16:19
-- This package implements the Execute command in Tioga
DIRECTORY
TiogaExecute,
RopeReader,
TextEdit,
EditSpan,
TextNode,
TextLooks,
RopeEdit,
NameSymbolTable;
TiogaExecuteImpl: PROGRAM
IMPORTS nsI:NameSymbolTable, rdrI:RopeReader, spanI:EditSpan, nodeI:TextNode,
ropeI:RopeEdit, editI:TextEdit
EXPORTS TiogaExecute =
BEGIN
OPEN TiogaExecute, looksI:TextLooks;
Ref: TYPE = nodeI.Ref;
-- ***** Execute
Exec: PUBLIC PROC [keyNode: RefTextNode, keyStart, keyLen: Offset, dictList: NodeList,
event: Event ← NIL]
RETURNS [foundIt: BOOLEAN, exec: Rope, resultStart, resultLen: Offset] = {
DoAbbreviation: PROC = {
looks: looksI.Looks;
allcaps, initialcap: BOOLEAN ← FALSE;
child: RefTextNode ← nodeI.NarrowToTextNode[nodeI.FirstChild[node]];
childSize: Offset;
IF AllCaps[] THEN allcaps ← TRUE
ELSE IF editI.FetchChar[keyNode,keyStart] IN ['A..'Z] THEN initialcap ← TRUE;
[resultStart,resultLen] ←
editI.ReplaceText[keyNode,keyStart,keyLen,child,0,editI.MaxLen,event];
IF child=NIL THEN RETURN;
childSize ← editI.Size[child];
IF (looks ← editI.FetchLooks[keyNode,keyStart]) # looksI.noLooks THEN
editI.AddLooks[keyNode,looks,keyStart,childSize];
IF allcaps THEN editI.InitialCaps[keyNode,keyStart,childSize]
ELSE IF initialcap AND childSize > 0 THEN editI.AllCaps[keyNode,keyStart,1];
IF nodeI.FirstChild[child] # NIL THEN -- insert as children of keyNode
[] ← spanI.Copy[nodeI.MakeNodeLoc[keyNode],
nodeI.MakeNodeSpan[nodeI.FirstChild[child],
nodeI.LastWithin[child]],
FALSE,after,1,event];
IF nodeI.Next[child] # NIL THEN -- insert as siblings of keyNode
[] ← spanI.Copy[nodeI.MakeNodeLoc[keyNode],
nodeI.MakeNodeSpan[nodeI.Next[child],
nodeI.LastWithin[nodeI.LastSibling[child]]],
FALSE,after,0,event];
};
AllCaps: PROC RETURNS [upper:BOOLEAN] = {
rdr1 ← rdr3; -- set for start of key
upper ← FALSE;
FOR i:Offset ← 0, i+1 UNTIL i >= keyLen DO
SELECT rdrI.Get[rdr1] FROM
IN ['a..'z] => RETURN [FALSE];
IN ['A..'Z] => upper ← TRUE; -- must have at least one uppercase
ENDCASE;
ENDLOOP };
DoCommand: PROC = {
child: RefTextNode ← nodeI.NarrowToTextNode[nodeI.FirstChild[node]];
IF child=NIL THEN RETURN;
exec ← child.rope };
rdr1, rdr2, rdr3: rdrI.Ref;
keyRope: Rope ← keyNode.rope;
node: RefTextNode;
rope: Rope;
size: Offset;
foundIt ← FALSE;
rdr1 ← rdrI.GetRopeReader[];
rdr2 ← rdrI.GetRopeReader[];
rdr3 ← rdrI.GetRopeReader[];
rdrI.SetPosition[rdr3,keyRope,keyStart]; -- leave this one permanently set at key
[] ← rdrI.Peek[rdr3];
FOR lst:NodeList ← dictList, lst.next UNTIL lst=NIL DO
FOR entry:Ref ← lst.node.child, nodeI.Next[entry] UNTIL entry=NIL DO
IF (node ← nodeI.NarrowToTextNode[entry])=NIL THEN LOOP;
IF (size ← ropeI.Size[rope ← node.rope]) # keyLen THEN LOOP;
rdr1 ← rdr3; -- already primed to read key
IF rdrI.CompareSubstrs[keyRope,rope,keyStart,keyLen,0,size,rdr1,rdr2,FALSE] = 0 THEN {
foundIt ← TRUE; -- have found a match
SELECT node.typename FROM
nodeI.nullTypeName, abbrev, abbreviation => DoAbbreviation[];
command => DoCommand[];
ENDCASE;
GOTO Finis };
ENDLOOP;
REPEAT Finis => NULL;
ENDLOOP;
rdrI.FreeRopeReader[rdr1];
rdrI.FreeRopeReader[rdr2];
rdrI.FreeRopeReader[rdr3] };
-- ***** Initialization
abbrev, abbreviation, command: nodeI.TypeName;
Start: PUBLIC PROC = { -- for initialization only
abbrev ← nsI.MakeName["abbrev"];
abbreviation ← nsI.MakeName["abbreviation"];
command ← nsI.MakeName["command"];
};
END.