TiogaAccessViewersImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Doug Wyatt, December 18, 1991 0:24 am PST
Provides a TiogaAccess interface to text viewers and the current selection.
DIRECTORY
EditSpan USING [CannotDoEdit, Transpose],
EditSpanSupport USING [CopySpan],
MessageWindow USING [Append, Blink],
NodeProps,
TextEdit,
TextNode,
TEditDocument USING [Selection, TEditDocumentData],
TEditInput USING [currentEvent],
TEditInputOps USING [CallWithLocks, Delete],
TEditSelection USING [GetSelectionGrain, MakeSelection],
Tioga,
TiogaAccess USING [Reader, Writer, FinishWrite, FromNode],
TiogaAccessViewers USING [],
ViewerClasses USING [Viewer],
ViewerOps USING [PaintViewer];
TiogaAccessViewersImpl: CEDAR PROGRAM
IMPORTS EditSpan, EditSpanSupport, MessageWindow, TEditInput, TEditInputOps, TEditSelection, TiogaAccess, ViewerOps, NodeProps, TextEdit, TextNode
EXPORTS TiogaAccessViewers
~ BEGIN
Node: TYPE ~ Tioga.Node;
Span: TYPE ~ Tioga.Span;
NodeItself: INT ~ Tioga.NodeItself;
Viewer: TYPE ~ ViewerClasses.Viewer;
Selection: TYPE ~ TEditDocument.Selection;
Reader: TYPE ~ TiogaAccess.Reader;
Writer: TYPE ~ TiogaAccess.Writer;
SelectionSpan: PROC [sel: Selection] RETURNS [span: Span] ~ {
start: Tioga.Location ~ sel.start.pos;
end: Tioga.Location ~ sel.end.pos;
IF TEditSelection.GetSelectionGrain[sel]<node THEN RETURN[[start, end]]
ELSE RETURN[TextNode.MakeNodeSpan[start.node, end.node]];
};
TakeNodeSubstr: PROC [t: Node, start: INT, length: INT] ~ {
root: Node ~ TextNode.Root[t];
[] ¬ TextEdit.ReplaceText[destRoot: root, sourceRoot: root,
dest: t, source: t, sourceStart: start, sourceLen: length];
};
CopyNodeProps: PROC [root, newRoot: Node] ~ {
CopyPropAction: NodeProps.MapPropsAction = {
[name: ATOM, value: REF] RETURNS [quit: BOOL ¬ FALSE];
NodeProps.PutProp[newRoot, name, NodeProps.CopyInfo[name, value]];
RETURN[FALSE];
};
[] ¬ NodeProps.MapProps[n: root, action: CopyPropAction];
};
CopySelection: PUBLIC PROC RETURNS [textNode: Node ¬ NIL, offset: INT ¬ 0] ~ {
LockedCopySelection: PROC [root: Node, tSel: Selection] ~ {
style ¬ Atom.GetPName[NodeStyleOps.StyleNameForNode[root]];
IF tSel.granularity # point THEN {
span: Span ~ SelectionSpan[tSel];
copy: Span ¬ EditSpanSupport.CopySpan[span];
offset ¬ TextNode.LocOffset[loc1: TextNode.MakeNodeLoc[root], loc2: span.start, skipCommentNodes: TRUE];
IF copy.end.where # NodeItself AND copy.end.node # NIL THEN {
TakeNodeSubstr[copy.end.node, 0, copy.end.where+1];
};
IF copy.start.where > 0 THEN {
TakeNodeSubstr[copy.start.node, copy.start.where, INT.LAST];
copy.start.where ¬ 0;
};
textNode ¬ copy.start.node;
CopyNodeProps[root: root, newRoot: TextNode.Root[textNode]];
};
};
TEditInputOps.CallWithLocks[LockedCopySelection, read];
};
FromSelection: PUBLIC PROC RETURNS [Reader] ~ {
textNode: Node ¬ NIL;
myOffset: INT ¬ 0;
[textNode, myOffset] ¬ CopySelection[];
RETURN [TiogaAccess.FromNode[textNode, myOffset]]
};
CopyDoc: PUBLIC PROC [root: Node] RETURNS [copy: Node ¬ NIL] ~ {
r: Node ¬ TextNode.Root[
EditSpanSupport.CopySpan[ -- adds an extra r node
TextNode.MakeNodeSpan[root, TextNode.LastWithin[root]]
]
.start.node
];
copy ¬ TextNode.FirstChild[r]; -- get rid of the extra r node
copy.parent ¬ copy.next ¬ NIL; -- no parent or siblings
r.child ¬ NIL; r ¬ NIL;-- don't want r any more
};
FromViewer: PUBLIC PROC [viewer: ViewerClasses.Viewer] RETURNS [Reader] ~ {
textNode: Node ¬ NIL;
WITH viewer.data SELECT FROM
tdd: TEditDocument.TEditDocumentData => textNode ¬ CopyDoc[tdd.text];
ENDCASE => NULL;
RETURN [TiogaAccess.FromNode[textNode]]
};
SetSelectionFromSpan: PROC [tSel: Selection, span: TextNode.Span] ~ {
IF span.start.node = span.end.node THEN {
IF (span.start.where = NodeItself) # (span.end.where = NodeItself) THEN ERROR; -- someone made a bogus span.
IF span.start.where = NodeItself THEN {
span is exactly one node.
span.start.where ¬ 0;
span.end.where ¬ MAX[TextEdit.Size[span.end.node]-1, 0];
tSel.granularity ¬ node;
}
ELSE {
part of a node
tSel.granularity ¬ MIN[tSel.granularity, word];
IF span.start.where <= span.end.where THEN {
tSel.granularity ¬ MAX[tSel.granularity, char];
}
ELSE {
last before first means a point selection
tSel.granularity ¬ point;
span.end.where ¬ span.start.where;
};
};
}
ELSE {
crosses multiple nodes
IF span.start.where = NodeItself AND span.end.where = NodeItself THEN {
includes all entire nodes.
tSel.granularity ¬ MAX[tSel.granularity, node];
}
ELSE {
includes partial nodes.
tSel.granularity ¬ char;
};
IF span.start.where=NodeItself THEN span.start.where ¬ 0;
IF span.end.where=NodeItself THEN span.end.where ¬ MAX[TextEdit.Size[span.end.node]-1, 0];
};
Now span has been sanitized of NodeItself flag, with the information (mostly) relayed to tSel.granularity. All that's left is to plug in the locations.
tSel.start.pos ¬ span.start;
tSel.end.pos ¬ span.end;
};
WriteSelection: PUBLIC PROC [writer: Writer] ~ {
action: PROC [root, first, last: Node] ~ {
IF root = NIL THEN TEditInputOps.Delete[]
ELSE {
success: BOOL ¬ FALSE;
lastSize: INT ¬ TextEdit.Size[last];
startOffset: INT ¬ IF lastSize=0 AND first=last THEN NodeItself ELSE 0;
endOffset: INT ¬ IF lastSize=0 THEN NodeItself ELSE lastSize-1;
alpha: Span ¬ [start: [node: first, where: startOffset], end: [node: last, where: endOffset]];
DoTranspose: PROC [root: Node, tSel: Selection] ~ {
beta: Span ¬ SelectionSpan[tSel];
documentRoot: Node ¬ TextNode.Root[beta.start.node];
IF tSel.granularity = node OR tSel.granularity = branch THEN {
alpha.start.where ¬ alpha.end.where ¬ NodeItself;
};
success ¬ TRUE;
[alpha, beta] ¬ EditSpan.Transpose[alphaRoot: root, betaRoot: documentRoot, alpha: alpha, beta: beta, event: TEditInput.currentEvent ! EditSpan.CannotDoEdit => {success ¬ FALSE; CONTINUE}];
IF success THEN {
tSel.pendingDelete ¬ FALSE;
SetSelectionFromSpan[tSel, alpha];
TEditSelection.MakeSelection[new: tSel, selection: primary];
};
};
TEditInputOps.CallWithLocks[DoTranspose, write];
IF NOT success THEN {
MessageWindow.Append["Can't do it.", TRUE];
MessageWindow.Blink[];
};
};
};
TiogaAccess.FinishWrite[writer, action];
};
WriteViewer: PUBLIC PROC [writer: Writer, viewer: ViewerClasses.Viewer] ~ {
action: PROC [root, first, last: Node] ~ {
IF viewer # NIL AND viewer.data # NIL AND viewer.class.set # NIL THEN {
viewer.class.set[viewer, root, FALSE, $TiogaDocument];
ViewerOps.PaintViewer[viewer, all];
};
};
TiogaAccess.FinishWrite[writer, action];
};
END.