@@ -834,6 +834,17 @@ public int getLineStopOffset(int line)
834834 return lineElement .getEndOffset ();
835835 }
836836
837+ /**
838+ * Returns the end offset of the specified line, but not past the end of the text
839+ * @param line The line
840+ * @return The end offset of the specified line, safe to use for a selection, or -1 if the line is
841+ * invalid.
842+ */
843+ public int getSafeLineStopOffset (int line )
844+ {
845+ return Math .min (getLineStopOffset (line ),getDocumentLength ());
846+ }
847+
837848 /**
838849 * Returns the length of the specified line.
839850 * @param line The line
@@ -1144,7 +1155,7 @@ public void select(int start, int end)
11441155 {
11451156 throw new IllegalArgumentException ("Bounds out of"
11461157 + " range: " + newStart + "," +
1147- newEnd );
1158+ newEnd + " [" + getDocumentLength () + "]" );
11481159 }
11491160
11501161 // If the new position is the same as the old, we don't
@@ -1201,6 +1212,86 @@ public void select(int start, int end)
12011212 // getLineOfOffset(end));
12021213 }
12031214 }
1215+
1216+ private boolean isWordCharacter ( char ch , String noWordSep )
1217+ {
1218+ return Character .isLetterOrDigit (ch ) || ch =='_' || noWordSep .indexOf (ch ) != -1 ;
1219+ }
1220+
1221+ protected void setNewSelectionWord ( int line , int offset )
1222+ {
1223+ if (getLineLength (line ) == 0 ) {
1224+ newSelectionStart = getLineStartOffset (line );
1225+ newSelectionEnd = newSelectionStart ;
1226+ return ;
1227+ }
1228+
1229+ String noWordSep = (String )document .getProperty ("noWordSep" );
1230+ if (noWordSep == null )
1231+ noWordSep = "" ;
1232+
1233+ String lineText = getLineText (line );
1234+
1235+ int wordStart = 0 ;
1236+ int wordEnd = lineText .length ();
1237+
1238+ char ch = lineText .charAt (Math .max (0 ,offset - 1 ));
1239+
1240+ // special case for whitespace (fry 0122, bug #348)
1241+ // this is really nasty.. turns out that double-clicking any non-letter
1242+ // or digit char gets lumped together.. sooo, this quickly gets messy,
1243+ // because really it needs to check whether the chars are of the same
1244+ // type.. so a double space or double - might be grouped together,
1245+ // but what about a +=1? do + and - get grouped but not the 1? blech,
1246+ // coming back to this later. it's not a difficult fix, just a
1247+ // time-consuming one to track down all the proper cases.
1248+ /*
1249+ if (ch == ' ') {
1250+ //System.out.println("yeehaa");
1251+
1252+ for(int i = offset - 1; i >= 0; i--) {
1253+ if (lineText.charAt(i) == ' ') {
1254+ wordStart = i;
1255+ } else {
1256+ break;
1257+ }
1258+ }
1259+ for(int i = offset; i < lineText.length(); i++) {
1260+ if (lineText.charAt(i) == ' ') {
1261+ wordEnd = i + 1;
1262+ } else {
1263+ break;
1264+ }
1265+ }
1266+
1267+ } else {
1268+ */
1269+
1270+ // If the user clicked on a non-letter char,
1271+ // we select the surrounding non-letters
1272+ boolean selectNoLetter = !isWordCharacter (ch ,noWordSep );
1273+
1274+ for (int i = offset - 1 ; i >= 0 ; i --) {
1275+ ch = lineText .charAt (i );
1276+ if (selectNoLetter ^ !isWordCharacter (ch ,noWordSep )) {
1277+ wordStart = i + 1 ;
1278+ break ;
1279+ }
1280+ }
1281+
1282+ for (int i = offset ; i < lineText .length (); i ++) {
1283+ ch = lineText .charAt (i );
1284+ if (selectNoLetter ^ !isWordCharacter (ch ,noWordSep )) {
1285+ wordEnd = i ;
1286+ break ;
1287+ }
1288+ }
1289+ //}
1290+ int lineStart = getLineStartOffset (line );
1291+
1292+ newSelectionStart = lineStart + wordStart ;
1293+ newSelectionEnd = lineStart + wordEnd ;
1294+ }
12041295
12051296
12061297 /**
@@ -1684,6 +1775,14 @@ public void processKeyEvent(KeyEvent evt) {
16841775 protected int selectionEnd ;
16851776 protected int selectionEndLine ;
16861777 protected boolean biasLeft ;
1778+
1779+ protected int newSelectionStart ; // hack to get around lack of multiple returns in Java
1780+ protected int newSelectionEnd ;
1781+
1782+ protected boolean selectWord ;
1783+ protected boolean selectLine ;
1784+ protected int selectionAncorStart ;
1785+ protected int selectionAncorEnd ;
16871786
16881787 protected int bracketPosition ;
16891788 protected int bracketLine ;
@@ -2021,9 +2120,26 @@ public void mouseDragged(MouseEvent evt)
20212120 {
20222121 if (popup != null && popup .isVisible ()) return ;
20232122
2024- setSelectionRectangular ((evt .getModifiers ()
2025- & InputEvent .CTRL_MASK ) != 0 );
2026- select (getMarkPosition (),xyToOffset (evt .getX (),evt .getY ()));
2123+ if ( !selectWord && !selectLine ) {
2124+ setSelectionRectangular ((evt .getModifiers ()
2125+ & InputEvent .CTRL_MASK ) != 0 );
2126+ select (getMarkPosition (),xyToOffset (evt .getX (),evt .getY ()));
2127+ } else {
2128+ int line = yToLine (evt .getY ());
2129+ if ( selectWord ) {
2130+ setNewSelectionWord ( line , xToOffset (line ,evt .getX ()) );
2131+ } else {
2132+ newSelectionStart = getLineStartOffset (line );
2133+ newSelectionEnd = getSafeLineStopOffset (line );
2134+ }
2135+ if ( newSelectionStart < selectionAncorStart ) {
2136+ select (newSelectionStart ,selectionAncorEnd );
2137+ } else if ( newSelectionEnd > selectionAncorEnd ) {
2138+ select (selectionAncorStart ,newSelectionEnd );
2139+ } else {
2140+ select (newSelectionStart ,newSelectionEnd );
2141+ }
2142+ }
20272143 }
20282144
20292145 final Cursor normalCursor = new Cursor (Cursor .DEFAULT_CURSOR );
@@ -2094,6 +2210,9 @@ public void mousePressed(MouseEvent evt)
20942210 int offset = xToOffset (line ,evt .getX ());
20952211 int dot = getLineStartOffset (line ) + offset ;
20962212
2213+ selectLine = false ;
2214+ selectWord = false ;
2215+
20972216 switch (evt .getClickCount ()) {
20982217
20992218 case 1 :
@@ -2159,74 +2278,11 @@ private void doDoubleClick(MouseEvent evt, int line,
21592278 bl .printStackTrace ();
21602279 }
21612280
2162- String noWordSep = (String )document .getProperty ("noWordSep" );
2163- if (noWordSep == null )
2164- noWordSep = "" ;
2165-
2166- // Ok, it's not a bracket... select the word
2167- String lineText = getLineText (line );
2168-
2169- int wordStart = 0 ;
2170- int wordEnd = lineText .length ();
2171-
2172- char ch = lineText .charAt (Math .max (0 ,offset - 1 ));
2173-
2174- // special case for whitespace (fry 0122, bug #348)
2175- // this is really nasty.. turns out that double-clicking any non-letter
2176- // or digit char gets lumped together.. sooo, this quickly gets messy,
2177- // because really it needs to check whether the chars are of the same
2178- // type.. so a double space or double - might be grouped together,
2179- // but what about a +=1? do + and - get grouped but not the 1? blech,
2180- // coming back to this later. it's not a difficult fix, just a
2181- // time-consuming one to track down all the proper cases.
2182- /*
2183- if (ch == ' ') {
2184- //System.out.println("yeehaa");
2185-
2186- for(int i = offset - 1; i >= 0; i--) {
2187- if (lineText.charAt(i) == ' ') {
2188- wordStart = i;
2189- } else {
2190- break;
2191- }
2192- }
2193- for(int i = offset; i < lineText.length(); i++) {
2194- if (lineText.charAt(i) == ' ') {
2195- wordEnd = i + 1;
2196- } else {
2197- break;
2198- }
2199- }
2200-
2201- } else {
2202- */
2203-
2204- // If the user clicked on a non-letter char,
2205- // we select the surrounding non-letters
2206- boolean selectNoLetter = (!Character .isLetterOrDigit (ch )
2207- && noWordSep .indexOf (ch ) == -1 );
2208-
2209- for (int i = offset - 1 ; i >= 0 ; i --) {
2210- ch = lineText .charAt (i );
2211- if (selectNoLetter ^ (!Character .isLetterOrDigit (ch ) &&
2212- noWordSep .indexOf (ch ) == -1 )) {
2213- wordStart = i + 1 ;
2214- break ;
2215- }
2216- }
2217-
2218- for (int i = offset ; i < lineText .length (); i ++) {
2219- ch = lineText .charAt (i );
2220- if (selectNoLetter ^ (!Character .isLetterOrDigit (ch ) &&
2221- noWordSep .indexOf (ch ) == -1 )) {
2222- wordEnd = i ;
2223- break ;
2224- }
2225- }
2226- //}
2227-
2228- int lineStart = getLineStartOffset (line );
2229- select (lineStart + wordStart ,lineStart + wordEnd );
2281+ setNewSelectionWord ( line , offset );
2282+ select (newSelectionStart ,newSelectionEnd );
2283+ selectWord = true ;
2284+ selectionAncorStart = selectionStart ;
2285+ selectionAncorEnd = selectionEnd ;
22302286
22312287 /*
22322288 String lineText = getLineText(line);
@@ -2242,7 +2298,10 @@ private void doDoubleClick(MouseEvent evt, int line,
22422298 private void doTripleClick (MouseEvent evt , int line ,
22432299 int offset , int dot )
22442300 {
2245- select (getLineStartOffset (line ),getLineStopOffset (line )-1 );
2301+ selectLine = true ;
2302+ select (getLineStartOffset (line ),getSafeLineStopOffset (line ));
2303+ selectionAncorStart = selectionStart ;
2304+ selectionAncorEnd = selectionEnd ;
22462305 }
22472306 }
22482307
0 commit comments