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.