TextView.st
changeset 131 208fa92f434d
parent 126 40228f4fd66b
child 132 596439fe4efd
--- a/TextView.st	Tue Jun 06 06:16:07 1995 +0200
+++ b/TextView.st	Tue Jun 27 04:24:41 1995 +0200
@@ -21,8 +21,7 @@
 			      selectStyle 
 			      directoryForFileDialog
 			      contentsWasSaved'
-       classVariableNames:'MyFontPanel
-			   DefaultFont
+       classVariableNames:'DefaultFont
 			   DefaultViewBackground
 			   DefaultSelectionForegroundColor
 			   DefaultSelectionBackgroundColor'
@@ -34,7 +33,7 @@
 COPYRIGHT (c) 1989 by Claus Gittinger
 	     All Rights Reserved
 
-$Header: /cvs/stx/stx/libwidg/TextView.st,v 1.22 1995-05-10 02:30:19 claus Exp $
+$Header: /cvs/stx/stx/libwidg/TextView.st,v 1.23 1995-06-27 02:24:18 claus Exp $
 '!
 
 !TextView class methodsFor:'documentation'!
@@ -55,7 +54,7 @@
 
 version
 "
-$Header: /cvs/stx/stx/libwidg/TextView.st,v 1.22 1995-05-10 02:30:19 claus Exp $
+$Header: /cvs/stx/stx/libwidg/TextView.st,v 1.23 1995-06-27 02:24:18 claus Exp $
 "
 !
 
@@ -706,7 +705,10 @@
 	    ^ self selectFromLine:endLine col:endCol toLine:startLine col:startCol
 	].
 	(endLine == startLine and:[endCol < startCol]) ifTrue:[
-	    ^ self selectFromLine:endLine col:endCol toLine:startLine col:startCol
+	    endCol ~~ 0 ifTrue:[
+		self selectFromLine:endLine col:endCol toLine:startLine col:startCol.
+	    ].
+	    ^ self
 	].
 
 " old:
@@ -853,9 +855,11 @@
 !
 
 selection
-    "return the selection as a collection of (line-)strings"
+    "return the selection as a collection of (line-)strings.
+     If the selection ends in a full line, the last entry in the returned
+     collection will be an empty string."
 
-    |text sz index 
+    |text sz index last
      startLine "{ Class: SmallInteger }"
      endLine   "{ Class: SmallInteger }"|
 
@@ -875,10 +879,11 @@
     "get 1st and last (possibly) partial lines"
     text at:1 put:(self listAt:startLine from:selectionStartCol).
     selectionEndCol == 0 ifTrue:[
-	text at:sz put:''
+	last := ''
     ] ifFalse:[
-	text at:sz put:(self listAt:selectionEndLine to:selectionEndCol).
+	last := self listAt:selectionEndLine to:selectionEndCol.
     ].
+    text at:sz put:last.
 
     "get bulk of text"
     index := 2.
@@ -889,6 +894,22 @@
     ^ text
 !
 
+selectionStartLine
+    ^ selectionStartLine
+!
+
+selectionStartCol
+    ^ selectionStartCol
+!
+
+selectionEndLine
+    ^ selectionEndLine
+!
+
+selectionEndCol
+    ^ selectionEndCol
+!
+
 makeSelectionVisible
     "scroll to make the selection visible"
 
@@ -995,6 +1016,26 @@
 " "
 !
 
+showMatch:pattern atLine:line col:col
+    "after a search, highlight the matched pattern.
+     The code below needs a rewrite to take care of match-characters
+     (for now, it only highlights simple patterns and '*string*' correctly)"
+
+    |realPattern|
+
+    realPattern := pattern.
+    (realPattern startsWith:$*) ifTrue:[
+	realPattern := realPattern copyFrom:2
+    ].
+    (realPattern endsWith:$*) ifTrue:[
+	realPattern := realPattern copyWithoutLast:1
+    ].
+
+    self selectFromLine:line col:col
+		 toLine:line col:(col + realPattern size - 1).
+    self makeLineVisible:line
+!
+
 searchFwd
     "search forward for pattern or selection"
 
@@ -1049,9 +1090,7 @@
     ].
     self searchForwardFor:pattern startingAtLine:startLine col:startCol
     ifFound:[:line :col |
-	self selectFromLine:line col:col
-		     toLine:line col:(col + pattern size - 1).
-	self makeLineVisible:line
+	self showMatch:pattern atLine:line col:col
     ] ifAbsent:aBlock
 !
 
@@ -1069,10 +1108,98 @@
     ].
     self searchBackwardFor:pattern startingAtLine:startLine col:startCol
     ifFound:[:line :col |
-	self selectFromLine:line col:col
-		     toLine:line col:(col + pattern size - 1).
-	self makeLineVisible:line
+	self showMatch:pattern atLine:line col:col
     ] ifAbsent:aBlock
+!
+
+searchForMatchingParenthesisFromLine:startLine col:startCol
+		     ifFound:foundBlock 
+		  ifNotFound:notFoundBlock
+		     onError:failBlock
+
+    "search for a matching parenthesis, parChar is one of '$( $[ ${ $) $] $}'. 
+     Search for the corresponding character is done forward if its an opening,
+     backwards if its a closing parenthesis.
+     Performs foundBlock with line/col as argument if found, notFoundBlock if not.
+     If there is a nesting error, performs failBlock."
+
+    |i direction lineString line col parChar charSet ignoreSet closingChar 
+     ignoring delta endCol cc incSet decSet nesting maxLine|
+
+    charSet := #( $( $) $[ $] ${ $} ).
+    ignoreSet := #( $' $" ).
+
+    parChar := self characterAtLine:startLine col:startCol.
+    i := charSet indexOf:parChar.
+    i == 0 ifTrue:[
+	^ failBlock value   "not a parenthesis"
+    ].
+    direction := #( fwd bwd fwd bwd fwd bwd) at:i.
+    closingChar := #( $) $( $] $[ $} ${ ) at:i.
+
+    col := startCol.
+    line := startLine.
+    direction == #fwd ifTrue:[
+	delta := 1.
+	incSet := #( $( $[ ${ ).
+	decSet := #( $) $] $} ).
+    ] ifFalse:[
+	delta := -1.
+	incSet := #( $) $] $} ).
+	decSet := #( $( $[ ${ ).
+    ].
+
+    nesting := 1.
+    ignoring := false.
+    lineString := list at:line.
+    maxLine := list size.
+
+    col := col + delta.
+    [nesting ~~ 0] whileTrue:[
+	lineString notNil ifTrue:[
+	    direction == #fwd ifTrue:[
+		endCol := lineString size.
+	    ] ifFalse:[
+		endCol := 1
+	    ].
+	    col to:endCol by:delta do:[:runCol |
+		cc := lineString at:runCol.
+
+		(ignoreSet includes:cc) ifTrue:[
+		    ignoring := ignoring not
+		].
+		ignoring ifFalse:[
+		    (incSet includes:cc) ifTrue:[
+			nesting := nesting + 1
+		    ] ifFalse:[
+			(decSet includes:cc) ifTrue:[
+			    nesting := nesting - 1
+			]
+		    ]
+		].
+		nesting == 0 ifTrue:[
+		    "check if legal"
+
+		    cc == closingChar ifFalse:[
+			^ failBlock value
+		    ].
+		    ^ foundBlock value:line value:runCol.
+		]
+	    ].
+	].
+	line := line + delta.
+	(line < 1 or:[line > maxLine]) ifTrue:[
+	    ^ failBlock value
+	].
+	lineString := list at:line.
+	direction == #fwd ifTrue:[
+	    col := 1
+	] ifFalse:[
+	    col := lineString size
+	]
+    ].
+
+    ^ notFoundBlock value
 ! !
 
 !TextView methodsFor:'redrawing'!
@@ -1413,7 +1540,8 @@
 
      (see EditTextView>>keyPress:x:y and Workspace>>keyPress:x:y)
     "
-    (#(F1 F2 F3 F4 F5 F6 F7 F8 F9) includes:key) ifTrue:[
+    (('[fF][0-9]' match:key)
+    or:['[fF][0-9][0-9]' match:key]) ifTrue:[
 	device shiftDown ifTrue:[
 	    (Smalltalk at:#FunctionKeySequences) isNil ifTrue:[
 		Smalltalk at:#FunctionKeySequences put:Dictionary new
@@ -1454,12 +1582,31 @@
 buttonMultiPress:button x:x y:y
     "multi-mouse-click - select word under pointer"
 
+    |sel|
+
     ((button == 1) or:[button == #select]) ifTrue:[
 	clickCount notNil ifTrue:[
 	    clickCount := clickCount + 1.
 	    (clickCount == 2) ifTrue:[
 		self selectWordAtX:x y:y.
 		"
+		 special - if clicked on a parenthesis, select to matching
+		"
+		((sel := self selection) size == 1 
+		and:[(sel := sel at:1) size == 1]) ifTrue:[
+		    ('()[]{}<>' includes:(sel at:1)) ifTrue:[
+			self searchForMatchingParenthesisFromLine:selectionStartLine col:selectionStartCol
+			      ifFound:[:line :col | 
+					  self selectFromLine:selectionStartLine col:selectionStartCol
+						       toLine:line col:col
+				      ]
+			   ifNotFound:[self showNotFound]
+			      onError:[device beep].
+			selectStyle := nil
+		    ]
+		].
+
+		"
 		 remember words position in case of a drag following
 		"
 		wordStartLine := selectionStartLine.