@@ -834,6 +834,17 @@ public int getLineStopOffset(int line)
834
834
return lineElement .getEndOffset ();
835
835
}
836
836
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
+
837
848
/**
838
849
* Returns the length of the specified line.
839
850
* @param line The line
@@ -1144,7 +1155,7 @@ public void select(int start, int end)
1144
1155
{
1145
1156
throw new IllegalArgumentException ("Bounds out of"
1146
1157
+ " range: " + newStart + "," +
1147
- newEnd );
1158
+ newEnd + " [" + getDocumentLength () + "]" );
1148
1159
}
1149
1160
1150
1161
// If the new position is the same as the old, we don't
@@ -1201,6 +1212,86 @@ public void select(int start, int end)
1201
1212
// getLineOfOffset(end));
1202
1213
}
1203
1214
}
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
+ }
1204
1295
1205
1296
1206
1297
/**
@@ -1684,6 +1775,14 @@ public void processKeyEvent(KeyEvent evt) {
1684
1775
protected int selectionEnd ;
1685
1776
protected int selectionEndLine ;
1686
1777
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 ;
1687
1786
1688
1787
protected int bracketPosition ;
1689
1788
protected int bracketLine ;
@@ -2021,9 +2120,26 @@ public void mouseDragged(MouseEvent evt)
2021
2120
{
2022
2121
if (popup != null && popup .isVisible ()) return ;
2023
2122
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
+ }
2027
2143
}
2028
2144
2029
2145
final Cursor normalCursor = new Cursor (Cursor .DEFAULT_CURSOR );
@@ -2094,6 +2210,9 @@ public void mousePressed(MouseEvent evt)
2094
2210
int offset = xToOffset (line ,evt .getX ());
2095
2211
int dot = getLineStartOffset (line ) + offset ;
2096
2212
2213
+ selectLine = false ;
2214
+ selectWord = false ;
2215
+
2097
2216
switch (evt .getClickCount ()) {
2098
2217
2099
2218
case 1 :
@@ -2159,74 +2278,11 @@ private void doDoubleClick(MouseEvent evt, int line,
2159
2278
bl .printStackTrace ();
2160
2279
}
2161
2280
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 ;
2230
2286
2231
2287
/*
2232
2288
String lineText = getLineText(line);
@@ -2242,7 +2298,10 @@ private void doDoubleClick(MouseEvent evt, int line,
2242
2298
private void doTripleClick (MouseEvent evt , int line ,
2243
2299
int offset , int dot )
2244
2300
{
2245
- select (getLineStartOffset (line ),getLineStopOffset (line )-1 );
2301
+ selectLine = true ;
2302
+ select (getLineStartOffset (line ),getSafeLineStopOffset (line ));
2303
+ selectionAncorStart = selectionStart ;
2304
+ selectionAncorEnd = selectionEnd ;
2246
2305
}
2247
2306
}
2248
2307
0 commit comments