class: EditTextView
authorClaus Gittinger <cg@exept.de>
Mon, 16 Sep 2013 10:52:24 +0200
changeset 4771 109861cbb78c
parent 4770 ac8f889cf805
child 4772 f1fb7b8ec64f
class: EditTextView added: #basicListAt:put: #basicListRemoveFromIndex:toIndex: removed: #basicWithoutRedrawInsertLine:before: changed:15 methods guide all basic line editing functions through 2 basic line modifying methods, which can be redefined in special subclasses (which use virtual arrays, for example).
EditTextView.st
--- a/EditTextView.st	Mon Sep 16 10:51:05 2013 +0200
+++ b/EditTextView.st	Mon Sep 16 10:52:24 2013 +0200
@@ -2760,7 +2760,7 @@
                         "/ not allow a cursor position beyond the end of line,
                         "/ so avoid that cursorLine:col: will force us to the beginning of the line
                         originalLine size < prevTab ifTrue:[
-                            list at:cursorLine put:ln
+                            self basicListAt:cursorLine put:ln
                         ]
                     ].
                     self cursorLine:cursorLine col:prevTab.
@@ -2926,7 +2926,7 @@
                     ]
                 ].
                 newLine ~~ line ifTrue:[
-                    list at:startLine put:newLine.
+                    self basicListAt:startLine put:newLine.
                 ].
                 "/ TODO: remember old maxwidth of linerange,
                 "/ only clear widthOfWidestLine, if this max
@@ -2981,15 +2981,15 @@
 
     |lastLine|
 
-    self checkModificationsAllowed ifFalse:[ ^ self].
+    self checkModificationsAllowed ifFalse:[^ false].
 
     (list isNil or:[startLine > list size]) ifTrue:[^ false].
     (endLine > list size) ifTrue:[
-	lastLine := list size
+        lastLine := list size
     ] ifFalse:[
-	lastLine := endLine
-    ].
-    list removeFromIndex:startLine toIndex:lastLine.
+        lastLine := endLine
+    ].
+    self basicListRemoveFromIndex:startLine toIndex:lastLine.
     "/ TODO: remember old maxwidth of linerange,
     "/ only clear widthOfWidestLine, if this max
     "/ length was (one of) the longest.
@@ -3094,6 +3094,82 @@
     "Modified: 6.9.1995 / 20:51:03 / claus"
 !
 
+insertLines:someText from:start to:end before:lineNr
+    "insert a bunch of lines before line lineNr.
+     The cursor position is left unchanged."
+
+    |text indent visLine w nLines "{ Class: SmallInteger }"
+     srcY "{ Class: SmallInteger }"
+     dstY "{ Class: SmallInteger }" |
+
+    autoIndent ifTrue:[
+        indent := self leftIndentForLine:lineNr.
+
+        text := someText collect:[:ln||line|
+            ln notNil ifTrue:[
+                line := ln withoutLeadingSeparators.
+                (line isEmpty or:[indent == 0]) ifFalse:[
+                    line := (String new:indent), line
+                ].
+                line
+            ] ifFalse:[
+                nil
+            ]
+        ].
+    ] ifFalse:[
+        text := someText
+    ].
+
+    visLine := self listLineToVisibleLine:lineNr.
+    (shown not or:[visLine isNil]) ifTrue:[
+        self withoutRedrawInsertLines:text
+             from:start to:end
+             before:lineNr.
+    ] ifFalse:[
+        nLines := end - start + 1.
+        ((visLine + nLines) >= nLinesShown) ifTrue:[
+            self withoutRedrawInsertLines:text
+                 from:start to:end
+                 before:lineNr.
+            self redrawFromVisibleLine:visLine to:nLinesShown
+        ] ifFalse:[
+            w := self widthForScrollBetween:(lineNr + nLines)
+                                        and:(firstLineShown + nLines + nLinesShown).
+            srcY := topMargin + ((visLine - 1) * fontHeight).
+            dstY := srcY + (nLines * fontHeight).
+
+            "/
+            "/ scroll ...
+            "/
+            "
+             stupid: must catchExpose before inserting new
+             stuff - since catchExpose may perform redraws
+            "
+            self catchExpose.
+            self withoutRedrawInsertLines:text
+                 from:start to:end
+                 before:lineNr.
+            self
+                copyFrom:self
+                x:textStartLeft y:srcY
+                toX:textStartLeft y:dstY
+                width:w
+                height:(height - dstY)
+                async:true.
+            self redrawFromVisibleLine:visLine to:(visLine + nLines - 1).
+            self waitForExpose
+        ].
+    ].
+    widthOfWidestLine notNil ifTrue:[
+        text do:[:line |
+            widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
+        ]
+    ].
+    self textChanged.
+
+    "Modified: 29.1.1997 / 13:02:39 / cg"
+!
+
 insertLines:lines withCR:withCr
     "insert a bunch of lines at cursor position.
      Cursor is moved behind insertion.
@@ -3366,25 +3442,25 @@
     lastLine := list size.
     finished := false.
     [finished] whileFalse:[
-	(lastLine <= 1) ifTrue:[
-	    finished := true
-	] ifFalse:[
-	    line := list at:lastLine.
-	    line notNil ifTrue:[
-		line isBlank ifTrue:[
-		    list at:lastLine put:nil.
-		    line := nil
-		]
-	    ].
-	    line notNil ifTrue:[
-		finished := true
-	    ] ifFalse:[
-		lastLine := lastLine - 1
-	    ]
-	]
+        (lastLine <= 1) ifTrue:[
+            finished := true
+        ] ifFalse:[
+            line := list at:lastLine.
+            line notNil ifTrue:[
+                line isBlank ifTrue:[
+                    self basicListAt:lastLine put:nil.
+                    line := nil
+                ]
+            ].
+            line notNil ifTrue:[
+                finished := true
+            ] ifFalse:[
+                lastLine := lastLine - 1
+            ]
+        ]
     ].
     (lastLine ~~ list size) ifTrue:[
-	list grow:lastLine.
+        list grow:lastLine.
 "/        self textChanged
     ]
 !
@@ -3725,7 +3801,7 @@
      becomes line lineNr; everything else is moved down; the view
      is not redrawn"
 
-    self basicWithoutRedrawInsertLine:aString before:lineNr.
+    self basicWithoutRedrawInsertLines:{ aString } from:1 to:1 before:lineNr.
     self addUndo:(DeleteRange line1:lineNr col1:1 line2:lineNr+1 col2:0 info:'insert').
 !
 
@@ -3848,7 +3924,7 @@
 
         prevWidth := self widthOfLine:lineNr.
 
-        list at:lineNr put:newLine.
+        self basicListAt:lineNr put:newLine.
 
         (prevWidth = widthOfWidestLine) ifTrue:[
             "/ remember old width of this line,
@@ -3894,7 +3970,7 @@
     "/ isnt this the same as:
     "/ self deleteLinesWithoutRedrawFrom:startLineNr to:endLineNr.
     startLineNr <= list size ifTrue:[
-        list removeFromIndex:startLineNr toIndex:(endLineNr min:list size).
+        self basicListRemoveFromIndex:startLineNr toIndex:(endLineNr min:list size).
     ].
     "/ TODO: remember old maxwidth of linerange,
     "/ only clear widthOfWidestLine, if this max
@@ -3997,7 +4073,7 @@
         drawCharacterOnly := false
     ].
 
-    list at:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
+    self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
     widthOfWidestLine notNil ifTrue:[
         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
     ].
@@ -4044,42 +4120,54 @@
     "Modified: / 09-11-2010 / 13:43:18 / cg"
 !
 
+basicListAt:lineNr put:newLine
+    "redefinable for special subclasses (with virtual list)"
+
+    list at:lineNr put:newLine.
+!
+
+basicListRemoveFromIndex:startLineNr toIndex:endLineNr
+    "redefinable for special subclasses (with virtual list)"
+
+    list removeFromIndex:startLineNr toIndex:(endLineNr min:list size).
+!
+
 basicMergeLine:lineNr removeBlanks:removeBlanks
     "merge line lineNr with line lineNr+1"
 
     |leftPart rightPart bothParts nextLineNr i|
 
     (list notNil and:[(list size) >= lineNr]) ifFalse:[
-	"/ empty list or beyond end of text
-	^ self
+        "/ empty list or beyond end of text
+        ^ self
     ].
     leftPart := self listAt:lineNr.
 
     leftPart isNil ifTrue:[
-	leftPart := ''.
-	autoIndent ifTrue:[
-	    (i := self leftIndentForLine:cursorLine) == 0 ifFalse:[
-		leftPart := String new:i
-	    ]
-	]
+        leftPart := ''.
+        autoIndent ifTrue:[
+            (i := self leftIndentForLine:cursorLine) == 0 ifFalse:[
+                leftPart := String new:i
+            ]
+        ]
     ].
     self cursorLine:lineNr col:((leftPart size) + 1).
     nextLineNr := self validateCursorLine:(lineNr + 1).
 
     nextLineNr > (list size) ifFalse:[
-	(rightPart := self listAt:nextLineNr) isNil ifTrue:[
-	    rightPart := ''
-	] ifFalse:[
-	    removeBlanks ifTrue:[
-		rightPart := rightPart withoutLeadingSeparators.
-	    ]
-	].
-
-	bothParts := leftPart , rightPart.
-	(trimBlankLines and:[bothParts isBlank]) ifTrue:[bothParts := nil].
-	list at:lineNr put:bothParts.
-	self redrawLine:lineNr.
-	self deleteLine:nextLineNr
+        (rightPart := self listAt:nextLineNr) isNil ifTrue:[
+            rightPart := ''
+        ] ifFalse:[
+            removeBlanks ifTrue:[
+                rightPart := rightPart withoutLeadingSeparators.
+            ]
+        ].
+
+        bothParts := leftPart , rightPart.
+        (trimBlankLines and:[bothParts isBlank]) ifTrue:[bothParts := nil].
+        self basicListAt:lineNr put:bothParts.
+        self redrawLine:lineNr.
+        self deleteLine:nextLineNr
     ]
 
     "Created: 9.9.1997 / 09:27:38 / cg"
@@ -4123,7 +4211,7 @@
         newLine := self withTabsExpanded:newLine.
         drawCharacterOnly := false
     ].
-    list at:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
+    self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
     widthOfWidestLine notNil ifTrue:[
         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
     ].
@@ -4181,7 +4269,7 @@
     (aString includes:(Character tab)) ifTrue:[
         newLine := self withTabsExpanded:newLine.
     ].
-    list at:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
+    self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
     widthOfWidestLine notNil ifTrue:[
         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
     ].
@@ -4230,7 +4318,7 @@
     leftRest notNil ifTrue:[
         (trimBlankLines and:[leftRest isBlank]) ifTrue:[leftRest := nil]
     ].
-    list at:lineNr put:leftRest.
+    self basicListAt:lineNr put:leftRest.
     self nonUndoableDo:[
         self withoutRedrawInsertLine:rightRest before:(lineNr + 1).
     ].
@@ -4260,50 +4348,6 @@
     "Modified: / 06-12-2010 / 13:12:55 / cg"
 !
 
-basicWithoutRedrawInsertLine:aString before:lineNr
-    "insert the argument, aString before line lineNr; the string
-     becomes line nileNr; everything else is moved down; the view
-     is not redrawn"
-
-    |line|
-
-    self checkModificationsAllowed ifFalse:[ ^ self].
-
-    line := aString.
-    line notNil ifTrue:[
-        line isString ifTrue:[
-            line isBlank ifTrue:[
-                line := nil
-            ] ifFalse:[
-                (line includes:(Character tab)) ifTrue:[
-                    line := self withTabsExpanded:line
-                ]
-            ]
-        ]
-    ].
-    list isNil ifTrue: [
-        list := StringCollection new:lineNr
-    ] ifFalse: [
-        list grow:((list size + 1) max:lineNr)
-    ].
-
-    "I have changed 'replaceFrom:to:with:startingAt:' to correctly handle
-     overlapping copy - if it didn't, we had to use:"
-"
-    index := list size.
-    [index > lineNr] whileTrue: [
-        pIndex := index - 1.
-        list at:index put:(list at:pIndex).
-        index := pIndex
-    ].
-"
-    list replaceFrom:(lineNr + 1) to:(list size) with:list startingAt:lineNr.
-    list at:lineNr put:(line isNil ifTrue:[nil] ifFalse:[line asSingleByteStringIfPossible]).
-    self contentsChanged
-
-    "Modified: / 10.6.1998 / 19:00:56 / cg"
-!
-
 basicWithoutRedrawInsertLines:lines from:start to:end before:lineNr
     "insert a bunch of lines before line lineNr; the view is not redrawn.
      Tabs are expanded here with a tab=8 setting (independent of any editor-setting,
@@ -4416,89 +4460,13 @@
         newLine := self withTabs:(ListView tab8Positions) expand:newLine
     ].
 
-    list at:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
+    self basicListAt:lineNr put:(newLine ifNil:[newLine] ifNotNil:[newLine asSingleByteStringIfPossible]).
     widthOfWidestLine notNil ifTrue:[
         widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
     ].
     self textChanged.
 
     "Modified: / 25-01-2012 / 00:37:29 / cg"
-!
-
-insertLines:someText from:start to:end before:lineNr
-    "insert a bunch of lines before line lineNr.
-     The cursor position is left unchanged."
-
-    |text indent visLine w nLines "{ Class: SmallInteger }"
-     srcY "{ Class: SmallInteger }"
-     dstY "{ Class: SmallInteger }" |
-
-    autoIndent ifTrue:[
-        indent := self leftIndentForLine:lineNr.
-
-        text := someText collect:[:ln||line|
-            ln notNil ifTrue:[
-                line := ln withoutLeadingSeparators.
-                (line isEmpty or:[indent == 0]) ifFalse:[
-                    line := (String new:indent), line
-                ].
-                line
-            ] ifFalse:[
-                nil
-            ]
-        ].
-    ] ifFalse:[
-        text := someText
-    ].
-
-    visLine := self listLineToVisibleLine:lineNr.
-    (shown not or:[visLine isNil]) ifTrue:[
-        self withoutRedrawInsertLines:text
-             from:start to:end
-             before:lineNr.
-    ] ifFalse:[
-        nLines := end - start + 1.
-        ((visLine + nLines) >= nLinesShown) ifTrue:[
-            self withoutRedrawInsertLines:text
-                 from:start to:end
-                 before:lineNr.
-            self redrawFromVisibleLine:visLine to:nLinesShown
-        ] ifFalse:[
-            w := self widthForScrollBetween:(lineNr + nLines)
-                                        and:(firstLineShown + nLines + nLinesShown).
-            srcY := topMargin + ((visLine - 1) * fontHeight).
-            dstY := srcY + (nLines * fontHeight).
-
-            "/
-            "/ scroll ...
-            "/
-            "
-             stupid: must catchExpose before inserting new
-             stuff - since catchExpose may perform redraws
-            "
-            self catchExpose.
-            self withoutRedrawInsertLines:text
-                 from:start to:end
-                 before:lineNr.
-            self
-                copyFrom:self
-                x:textStartLeft y:srcY
-                toX:textStartLeft y:dstY
-                width:w
-                height:(height - dstY)
-                async:true.
-            self redrawFromVisibleLine:visLine to:(visLine + nLines - 1).
-            self waitForExpose
-        ].
-    ].
-    widthOfWidestLine notNil ifTrue:[
-        text do:[:line |
-            widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
-        ]
-    ].
-    self textChanged.
-
-    "Modified: 29.1.1997 / 13:02:39 / cg"
 ! !
 
 !EditTextView methodsFor:'event handling'!
@@ -5287,8 +5255,19 @@
 keyPress:key x:x y:y
     "handle keyboard input"
 
-    self undoableDo:[
-        self doKeyPress:key x:x y:y
+    |wasOn|
+
+    wasOn := cursorShown.
+
+    NoModificationError handle:[:ex |
+        self flash.
+        (cursorShown not and:[wasOn]) ifTrue:[
+            self makeCursorVisibleAndShowCursor:wasOn.
+        ].
+    ] do:[
+        self undoableDo:[
+            self doKeyPress:key x:x y:y
+        ].
     ].
     self repairDamage
 
@@ -5450,7 +5429,7 @@
         line := self listAt:lineNr.
         line notNil ifTrue:[
             line isBlank ifTrue:[
-                list at:lineNr put:nil
+                self basicListAt:lineNr put:nil
             ] ifFalse:[
                 (delta > 0) ifTrue:[
                     line := spaces , line.
@@ -5520,13 +5499,6 @@
     ^ self class codeCompletionServiceClass
 !
 
-release
-    completionService notNil ifTrue:[
-        completionService release
-    ].
-    super release
-!
-
 fetchDeviceResources
     "fetch device colors, to avoid reallocation at redraw time"
 
@@ -5620,6 +5592,13 @@
             completionService := serviceClass for:self.            
         ].
     ].
+!
+
+release
+    completionService notNil ifTrue:[
+        completionService release
+    ].
+    super release
 ! !
 
 !EditTextView methodsFor:'macros'!
@@ -8336,10 +8315,10 @@
 !EditTextView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.581 2013-09-12 08:31:29 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.582 2013-09-16 08:52:24 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.581 2013-09-12 08:31:29 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libwidg/EditTextView.st,v 1.582 2013-09-16 08:52:24 cg Exp $'
 ! !