1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.RE; 25 import gnu.regexp.REMatch; 26 import gnu.regexp.UncheckedRE; 27 import java.io.IOException ; 28 import java.io.OutputStream ; 29 import javax.swing.undo.CompoundEdit ; 30 import org.armedbear.j.mail.Base64Decoder; 31 32 public final class RegionCommands 33 { 34 public static void detabRegion() 35 { 36 detabOrEntabRegion(false); 37 } 38 39 public static void entabRegion() 40 { 41 detabOrEntabRegion(true); 42 } 43 44 private static void detabOrEntabRegion(boolean entab) 45 { 46 final Editor editor = Editor.currentEditor(); 47 final Position mark = editor.getMark(); if (mark == null) 49 return; 50 editor.setWaitCursor(); 51 final Buffer buffer = editor.getBuffer(); 52 final int count = Editor.getEditorCount(); 53 Editor[] editors = new Editor[count]; 54 int[] dotCol = new int[count]; 55 int[] markCol = new int[count]; 56 int i = 0; 57 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 58 Editor ed = it.nextEditor(); 59 editors[i] = ed; 60 if (ed.getBuffer() == buffer) { 61 dotCol[i] = ed.getDotCol(); 62 if (ed.getMark() != null) 63 markCol[i] = buffer.getCol(ed.getMark()); 64 } 65 ++i; 66 } 67 final Region r = new Region(editor); 68 final int tabWidth = buffer.getTabWidth(); 69 try { 70 buffer.lockWrite(); 71 } 72 catch (InterruptedException e) { 73 Log.error(e); 74 return; 75 } 76 try { 77 detabOrEntabRegion(editor, buffer, r, entab, tabWidth); 78 } 79 finally { 80 buffer.unlockWrite(); 81 } 82 for (i = 0; i < count; i++) { 83 Editor ed = editors[i]; 84 if (ed.getBuffer() == buffer) { 85 ed.moveDotToCol(dotCol[i]); 86 if (ed.getMark() != null) 87 ed.getMark().moveToCol(markCol[i], tabWidth); 88 } 89 } 90 buffer.repaint(); 91 editor.setDefaultCursor(); 92 } 93 94 private static void detabOrEntabRegion(Editor editor, Buffer buffer, 95 Region r, boolean entab, int tabWidth) 96 { 97 CompoundEdit compoundEdit = new CompoundEdit (); 98 compoundEdit.addEdit(new UndoMove(editor)); 99 boolean changed = false; 100 final Line beginLine = r.getBeginLine(); 101 final int beginOffset = r.getBeginOffset(); 102 final Line endLine = r.getEndLine(); 103 final int endOffset = r.getEndOffset(); 104 final int startCol = buffer.getCol(beginLine, beginOffset); 105 if (beginLine == endLine) { 106 final String oldText = beginLine.getText(); 107 final String head = oldText.substring(0, beginOffset); 108 final String toBeChanged = oldText.substring(beginOffset, 109 endOffset); 110 final String tail = oldText.substring(endOffset); 111 FastStringBuffer sb = new FastStringBuffer(head); 112 if (entab) 113 sb.append(Utilities.entab(toBeChanged, tabWidth, startCol)); 114 else 115 sb.append(Utilities.detab(toBeChanged, tabWidth, startCol)); 116 sb.append(tail); 117 final String newText = sb.toString(); 118 if (!newText.equals(oldText)) { 119 compoundEdit.addEdit(new UndoLineEdit(buffer, beginLine)); 120 beginLine.setText(newText); 121 changed = true; 122 } 123 } else { 124 String oldText = beginLine.getText(); 126 final String head = oldText.substring(0, beginOffset); 127 String toBeChanged = oldText.substring(beginOffset); 128 FastStringBuffer sb = new FastStringBuffer(head); 129 if (entab) 130 sb.append(Utilities.entab(toBeChanged, tabWidth, startCol)); 131 else 132 sb.append(Utilities.detab(toBeChanged, tabWidth, startCol)); 133 String newText = sb.toString(); 134 if (!newText.equals(oldText)) { 135 compoundEdit.addEdit(new UndoLineEdit(buffer, beginLine)); 136 beginLine.setText(newText); 137 changed = true; 138 } 139 140 Line line = beginLine.next(); 142 while (line != null && line != endLine) { 143 oldText = line.getText(); 144 if (entab) 145 newText = Utilities.entab(oldText, tabWidth); 146 else 147 newText = Utilities.detab(oldText, tabWidth); 148 if (!newText.equals(oldText)) { 149 compoundEdit.addEdit(new UndoLineEdit(buffer, line)); 150 line.setText(newText); 151 changed = true; 152 } 153 line = line.next(); 154 } 155 156 oldText = endLine.getText(); 158 toBeChanged = oldText.substring(0, endOffset); 159 final String tail = oldText.substring(endOffset); 160 sb.setLength(0); 161 if (entab) 162 sb.append(Utilities.entab(toBeChanged, tabWidth)); 163 else 164 sb.append(Utilities.detab(toBeChanged, tabWidth)); 165 sb.append(tail); 166 newText = sb.toString(); 167 if (!newText.equals(oldText)) { 168 compoundEdit.addEdit(new UndoLineEdit(buffer, endLine)); 169 endLine.setText(newText); 170 changed = true; 171 } 172 } 173 if (changed) { 174 compoundEdit.end(); 175 buffer.addEdit(compoundEdit); 176 buffer.modified(); 177 } 178 } 179 180 public static void upperCaseRegion() 181 { 182 final Editor editor = Editor.currentEditor(); 183 editor.setWaitCursor(); 184 changeCaseRegion(editor, true); 185 editor.setDefaultCursor(); 186 } 187 188 public static void lowerCaseRegion() 189 { 190 final Editor editor = Editor.currentEditor(); 191 editor.setWaitCursor(); 192 changeCaseRegion(editor, false); 193 editor.setDefaultCursor(); 194 } 195 196 private static void changeCaseRegion(Editor editor, boolean toUpper) 197 { 198 if (!editor.checkReadOnly()) 199 return; 200 if (editor.getDot() == null || editor.getMark() == null) 201 return; 202 if (editor.getDot().equals(editor.getMark())) 203 return; 204 final Buffer buffer = editor.getBuffer(); 205 206 boolean hard = editor.getDotLine() != editor.getMarkLine(); 208 209 try { 210 buffer.lockWrite(); 211 } 212 catch (InterruptedException e) { 213 Log.error(e); 214 return; 215 } 216 try { 217 CompoundEdit compoundEdit = editor.beginCompoundEdit(); 218 editor.addUndo(SimpleEdit.MOVE); 219 final Region r = new Region(editor); 220 final String s = r.toString(); 221 editor.getDot().moveTo(r.getBegin()); 222 223 editor.addUndoDeleteRegion(r); 226 227 r.delete(); 229 230 editor.addUndo(SimpleEdit.INSERT_STRING); 231 editor.insertStringInternal(toUpper ? s.toUpperCase() : s.toLowerCase()); 232 editor.endCompoundEdit(compoundEdit); 233 editor.moveCaretToDotCol(); 234 if (hard) 235 buffer.repaint(); 236 else 237 Editor.updateInAllEditors(editor.getDotLine()); 238 editor.setMark(null); 239 } 240 finally { 241 buffer.unlockWrite(); 242 } 243 } 244 245 public static void decodeRegion() 246 { 247 final Editor editor = Editor.currentEditor(); 248 ByteBuffer bb = new ByteBuffer(); 249 if (editor.getMark() != null) { 250 if (editor.getMarkOffset() == 0 && editor.getDotOffset() == 0) { 251 Region r = new Region(editor); 252 for (Line line = r.getBeginLine(); line != r.getEndLine(); line = line.next()) { 253 byte[] decodedBytes = decodeLine(line); 254 if (decodedBytes == null) { 255 MessageDialog.showMessageDialog("Unable to decode region", "Decode Region"); 256 return; 257 } 258 bb.append(decodedBytes); 259 } 260 } else { 261 MessageDialog.showMessageDialog("Region must consist of whole lines only.", "Decode Region"); 262 return; 263 } 264 } else { 265 byte[] decodedBytes = decodeLine(editor.getDotLine()); 266 if (decodedBytes == null) { 267 MessageDialog.showMessageDialog("Unable to decode region", "Decode Region"); 268 return; 269 } 270 bb.append(decodedBytes); 271 } 272 byte[] bytes = bb.getBytes(); 273 final int length = bb.length(); 274 boolean isBinary = false; 275 for (int i = 0; i < length; i++) { 276 byte b = bytes[i]; 277 if (b == 0) { 278 isBinary = true; 279 break; 280 } 281 } 282 if (isBinary) { 283 SaveFileDialog d = new SaveFileDialog(editor, "Save As"); 284 editor.centerDialog(d); 285 d.show(); 286 File saveAs = d.getDestination(); 287 if (saveAs == null) 288 return; 289 try { 292 OutputStream out = saveAs.getOutputStream(); 293 if (out != null) { 294 out.write(bytes, 0, length); 295 out.flush(); 296 out.close(); 297 } 298 } 299 catch (IOException e) { 300 Log.error(e); 301 } 302 } else { 303 Buffer buf = new Buffer(0); 304 buf.setText(new String (bytes, 0, length)); 305 editor.makeNext(buf); 306 editor.activate(buf); 307 } 308 } 309 310 private static final byte[] decodeLine(Line line) 311 { 312 return Base64Decoder.decode(line.trim()); 313 } 314 315 public static void renumberRegion() 316 { 317 renumberRegion(null); 318 } 319 320 public static void renumberRegion(String arg) 321 { 322 final Editor editor = Editor.currentEditor(); 323 if (editor.getMark() == null) 324 return; 325 final Region region = new Region(editor); 326 if (region.getEndLineNumber() - region.getBeginLineNumber() < 2) 327 return; 328 if (!editor.checkReadOnly()) 329 return; 330 int start = -1; 331 if (arg != null) { 332 try { 333 start = Integer.parseInt(arg); 334 } 335 catch (NumberFormatException e) { 336 MessageDialog.showMessageDialog( 337 "Invalid number \"" + arg + '"', 338 "Error"); 339 return; 340 } 341 } 342 final Buffer buffer = editor.getBuffer(); 343 try { 344 buffer.lockWrite(); 345 } 346 catch (InterruptedException e) { 347 Log.error(e); 348 return; 349 } 350 try { 351 _renumberRegion(editor, buffer, region, start); 352 } 353 finally { 354 buffer.unlockWrite(); 355 } 356 } 357 358 private static void _renumberRegion(Editor editor, Buffer buffer, 359 Region region, int start) 360 { 361 CompoundEdit compoundEdit = null; 362 if (start < 0) { 363 for (Line line = region.getBeginLine(); line != region.getEndLine(); line = line.next()) { 364 final String text = line.getText(); 365 int index = findNumber(text, buffer.getMode()); 366 if (index >= 0) { 367 FastStringBuffer sb = new FastStringBuffer(); 368 while (index < text.length()) { 369 char c = text.charAt(index++); 370 if (c >= '0' && c <= '9') 371 sb.append(c); 372 else 373 break; 374 } 375 try { 376 int n = Integer.parseInt(sb.toString()); 377 if (start < 0) 378 start = n; 379 else if (n < start) 380 start = n; 381 } 382 catch (NumberFormatException e) { 383 Log.error(e); 384 } 385 } 386 } 387 } 388 for (Line line = region.getBeginLine(); line != region.getEndLine(); line = line.next()) { 389 final String text = line.getText(); 390 int index = findNumber(text, buffer.getMode()); 391 if (index < 0) 392 continue; 393 FastStringBuffer sb = new FastStringBuffer(text.substring(0, index)); 394 while (index < text.length() && Character.isDigit(text.charAt(index))) 395 ++index; 396 sb.append(start++); 397 sb.append(text.substring(index)); 398 String newText = sb.toString(); 399 if (!newText.equals(text)) { 400 if (compoundEdit == null) { 401 compoundEdit = new CompoundEdit (); 402 compoundEdit.addEdit(new UndoMove(editor)); 403 } 404 compoundEdit.addEdit(new UndoLineEdit(buffer, line)); 405 line.setText(newText); 406 } 407 } 408 if (compoundEdit != null) { 409 compoundEdit.end(); 410 buffer.addEdit(compoundEdit); 411 buffer.modified(); 412 } 413 buffer.setNeedsParsing(true); 414 buffer.getFormatter().parseBuffer(); 415 buffer.repaint(); 416 } 417 418 private static int findNumber(String text, Mode mode) 419 { 420 RE re = new UncheckedRE("[0-9]+"); 421 int index = 0; 422 int limit = text.length(); 423 while (index <= limit) { 424 REMatch match = re.getMatch(text, index); 425 if (match == null) 426 return -1; 427 if (isDelimited(text, match.getStartIndex(), match.toString().length(), mode)) 428 return match.getStartIndex(); 429 index = match.getStartIndex() + 1; 430 } 431 return -1; 432 } 433 434 private static boolean isDelimited(String text, int index, int length, Mode mode) 435 { 436 final int before = index - 1; 437 if (before >= 0 && mode.isIdentifierPart(text.charAt(before))) 438 return false; 439 final int after = index + length; 440 if (after < text.length() && mode.isIdentifierPart(text.charAt(after))) 441 return false; 442 return true; 443 } 444 445 public void doShellCommandOnRegion() 446 { 447 if (!Editor.checkExperimental()) 448 return; 449 final Editor editor = Editor.currentEditor(); 450 if (!editor.checkReadOnly()) 451 return; 452 if (editor.getMark() == null) { 453 MessageDialog.showMessageDialog(editor, "No region selected", 454 "Error"); 455 return; 456 } 457 InputDialog d = new InputDialog(editor, "Command:", 458 "Do Shell Command On Region", null); 459 d.setHistory(new History("doShellCommandOnRegion")); 460 editor.centerDialog(d); 461 d.show(); 462 String command = d.getInput(); 463 if (command == null || command.length() == 0) 464 return; 465 editor.setWaitCursor(); 466 Region r = new Region(editor); 467 ShellCommand shellCommand = 470 new ShellCommand(command, null, r.toString()); 471 shellCommand.run(); 472 String output = shellCommand.getOutput(); 473 if (output != null && output.length() > 0) { 474 CompoundEdit compoundEdit = editor.beginCompoundEdit(); 475 editor.deleteRegion(); 476 editor.addUndo(SimpleEdit.INSERT_STRING); 477 editor.insertStringInternal(output); 478 editor.moveCaretToDotCol(); 479 editor.endCompoundEdit(compoundEdit); 480 if (editor.getFormatter().parseBuffer()) 481 editor.getBuffer().repaint(); 482 } 483 editor.setDefaultCursor(); 484 } 485 } 486 | Popular Tags |