DIRECTORY Carets USING [StartCaret, StopCaret], Graphics USING [black, Context, DrawBox, SetColor, SetPaintMode, SetStipple], EditSpan USING [CompareNodeOrder, NodeOrder], InputFocus USING [Focus, GetInputFocus, SetInputFocus], Process USING [Detach], TextEdit USING [FetchChar, Offset, Size], TextLooks USING [Looks, noLooks], TextNode USING [FirstChild, ForwardClipped, LastWithin, Level, Location, NarrowToTextNode, Offset, Parent, Ref, RefTextNode, Root, Span, StepBackward, StepForward], TEditDocument USING [BeforeAfter, LineTable, maxClip, PunctuationPosition, SelectionGrain, SelectionId, SelectionPoint, Selection, TEditDocumentData], TEditSelection USING [Alloc, Copy, Create, Free, CharPositionInCachedLine, IsDown, ForceDown, LockBothSelections, LockSel, fSel, nilSel, pSel, sSel, UnlockBothSelections, UnlockSel], TEditTouchup USING [LockAfterRefresh, UnlockAfterRefresh], ViewerOps USING [AddProp, FetchProp, PaintViewer], ViewerClasses USING [ModifyProc, Viewer]; TEditSelectionImpl: CEDAR PROGRAM IMPORTS Carets, EditSpan, Graphics, InputFocus, Process, TextEdit, TextNode, TEditSelection, TEditTouchup, ViewerOps EXPORTS TEditSelection = BEGIN OPEN TEditSelection ; MakePointSelection: PUBLIC PROC [selection: TEditDocument.Selection, pos: TextNode.Location] = BEGIN tSel: TEditDocument.Selection _ Alloc[]; Copy[source: selection, dest: tSel]; tSel.start.pos _ tSel.end.pos _ pos; tSel.granularity _ point; tSel.pendingDelete _ FALSE; tSel.insertion _ before; MakeSelection[selection: primary, new: tSel]; Free[tSel]; END; ChangeSelections: PROC [proc: PROC [tSel: TEditDocument.Selection], sel: TEditDocument.Selection] = { tSel: TEditDocument.Selection _ Alloc[]; LockBothSelections["ChangeBothSelections"]; { ENABLE UNWIND => UnlockBothSelections[]; Copy[source: sel, dest: tSel]; proc[tSel] }; UnlockBothSelections[]; Free[tSel] }; PushOrExchangeSelections: PUBLIC PROC = { DoPush: PROC [tSel: TEditDocument.Selection] = { MakeSelection[IF sSel.viewer=NIL THEN NIL ELSE sSel, primary]; MakeSelection[IF tSel.viewer=NIL THEN NIL ELSE tSel, secondary] }; ChangeSelections[DoPush, pSel] }; MakePrimary: PUBLIC PROC = { -- make secondary selection be the primary DoMakePrimary: PROC [tSel: TEditDocument.Selection] = { Deselect[secondary]; MakeSelection[tSel, primary] }; ChangeSelections[DoMakePrimary, sSel] }; MakeSecondary: PUBLIC PROC = { -- make secondary selection be the primary DoMakeSecondary: PROC [tSel: TEditDocument.Selection] = { Deselect[primary]; MakeSelection[tSel, secondary] }; ChangeSelections[DoMakeSecondary, pSel] }; CancelPrimary: PUBLIC PROC = { MakeSelection[NIL, primary] }; CancelSecondary: PUBLIC PROC = { MakeSelection[NIL, secondary] }; CancelFeedback: PUBLIC PROC = { MakeSelection[NIL, feedback] }; FakeSecondary: PUBLIC PROC [sel: TEditDocument.Selection] = { LockSel[secondary, "FakeSecondary"]; { ENABLE UNWIND => UnlockSel[secondary]; IF sSel.viewer # NIL THEN Deselect[secondary]; Copy[source: sel, dest: sSel] }; UnlockSel[secondary] }; Deselect: PUBLIC PROC [selection: TEditDocument.SelectionId _ primary] = { LockSel[selection, "Deselect"]; { ENABLE UNWIND => UnlockSel[selection]; sel: TEditDocument.Selection = SELECT selection FROM primary => pSel, secondary => sSel, feedback => fSel, ENDCASE => ERROR; viewer: ViewerClasses.Viewer = sel.viewer; op: ATOM = SELECT selection FROM primary => $TakeDownPSel, secondary => $TakeDownSSel, feedback => $TakeDownFSel, ENDCASE => ERROR; down: BOOL = IsDown[selection]; Copy[source: nilSel, dest: sel]; IF viewer#NIL AND ~down THEN { -- take the selection down from the screen ViewerOps.PaintViewer[viewer, client, FALSE, op]; IF ~IsDown[selection] THEN ForceDown[selection]; }}; UnlockSel[selection] }; MakeSelection: PUBLIC PROC [new: TEditDocument.Selection _ NIL, selection: TEditDocument.SelectionId _ primary, startValid, endValid: BOOLEAN _ FALSE, forkPaint: BOOL _ TRUE] = { sel: TEditDocument.Selection; op: ATOM; LockSel[selection, "MakeSelection"]; { ENABLE UNWIND => UnlockSel[selection]; SELECT selection FROM primary => BEGIN if: ViewerClasses.Viewer = InputFocus.GetInputFocus[].owner; sel _ pSel; op _ $ShowPSel; IF new=NIL THEN {IF if#NIL THEN InputFocus.SetInputFocus[NIL]} ELSE IF if#new.viewer THEN InputFocus.SetInputFocus[new.viewer]; END; feedback => { sel _ fSel; op _ $ShowFSel }; secondary => { sel _ sSel; op _ $ShowSSel }; ENDCASE => ERROR; IF new=NIL OR new.viewer # sel.viewer THEN Deselect[selection]; IF new#NIL THEN { IF selection#feedback AND fSel.viewer=new.viewer THEN Deselect[feedback]; Copy[source: new, dest: sel]; sel.start.metricsValid _ startValid; sel.end.metricsValid _ endValid; IF sel.granularity=point THEN sel.pendingDelete _ FALSE; IF forkPaint THEN { showSel: REF ShowSelRec = SELECT selection FROM primary => showPSel, secondary => showSSel, ENDCASE => showFSel; IF showSel.process = NIL THEN TRUSTED {Process.Detach[showSel.process _ FORK ShowSel[showSel, op ! ABORTED => CONTINUE]]} } ELSE ViewerOps.PaintViewer[sel.viewer, client, FALSE, op] }}; UnlockSel[selection] }; ShowSelRec: TYPE = RECORD [ process: PROCESS, selection: TEditDocument.SelectionId ]; showPSel: REF ShowSelRec _ NEW[ShowSelRec _ [NIL, primary]]; showSSel: REF ShowSelRec _ NEW[ShowSelRec _ [NIL, secondary]]; showFSel: REF ShowSelRec _ NEW[ShowSelRec _ [NIL, feedback]]; ShowSel: PROC [my: REF ShowSelRec, op: ATOM] = { selection: TEditDocument.SelectionId _ my.selection; sel: TEditDocument.Selection _ SELECT selection FROM primary => pSel, secondary => sSel, feedback => fSel, ENDCASE => ERROR; LockSel[selection, "ShowSel"]; { ENABLE UNWIND => UnlockSel[selection]; viewer: ViewerClasses.Viewer _ sel.viewer; IF viewer#NIL THEN { tdd: TEditDocument.TEditDocumentData _ NARROW[viewer.data]; IF tdd # NIL AND TEditTouchup.LockAfterRefresh[tdd, "ShowSel"] THEN { ViewerOps.PaintViewer[viewer, client, FALSE, op]; TEditTouchup.UnlockAfterRefresh[tdd] }}; my.process _ NIL }; UnlockSel[selection] }; lightGrey: CARDINAL _ 0208H; darkGrey: CARDINAL _ 0A5A5H; veryDarkGrey: CARDINAL _ 0EBEBH; SelColor: TYPE = {black, lightGrey, darkGrey, veryDarkGrey} _ black; SelBound: TYPE = {solid, line} _ solid; feedbackLineWidth: CARDINAL _ 4; feedbackLineRaise: INTEGER _ 1; MarkSelection: PUBLIC PROC [dc: Graphics.Context, viewer: ViewerClasses.Viewer, selection: TEditDocument.Selection, id: TEditDocument.SelectionId] = { WITH viewer.data SELECT FROM tdd: TEditDocument.TEditDocumentData => { OPEN selection; lines: TEditDocument.LineTable = tdd.lineTable; vHeight: INTEGER = viewer.ch; selBound: SelBound = IF selection.pendingDelete AND id#feedback THEN solid ELSE line; selColor: SelColor = IF id=primary THEN black ELSE IF id=feedback THEN veryDarkGrey ELSE IF selection.pendingDelete THEN lightGrey ELSE darkGrey; EffectSelect: PROC [x, y, w, h: INTEGER] = BEGIN lineHeight: CARDINAL _ 2; bottom: INTEGER _ vHeight-y-h; IF id=feedback THEN { lineHeight _ feedbackLineWidth; bottom _ bottom-feedbackLineRaise }; SELECT selColor FROM black => Graphics.SetColor[dc, Graphics.black]; darkGrey => Graphics.SetStipple[dc, darkGrey]; lightGrey => Graphics.SetStipple[dc, lightGrey]; veryDarkGrey=> Graphics.SetStipple[dc, veryDarkGrey]; ENDCASE => ERROR; SELECT selBound FROM solid => Graphics.DrawBox[dc, [x, bottom, x+w, vHeight-y]]; line => Graphics.DrawBox[dc, [x, bottom, x+w, bottom+lineHeight]]; ENDCASE => ERROR; END; IF end.line<0 OR start.line=LAST[INTEGER] OR (start.line=end.line AND end.clipped) THEN RETURN; -- not visible [] _ Graphics.SetPaintMode[dc, invert]; IF start.line = end.line OR (start.line < 0 AND end.line = 0) THEN { -- one liner x, y: INTEGER; IF start.line < 0 OR start.clipped THEN { -- select from beginning of line line: INTEGER _ MAX[0,start.line]; x _ lines[line].xOffset; y _ lines[line].yOffset-lines[line].ascent } ELSE { x _ start.x; y _ start.y }; IF end.clipped THEN ERROR; -- previous tests imply ~end.clipped EffectSelect[x, y, end.x-x+end.w, end.h] } ELSE IF start.line=lines.lastLine AND end.line>lines.lastLine THEN -- one liner EffectSelect[start.x, start.y, lines[start.line].width + lines[start.line].xOffset - start.x, start.h] ELSE BEGIN sl: INTEGER = NormalizeLineIndex[lines, start.line]; el: INTEGER = NormalizeLineIndex[lines, end.line]; EffectSelAll: PROC [n: INTEGER] = { EffectSelect[lines[n].xOffset, lines[n].yOffset-lines[n].ascent, lines[n].width, lines[n].ascent+lines[n].descent] }; IF sl=start.line AND ~start.clipped THEN -- select end portion of sl EffectSelect[start.x, start.y, (lines[sl].width + lines[sl].xOffset - start.x), start.h] ELSE EffectSelAll[sl];-- select all of sl FOR n: INTEGER IN (sl..el) DO -- select all of the intermediate lines EffectSelAll[n]; ENDLOOP; IF end.clipped THEN NULL -- end.line is not actually part of the selection ELSE IF el=end.line THEN -- end.line is on the screen, so select initial part of el EffectSelect[lines[el].xOffset, end.y, end.x - lines[el].xOffset + end.w, end.h] ELSE EffectSelAll[el];-- end.line is off screen, so select all of el END; [] _ Graphics.SetPaintMode[dc, opaque]; }; ENDCASE => NULL; }; NormalizeLineIndex: PROC [lines: TEditDocument.LineTable, line: INTEGER] RETURNS [INTEGER] = { RETURN [MAX[0,MIN[lines.lastLine,line]]] }; ExtendSelection: PUBLIC PROC [dc: Graphics.Context, viewer: ViewerClasses.Viewer, old, new: TEditDocument.Selection, id: TEditDocument.SelectionId, updateEnd: BOOLEAN] = BEGIN TooHard: PROC = BEGIN MarkSelection[dc, viewer, old, id]; -- take it down FixupSelection[new, viewer]; -- get position info about the new selection MarkSelection[dc, viewer, new, id]; -- put it up Copy[source: new, dest: old]; END; IF updateEnd THEN BEGIN -- update right end BumpLoc: PROC [loc: TextNode.Location] RETURNS [TextNode.Location] = { n: TextNode.RefTextNode = TextNode.NarrowToTextNode[loc.node]; where: TextNode.Offset _ loc.where+1; IF where >= TextEdit.Size[n] THEN RETURN [[TextNode.StepForward[n],0]]; RETURN [[n,where]]; }; tooHard: BOOLEAN = old.end.line NOT IN [0..LAST[INTEGER]); sameNode: BOOLEAN = (new.end.pos.node = old.end.pos.node); IF tooHard THEN {TooHard; RETURN}; IF new.end.pos=old.end.pos THEN NULL ELSE IF (sameNode AND new.end.pos.where>old.end.pos.where) OR (~sameNode AND EditSpan.CompareNodeOrder[new.end.pos.node, old.end.pos.node]=after) THEN BEGIN -- new end after old end new.start _ old.end; new.start.pos _ BumpLoc[new.start.pos]; IF sameNode AND new.start.pos.node # new.end.pos.node THEN new.start.pos _ new.end.pos; FixupSelection[new, viewer]; MarkSelection[dc, viewer, new, id]; old.end _ new.end; END ELSE BEGIN -- new end before old end save: TextNode.Location = new.end.pos; new.start _ new.end; new.start.pos _ BumpLoc[save]; IF sameNode AND new.start.pos.node # new.end.pos.node THEN new.start.pos _ old.end.pos; new.end _ old.end; FixupSelection[new, viewer, TRUE, FALSE]; -- fix start MarkSelection[dc, viewer, new, id]; old.end _ new.start; old.end.pos _ save; FixupSelection[old, viewer, FALSE, TRUE]; END; END ELSE BEGIN -- update start DecLoc: PROC [loc: TextNode.Location] RETURNS [TextNode.Location] = { n: TextNode.RefTextNode; IF loc.where > 0 THEN RETURN [[loc.node, loc.where-1]]; n _ TextNode.NarrowToTextNode[TextNode.StepBackward[loc.node]]; RETURN [[n,MAX[TextEdit.Size[n],1]-1]] }; tooHard: BOOLEAN = old.start.line NOT IN [0..LAST[INTEGER]); sameNode: BOOLEAN = (new.start.pos.node = old.start.pos.node); IF tooHard THEN {TooHard; RETURN}; IF new.start.pos=old.start.pos THEN NULL ELSE IF (sameNode AND new.start.pos.where= next AND lines[line].end # eon THEN RETURN [TRUE]; -- it is past this line RETURN [FALSE] }; FindPos: PROC [pos: TextNode.Location] RETURNS [found: BOOLEAN, line: INTEGER] = CHECKED { found _ FALSE; FOR n: INTEGER IN [firstLine..lines.lastLine] DO IF lines[n].pos.node=pos.node THEN { IF pos.where < lines[n].pos.where THEN EXIT; -- have gone past it found _ TRUE; line _ n } ELSE IF found THEN EXIT; -- have gone past pos.node ENDLOOP}; IF tdd = NIL THEN RETURN; lines _ tdd.lineTable; sp.pos _ pos; IF (lines[0].pos.node=pos.node AND lines[0].pos.where>pos.where) THEN BEGIN sp.y _ sp.line _ -LAST[INTEGER]; -- before beginning of text RETURN; END; IF lines[lines.lastLine].pos.node=pos.node AND IsPosPastLine[pos,lines.lastLine] THEN BEGIN sp.y _ sp.line _ LAST[INTEGER]; -- after end of text RETURN; END; firstLine _ MIN[lines.lastLine,MAX[firstLine,0]]; [foundPos, sp.line] _ FindPos[pos]; sp.clipped _ FALSE; IF ~foundPos THEN SELECT EditSpan.CompareNodeOrder[pos.node, lines[0].pos.node] FROM same => ERROR; disjoint => ERROR CannotFindIt; before => { sp.line _ sp.y _ -LAST[INTEGER]; RETURN }; -- before beginning ENDCASE => -- pos.node comes after first line node IF tdd.clipLevel = TEditDocument.maxClip AND tdd.commentFilter=includeComments THEN { sp.line _ sp.y _ LAST[INTEGER]; RETURN } -- after end ELSE { -- must think about this harder SELECT EditSpan.CompareNodeOrder[pos.node, lines[lines.lastLine].pos.node] FROM same => ERROR; disjoint => ERROR CannotFindIt; -- may have been deleted or moved after => { -- it really is after the end sp.line _ sp.y _ LAST[INTEGER]; RETURN } ENDCASE => { -- it got clipped n: TextNode.Ref _ pos.node; delta: INTEGER _ TextNode.Level[n]-tdd.clipLevel; firstLine _ 0; -- need to let FindPos look at all the previous lines FOR i:INTEGER IN [0..delta) DO n _ TextNode.Parent[n]; ENDLOOP; n _ TextNode.ForwardClipped[n,tdd.clipLevel].nx; [foundPos, sp.line] _ FindPos[[n,0]]; IF ~foundPos THEN ERROR CannotFindIt; -- may have been restored by Undo sp.clipped _ TRUE; }; }; IF lineOnly OR sp.clipped THEN RETURN; -- otherwise, compute metrics sp.y _ lines[sp.line].yOffset-lines[sp.line].ascent; sp.h _ lines[sp.line].ascent+lines[sp.line].descent; [sp.x, sp.w] _ CharPositionInCachedLine[viewer, tdd, sp.line, pos]; IF sp.x = LAST[INTEGER] THEN { IF sp.line=lines.lastLine THEN sp.line _ sp.y _ LAST[INTEGER] ELSE {sp.x _ lines[sp.line].width; sp.w _ 0}; }; sp.metricsValid _ TRUE; END; FixupSelection: PUBLIC PROC [selection: TEditDocument.Selection, viewer: ViewerClasses.Viewer, start, end: BOOLEAN _ TRUE] = BEGIN IF start THEN selection.start _ ComputePosPoint[viewer, selection.start.pos]; IF end THEN BEGIN IF selection.start.pos=selection.end.pos THEN selection.end _ selection.start -- no need to re-compute ELSE IF selection.start.line=LAST[INTEGER] THEN -- scrolled off bottom {selection.end.line _ LAST[INTEGER]; selection.end.metricsValid _ TRUE} ELSE { firstLine: INTEGER = IF selection.start.line<=0 THEN 0 ELSE IF selection.start.clipped THEN selection.start.line-1 ELSE selection.start.line; selection.end _ ComputePosPoint[viewer, selection.end.pos, firstLine] }; END; END; FixupCaret: PUBLIC PROC [selection: TEditDocument.Selection] = BEGIN OPEN selection; lines: TEditDocument.LineTable = data.lineTable; node: TextNode.RefTextNode _ TextNode.NarrowToTextNode[end.pos.node]; size: TextNode.Offset _ TextEdit.Size[node]; PutCaretOnNextLine: PROC = BEGIN SELECT end.line FROM IN [0..lines.lastLine) => BEGIN nextLine: INTEGER _ end.line+1; caretX _ lines[nextLine].xOffset; caretY _ viewer.ch - lines[nextLine].yOffset - lines[nextLine].descent; END; = lines.lastLine => BEGIN caretX _ lines[end.line].xOffset; caretY _ viewer.ch - end.y - end.h - end.h; END; ENDCASE => ERROR; END; IF insertion=before THEN BEGIN IF start.clipped THEN caretY _ LAST[INTEGER] -- caret not visible ELSE BEGIN caretX _ start.x; caretY _ IF start.line NOT IN [0..lines.lastLine] THEN LAST[INTEGER] ELSE viewer.ch - start.y - start.h; END; END ELSE BEGIN IF end.clipped THEN caretY _ LAST[INTEGER] -- caret not visible ELSE IF end.pos.where IN [0..size) AND end.line IN [0..lines.lastLine] AND TextEdit.FetchChar[node,end.pos.where]=15C THEN PutCaretOnNextLine ELSE BEGIN caretX _ end.x+end.w; caretY _ IF end.line NOT IN [0..lines.lastLine] THEN LAST[INTEGER] ELSE viewer.ch - end.y - end.h; END END; END; KillSelection: PUBLIC PROCEDURE = BEGIN IF InputFocus.GetInputFocus[]#NIL THEN InputFocus.SetInputFocus[]; END; ModifyPSel: PROC [proc: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection]] = { tSel: TEditDocument.Selection; { ENABLE UNWIND => { UnlockSel[primary]; IF tSel # NIL THEN Free[tSel] }; root: TextNode.Ref; LockSel[primary, "CallWithSelLock"]; IF (root _ SelectionRoot[pSel])=NIL THEN { UnlockSel[primary]; RETURN }; tSel _ Alloc[]; TEditSelection.Copy[source: pSel, dest: tSel]; proc[root, tSel]; MakeSelection[new: tSel] }; Free[tSel]; tSel _ NIL; UnlockSel[primary] }; SelectEverything: PUBLIC PROC = { -- expand to include everything DoSelEverything: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { root _ TextNode.Root[tSel.start.pos.node]; tSel.start.pos _ [TextNode.FirstChild[root], 0]; tSel.end.pos.node _ TextNode.LastWithin[root]; tSel.end.pos.where _ TextEdit.Size[TextNode.NarrowToTextNode[tSel.end.pos.node]]-1; tSel.granularity _ branch }; ModifyPSel[DoSelEverything] }; PendingDeleteSelection: PUBLIC PROC = { DoPDel: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { tSel.pendingDelete _ TRUE }; ModifyPSel[DoPDel] }; NotPendingDeleteSelection: PUBLIC PROC = { DoNotPDel: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { tSel.pendingDelete _ FALSE }; ModifyPSel[DoNotPDel] }; CaretBeforeSelection: PUBLIC PROC = { DoCaretBeforeSelection: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { tSel.insertion _ before }; ModifyPSel[DoCaretBeforeSelection] }; CaretAfterSelection: PUBLIC PROC = { DoCaretAfterSelection: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { IF tSel.granularity # point THEN tSel.insertion _ after }; ModifyPSel[DoCaretAfterSelection] }; SelectionRoot: PUBLIC PROC [s: TEditDocument.Selection _ pSel] RETURNS [root: TextNode.Ref] = { tdd: TEditDocument.TEditDocumentData; IF s.viewer=NIL THEN RETURN [TextNode.Root[s.start.pos.node]]; tdd _ NARROW[s.viewer.data]; IF tdd = NIL THEN RETURN [NIL]; RETURN [tdd.text] }; InputModify: PUBLIC ViewerClasses.ModifyProc = BEGIN tdd: TEditDocument.TEditDocumentData = NARROW[self.data]; IF tdd = NIL THEN RETURN; SELECT change FROM set, pop => Carets.StartCaret[self, pSel.caretX, pSel.caretY, primary]; kill => BEGIN prop: TEditDocument.Selection _ NARROW[ViewerOps.FetchProp[self, $SelectionHistory]]; Carets.StopCaret[primary]; IF prop=NIL THEN ViewerOps.AddProp[self, $SelectionHistory, prop _ Create[]]; LockSel[primary, "InputModify"]; { ENABLE UNWIND => UnlockSel[primary]; Copy[source: pSel, dest: prop]; Deselect[primary] }; UnlockSel[primary]; END; push => Carets.StopCaret[primary]; ENDCASE => ERROR; END; END. JTEditSelectionImpl.mesa Copyright (C) 1982, Xerox Corporation. All rights reserved. Edited by Paxton on December 28, 1982 2:23 pm Last Edited by: Maxwell, January 6, 1983 11:35 am Edited by Plass on December 26, 1984 3:38:13 pm PST - - - - - Selection Display and Control - - - - - make a point selection at pos out the the current primary selection Take down the selection without changing the input focus. If the selection was not in a visible viewer, PaintViewer didn't call our paint proc, so the state didn't change. Force change directly. Changes input focus as well as the selection. When called to make a non-feedback selection is the viewer containing the feedback selection, automatically cancel the feedback selection. when done, old is valid (it's = pSel, e.g.) and new^ = old^ This weird case can happen if old ended with final CR of node and new is in the null line displayed after the CR. old ended in null line after final CR, new ends with the final CR this must work correctly even if the node was filtered out for some reason if pos was filtered, return line where it would have been and set clipped=TRUE nothing special going on, so would have found it if not after end past this line recompute the xywh fields in the selection fixes selection screen info assuming start.pos and end.pos are correct recompute the xy fields in the caret ELSE IF start.line=lines.lastLine AND granularity=point AND start.pos.where=size AND size>0 AND TextEdit.FetchChar[node, size-1]=15C THEN PutCaretOnNextLine selection actually get taken down in our InputModify Proc ---- Misc functions ------ ÊA˜Jšœ™J™Jš œœ œœœœ˜B—J˜!J˜—šž œœœÏc*˜Gšž œœ$˜7J˜4—J˜(J˜—šž œœœŸ*˜Išžœœ$˜9J˜4—J˜*J˜—Jšž œœœœ ˜=J˜Jšžœœœœ˜AJ˜Jšžœœœœ˜?J˜šž œœœ#˜=J˜$šœœœ˜(Jšœœœ˜.J˜ —J˜J˜—šžœœœ5˜JJšœ9™9J˜šœœœ˜(šœœ ˜4Jšœ6œœ˜G—J˜*šœœœ ˜ J˜J˜J˜Jšœœ˜—Jšœœ˜J˜ š œœœœŸ*˜IJšœ&œ˜1šœœ˜0Jšœ‰™‰—J˜——J˜J˜—šž œœ˜šœ œ1˜TJš œœœ œœ˜B—Jšœ-™-J˜Jšœœ˜ J˜$šœœœ˜(šœ ˜šœ ˜J˜Jšœœœ&˜@Jšœ˜—J˜+J˜,Jšœœ˜—Jšœœœœ˜?šœœœ˜šœœœ˜IJšœŠ™Š—J˜J˜$J˜ Jšœœœ˜8šœ œ˜šœ œœ ˜/Jšœ,œ ˜@—šœœ˜šœ"˜)Jšœœœ˜3———Jšœ+œ ˜=——J˜J˜—Jšœ œœ œ)˜UJšœ œœœ ˜Jšœ œœœ ˜=J˜šžœœœœ˜0J˜4šœœ ˜4Jšœ6œœ˜G—J˜šœœœ˜(J˜*šœœœ˜Jšœ'œ˜;šœœœ/œ˜EJšœ&œ˜1J˜(——Jšœ œ˜—J˜J˜—Jšœ œ ˜Jšœ œ ˜Jšœœ ˜ Jšœ œ6˜DJšœ œ˜'Jšœœ˜ Jšœœ˜J˜šž œœœ5˜OJ˜Fšœ œ˜˜)Jšœ ˜J˜/Jšœ œ ˜Jš œœœ œœ˜Uš œœ œœœ œ ˜SJšœœœ œ ˜=—šž œœœ˜*Jšœ˜Jšœ œ˜Jšœœ˜Jšœ œG˜Zšœ ˜J˜1J˜/J˜1J˜5Jšœœ˜—šœ ˜J˜J˜%Jšœœœ˜GJšœ ˜J˜—Jš œ œœœœœ˜:Jšœ œ)˜:Jšœ œ œ˜"Jšœœ˜$šœœ œ&˜=šœ ˜JšœE˜I—JšœŸ˜J˜J˜'šœ œ'˜:J˜Jšœq™q—J˜J˜#J˜Jš˜—šœœŸ˜$J˜&J˜J˜šœ œ'œ˜WJšœA™A—J˜JšœœœŸ ˜6J˜#J˜J˜Jšœœœ˜)Jšœ˜—Jš˜—šœœŸ˜šžœœœ˜EJ˜Jšœœœ˜7J˜?Jšœœ˜)—Jš œ œœœœœ˜Jšœ œ œ˜"Jšœœ˜(šœœ œ*˜Ašœ ˜JšœJ˜N—JšœŸ#˜)J˜$J˜J˜#J˜Jš˜—šœœŸ"˜-J˜(J˜J˜Jšœœœ˜)J˜#J˜Jšœœœ˜)Jšœ˜—Jšœ˜—J˜Jšœ˜J˜—Jšœœœœ˜"J˜šžœœœ4˜QJšœœœ˜HJ˜:Jšœœ+˜FJšœœœœœœœŸ˜Kšœ˜šœ œœ œ˜,Jšœœ œ˜(—J˜A—Jšœ˜J˜—šžœœœ˜JšœAœ˜MJšœœ œ˜1JšœKœ˜QJšœ˜Jšœ˜J˜—šžœœœ˜J˜5Jšœ œœœ˜2Jšœ&œ˜:J˜JšœJ™JJšœN™NJ˜Jšœ œœ˜Jšœ'œ˜;J˜J˜š ž œœ œœœœ˜YJ˜J˜0Jš œœœœœŸ˜ZJšœœ˜J˜—šžœœ˜&Jšœ œœœ˜3Jšœœ˜šœœœ˜0šœœ˜$Jšœ œœŸ˜AJšœœ ˜—Jš œœœœŸ˜3—Jšœ˜ J˜—Jšœœœœ˜J˜J˜ J˜šœ˜"Jšœœ˜(JšœœœŸ˜Jšœœ˜Jš œœœœœ˜Jšœ˜J˜—šž œœ˜4Jšœ'œ ˜9Jšœœœœ˜Jšœ˜J˜Gšœ˜ ˜Jšœ/˜5—J˜Jšœœœ=˜MJ˜ šœœœ˜&J˜4—J˜Jšœ˜—J˜"Jšœœ˜Jšœ˜J˜—Jšœ˜J˜J˜—…—Pl›