ETxtView.st
changeset 118 3ee5ea99d0e2
parent 105 3d064ba4a0cc
child 121 4e63bbdb266a
equal deleted inserted replaced
117:53cbfeaa9c9a 118:3ee5ea99d0e2
    12 
    12 
    13 'From Smalltalk/X, Version:2.10.5 on 14-mar-1995 at 11:12:00 am'!
    13 'From Smalltalk/X, Version:2.10.5 on 14-mar-1995 at 11:12:00 am'!
    14 
    14 
    15 TextView subclass:#EditTextView
    15 TextView subclass:#EditTextView
    16 	 instanceVariableNames:'cursorLine cursorVisibleLine cursorCol cursorShown
    16 	 instanceVariableNames:'cursorLine cursorVisibleLine cursorCol cursorShown
    17                 prevCursorState readOnly modified fixedSize exceptionBlock
    17 		prevCursorState readOnly modified fixedSize exceptionBlock
    18                 errorMessage cursorFgColor cursorBgColor cursorType undoAction
    18 		errorMessage cursorFgColor cursorBgColor cursorType undoAction
    19                 typeOfSelection lastString lastReplacement lastAction replacing
    19 		typeOfSelection lastString lastReplacement lastAction replacing
    20                 showMatchingParenthesis hasKeyboardFocus'
    20 		showMatchingParenthesis hasKeyboardFocus'
    21 	 classVariableNames:'DefaultCursorForegroundColor DefaultCursorBackgroundColor
    21 	 classVariableNames:'DefaultCursorForegroundColor DefaultCursorBackgroundColor
    22                 DefaultCursorType'
    22 		DefaultCursorType'
    23 	 poolDictionaries:''
    23 	 poolDictionaries:''
    24 	 category:'Views-Text'
    24 	 category:'Views-Text'
    25 !
    25 !
    26 
    26 
    27 EditTextView comment:'
    27 EditTextView comment:'
    28 COPYRIGHT (c) 1989 by Claus Gittinger
    28 COPYRIGHT (c) 1989 by Claus Gittinger
    29 	    All Rights Reserved
    29 	    All Rights Reserved
    30 
    30 
    31 $Header: /cvs/stx/stx/libwidg/Attic/ETxtView.st,v 1.23 1995-03-18 05:14:09 claus Exp $
    31 $Header: /cvs/stx/stx/libwidg/Attic/ETxtView.st,v 1.24 1995-05-03 00:29:07 claus Exp $
    32 '!
    32 '!
    33 
    33 
    34 !EditTextView class methodsFor:'documentation'!
    34 !EditTextView class methodsFor:'documentation'!
    35 
    35 
    36 copyright
    36 copyright
    47 "
    47 "
    48 !
    48 !
    49 
    49 
    50 version
    50 version
    51 "
    51 "
    52 $Header: /cvs/stx/stx/libwidg/Attic/ETxtView.st,v 1.23 1995-03-18 05:14:09 claus Exp $
    52 $Header: /cvs/stx/stx/libwidg/Attic/ETxtView.st,v 1.24 1995-05-03 00:29:07 claus Exp $
    53 "
    53 "
    54 !
    54 !
    55 
    55 
    56 documentation
    56 documentation
    57 "
    57 "
   115     "insert a single character at lineNr/colNr"
   115     "insert a single character at lineNr/colNr"
   116 
   116 
   117     |line lineSize newLine drawCharacterOnly|
   117     |line lineSize newLine drawCharacterOnly|
   118 
   118 
   119     readOnly ifTrue: [
   119     readOnly ifTrue: [
   120         exceptionBlock value:errorMessage.
   120 	exceptionBlock value:errorMessage.
   121         ^ self
   121 	^ self
   122     ].
   122     ].
   123     aCharacter == (Character cr) ifTrue:[
   123     aCharacter == (Character cr) ifTrue:[
   124         self splitLine:lineNr before:colNr.
   124 	self splitLine:lineNr before:colNr.
   125         ^ self
   125 	^ self
   126     ].
   126     ].
   127     drawCharacterOnly := false.
   127     drawCharacterOnly := false.
   128     self checkForExistingLine:lineNr.
   128     self checkForExistingLine:lineNr.
   129     line := list at:lineNr.
   129     line := list at:lineNr.
   130     lineSize := line size.
   130     lineSize := line size.
   131     (aCharacter == Character space) ifTrue:[
   131     (aCharacter == Character space) ifTrue:[
   132         (colNr > lineSize)  ifTrue:[
   132 	(colNr > lineSize)  ifTrue:[
   133             ^ self
   133 	    ^ self
   134         ]
   134 	]
   135     ].
   135     ].
   136     (lineSize == 0) ifTrue: [
   136     (lineSize == 0) ifTrue: [
   137         newLine := String new:colNr.
   137 	newLine := String new:colNr.
   138         drawCharacterOnly := true
   138 	drawCharacterOnly := true
   139     ] ifFalse: [
   139     ] ifFalse: [
   140         (colNr > lineSize) ifTrue: [
   140 	(colNr > lineSize) ifTrue: [
   141             newLine := String new:colNr.
   141 	    newLine := String new:colNr.
   142             newLine replaceFrom:1 to:lineSize
   142 	    newLine replaceFrom:1 to:lineSize
   143                            with:line startingAt:1.
   143 			   with:line startingAt:1.
   144             drawCharacterOnly := true
   144 	    drawCharacterOnly := true
   145         ] ifFalse: [
   145 	] ifFalse: [
   146             newLine := String new:(lineSize + 1).
   146 	    newLine := String new:(lineSize + 1).
   147             newLine replaceFrom:1 to:(colNr - 1)
   147 	    newLine replaceFrom:1 to:(colNr - 1)
   148                            with:line startingAt:1.
   148 			   with:line startingAt:1.
   149             newLine replaceFrom:(colNr + 1) to:(lineSize + 1)
   149 	    newLine replaceFrom:(colNr + 1) to:(lineSize + 1)
   150                            with:line startingAt:colNr
   150 			   with:line startingAt:colNr
   151         ]
   151 	]
   152     ].
   152     ].
   153     newLine at:colNr put:aCharacter.
   153     newLine at:colNr put:aCharacter.
   154     aCharacter == (Character tab) ifTrue:[
   154     aCharacter == (Character tab) ifTrue:[
   155         newLine := self withTabsExpanded:newLine.
   155 	newLine := self withTabsExpanded:newLine.
   156         drawCharacterOnly := false
   156 	drawCharacterOnly := false
   157     ].
   157     ].
   158     list at:lineNr put:newLine.
   158     list at:lineNr put:newLine.
       
   159     widthOfWidestLine notNil ifTrue:[
       
   160 	widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
       
   161     ].
   159     self textChanged.
   162     self textChanged.
   160     shown ifTrue:[
   163     shown ifTrue:[
   161         drawCharacterOnly ifTrue:[
   164 	drawCharacterOnly ifTrue:[
   162             self redrawLine:lineNr col:colNr
   165 	    self redrawLine:lineNr col:colNr
   163         ] ifFalse:[
   166 	] ifFalse:[
   164             self redrawLine:lineNr from:colNr
   167 	    self redrawLine:lineNr from:colNr
   165         ]
   168 	]
   166     ]
   169     ]
   167 !
   170 !
   168 
   171 
   169 withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr
   172 withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr
   170     "insert aString (which has no crs) at lineNr/colNr"
   173     "insert aString (which has no crs) at lineNr/colNr"
   171 
   174 
   172     |strLen line lineSize newLine|
   175     |strLen line lineSize newLine|
   173 
   176 
   174     aString isNil ifTrue:[^ self].
   177     aString isNil ifTrue:[^ self].
   175     readOnly ifTrue: [
   178     readOnly ifTrue: [
   176         exceptionBlock value:errorMessage.
   179 	exceptionBlock value:errorMessage.
   177         ^ self
   180 	^ self
   178     ].
   181     ].
   179     strLen := aString size.
   182     strLen := aString size.
   180     self checkForExistingLine:lineNr.
   183     self checkForExistingLine:lineNr.
   181     line := list at:lineNr.
   184     line := list at:lineNr.
   182     line notNil ifTrue:[
   185     line notNil ifTrue:[
   183         lineSize := line size
   186 	lineSize := line size
   184     ] ifFalse:[
   187     ] ifFalse:[
   185         lineSize := 0
   188 	lineSize := 0
   186     ].
   189     ].
   187     ((colNr == 1) and:[lineSize == 0]) ifTrue: [
   190     ((colNr == 1) and:[lineSize == 0]) ifTrue: [
   188         newLine := aString
   191 	newLine := aString
   189     ] ifFalse:[
   192     ] ifFalse:[
   190         (lineSize == 0) ifTrue: [
   193 	(lineSize == 0) ifTrue: [
   191             newLine := String new:(colNr + strLen - 1)
   194 	    newLine := String new:(colNr + strLen - 1)
   192         ] ifFalse: [
   195 	] ifFalse: [
   193             (colNr > lineSize) ifTrue: [
   196 	    (colNr > lineSize) ifTrue: [
   194                 newLine := String new:(colNr + strLen - 1).
   197 		newLine := String new:(colNr + strLen - 1).
   195                 newLine replaceFrom:1 to:lineSize
   198 		newLine replaceFrom:1 to:lineSize
   196                                with:line startingAt:1
   199 			       with:line startingAt:1
   197             ] ifFalse: [
   200 	    ] ifFalse: [
   198                 newLine := String new:(lineSize + strLen).
   201 		newLine := String new:(lineSize + strLen).
   199                 newLine replaceFrom:1 to:(colNr - 1)
   202 		newLine replaceFrom:1 to:(colNr - 1)
   200                                with:line startingAt:1.
   203 			       with:line startingAt:1.
   201                 newLine replaceFrom:(colNr + strLen) to:(lineSize + strLen)
   204 		newLine replaceFrom:(colNr + strLen) to:(lineSize + strLen)
   202                                with:line startingAt:colNr
   205 			       with:line startingAt:colNr
   203             ]
   206 	    ]
   204         ].
   207 	].
   205         newLine replaceFrom:colNr to:(colNr + strLen - 1)
   208 	newLine replaceFrom:colNr to:(colNr + strLen - 1)
   206                        with:aString startingAt:1
   209 		       with:aString startingAt:1
   207     ].
   210     ].
   208 
   211 
   209     (aString occurrencesOf:(Character tab)) == 0 ifFalse:[
   212     (aString occurrencesOf:(Character tab)) == 0 ifFalse:[
   210         newLine := self withTabsExpanded:newLine
   213 	newLine := self withTabsExpanded:newLine
   211     ].
   214     ].
   212 
   215 
   213     list at:lineNr put:newLine.
   216     list at:lineNr put:newLine.
       
   217     widthOfWidestLine notNil ifTrue:[
       
   218 	widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:newLine).
       
   219     ].
   214     self textChanged.
   220     self textChanged.
   215 
       
   216 !
   221 !
   217 
   222 
   218 splitLine:lineNr before:colNr
   223 splitLine:lineNr before:colNr
   219     "split the line linNr before colNr; the right part (from colNr)
   224     "split the line linNr before colNr; the right part (from colNr)
   220      is cut off and inserted after lineNr; the view is redrawn"
   225      is cut off and inserted after lineNr; the view is redrawn"
   221 
   226 
   222     |line lineSize leftRest rightRest visLine w      
   227     |line lineSize leftRest rightRest visLine w      
   223      srcY    "{ Class: SmallInteger }" |
   228      srcY    "{ Class: SmallInteger }" |
   224 
   229 
   225     list isNil ifFalse:[
   230     list isNil ifFalse:[
   226         lineNr > (list size) ifFalse:[
   231 	lineNr > (list size) ifFalse:[
   227             (colNr == 1) ifTrue:[
   232 	    (colNr == 1) ifTrue:[
   228                 self insertLine:nil before:lineNr.
   233 		self insertLine:nil before:lineNr.
   229                 ^ self
   234 		^ self
   230             ].
   235 	    ].
   231             line := list at:lineNr.
   236 	    line := list at:lineNr.
   232             line isNil ifFalse:[
   237 	    line isNil ifFalse:[
   233                 lineSize := line size.
   238 		lineSize := line size.
   234                 (colNr <= lineSize) ifTrue:[
   239 		(colNr <= lineSize) ifTrue:[
   235                     rightRest := line copyFrom:colNr to:lineSize.
   240 		    rightRest := line copyFrom:colNr to:lineSize.
   236                     (colNr > 1) ifTrue:[
   241 		    (colNr > 1) ifTrue:[
   237                         leftRest := line copyTo:(colNr - 1)
   242 			leftRest := line copyTo:(colNr - 1)
   238                     ]
   243 		    ]
   239                 ] ifFalse:[
   244 		] ifFalse:[
   240                     leftRest := line
   245 		    leftRest := line
   241                 ]
   246 		]
   242             ].
   247 	    ].
   243             leftRest notNil ifTrue:[
   248 	    leftRest notNil ifTrue:[
   244                 leftRest isBlank ifTrue:[leftRest := nil]
   249 		leftRest isBlank ifTrue:[leftRest := nil]
   245             ].
   250 	    ].
   246             list at:lineNr put:leftRest.
   251 	    list at:lineNr put:leftRest.
   247             self withoutRedrawInsertLine:rightRest before:(lineNr + 1).
   252 	    self withoutRedrawInsertLine:rightRest before:(lineNr + 1).
   248 
   253 
   249             visLine := self listLineToVisibleLine:(lineNr).
   254 	    visLine := self listLineToVisibleLine:(lineNr).
   250             visLine notNil ifTrue:[
   255 	    visLine notNil ifTrue:[
   251                 w := self widthForScrollBetween:lineNr
   256 		w := self widthForScrollBetween:lineNr
   252                                             and:(firstLineShown + nLinesShown).
   257 					    and:(firstLineShown + nLinesShown).
   253                 srcY := topMargin + (visLine * fontHeight).
   258 		srcY := topMargin + (visLine * fontHeight).
   254                 self catchExpose.
   259 		self catchExpose.
   255                 self copyFrom:self x:textStartLeft y:srcY
   260 		self copyFrom:self x:textStartLeft y:srcY
   256                                  toX:textStartLeft y:(srcY + fontHeight)
   261 				 toX:textStartLeft y:(srcY + fontHeight)
   257                                width:w
   262 			       width:w
   258                               height:((nLinesShown - visLine - 1) * fontHeight).
   263 			      height:((nLinesShown - visLine - 1) * fontHeight).
   259                 self redrawLine:lineNr.
   264 		self redrawLine:lineNr.
   260                 self redrawLine:(lineNr + 1).
   265 		self redrawLine:(lineNr + 1).
   261                 self waitForExpose
   266 		self waitForExpose
   262             ].
   267 	    ].
   263             self textChanged.
   268 	    widthOfWidestLine := nil. "/ unknown
   264         ]
   269 	    self textChanged.
       
   270 	]
   265     ]
   271     ]
   266 !
   272 !
   267 
   273 
   268 withoutRedrawInsertLine:aString before:lineNr
   274 withoutRedrawInsertLine:aString before:lineNr
   269     "insert the argument, aString before line lineNr; the string
   275     "insert the argument, aString before line lineNr; the string
   312     |visLine w nLines "{ Class: SmallInteger }"
   318     |visLine w nLines "{ Class: SmallInteger }"
   313      srcY "{ Class: SmallInteger }"
   319      srcY "{ Class: SmallInteger }"
   314      dstY "{ Class: SmallInteger }" |
   320      dstY "{ Class: SmallInteger }" |
   315 
   321 
   316     readOnly ifTrue:[
   322     readOnly ifTrue:[
   317         ^ self
   323 	^ self
   318     ].
   324     ].
   319     visLine := self listLineToVisibleLine:lineNr.
   325     visLine := self listLineToVisibleLine:lineNr.
   320     (shown not or:[visLine isNil]) ifTrue:[
   326     (shown not or:[visLine isNil]) ifTrue:[
   321         self withoutRedrawInsertLines:someText
   327 	self withoutRedrawInsertLines:someText
   322                                  from:start to:end
   328 				 from:start to:end
   323                                before:lineNr.
   329 			       before:lineNr.
   324         self textChanged.
       
   325         ^ self
       
   326     ].
       
   327 
       
   328     nLines := end - start + 1.
       
   329     ((visLine + nLines) >= nLinesShown) ifTrue:[
       
   330         self withoutRedrawInsertLines:someText
       
   331                                  from:start to:end
       
   332                                before:lineNr.
       
   333         self redrawFromVisibleLine:visLine to:nLinesShown
       
   334     ] ifFalse:[
   330     ] ifFalse:[
   335         w := self widthForScrollBetween:(lineNr + nLines)
   331 	nLines := end - start + 1.
   336                                     and:(firstLineShown + nLines + nLinesShown).
   332 	((visLine + nLines) >= nLinesShown) ifTrue:[
   337         srcY := topMargin + ((visLine - 1) * fontHeight).
   333 	    self withoutRedrawInsertLines:someText
   338         dstY := srcY + (nLines * fontHeight).
   334 				     from:start to:end
   339         "
   335 				   before:lineNr.
   340          stupid: must catchExpose before inserting new
   336 	    self redrawFromVisibleLine:visLine to:nLinesShown
   341          stuff - since catchExpose may perform redraws
   337 	] ifFalse:[
   342         "
   338 	    w := self widthForScrollBetween:(lineNr + nLines)
   343         self catchExpose.
   339 					and:(firstLineShown + nLines + nLinesShown).
   344         self withoutRedrawInsertLines:someText
   340 	    srcY := topMargin + ((visLine - 1) * fontHeight).
   345                                  from:start to:end
   341 	    dstY := srcY + (nLines * fontHeight).
   346                                before:lineNr.
   342 	    "
   347         self copyFrom:self x:textStartLeft y:srcY
   343 	     stupid: must catchExpose before inserting new
   348                          toX:textStartLeft y:dstY
   344 	     stuff - since catchExpose may perform redraws
   349                        width:w
   345 	    "
   350                       height:(height - dstY).
   346 	    self catchExpose.
   351         self redrawFromVisibleLine:visLine to:(visLine + nLines - 1).
   347 	    self withoutRedrawInsertLines:someText
   352         self waitForExpose
   348 				     from:start to:end
       
   349 				   before:lineNr.
       
   350 	    self copyFrom:self x:textStartLeft y:srcY
       
   351 			     toX:textStartLeft y:dstY
       
   352 			   width:w
       
   353 			  height:(height - dstY).
       
   354 	    self redrawFromVisibleLine:visLine to:(visLine + nLines - 1).
       
   355 	    self waitForExpose
       
   356 	].
       
   357     ].
       
   358     widthOfWidestLine notNil ifTrue:[
       
   359 	someText do:[:line |
       
   360 	    widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
       
   361 	]
   353     ].
   362     ].
   354     self textChanged.
   363     self textChanged.
   355 !
   364 !
   356 
   365 
   357 deleteFromLine:startLine col:startCol toLine:endLine col:endCol
   366 deleteFromLine:startLine col:startCol toLine:endLine col:endCol
   359      joining lines if nescessary"
   368      joining lines if nescessary"
   360 
   369 
   361     |line lineSize|
   370     |line lineSize|
   362 
   371 
   363     readOnly ifTrue: [
   372     readOnly ifTrue: [
   364         exceptionBlock value:errorMessage.
   373 	exceptionBlock value:errorMessage.
   365         ^ self
   374 	^ self
   366     ].
   375     ].
   367     list isNil ifTrue:[^ self].
   376     list isNil ifTrue:[^ self].
   368 
   377 
   369     (startLine == endLine) ifTrue:[
   378     (startLine == endLine) ifTrue:[
   370         "delete chars within a line"
   379 	"delete chars within a line"
   371         self deleteCharsAtLine:startLine fromCol:startCol toCol:endCol.
   380 	self deleteCharsAtLine:startLine fromCol:startCol toCol:endCol.
   372         ^ self
   381 	^ self
   373     ].
   382     ].
   374 
   383 
   375     ((startCol == 1) and:[endCol == 0]) ifTrue:[
   384     ((startCol == 1) and:[endCol == 0]) ifTrue:[
   376         "delete full lines only"
   385 	"delete full lines only"
   377         endLine > startLine ifTrue:[
   386 	endLine > startLine ifTrue:[
   378             self deleteFromLine:startLine toLine:(endLine - 1)
   387 	    self deleteFromLine:startLine toLine:(endLine - 1)
   379         ].
   388 	].
   380         ^ self
   389 	^ self
   381     ].
   390     ].
   382 
   391 
   383     "delete right rest of 1st line"
   392     "delete right rest of 1st line"
   384     self deleteCharsAtLine:startLine fromCol:startCol.
   393     self deleteCharsAtLine:startLine fromCol:startCol.
   385 
   394 
   386     "delete the inner lines ..."
   395     "delete the inner lines ..."
   387     endLine > (startLine + 1) ifTrue:[
   396     endLine > (startLine + 1) ifTrue:[
   388         self deleteFromLine:(startLine + 1) toLine:(endLine - 1)
   397 	self deleteFromLine:(startLine + 1) toLine:(endLine - 1)
   389     ].
   398     ].
   390 
   399 
   391     (endCol ~~ 0) ifTrue:[
   400     (endCol ~~ 0) ifTrue:[
   392         "delete the left rest of the last line"
   401 	"delete the left rest of the last line"
   393         self deleteCharsAtLine:(startLine + 1) toCol:endCol.
   402 	self deleteCharsAtLine:(startLine + 1) toCol:endCol.
   394 
   403 
   395         "must add blanks, if startCal lies behond end of startLine"
   404 	"must add blanks, if startCal lies behond end of startLine"
   396         line := list at:startLine.
   405 	line := list at:startLine.
   397         lineSize := line size.
   406 	lineSize := line size.
   398         (startCol > lineSize) ifTrue:[
   407 	(startCol > lineSize) ifTrue:[
   399             line isNil ifTrue:[
   408 	    line isNil ifTrue:[
   400                 line := String new:(startCol - 1)
   409 		line := String new:(startCol - 1)
   401             ] ifFalse:[
   410 	    ] ifFalse:[
   402                 line := line , (String new:(startCol - 1 - lineSize))
   411 		line := line , (String new:(startCol - 1 - lineSize))
   403             ].
   412 	    ].
   404             list at:startLine put:line.
   413 	    list at:startLine put:line.
   405             self textChanged.
   414 	    widthOfWidestLine := nil. "/ i.e. unknown
   406         ]
   415 	    self textChanged.
       
   416 	]
   407     ].
   417     ].
   408 
   418 
   409     "merge the left rest of 1st line with right rest of last line into one"
   419     "merge the left rest of 1st line with right rest of last line into one"
   410     self mergeLine:startLine
   420     self mergeLine:startLine
   411 !
   421 !
   562 "
   572 "
   563     list replaceFrom:(lineNr + nLines) to:(list size) with:list startingAt:lineNr.
   573     list replaceFrom:(lineNr + nLines) to:(list size) with:list startingAt:lineNr.
   564     list replaceFrom:lineNr to:(lineNr + nLines - 1) with:newLines startingAt:start.
   574     list replaceFrom:lineNr to:(lineNr + nLines - 1) with:newLines startingAt:start.
   565 !
   575 !
   566 
   576 
   567 deleteCharsAtLine:lineNr fromCol:startCol toCol:endCol
       
   568     "delete characters from startCol to endCol in line lineNr"
       
   569 
       
   570     |line lineSize newLine|
       
   571 
       
   572     readOnly ifTrue: [
       
   573         exceptionBlock value:errorMessage.
       
   574         ^ self
       
   575     ].
       
   576     list isNil ifTrue: [^self].
       
   577     (list size < lineNr) ifTrue: [^ self].
       
   578 
       
   579     line := list at:lineNr.
       
   580     line isNil ifTrue: [^self].
       
   581     lineSize := line size.
       
   582     (startCol > lineSize) ifTrue: [^ self].
       
   583     (endCol == 0) ifTrue:[^ self].
       
   584     (endCol < startCol) ifTrue:[^ self].
       
   585     (startCol == endCol) ifTrue:[
       
   586         self deleteCharAtLine:lineNr col:startCol.
       
   587         ^ self
       
   588     ].
       
   589     (endCol >= lineSize) ifTrue:[
       
   590         self deleteCharsAtLine:lineNr fromCol:startCol.
       
   591         ^ self
       
   592     ].
       
   593     (startCol <= 1) ifTrue:[
       
   594         self deleteCharsAtLine:lineNr toCol:endCol.
       
   595         ^ self
       
   596     ].
       
   597     newLine := (line copyTo:(startCol - 1)) 
       
   598                , (line copyFrom:(endCol + 1) to:lineSize).
       
   599 
       
   600     newLine isBlank ifTrue:[
       
   601         newLine := nil
       
   602     ].
       
   603     list at:lineNr put:newLine.
       
   604     self textChanged.
       
   605     self redrawLine:lineNr
       
   606 !
       
   607 
       
   608 insertStringWithoutCRs:aString atLine:lineNr col:colNr
   577 insertStringWithoutCRs:aString atLine:lineNr col:colNr
   609     "insert aString (which has no crs) at lineNr/colNr"
   578     "insert aString (which has no crs) at lineNr/colNr"
   610 
   579 
   611     self withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr.
   580     self withoutRedrawInsertStringWithoutCRs:aString atLine:lineNr col:colNr.
   612     shown ifTrue:[self redrawLine:lineNr from:colNr]
   581     shown ifTrue:[self redrawLine:lineNr from:colNr]
   660 	].
   629 	].
   661 	self makeCursorVisible
   630 	self makeCursorVisible
   662     ]
   631     ]
   663 !
   632 !
   664 
   633 
   665 deleteFromLine:startLineNr toLine:endLineNr
       
   666     "delete some lines"
       
   667 
       
   668     readOnly ifTrue: [
       
   669         exceptionBlock value:errorMessage.
       
   670         ^ self
       
   671     ].
       
   672     list isNil ifTrue:[^ self].
       
   673     list removeFromIndex:startLineNr toIndex:endLineNr.
       
   674     self textChanged.
       
   675     self redrawFromLine:startLineNr.
       
   676     (firstLineShown >= list size) ifTrue:[
       
   677         self makeLineVisible:(list size)
       
   678     ]
       
   679 !
       
   680 
       
   681 insertLine:aString before:lineNr
   634 insertLine:aString before:lineNr
   682     "insert the line aString before line lineNr"
   635     "insert the line aString before line lineNr"
   683 
   636 
   684     |visLine w 
   637     |visLine w 
   685      dstY "{ Class: SmallInteger }" |
   638      dstY "{ Class: SmallInteger }" |
   686 
   639 
   687     visLine := self listLineToVisibleLine:lineNr.
   640     visLine := self listLineToVisibleLine:lineNr.
   688     (shown not or:[visLine isNil]) ifTrue:[
   641     (shown not or:[visLine isNil]) ifTrue:[
   689         self withoutRedrawInsertLine:aString before:lineNr.
   642 	self withoutRedrawInsertLine:aString before:lineNr.
   690     ] ifFalse:[
   643     ] ifFalse:[
   691         w := self widthForScrollBetween:lineNr
   644 	w := self widthForScrollBetween:lineNr
   692                                     and:(firstLineShown + nLinesShown).
   645 				    and:(firstLineShown + nLinesShown).
   693         dstY := topMargin + ((visLine ) * fontHeight).
   646 	dstY := topMargin + ((visLine ) * fontHeight).
   694         self catchExpose.
   647 	self catchExpose.
   695         self withoutRedrawInsertLine:aString before:lineNr.
   648 	self withoutRedrawInsertLine:aString before:lineNr.
   696         self copyFrom:self x:textStartLeft y:(dstY - fontHeight)
   649 	self copyFrom:self x:textStartLeft y:(dstY - fontHeight)
   697                          toX:textStartLeft y:dstY
   650 			 toX:textStartLeft y:dstY
   698                        width:w
   651 		       width:w
   699                       height:((nLinesShown - visLine "- 1") * fontHeight).
   652 		      height:((nLinesShown - visLine "- 1") * fontHeight).
   700         self redrawVisibleLine:visLine.
   653 	self redrawVisibleLine:visLine.
   701         self waitForExpose.
   654 	self waitForExpose.
       
   655     ].
       
   656     widthOfWidestLine notNil ifTrue:[
       
   657 	widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:aString).
   702     ].
   658     ].
   703     self textChanged.
   659     self textChanged.
   704 !
   660 !
   705 
   661 
   706 mergeLine:lineNr
   662 mergeLine:lineNr
   740     self insertStringAtCursor:aString.
   696     self insertStringAtCursor:aString.
   741     self selectFromLine:startLine col:startCol
   697     self selectFromLine:startLine col:startCol
   742 		 toLine:cursorLine col:(cursorCol - 1)
   698 		 toLine:cursorLine col:(cursorCol - 1)
   743 !
   699 !
   744 
   700 
       
   701 deleteCharsAtLine:lineNr fromCol:startCol toCol:endCol
       
   702     "delete characters from startCol to endCol in line lineNr"
       
   703 
       
   704     |line lineSize newLine|
       
   705 
       
   706     readOnly ifTrue: [
       
   707 	exceptionBlock value:errorMessage.
       
   708 	^ self
       
   709     ].
       
   710     list isNil ifTrue: [^self].
       
   711     (list size < lineNr) ifTrue: [^ self].
       
   712 
       
   713     line := list at:lineNr.
       
   714     line isNil ifTrue: [^self].
       
   715     lineSize := line size.
       
   716     (startCol > lineSize) ifTrue: [^ self].
       
   717     (endCol == 0) ifTrue:[^ self].
       
   718     (endCol < startCol) ifTrue:[^ self].
       
   719     (startCol == endCol) ifTrue:[
       
   720 	self deleteCharAtLine:lineNr col:startCol.
       
   721 	^ self
       
   722     ].
       
   723     (endCol >= lineSize) ifTrue:[
       
   724 	self deleteCharsAtLine:lineNr fromCol:startCol.
       
   725 	^ self
       
   726     ].
       
   727     (startCol <= 1) ifTrue:[
       
   728 	self deleteCharsAtLine:lineNr toCol:endCol.
       
   729 	^ self
       
   730     ].
       
   731     newLine := (line copyTo:(startCol - 1)) 
       
   732 	       , (line copyFrom:(endCol + 1) to:lineSize).
       
   733 
       
   734     newLine isBlank ifTrue:[
       
   735 	newLine := nil
       
   736     ].
       
   737     list at:lineNr put:newLine.
       
   738     widthOfWidestLine := nil. "/ i.e. unknown
       
   739     self textChanged.
       
   740     self redrawLine:lineNr
       
   741 !
       
   742 
   745 deleteCharAtLine:lineNr col:colNr
   743 deleteCharAtLine:lineNr col:colNr
   746     "delete single character at colNr in line lineNr"
   744     "delete single character at colNr in line lineNr"
   747 
   745 
   748     |line lineSize newLine drawCharacterOnly|
   746     |line lineSize newLine drawCharacterOnly wasLargest|
   749 
   747 
   750     readOnly ifTrue: [
   748     readOnly ifTrue: [
   751         exceptionBlock value:errorMessage.
   749 	exceptionBlock value:errorMessage.
   752         ^ self
   750 	^ self
   753     ].
   751     ].
   754     list isNil ifTrue: [^self].
   752     list isNil ifTrue: [^self].
   755     (list size < lineNr) ifTrue: [^ self].
   753     (list size < lineNr) ifTrue: [^ self].
   756 
   754 
   757     line := list at:lineNr.
   755     line := list at:lineNr.
   758     line isNil ifTrue: [^self].
   756     line isNil ifTrue: [^self].
   759     lineSize := line size.
   757     lineSize := line size.
   760     (colNr > lineSize) ifTrue: [^ self].
   758     (colNr > lineSize) ifTrue: [^ self].
   761 
   759 
       
   760     wasLargest := (self widthOfLineString:line) == widthOfWidestLine.
       
   761 
   762     drawCharacterOnly := false.
   762     drawCharacterOnly := false.
   763     (colNr == lineSize) ifTrue:[
   763     (colNr == lineSize) ifTrue:[
   764         newLine := line copyTo:(lineSize - 1).
   764 	newLine := line copyTo:(lineSize - 1).
   765         fontIsFixedWidth ifTrue:[
   765 	fontIsFixedWidth ifTrue:[
   766             drawCharacterOnly := true
   766 	    drawCharacterOnly := true
   767         ]
   767 	]
   768     ] ifFalse:[
   768     ] ifFalse:[
   769         newLine := String new:(lineSize - 1).
   769 	newLine := String new:(lineSize - 1).
   770         newLine replaceFrom:1 to:(colNr - 1)
   770 	newLine replaceFrom:1 to:(colNr - 1)
   771                        with:line startingAt:1.
   771 		       with:line startingAt:1.
   772         newLine replaceFrom:colNr to:(lineSize - 1)
   772 	newLine replaceFrom:colNr to:(lineSize - 1)
   773                        with:line startingAt:(colNr + 1)
   773 		       with:line startingAt:(colNr + 1)
   774     ].
   774     ].
   775 
   775 
   776     newLine isBlank ifTrue:[
   776     newLine isBlank ifTrue:[
   777         newLine := nil
   777 	newLine := nil
   778     ].
   778     ].
   779     list at:lineNr put:newLine.
   779     list at:lineNr put:newLine.
       
   780     wasLargest ifTrue:[
       
   781 	widthOfWidestLine := nil. "/ i.e. unknown
       
   782     ].
   780     self textChanged.
   783     self textChanged.
   781     drawCharacterOnly ifTrue:[
   784     drawCharacterOnly ifTrue:[
   782         self redrawLine:lineNr col:colNr
   785 	self redrawLine:lineNr col:colNr
   783     ] ifFalse:[
   786     ] ifFalse:[
   784         self redrawLine:lineNr from:colNr
   787 	self redrawLine:lineNr from:colNr
   785     ]
   788     ]
   786 !
   789 !
   787 
   790 
   788 removeTrailingBlankLines
   791 removeTrailingBlankLines
   789     "remove all blank lines at end of text"
   792     "remove all blank lines at end of text"
   792      line finished|
   795      line finished|
   793 
   796 
   794     lastLine := list size.
   797     lastLine := list size.
   795     finished := false.
   798     finished := false.
   796     [finished] whileFalse:[
   799     [finished] whileFalse:[
   797         (lastLine <= 1) ifTrue:[
   800 	(lastLine <= 1) ifTrue:[
   798             finished := true
   801 	    finished := true
   799         ] ifFalse:[
   802 	] ifFalse:[
   800             line := list at:lastLine.
   803 	    line := list at:lastLine.
   801             line notNil ifTrue:[
   804 	    line notNil ifTrue:[
   802                 line isBlank ifTrue:[
   805 		line isBlank ifTrue:[
   803                     list at:lastLine put:nil.
   806 		    list at:lastLine put:nil.
   804                     line := nil
   807 		    line := nil
   805                 ]
   808 		]
   806             ].
   809 	    ].
   807             line notNil ifTrue:[
   810 	    line notNil ifTrue:[
   808                 finished := true
   811 		finished := true
   809             ] ifFalse:[
   812 	    ] ifFalse:[
   810                 lastLine := lastLine - 1
   813 		lastLine := lastLine - 1
   811             ]
   814 	    ]
   812         ]
   815 	]
   813     ].
   816     ].
   814     (lastLine ~~ list size) ifTrue:[
   817     (lastLine ~~ list size) ifTrue:[
   815         list grow:lastLine.
   818 	list grow:lastLine.
   816 "/        self textChanged
   819 "/        self textChanged
   817     ]
   820     ]
   818 !
   821 !
   819 
   822 
   820 deleteCharsAtLine:lineNr toCol:colNr
   823 deleteCharsAtLine:lineNr toCol:colNr
   821     "delete characters from start up to colNr in line lineNr"
   824     "delete characters from start up to colNr in line lineNr"
   822 
   825 
   823     |line lineSize newLine|
   826     |line lineSize newLine|
   824 
   827 
   825     readOnly ifTrue: [
   828     readOnly ifTrue: [
   826         exceptionBlock value:errorMessage.
   829 	exceptionBlock value:errorMessage.
   827         ^ self
   830 	^ self
   828     ].
   831     ].
   829     list isNil ifTrue: [^self].
   832     list isNil ifTrue: [^self].
   830     (list size < lineNr) ifTrue: [^ self].
   833     (list size < lineNr) ifTrue: [^ self].
   831     line := list at:lineNr.
   834     line := list at:lineNr.
   832     line isNil ifTrue: [^self].
   835     line isNil ifTrue: [^self].
   833     lineSize := line size.
   836     lineSize := line size.
   834     (colNr >= lineSize) ifTrue:[
   837     (colNr >= lineSize) ifTrue:[
   835         newLine := nil
   838 	newLine := nil
   836     ] ifFalse:[
   839     ] ifFalse:[
   837         newLine := line copyFrom:(colNr + 1) to:lineSize.
   840 	newLine := line copyFrom:(colNr + 1) to:lineSize.
   838         newLine isBlank ifTrue:[
   841 	newLine isBlank ifTrue:[
   839             newLine := nil
   842 	    newLine := nil
   840         ]
   843 	]
   841     ].
   844     ].
   842     list at:lineNr put:newLine.
   845     list at:lineNr put:newLine.
       
   846     widthOfWidestLine := nil. "/ i.e. unknown
   843     self textChanged.
   847     self textChanged.
   844     self redrawLine:lineNr
   848     self redrawLine:lineNr
   845 !
   849 !
   846 
   850 
   847 insertTabAtCursor
   851 insertTabAtCursor
   880 	    self makeCursorVisible
   884 	    self makeCursorVisible
   881 	]
   885 	]
   882     ]
   886     ]
   883 !
   887 !
   884 
   888 
       
   889 deleteFromLine:startLineNr toLine:endLineNr
       
   890     "delete some lines"
       
   891 
       
   892     readOnly ifTrue: [
       
   893 	exceptionBlock value:errorMessage.
       
   894 	^ self
       
   895     ].
       
   896     list isNil ifTrue:[^ self].
       
   897     list removeFromIndex:startLineNr toIndex:endLineNr.
       
   898     widthOfWidestLine := nil. "/ i.e. unknown
       
   899     self textChanged.
       
   900     self redrawFromLine:startLineNr.
       
   901     (firstLineShown >= list size) ifTrue:[
       
   902 	self makeLineVisible:(list size)
       
   903     ]
       
   904 !
       
   905 
   885 deleteLineWithoutRedraw:lineNr
   906 deleteLineWithoutRedraw:lineNr
   886     "delete line - no redraw;
   907     "delete line - no redraw;
   887      return true, if something was really deleted"
   908      return true, if something was really deleted"
   888 
   909 
   889     readOnly ifTrue:[
   910     readOnly ifTrue:[
   890         exceptionBlock value:errorMessage.
   911 	exceptionBlock value:errorMessage.
   891         ^ false
   912 	^ false
   892     ].
   913     ].
   893     (list isNil or:[lineNr > list size]) ifTrue:[^ false].
   914     (list isNil or:[lineNr > list size]) ifTrue:[^ false].
   894     list removeIndex:lineNr.
   915     list removeIndex:lineNr.
       
   916     widthOfWidestLine := nil. "/ i.e. unknown
   895     self textChanged.
   917     self textChanged.
   896     ^ true
   918     ^ true
   897 !
   919 !
   898 
   920 
   899 deleteLinesWithoutRedrawFrom:startLine to:endLine
   921 deleteLinesWithoutRedrawFrom:startLine to:endLine
   901      return true, if something was really deleted"
   923      return true, if something was really deleted"
   902 
   924 
   903     |lastLine|
   925     |lastLine|
   904 
   926 
   905     readOnly ifTrue:[
   927     readOnly ifTrue:[
   906         exceptionBlock value:errorMessage.
   928 	exceptionBlock value:errorMessage.
   907         ^ false
   929 	^ false
   908     ].
   930     ].
   909     (list isNil or:[startLine > list size]) ifTrue:[^ false].
   931     (list isNil or:[startLine > list size]) ifTrue:[^ false].
   910     (endLine > list size) ifTrue:[
   932     (endLine > list size) ifTrue:[
   911         lastLine := list size
   933 	lastLine := list size
   912     ] ifFalse:[
   934     ] ifFalse:[
   913         lastLine := endLine
   935 	lastLine := endLine
   914     ].
   936     ].
   915     list removeFromIndex:startLine toIndex:lastLine.
   937     list removeFromIndex:startLine toIndex:lastLine.
       
   938     widthOfWidestLine := nil. "/ i.e. unknown
   916     self textChanged.
   939     self textChanged.
   917     ^ true
   940     ^ true
   918 !
   941 !
   919 
   942 
   920 deleteLine:lineNr
   943 deleteLine:lineNr
   954     "delete characters from colNr up to the end in line lineNr"
   977     "delete characters from colNr up to the end in line lineNr"
   955 
   978 
   956     |line newLine|
   979     |line newLine|
   957 
   980 
   958     readOnly ifTrue: [
   981     readOnly ifTrue: [
   959         exceptionBlock value:errorMessage.
   982 	exceptionBlock value:errorMessage.
   960         ^ self
   983 	^ self
   961     ].
   984     ].
   962     list isNil ifTrue: [^self].
   985     list isNil ifTrue: [^self].
   963     (list size < lineNr) ifTrue: [^ self].
   986     (list size < lineNr) ifTrue: [^ self].
   964     line := list at:lineNr.
   987     line := list at:lineNr.
   965     line isNil ifTrue: [^self].
   988     line isNil ifTrue: [^self].
   966     (colNr > line size) ifTrue: [^ self].
   989     (colNr > line size) ifTrue: [^ self].
   967     newLine := line copyTo:(colNr - 1).
   990     newLine := line copyTo:(colNr - 1).
   968     newLine isBlank ifTrue:[
   991     newLine isBlank ifTrue:[
   969         newLine := nil
   992 	newLine := nil
   970     ].
   993     ].
   971     list at:lineNr put:newLine.
   994     list at:lineNr put:newLine.
       
   995     widthOfWidestLine := nil. "/ i.e. unknown
   972     self textChanged.
   996     self textChanged.
   973     self redrawLine:lineNr
   997     self redrawLine:lineNr
   974 !
   998 !
   975 
   999 
   976 replaceSelectionBy:something
  1000 replaceSelectionBy:something
  2196 
  2220 
  2197     "find a line to base indent on..."
  2221     "find a line to base indent on..."
  2198     leftStart := 0.
  2222     leftStart := 0.
  2199     lnr := start.
  2223     lnr := start.
  2200     [(leftStart == 0) and:[lnr ~~ 1]] whileTrue:[
  2224     [(leftStart == 0) and:[lnr ~~ 1]] whileTrue:[
  2201         lnr := lnr - 1.
  2225 	lnr := lnr - 1.
  2202         leftStart := self leftIndentOfLine:lnr
  2226 	leftStart := self leftIndentOfLine:lnr
  2203     ].
  2227     ].
  2204 
  2228 
  2205     (leftStart == 0) ifTrue:[^ self].
  2229     (leftStart == 0) ifTrue:[^ self].
  2206 
  2230 
  2207     delta := leftStart - (self leftIndentOfLine:start).
  2231     delta := leftStart - (self leftIndentOfLine:start).
  2208     (delta == 0) ifTrue:[^ self].
  2232     (delta == 0) ifTrue:[^ self].
  2209     (delta > 0) ifTrue:[
  2233     (delta > 0) ifTrue:[
  2210         spaces := String new:delta
  2234 	spaces := String new:delta
  2211     ].
  2235     ].
  2212     start to:end do:[:lineNr |
  2236     start to:end do:[:lineNr |
  2213         line := self listAt:lineNr.
  2237 	line := self listAt:lineNr.
  2214         line notNil ifTrue:[
  2238 	line notNil ifTrue:[
  2215             line isBlank ifTrue:[
  2239 	    line isBlank ifTrue:[
  2216                 list at:lineNr put:nil
  2240 		list at:lineNr put:nil
  2217             ] ifFalse:[
  2241 	    ] ifFalse:[
  2218                 (delta > 0) ifTrue:[
  2242 		(delta > 0) ifTrue:[
  2219                     line := spaces , line
  2243 		    line := spaces , line.
  2220                 ] ifFalse:[
  2244 		    widthOfWidestLine notNil ifTrue:[
  2221                     "check if deletion is ok"
  2245 			widthOfWidestLine := widthOfWidestLine max:(self widthOfLineString:line).
  2222                     d := delta negated + 1.
  2246 		    ]
  2223 
  2247 		] ifFalse:[
  2224                     line size > d ifTrue:[
  2248 		    "check if deletion is ok"
  2225                         (line copyTo:(d - 1)) withoutSeparators isEmpty ifTrue:[
  2249 		    d := delta negated + 1.
  2226                             line := line copyFrom:d
  2250 
  2227                         ]
  2251 		    line size > d ifTrue:[
  2228                     ]
  2252 			(line copyTo:(d - 1)) withoutSeparators isEmpty ifTrue:[
  2229                 ].
  2253 			    line := line copyFrom:d
  2230                 list at:lineNr put:line.
  2254 			]
  2231                 self textChanged.
  2255 		    ].
  2232             ]
  2256 		    widthOfWidestLine := nil
  2233         ]
  2257 		].
       
  2258 		list at:lineNr put:line.
       
  2259 		self textChanged.
       
  2260 	    ]
       
  2261 	]
  2234     ].
  2262     ].
  2235     self redrawFromLine:start to:end
  2263     self redrawFromLine:start to:end
  2236 ! !
  2264 ! !
  2237 
  2265 
  2238 !EditTextView methodsFor:'undo & again'!
  2266 !EditTextView methodsFor:'undo & again'!
  2525 !
  2553 !
  2526 
  2554 
  2527 searchFwd:pattern ifAbsent:aBlock
  2555 searchFwd:pattern ifAbsent:aBlock
  2528     "do a forward search"
  2556     "do a forward search"
  2529 
  2557 
  2530     self searchFwd:pattern startingAtLine:cursorLine col:cursorCol ifAbsent:aBlock
  2558     |startCol|
       
  2559 
       
  2560     "/ if there is no selection and the cursor is at the origin, 
       
  2561     "/ assume its the first search and do not skip the very first match
       
  2562     startCol := cursorCol.
       
  2563     self hasSelection ifFalse:[
       
  2564 	(cursorLine == 1 and:[cursorCol == 1]) ifTrue:[
       
  2565 	    startCol := 0
       
  2566 	]
       
  2567     ].
       
  2568 
       
  2569     self searchFwd:pattern startingAtLine:cursorLine col:startCol ifAbsent:aBlock
  2531 !
  2570 !
  2532 
  2571 
  2533 searchBwd:pattern ifAbsent:aBlock
  2572 searchBwd:pattern ifAbsent:aBlock
  2534     "do a backward search"
  2573     "do a backward search"
  2535 
  2574