-- TiogaMiscOps2Impl.mesa Edited by Paxton on December 28, 1982 2:23 pm
Last Edited by: Maxwell, January 6, 1983 11:34 am
DIRECTORY
AbbrevExpand USING [Expand, Load],
CIFS USING [Error],
EditSpan USING [ChangeCaps],
Inline USING [BITAND],
MessageWindow USING [Append, Blink],
NameSymbolTable USING [MakeName, Name, RopeFromName],
NodeProps USING [false, true],
NodeStyle USING [Name, ReloadStyle, StyleNameForNode],
NodeStyleExtra USING [ForEachAttachedStyle],
Rope USING [Concat, Fetch, Flatten, FromProc, Lower, ROPE, Size, Substr],
RopeEdit USING [AlphaNumericChar, Substr],
RopeReader USING [FreeRopeReader, Get, GetIndex, GetRopeReader, Ref, SetPosition],
TextEdit USING [CapChange, ChangeFormat, ChangeStyle, FetchChar, FetchLooks, GetRope, PutProp, ReplaceByChar],
TiogaNode USING [Location, NodeItself, nullName, Offset, Ref, RefBranchNode, RefTextNode, Name],
TiogaNodeOps USING [NarrowToTextNode, Root, StepForwardNode],
TiogaDocument USING [BeforeAfter, Selection, SelectionId, SelectionPoint],
TiogaInput USING [currentEvent, Interpret],
TiogaInputOps,
TiogaLocks USING [Lock, Unlock],
TiogaOps,
TiogaSelection USING [Alloc, Copy, Free, CaretAfterSelection, Deselect, InsertionPoint, LockSel, MakePointSelection, MakeSelection, oldSel, pSel, SelectionRoot, sSel, UnlockSel],
TiogaTouchup USING [fullUpdate],
ViewerClasses USING [Viewer],
ViewerOps USING [PaintViewer];
TiogaMiscOps2Impl: CEDAR PROGRAM
IMPORTS AbbrevExpand, CIFS, EditSpan, Inline, MessageWindow, NameSymbolTable, NodeProps, NodeStyle, NodeStyleExtra, Rope, RopeEdit, RopeReader, TiogaInput, TiogaInputOps, TiogaLocks, TiogaSelection, TiogaTouchup, TextEdit, TiogaNodeOps, ViewerOps
EXPORTS TiogaInputOps = BEGIN
OPEN TiogaDocument, TiogaSelection, TiogaOps, TiogaInputOps;
Capitalise:
PUBLIC
PROCEDURE [flavor: TextEdit.CapChange] = {
DoCapitalise:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
Deselect[];
EditSpan.ChangeCaps[root, [tSel.start.pos, tSel.end.pos], flavor, TiogaInput.currentEvent];
tSel.pendingDelete ← FALSE;
MakeSelection[tSel,primary] };
CallWithLocks[DoCapitalise] };
ControlChar:
PROC [make:
BOOLEAN] = {
DoControlChar:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
caret: TiogaNode.Location ← InsertionPoint[tSel];
node: TiogaNode.RefTextNode;
where: TiogaNode.Offset;
char: CHAR;
IF caret.where=TiogaNode.NodeItself OR caret.where=0 THEN GOTO Bad;
IF (node ← TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad;
where ← caret.where-1;
char ← TextEdit.FetchChar[node,where];
IF ~make AND char > 37C THEN GOTO Bad;
char ←
IF ~make
THEN 'A+
LOOPHOLE[char-1,
CARDINAL]
ELSE LOOPHOLE[Inline.BITAND[char,37B],CHAR];
Deselect[];
[] ← TextEdit.ReplaceByChar[
root: root, dest:node, char:char, start:where, len:1,
inherit:FALSE, looks:TextEdit.FetchLooks[node,where], event:TiogaInput.currentEvent];
MakePointSelection[tSel, caret];
EXITS Bad => EditFailed[] };
CallWithLocks[DoControlChar] };
MakeControlCharacter: PUBLIC PROC = { ControlChar[TRUE] };
UnMakeControlCharacter: PUBLIC PROC = { ControlChar[FALSE] };
UnMakeOctalCharacter:
PUBLIC
PROC = {
DoUnMakeOctalCharacter:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
caret: TiogaNode.Location ← InsertionPoint[tSel];
node: TiogaNode.RefTextNode;
char: CARDINAL;
IF caret.where=TiogaNode.NodeItself OR caret.where=0 THEN GOTO Bad;
IF (node ← TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad;
char ← LOOPHOLE[TextEdit.FetchChar[node,caret.where-1]];
BackSpace[1];
InsertChar[char/64 + '0];
InsertChar[(char/8) MOD 8 + '0];
InsertChar[char MOD 8 + '0];
EXITS Bad => EditFailed[] };
CallWithLocks[DoUnMakeOctalCharacter] };
MakeOctalCharacter:
PUBLIC
PROC = {
DoMakeOctalCharacter:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
caret: TiogaNode.Location ← InsertionPoint[tSel];
node: TiogaNode.RefTextNode;
where: TiogaNode.Offset;
char: CHAR;
d: CARDINAL;
IF caret.where=TiogaNode.NodeItself OR caret.where<3 THEN GOTO Bad;
IF (node ← TiogaNodeOps.NarrowToTextNode[caret.node]) = NIL THEN GOTO Bad;
where ← caret.where-3;
char ← TextEdit.FetchChar[node,where];
IF char NOT IN ['0..'3] THEN GOTO Bad;
d ← char-'0;
IF (char ← TextEdit.FetchChar[node,where+1]) NOT IN ['0..'7] THEN GOTO Bad;
d ← d*8 + char-'0;
IF (char ← TextEdit.FetchChar[node,where+2]) NOT IN ['0..'7] THEN GOTO Bad;
d ← d*8 + char-'0;
Deselect[];
[] ← TextEdit.ReplaceByChar[
root:root, dest:node, char:LOOPHOLE[d], start:where, len:3,
inherit:FALSE, looks:TextEdit.FetchLooks[node,where], event:TiogaInput.currentEvent];
caret.where ← where+1;
MakePointSelection[tSel, caret];
EXITS Bad => EditFailed[] };
CallWithLocks[DoMakeOctalCharacter] };
NameFromRope:
PROC [name: Rope.
ROPE]
RETURNS [NameSymbolTable.Name] =
TRUSTED
INLINE {
RETURN [NameSymbolTable.MakeName[LOOPHOLE[Rope.Flatten[name]]]]};
GetWord:
PROC
RETURNS [word: Rope.
ROPE] = {
tSel: Selection;
start: TiogaNode.Offset;
pos: TiogaNode.Location;
node: TiogaNode.RefTextNode;
nChars: CARDINAL ← 0;
CaretAfterSelection;
pos ← InsertionPoint[];
IF (node ← TiogaNodeOps.NarrowToTextNode[pos.node])=NIL THEN RETURN [NIL];
IF pos.where = TiogaNode.NodeItself THEN RETURN [NIL];
start ← pos.where-1;
WHILE start>=0
AND RopeEdit.AlphaNumericChar[TextEdit.FetchChar[node,start]]
DO
start ← start - 1; nChars ← nChars + 1; ENDLOOP;
IF nChars = 0 THEN RETURN [NIL];
start ← pos.where-nChars;
word ← RopeEdit.Substr[node.rope, start, nChars];
tSel ← Alloc[];
TiogaSelection.Copy[source: pSel, dest: tSel];
tSel.start.pos ← [node,start];
tSel.end.pos ← [node,start+nChars-1];
tSel.granularity ← char;
MakeSelection[tSel, primary];
Free[tSel];
Delete[];
};
SetStyle:
PUBLIC
PROC = {
DoSetStyle:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
name: Rope.ROPE ← GetWord[];
IF name=NIL THEN { EditFailed[]; RETURN };
SetStyleName[name] };
CallWithLocks[DoSetStyle] };
ForceLower:
PROC [r: Rope.
ROPE]
RETURNS [Rope.
ROPE] = {
Force: PROC RETURNS [c: CHAR] = { c ← Rope.Lower[Rope.Fetch[r,i]]; i ← i+1 };
i: INT ← 0;
RETURN [Rope.FromProc[Rope.Size[r], Force]] };
SetStyleName:
PUBLIC
PROC [name: Rope.
ROPE, node: TiogaNode.Ref ←
NIL] =
BEGIN
root: TiogaNode.RefBranchNode;
IF node=
NIL
THEN
node ← IF pSel.insertion=before THEN pSel.start.pos.node ELSE pSel.end.pos.node;
root ← TiogaNodeOps.Root[node];
[] ← TiogaLocks.Lock[root, "SetStyleName"];
TextEdit.ChangeStyle[node, ForceLower[name], TiogaInput.currentEvent, root !
UNWIND => TiogaLocks.Unlock[root]];
TiogaLocks.Unlock[root];
END;
ReloadStyle:
PUBLIC
PROC =
BEGIN
styleName: NodeStyle.Name ← NodeStyle.StyleNameForNode[InsertionPoint[].node];
IF ~NodeStyle.ReloadStyle[styleName] THEN CannotReload[styleName]
ELSE ViewerOps.PaintViewer[pSel.viewer, client, FALSE, TiogaTouchup.fullUpdate];
END;
ReloadStyleName:
PUBLIC
PROC [name: Rope.
ROPE] =
BEGIN
styleName: NodeStyle.Name;
IF Rope.Size[name]=0 THEN RETURN;
styleName ← NameFromRope[name];
IF ~NodeStyle.ReloadStyle[styleName] THEN CannotReload[styleName];
END;
CannotReload:
PROC [styleName: NodeStyle.Name] = {
OPEN MessageWindow;
Append["Failed in attempt to load style named ", TRUE];
Append[NameSymbolTable.RopeFromName[styleName]];
Blink[] };
SetFormat:
PUBLIC
PROC = {
DoSetFormat:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
name: Rope.ROPE ← GetWord[];
IF name=NIL THEN { EditFailed[]; RETURN };
SetFormatName[name] };
CallWithLocks[DoSetFormat] };
GetFormat:
PUBLIC
PROC = {
DoGetFormat:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
name: Rope.ROPE;
format: TiogaNode.Name ← InsertionPoint[].node.format;
name ←
IF format=TiogaNode.nullName
THEN "default"
ELSE NameSymbolTable.RopeFromName[format];
InsertRope[name] };
CallWithLocks[DoGetFormat] };
TransposeFormat:
PUBLIC
PROC [target: SelectionId ← primary] = {
-- Transpose the formats of the primary and secondary selections
targetSel: Selection ← IF target=primary THEN pSel ELSE sSel;
srcSel: Selection ← IF target=primary THEN sSel ELSE pSel;
DoTransFormat:
PROC [
sourceRoot, destRoot: TiogaNode.RefBranchNode, tSel, srcSel, targetSel: Selection] = {
targetFormat, srcFormat: TiogaNode.Name;
targetNode, srcNode: TiogaNode.Ref;
srcNode ← IF srcSel.insertion=before THEN srcSel.start.pos.node ELSE srcSel.end.pos.node;
srcFormat ← srcNode.format;
targetNode ←
IF targetSel.insertion=before
THEN targetSel.start.pos.node
ELSE targetSel.end.pos.node;
targetFormat ← targetNode.format;
TiogaSelection.Copy[source: targetSel, dest: oldSel]; -- save for Repeat's
FOR node: TiogaNode.Ref ← targetSel.start.pos.node, TiogaNodeOps.StepForwardNode[node]
DO
TextEdit.ChangeFormat[node, srcFormat, TiogaInput.currentEvent, destRoot];
IF node = targetSel.end.pos.node THEN EXIT;
ENDLOOP;
FOR node: TiogaNode.Ref ← srcSel.start.pos.node, TiogaNodeOps.StepForwardNode[node]
DO
TextEdit.ChangeFormat[node, targetFormat, TiogaInput.currentEvent, sourceRoot];
IF node = srcSel.end.pos.node THEN EXIT;
ENDLOOP;
MakeSelection[IF target=primary THEN targetSel ELSE srcSel, primary] };
CallWithBothLocked[DoTransFormat, targetSel, srcSel, write] };
CopyFormat:
PUBLIC
PROCEDURE [target: SelectionId ← primary] = {
targetSel: Selection ← IF target=primary THEN pSel ELSE sSel;
srcSel: Selection ← IF target=primary THEN sSel ELSE pSel;
DoCopyFormat:
PROC [
sourceRoot, destRoot: TiogaNode.RefBranchNode, tSel, srcSel, targetSel: Selection] = {
srcNode: TiogaNode.Ref ←
IF srcSel.insertion=before THEN srcSel.start.pos.node ELSE srcSel.end.pos.node;
format: TiogaNode.Name ← srcNode.format;
TiogaSelection.Copy[source: srcSel, dest: oldSel]; -- save for Repeat's
FOR node: TiogaNode.Ref ← targetSel.start.pos.node, TiogaNodeOps.StepForwardNode[node]
DO
TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, destRoot];
IF node = targetSel.end.pos.node THEN EXIT;
ENDLOOP;
MakeSelection[IF target=primary THEN targetSel ELSE srcSel, primary] };
CallWithBothLocked[DoCopyFormat, targetSel, srcSel, read] };
SetFormatName:
PUBLIC
PROC [name: Rope.
ROPE, node: TiogaNode.Ref ←
NIL] = {
root: TiogaNode.RefBranchNode;
lockSel: BOOL = (node=NIL);
format: TiogaNode.Name ←
IF name=
NIL
THEN TiogaNode.nullName
ELSE NameFromRope[ForceLower[name]];
IF lockSel
THEN {
LockSel[primary, "SetFormatName"];
IF ~CheckReadonly[pSel]
OR (root ← SelectionRoot[pSel])=
NIL
THEN {
UnlockSel[primary]; RETURN };
node ← InsertionPoint[].node }
ELSE root ← TiogaNodeOps.Root[node];
{ ENABLE UNWIND => IF lockSel THEN UnlockSel[primary];
[] ← TiogaLocks.Lock[root, "SetFormatName"];
TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, root];
TiogaLocks.Unlock[root];
IF lockSel THEN UnlockSel[primary] }};
SetSelFormatName:
PROC [name: Rope.
ROPE, sel: Selection] = {
DoSetSelFormatName:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
format: TiogaNode.Name ←
IF name=
NIL
THEN TiogaNode.nullName
ELSE NameFromRope[ForceLower[name]];
FOR node: TiogaNode.Ref ← tSel.start.pos.node, TiogaNodeOps.StepForwardNode[node]
DO
TextEdit.ChangeFormat[node, format, TiogaInput.currentEvent, root];
IF node = tSel.end.pos.node THEN EXIT;
ENDLOOP };
CallWithLocks[DoSetSelFormatName] };
SetCommentProp:
PUBLIC
PROC [flag:
BOOLEAN] = {
DoSetCommentProp:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
FOR node: TiogaNode.Ref ← tSel.start.pos.node, TiogaNodeOps.StepForwardNode[node]
DO
n: TiogaNode.RefTextNode ← TiogaNodeOps.NarrowToTextNode[node];
IF n #
NIL
THEN
TextEdit.PutProp[n, "Comment",
IF flag THEN NodeProps.true ELSE NodeProps.false,
TiogaInput.currentEvent];
IF node = tSel.end.pos.node THEN EXIT;
ENDLOOP };
CallWithLocks[DoSetCommentProp] };
abbrevFailedProc: PROC RETURNS [BOOL] ← NIL;
RegisterAbbrevFailedProc:
PUBLIC
PROC [proc:
PROC
RETURNS [
BOOL]] = {
abbrevFailedProc ← proc };
ExpandAbbreviation:
PUBLIC
PROC = {
DoExpand:
PROC [root: TiogaNode.RefBranchNode, tSel: Selection] = {
pos: TiogaNode.Location;
node: TiogaNode.RefTextNode;
offset: TiogaNode.Offset;
done, keyDeterminesDict: BOOLEAN ← FALSE;
clearedMessageWindow: BOOLEAN ← FALSE;
keyStart, keyLen, resultLen: TiogaNode.Offset;
rdr: RopeReader.Ref;
commands: LIST OF REF ANY;
styleName: NameSymbolTable.Name;
Try:
PROC [name: NameSymbolTable.Name]
RETURNS [stop:
BOOLEAN] = {
dict: Rope.ROPE = NameSymbolTable.RopeFromName[name];
[done,keyDeterminesDict,keyStart,keyLen,resultLen,commands] ←
AbbrevExpand.Expand[node,offset,dict,TiogaInput.currentEvent];
IF ~done AND ~keyDeterminesDict THEN NodeStyleExtra.ForEachAttachedStyle[name,Try];
RETURN [done] };
CaretAfterSelection;
pos ← InsertionPoint[];
node ← TiogaNodeOps.NarrowToTextNode[pos.node];
offset ← pos.where;
styleName ← NodeStyle.StyleNameForNode[node];
Deselect[];
IF ~Try[styleName]
THEN {
OPEN MessageWindow;
MakeSelection[tSel, primary];
IF abbrevFailedProc # NIL AND abbrevFailedProc[] THEN RETURN;
Append[Rope.Substr[TextEdit.GetRope[node], keyStart, keyLen], ~clearedMessageWindow];
Append["? Unknown abbreviation."];
RETURN };
tSel.end.pos.node ← tSel.start.pos.node ← node;
tSel.start.pos.where ← keyStart;
tSel.pendingDelete ← FALSE;
IF resultLen = 0
THEN {
-- make a caret
tSel.end.pos.where ← keyStart;
tSel.insertion ← before;
tSel.granularity ← point }
ELSE {
tSel.end.pos.where ← keyStart+resultLen-1;
tSel.insertion ← after;
tSel.granularity ← char };
MakeSelection[tSel, primary];
rdr ← RopeReader.GetRopeReader[];
RopeReader.SetPosition[rdr, TextEdit.GetRope[node], keyStart];
FOR i:
INT
IN [0..resultLen)
DO
-- check for placeholder
IF RopeReader.Get[rdr] = 1C
THEN {
-- found one
MakePointSelection[tSel,[node,keyStart+i]];
FindPlaceholders[TRUE];
EXIT };
ENDLOOP;
RopeReader.FreeRopeReader[rdr];
IF commands # NIL THEN TiogaInput.Interpret[pSel.viewer, commands] };
CallWithLocks[DoExpand] };
LoadAbbreviations:
PUBLIC
PROC [dictName: Rope.
ROPE] = {
count: LONG INTEGER ← 0;
fileName: Rope.ROPE;
IF Rope.Size[dictName]=0 THEN RETURN;
fileName ← Rope.Concat[dictName,".Abbreviations"];
count ← AbbrevExpand.Load[fileName,
dictName ! CIFS.Error => {CONTINUE}];
IF count = 0
THEN {
-- something went wrong
OPEN MessageWindow;
Append["The file named <", TRUE];
Append[fileName];
Append["> was not found or was not an abbreviation dictionary"] }};
END.