1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.RE; 25 import gnu.regexp.REMatch; 26 import gnu.regexp.RESyntax; 27 import gnu.regexp.UncheckedRE; 28 import java.awt.AWTEvent ; 29 import java.awt.event.MouseEvent ; 30 import java.io.BufferedReader ; 31 import java.io.IOException ; 32 import java.io.InputStreamReader ; 33 import java.io.StringReader ; 34 import java.util.ArrayList ; 35 import java.util.Collections ; 36 import java.util.Comparator ; 37 import java.util.List ; 38 import java.util.Vector ; 39 import javax.swing.Icon ; 40 import javax.swing.SwingUtilities ; 41 42 public final class Directory extends Buffer 43 { 44 private static final Preferences preferences = Editor.preferences(); 45 46 private boolean usingNativeFormat; 48 49 public static final int SORT_BY_NAME = 0; 50 public static final int SORT_BY_DATE = 1; 51 public static final int SORT_BY_SIZE = 2; 52 53 private int sortBy = SORT_BY_NAME; 54 55 private String limitPattern; 56 57 private ArrayList entries = new ArrayList (); 58 59 private int numMarked = 0; 60 61 private DirectoryHistory history = new DirectoryHistory(); 62 63 private static final RE nativeMoveToFilenameRegExp; 64 private static final RE internalMoveToFilenameRegExp; 65 66 private boolean loadError; 67 68 static { 69 final String letter = "[[:alpha:]]"; 71 72 final String month = letter + letter + "+"; 74 75 final String yyyy = "[0-9][0-9][0-9][0-9]"; 77 78 final String dd = "[ 0-3][0-9][.]?"; 80 81 final String monthAndDay = 83 "(" + month + " *" + dd + " " + "|" + dd + " " + month + " *" + ")"; 84 85 final String HHMM = "[ 0-2][0-9]:[0-5][0-9]"; 87 88 final String timeOrYear = 90 "(" + HHMM + "|" + " " + yyyy + "|" + yyyy + " " + ")"; 91 92 RESyntax syntax = new RESyntax(RESyntax.RE_SYNTAX_PERL5); 93 syntax.set(RESyntax.RE_CHAR_CLASSES); 94 95 String traditional = "[0-9]+" + " " + monthAndDay + timeOrYear + " "; 96 97 final String isoMaybeYear = "(" + yyyy + "-)?"; 103 final String isoMonthAndDay = "[01][0-9]-[0-3][0-9]"; 104 final String isoMaybeTime = "(" + HHMM + ")?"; 105 String iso = "[0-9]+" + " " + isoMaybeYear + isoMonthAndDay + " " + 106 isoMaybeTime + " *"; 107 108 String osx = "[0-9]+" + " " + dd + " " + month + " " + timeOrYear + " "; 114 115 nativeMoveToFilenameRegExp = 116 new UncheckedRE("(" + traditional + ")|(" + iso + ")|(" + osx + ")", 117 0, 118 syntax); 119 120 internalMoveToFilenameRegExp = new UncheckedRE(":[0-5][0-9]" + " "); 121 } 122 123 public static final RE getNativeMoveToFilenameRegExp() 124 { 125 return nativeMoveToFilenameRegExp; 126 } 127 128 public static final RE getInternalMoveToFilenameRegExp() 129 { 130 return internalMoveToFilenameRegExp; 131 } 132 133 public Directory(File dir) 134 { 135 super(); 136 supportsUndo = false; 137 setFile(dir); 138 type = TYPE_DIRECTORY; 139 readOnly = true; 140 mode = DirectoryMode.getMode(); 141 formatter = mode.getFormatter(this); 142 setInitialized(true); 143 } 144 145 public Directory(File dir, String listing) 146 { 147 this(dir); 148 setListing(listing); 149 } 150 151 public final boolean isUsingNativeFormat() 152 { 153 return usingNativeFormat; 154 } 155 156 public File getCurrentDirectory() 157 { 158 return getFile(); 159 } 160 161 public int getSortBy() 162 { 163 return sortBy; 164 } 165 166 public Position getInitialDotPos() 167 { 168 Line line = getFirstLine(); 169 Line upLine = null; while (true) { 171 if (line.next() == null) 172 break; 173 String name = getName(line); 174 if (name != null) { 175 if (name.equals("..")) 176 upLine = line; 177 else if (!name.equals(".")) 178 return new Position(line, getNameOffset(line)); 179 } 180 line = line.next(); 181 } 182 if (upLine != null) 184 return new Position(upLine, getNameOffset(upLine)); 185 else 186 return new Position(line, getNameOffset(line)); 187 } 188 189 private void setLimitPattern(String s) 190 { 191 if (s == null || s.length() == 0) 192 limitPattern = null; 193 else 194 limitPattern = s; 195 } 196 197 public final String getLimitPattern() 198 { 199 return limitPattern; 200 } 201 202 public static void dirLimit() 203 { 204 final Editor editor = Editor.currentEditor(); 205 final Buffer buffer = editor.getBuffer(); 206 if (buffer instanceof Directory) { 207 Directory directory = (Directory) buffer; 208 InputDialog dialog = new InputDialog(editor, "Pattern:", "Limit", 209 directory.getLimitPattern()); 210 dialog.setHistory(new History("dirLimit")); 211 editor.centerDialog(dialog); 212 dialog.show(); 213 String pattern = dialog.getInput(); 214 if (pattern != null) { 216 editor.repaintNow(); 217 directory.limit(pattern); 218 } 219 } 220 } 221 222 public static void dirLimit(String pattern) 223 { 224 final Editor editor = Editor.currentEditor(); 225 final Buffer buffer = editor.getBuffer(); 226 if (buffer instanceof Directory) 227 ((Directory)buffer).limit(pattern); 228 } 229 230 public static void dirUnlimit() 231 { 232 final Editor editor = Editor.currentEditor(); 233 final Buffer buffer = editor.getBuffer(); 234 if (buffer instanceof Directory) { 235 Directory directory = (Directory) buffer; 236 if (directory.getLimitPattern() != null) 237 directory.limit(null); 238 } 239 } 240 241 private void limit(String pattern) 242 { 243 if (pattern != null) { 244 pattern = pattern.trim(); 245 if (pattern.length() == 0) 246 pattern = null; 247 } 248 boolean reload = false; 249 if (pattern == null && limitPattern != null) 250 reload = true; 251 else if (pattern != null && !pattern.equals(limitPattern)) 252 reload = true; 253 if (reload) { 254 final Editor editor = Editor.currentEditor(); 255 editor.setWaitCursor(); 256 String name = null; 257 Line dotLine = editor.getDotLine(); 258 if (dotLine instanceof DirectoryLine) 259 name = getName(dotLine); 260 setLimitPattern(pattern); 261 if (getListing() != null) 262 reloadFromListing(); 263 else 264 reload(); 265 Line line = findName(name); 266 Position pos; 267 if (line != null) 268 pos = new Position(line, getNameOffset(line)); 269 else 270 pos = getInitialDotPos(); 271 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 272 Editor ed = it.nextEditor(); 273 if (ed.getBuffer() == this) { 274 ed.setTopLine(getFirstLine()); 275 ed.setDot(pos); 276 ed.setMark(null); 277 ed.moveCaretToDotCol(); 278 ed.setUpdateFlag(REFRAME | REPAINT); 279 } 280 } 281 editor.setDefaultCursor(); 282 } 283 } 284 285 public void rescan() 286 { 287 final File file = getFile(); 288 if (file.isRemote()) 289 DirectoryCache.getDirectoryCache().purge(file.getHostName()); 290 reload(); 291 if (loadError) 292 return; 293 boolean rescanned = false; 294 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 295 Editor ed = it.nextEditor(); 296 if (ed.getBuffer() == this) { 297 if (ed.getSidebar() != null) { 298 NavigationComponent c = ed.getSidebar().getBottomComponent(); 299 if (c instanceof DirectoryTree) { 300 DirectoryTree tree = (DirectoryTree) c; 301 DirectoryTreeModel treeModel = tree.getTreeModel(); 302 if (!rescanned) { 303 treeModel.rescan(file); 304 rescanned = true; 305 } 306 tree.refresh(); 307 } 308 } 309 } 310 } 311 } 312 313 public synchronized void reload() 314 { 315 ArrayList editors = new ArrayList (); 316 317 ArrayList names = new ArrayList (); 319 320 ArrayList lineNumbers = new ArrayList (); 322 323 ArrayList topLineNumbers = new ArrayList (); 325 326 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 327 Editor ed = it.nextEditor(); 328 String name = null; 329 int lineNumber = 0; 330 int topLineNumber = 0; 331 if (ed.getBuffer() == this) { 332 name = getName(ed.getDotLine()); 333 lineNumber = ed.getDotLineNumber(); 334 topLineNumber = ed.getDisplay().getTopLineNumber(); 335 } 336 editors.add(ed); 337 names.add(name); 338 lineNumbers.add(new Integer (lineNumber)); 339 topLineNumbers.add(new Integer (topLineNumber)); 340 } 341 342 empty(); 343 entries.clear(); 344 numMarked = 0; 345 setListing(null); 346 347 load(); 348 349 for (int i = 0; i < editors.size(); i++) { 351 final Editor ed = (Editor) editors.get(i); 352 if (ed.getBuffer() == this) { 353 Line dotLine = findName((String )names.get(i)); 354 if (dotLine == null) { 355 dotLine = 356 getLine(((Integer )lineNumbers.get(i)).intValue()); 357 if (dotLine == null) { 358 if (getFirstLine() == null) { 359 Debug.bug(); 360 appendLine(""); 361 } 362 dotLine = getFirstLine(); 363 while (dotLine.next() != null) 364 dotLine = dotLine.next(); 365 } 366 } 367 ed.setDot(dotLine, getNameOffset(dotLine)); 368 ed.setMark(null); 369 final Display display = ed.getDisplay(); 370 display.setShift(0); 371 display.moveCaretToDotCol(); 372 373 Line line = 374 getLine(((Integer )topLineNumbers.get(i)).intValue()); 375 if (line == null) { 376 Debug.assertTrue(getFirstLine() != null); 377 line = getFirstLine(); 378 while (line.next() != null) 379 line = line.next(); 380 } 381 display.setTopLine(line); 382 display.setUpdateFlag(REPAINT); 383 ed.updateLocation(); 384 } 385 } 386 } 387 388 private synchronized void reloadFromListing() 389 { 390 Debug.assertTrue(getListing() != null); 391 empty(); 392 entries.clear(); 393 numMarked = 0; 394 load(); 395 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 396 Editor ed = it.nextEditor(); 397 if (ed.getBuffer() == this) { 398 final Line line = getFirstLine(); 399 ed.setDot(line, getNameOffset(line)); 400 ed.setMark(null); 401 final Display display = ed.getDisplay(); 402 display.setShift(0); 403 display.moveCaretToDotCol(); 404 display.setTopLine(getFirstLine()); 405 display.setUpdateFlag(REPAINT); 406 ed.updateLocation(); 407 } 408 } 409 } 410 411 private void addEntry(String name) 413 { 414 Debug.assertTrue(!usingNativeFormat); 415 File f = File.getInstance(getFile(), name); 416 if (f == null) 417 return; 418 DirectoryEntry de; 419 if (f.isDirectory()) 420 de = new DirectoryEntry(name, f.lastModified(), 0, true); 421 else 422 de = new DirectoryEntry(name, f.lastModified(), f.length()); 423 if (!name.equals(".") && !name.equals("..")) { 424 try { 425 String cp = f.getCanonicalPath(); 426 String ap = f.getAbsolutePath(); 427 if (!cp.equals(ap)) { 428 final String canonicalPath = getFile().canonicalPath(); 429 if (cp.startsWith(canonicalPath + LocalFile.getSeparator())) 430 de.setLinkedTo(cp.substring(canonicalPath.length()+1)); 431 else 432 de.setLinkedTo(cp); 433 } 434 } 435 catch (IOException e) { 436 Log.error(e); 437 } 438 } 439 entries.add(de); 440 } 441 442 private final void appendLine(DirectoryEntry entry) 443 { 444 appendLine(new DirectoryLine(entry)); 445 } 446 447 private synchronized DirectoryEntry findEntry(String name) 448 { 449 for (int i = 0; i < entries.size(); i++) { 450 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 451 if (name.equals(entry.getName())) 452 return entry; 453 } 454 return null; 455 } 456 457 private synchronized DirectoryEntry findNativeEntry(String string) 458 { 459 for (int i = 0; i < entries.size(); i++) { 460 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 461 if (string.equals(entry.getString())) 462 return entry; 463 } 464 return null; 465 } 466 467 private synchronized void sort() 468 { 469 if (usingNativeFormat) { 470 Debug.bug(); 471 return; 472 } 473 if (sortBy == SORT_BY_NAME) 474 sortByName(); 475 else if (sortBy == SORT_BY_DATE) 476 sortByDate(); 477 else if (sortBy == SORT_BY_SIZE) 478 sortBySize(); 479 } 480 481 private void sortByName() 483 { 484 Debug.assertTrue(!usingNativeFormat); 485 Comparator comparator = new Comparator () { 486 public int compare(Object o1, Object o2) 487 { 488 String name1 = ((DirectoryEntry)o1).getName(); 489 String name2 = ((DirectoryEntry)o2).getName(); 490 return name1.compareToIgnoreCase(name2); 491 } 492 }; 493 Collections.sort(entries, comparator); 494 } 495 496 private void sortByDate() { 498 Comparator comparator = new Comparator () { 499 public int compare(Object o1, Object o2) 500 { 501 long date1 = ((DirectoryEntry)o1).getDate(); 503 long date2 = ((DirectoryEntry)o2).getDate(); 504 if (date1 > date2) 505 return -1; 506 if (date1 < date2) 507 return 1; 508 return 0; 509 } 510 }; 511 Collections.sort(entries, comparator); 512 } 513 514 private void sortBySize() 516 { 517 Comparator comparator = new Comparator () { 518 public int compare(Object o1, Object o2) 519 { 520 long size1 = ((DirectoryEntry)o1).getSize(); 522 long size2 = ((DirectoryEntry)o2).getSize(); 523 if (size1 > size2) 524 return -1; 525 if (size1 < size2) 526 return 1; 527 return 0; 528 } 529 }; 530 Collections.sort(entries, comparator); 531 } 532 533 private void addEntriesToBuffer() 535 { 536 final int size = entries.size(); 537 if (preferences.getBooleanProperty(Property.DIR_SORT_DIRECTORIES_FIRST, !usingNativeFormat)) { 538 for (int i = 0; i < size; i++) { 540 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 541 if (entry.isDirectory()) 542 appendLine(entry); 543 } 544 for (int i = 0; i < size; i++) { 545 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 546 if (!entry.isDirectory()) 547 appendLine(entry); 548 } 549 } else { 550 for (int i = 0; i < size; i++) { 551 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 552 appendLine(entry); 553 } 554 } 555 if (getFirstLine() == null) 556 appendLine(""); 557 setLoaded(true); 558 } 559 560 public static void dirCycleSortBy() 561 { 562 final Editor editor = Editor.currentEditor(); 563 final Buffer buffer = editor.getBuffer(); 564 if (buffer instanceof Directory) { 565 editor.setWaitCursor(); 566 ((Directory)buffer).cycleSortBy(); 567 editor.setDefaultCursor(); 568 } 569 } 570 571 private synchronized void cycleSortBy() 572 { 573 if (sortBy == SORT_BY_NAME) 574 sortBy = SORT_BY_DATE; 575 else if (sortBy == SORT_BY_DATE) 576 sortBy = SORT_BY_SIZE; 577 else 578 sortBy = SORT_BY_NAME; 579 resort(); 580 } 581 582 public void resort(int sortBy) 583 { 584 if (this.sortBy != sortBy) { 585 this.sortBy = sortBy; 586 resort(); 587 } 588 } 589 590 private void resort() 591 { 592 if (usingNativeFormat) { 593 reload(); 594 } else { 595 sort(); 596 try { 597 lockWrite(); 598 } 599 catch (InterruptedException e) { 600 Log.error(e); 601 return; } 603 try { 604 empty(); 605 addEntriesToBuffer(); 606 renumber(); 607 } 608 finally { 609 unlockWrite(); 610 } 611 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 612 Editor ed = it.nextEditor(); 613 if (ed.getBuffer() == this) { 614 ed.setDot(getFirstLine(), 0); 615 ed.setMark(null); 616 final Display display = ed.getDisplay(); 617 display.setTopLine(getFirstLine()); 618 display.setShift(0); 619 display.setCaretCol(0); 620 display.setUpdateFlag(REPAINT); 621 ed.updateLocation(); 622 } 623 } 624 } 625 } 626 627 private synchronized void loadInternal() 628 { 629 boolean useNativeFormat = 631 preferences.getBooleanProperty(Property.DIR_USE_NATIVE_FORMAT, 632 Platform.isPlatformUnix()); 633 if (useNativeFormat) { 634 if (!Utilities.haveLs()) 635 useNativeFormat = false; 636 } 637 loadError = false; 638 try { 639 final DirectoryFilenameFilter dff; 640 if (limitPattern != null) 641 dff = new DirectoryFilenameFilter(limitPattern); 642 else 643 dff = null; 644 final File file = getFile(); 645 if (useNativeFormat || file.isRemote()) { 646 usingNativeFormat = true; 647 String flags = "-la"; if (sortBy == SORT_BY_DATE) 649 flags = "-lat"; 650 else if (sortBy == SORT_BY_SIZE) 651 flags = "-laS"; 652 String extraOptions = 653 getStringProperty(Property.LS_EXTRA_OPTIONS); 654 if (extraOptions != null) { 655 flags += " "; 656 flags += extraOptions; 657 Log.debug("Directory.loadInternal flags = " + flags); 658 } 659 BufferedReader reader = null; 660 if (getListing() != null) { 661 reader = new BufferedReader (new StringReader (getListing())); 662 } else if (file instanceof FtpFile || file instanceof SshFile) { 663 setListing(file.getDirectoryListing()); 664 if (getListing() != null) 665 reader = new BufferedReader (new StringReader (getListing())); 666 else 667 loadError = true; 668 } else { 669 Process process = null; 671 if (Platform.isPlatformUnix()) { 672 String cmd = 673 "(\\cd \"" + file.canonicalPath() + "\" && \\ls " + 674 flags + ")"; 675 String [] cmdarray = {"/bin/sh", "-c", cmd}; 676 process = Runtime.getRuntime().exec(cmdarray); 677 } else { 678 String cp = file.canonicalPath(); 680 if (cp.length() == 3 && cp.charAt(1) == ':' && cp.charAt(2) == '\\') 682 cp = "//" + Character.toLowerCase(cp.charAt(0)); 683 String [] cmdarray = {"ls", flags, cp}; 684 process = Runtime.getRuntime().exec(cmdarray); 685 } 686 reader = 687 new BufferedReader (new InputStreamReader (process.getInputStream())); 688 } 689 if (reader != null) { 690 String s; 691 while ((s = reader.readLine()) != null) { 692 DirectoryEntry entry = 693 DirectoryEntry.getDirectoryEntry(s, dff); 694 if (entry != null) 695 entries.add(entry); 696 } 697 } 698 } else { 699 usingNativeFormat = false; 700 boolean dirIsRoot = false; 701 if (Platform.isPlatformWindows()) { 702 String cp = file.canonicalPath(); 703 if (cp.length() == 3 && cp.endsWith(":\\")) dirIsRoot = true; 705 } 706 if (!dirIsRoot) { 707 addEntry("."); 708 addEntry(".."); 709 } 710 String [] names = file.list(); 711 if (names != null) { 712 if (dff == null) { 713 for (int i = 0; i < names.length; i++) 714 addEntry(names[i]); 715 } else { 716 for (int i = 0; i < names.length; i++) { 717 if (dff.accepts(names[i])) 718 addEntry(names[i]); 719 else { 720 File f = File.getInstance(file, names[i]); 721 if (f != null && f.isDirectory()) 722 addEntry(names[i]); 723 } 724 } 725 } 726 } 727 sort(); 728 } 729 try { 730 lockWrite(); 731 } 732 catch (InterruptedException e) { 733 Log.error(e); 734 return; } 736 try { 737 addEntriesToBuffer(); 738 long totalSize = getTotalSize(); 739 if (totalSize > 0) { 740 int end; 741 if (usingNativeFormat) { 742 end = getFileSizeEndOffset(); 743 if (end <= 0) 744 end = 45; 745 } else { 746 int nameOffset = getNameOffset(); 747 end = nameOffset - 19; 748 if (end <= 0) 749 end = 13; 750 } 751 String s = String.valueOf(totalSize); 752 int begin = end - s.length(); 753 if (begin < 0) 754 begin = 0; 755 FastStringBuffer sb = new FastStringBuffer(80); 756 sb.append(Utilities.spaces(begin)); 757 for (int i = s.length(); i > 0; i--) 758 sb.append('-'); 759 appendLine(sb.toString()); 760 sb.setLength(0); 761 sb.append(Utilities.spaces(begin)); 762 sb.append(s); 763 appendLine(sb.toString()); 764 } 765 renumber(); 766 } 767 finally { 768 unlockWrite(); 769 } 770 } 771 catch (Exception e) { 772 Log.error(e); 773 } 774 } 775 776 private long getTotalSize() 777 { 778 long totalSize = 0; 779 int endOffset = -1; 780 final int limit = entries.size(); 781 for (int i = 0; i < limit; i++) { 782 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 783 long size = entry.getSize(); 784 if (size >= 0) { 785 totalSize += size; 786 continue; 787 } 788 String text = entry.getString(); 789 if (endOffset < 0) { 790 REMatch match = nativeMoveToFilenameRegExp.getMatch(text); 791 if (match != null) { 792 endOffset = text.indexOf(' ', match.getStartIndex()); 794 } 795 if (endOffset < 0) 796 endOffset = 42; 797 } 798 if (endOffset < text.length()) { 799 int end; 800 if (text.charAt(endOffset) == ' ') { 801 end = endOffset; 803 } else { 804 REMatch match = nativeMoveToFilenameRegExp.getMatch(text); 806 if (match == null) 807 return totalSize = -1; 808 end = text.indexOf(' ', match.getStartIndex()); 809 if (end < endOffset) { 810 endOffset = end; 812 Log.debug("endOffset = " + endOffset); 813 } 814 } 815 int begin = text.lastIndexOf(' ', end - 1); 816 if (begin < 0) 817 return -1; 818 try { 819 size = Long.parseLong(text.substring(begin + 1, end)); 820 entry.setSize(size); 821 totalSize += size; 822 } 823 catch (NumberFormatException e) { 824 Log.error(e); 825 return -1; 826 } 827 } else 828 return -1; } 830 return totalSize; 831 } 832 833 public int load() 834 { 835 if (!isLoaded()) { 836 final Editor editor = Editor.currentEditor(); 837 String reading = "Reading directory..."; 838 if (editor != null) 839 editor.status(reading); 840 loadInternal(); 841 if (editor != null) 842 editor.status(reading + "done"); 843 } 844 return LOAD_COMPLETED; 845 } 846 847 public void tagFileAtDot() 848 { 849 final Editor editor = Editor.currentEditor(); 850 Line line = editor.getDotLine(); 851 if (!(line instanceof DirectoryLine)) 852 return; 853 String name = getName(line); 854 if (name == null) 855 return; 856 if (name.equals(".")) 857 return; 858 if (name.equals("..")) 859 return; 860 DirectoryEntry de = null; 861 if (usingNativeFormat) { 862 de = findNativeEntry(line.substring(2)); 864 } else { 865 de = findEntry(name); 866 } 867 if (de != null) { 868 if (de.isMarked()) { 869 de.setMarked(false); 870 --numMarked; 871 } else { 872 de.setMarked(true); 873 ++numMarked; 874 } 875 line.setText(de.toString()); 876 editor.update(line); 877 editor.down(); 878 resetUndo(); 879 } 880 } 881 882 public void upDir() 883 { 884 final Editor editor = Editor.currentEditor(); 885 editor.setWaitCursor(); 886 final File parent = getFile().getParentFile(); 887 if (parent == null) 888 return; 889 history.truncate(); 890 history.append(getFile(), getName(editor.getDotLine()), editor.getDotOffset()); 891 history.reset(); 892 String name = getFile().getName(); 893 setFile(parent); 894 reload(); 895 Line line = findName(name); 896 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 897 Editor ed = it.nextEditor(); 898 if (ed.getBuffer() == this) { 899 if (line != null) 900 ed.setDot(line, getNameOffset(line)); 901 else 902 ed.setDot(getFirstLine(), getNameOffset(getFirstLine())); 903 ed.moveCaretToDotCol(); 904 } 905 } 906 Sidebar.setUpdateFlagInAllFrames(SIDEBAR_REPAINT_BUFFER_LIST); 907 } 908 909 public String getPathAtDot() 910 { 911 Editor editor = Editor.currentEditor(); 912 if (!(editor.getDotLine() instanceof DirectoryLine)) 913 return null; 914 String name = getName(editor.getDotLine()); 915 if (name == null) 916 return null; 917 final File dir = getFile(); 918 if (name.equals(".")) 919 return dir.netPath(); 920 if (name.equals("..")) { 921 File parent = dir.getParentFile(); 922 if (parent == null) 923 return null; 924 else 925 return parent.netPath(); 926 } 927 File file = File.getInstance(dir, name); 928 if (file == null) 929 return null; 930 else 931 return file.netPath(); 932 } 933 934 public static void dir() 935 { 936 final Editor editor = Editor.currentEditor(); 937 final Buffer buffer = editor.getBuffer(); 938 if (buffer instanceof Directory) 939 return; 940 File directory = editor.getCurrentDirectory(); 941 if (directory == null) 942 return; 943 if (directory.getProtocol() == File.PROTOCOL_HTTP) 944 return; 945 Buffer buf = Editor.getBuffer(directory); 947 if (buf != null) { 949 File file = buffer.getFile(); 950 editor.makeNext(buf); 951 editor.switchToBuffer(buf); 952 if (buf instanceof Directory && file != null) { 953 Directory dir = (Directory) buf; 954 Line line = dir.findName(file.getName()); 955 if (line != null) { 956 editor.setDot(new Position(line, dir.getNameOffset(line))); 957 editor.setUpdateFlag(REFRAME); 958 editor.reframe(); 959 } 960 } 961 } 962 } 963 964 public static void dirOpenFile() 965 { 966 _dirOpenFile(false); 967 } 968 969 public static void dirOpenFileAndKillDirectory() 970 { 971 _dirOpenFile(true); 972 } 973 974 private static void _dirOpenFile(boolean killDirectory) 975 { 976 final Editor editor = Editor.currentEditor(); 977 final Buffer buffer = editor.getBuffer(); 978 if (buffer instanceof Directory) { 979 AWTEvent e = editor.getDispatcher().getLastEvent(); 982 if (e instanceof MouseEvent ) 983 editor.mouseMoveDotToPoint((MouseEvent ) e); 984 ((Directory)buffer).openFileAtDot(killDirectory); 985 } 986 } 987 988 private synchronized void openFileAtDot(boolean killDirectory) 989 { 990 final Editor editor = Editor.currentEditor(); 991 editor.setWaitCursor(); 992 if (!(editor.getDotLine() instanceof DirectoryLine)) 993 return; 994 String name = getName(editor.getDotLine()); 995 if (name == null) 996 return; 997 if (name.equals(".")) 998 return; 999 if (name.equals("..")) { 1000 upDir(); 1001 return; 1002 } 1003 final File dir = getFile(); 1004 if (dir.isRemote()) { 1005 String fullpath = dir.canonicalPath(); 1006 if (!fullpath.endsWith("/")) 1007 fullpath += "/"; 1008 fullpath += name; 1009 File newFile = File.getInstance(dir, fullpath); 1010 Buffer buf = Editor.getBufferList().findBuffer(newFile); 1011 if (buf != null) { 1012 editor.makeNext(buf); 1013 editor.activate(buf); 1014 return; 1015 } 1016 DirectoryLine line = (DirectoryLine) editor.getDotLine(); 1017 DirectoryEntry de = line.getDirectoryEntry(); 1018 boolean isDirectory = false; 1019 if (de.isDirectory()) 1020 isDirectory = true; 1021 else if (de.isLink()) 1022 isDirectory = newFile.isDirectory(); 1023 if (isDirectory) { 1024 setBusy(true); 1025 history.truncate(); 1026 history.append(dir, getName(editor.getDotLine()), 1027 editor.getDotOffset()); 1028 history.reset(); 1029 empty(); 1030 entries.clear(); 1031 numMarked = 0; 1032 setListing(null); 1033 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1034 Editor ed = it.nextEditor(); 1035 if (ed.getBuffer() == this) { 1036 ed.setTopLine(null); 1037 ed.setDot(null); 1038 ed.setMark(null); 1039 } 1040 } 1041 setFile(newFile); 1042 Runnable reloadRunnable = new Runnable () { 1043 public void run() 1044 { 1045 load(); 1046 Runnable updateRunnable = new Runnable () { 1047 public void run() 1048 { 1049 setBusy(false); 1050 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1051 Editor ed = it.nextEditor(); 1052 if (ed.getBuffer() == Directory.this) { 1053 ed.setTopLine(getFirstLine()); 1054 ed.setDot(getInitialDotPos()); 1055 ed.setMark(null); 1056 ed.moveCaretToDotCol(); 1057 ed.setUpdateFlag(REPAINT); 1058 ed.updateDisplay(); 1059 ed.updateLocation(); 1060 } 1061 } 1062 Sidebar.setUpdateFlagInAllFrames(SIDEBAR_ALL); 1063 } 1064 }; 1065 SwingUtilities.invokeLater(updateRunnable); 1066 } 1067 }; 1068 new Thread (reloadRunnable).start(); 1069 } else { 1070 if (newFile instanceof FtpFile) 1072 buf = new RemoteBuffer((FtpFile) newFile, 1073 FtpSession.getSession((FtpFile) newFile)); 1074 else if (newFile instanceof SshFile) 1075 buf = new RemoteBuffer(newFile); 1076 else 1077 Debug.assertTrue(false); 1078 editor.makeNext(buf); 1079 editor.activate(buf); 1080 } 1081 return; 1082 } 1083 1084 File f = File.getInstance(getFile(), name); 1086 if (!f.exists()) { 1087 editor.status("File not found"); 1088 return; 1089 } 1090 if (f.isDirectory()) { 1091 changeDirectory(f); 1092 return; 1093 } 1094 Buffer buf = editor.getBuffer(f); 1095 if (buf != null) { 1096 editor.makeNext(buf); 1097 editor.activate(buf); 1098 } 1099 if (killDirectory) 1100 kill(); 1101 } 1102 1103 public synchronized void changeDirectory(File f) 1104 { 1105 if (f.isDirectory()) { 1106 final Editor editor = Editor.currentEditor(); 1107 if (f.isLocal() && !f.canRead()) { 1108 showMessageDialog("Directory is not readable"); 1109 return; 1110 } 1111 final String name; 1112 final int offset; 1113 if (editor.getDot() != null) { 1114 name = getName(editor.getDotLine()); 1115 offset = editor.getDotOffset(); 1116 } else { 1117 name = null; 1118 offset = 0; 1119 } 1120 history.truncate(); 1121 history.append(getFile(), name, offset); 1122 history.reset(); 1123 empty(); 1124 entries.clear(); 1125 numMarked = 0; 1126 setListing(null); 1127 setFile(f); 1128 load(); 1129 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1130 Editor ed = it.nextEditor(); 1131 if (ed.getBuffer() == this) { 1132 ed.setTopLine(getFirstLine()); 1133 ed.setDot(getInitialDotPos()); 1134 ed.setMark(null); 1135 ed.moveCaretToDotCol(); 1136 ed.setUpdateFlag(REPAINT); 1137 ed.updateLocation(); 1138 } 1139 } 1140 Sidebar.setUpdateFlagInAllFrames(SIDEBAR_REPAINT_BUFFER_LIST); 1141 } 1142 } 1143 1144 private synchronized void changeDirectory(DirectoryHistoryEntry entry) 1146 { 1147 empty(); 1148 entries.clear(); 1149 numMarked = 0; 1150 setListing(null); 1151 setFile(entry.file); 1152 load(); 1153 Line line = findName(entry.name); 1154 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1155 Editor ed = it.nextEditor(); 1156 if (ed.getBuffer() == this) { 1157 ed.getDisplay().setTopLine(getFirstLine()); 1158 ed.setUpdateFlag(REPAINT); 1159 if (line != null) 1160 ed.setDot(line, entry.offset); 1161 else 1162 ed.setDot(getFirstLine(), getNameOffset(getFirstLine())); 1163 ed.setMark(null); 1164 ed.moveCaretToDotCol(); 1165 ed.updateLocation(); 1166 } 1167 } 1168 Sidebar.setUpdateFlagInAllFrames(SIDEBAR_REPAINT_BUFFER_LIST); 1169 } 1170 1171 public static void dirBack() 1172 { 1173 final Editor editor = Editor.currentEditor(); 1174 final Buffer buffer = editor.getBuffer(); 1175 if (buffer instanceof Directory) { 1176 editor.setWaitCursor(); 1177 ((Directory)buffer).back(editor); 1178 editor.setDefaultCursor(); 1179 } 1180 } 1181 1182 private void back(Editor editor) 1183 { 1184 boolean atEnd = history.atEnd(); 1185 DirectoryHistoryEntry entry = history.getPrevious(); 1186 if (entry != null) { 1187 if (atEnd) { 1188 String name = getName(editor.getDotLine()); 1189 int offset = editor.getDotOffset(); 1190 history.append(getFile(), name, offset); 1191 } 1192 changeDirectory(entry); 1193 } else 1194 editor.status("Can't go back"); 1195 } 1196 1197 public static void dirForward() 1198 { 1199 final Editor editor = Editor.currentEditor(); 1200 final Buffer buffer = editor.getBuffer(); 1201 if (buffer instanceof Directory) { 1202 editor.setWaitCursor(); 1203 ((Directory)buffer).forward(editor); 1204 editor.setDefaultCursor(); 1205 } 1206 } 1207 1208 private void forward(Editor editor) 1209 { 1210 DirectoryHistoryEntry entry = history.getNext(); 1211 if (entry != null) 1212 changeDirectory(entry); 1213 else 1214 editor.status("Can't go forward"); 1215 } 1216 1217 public void browseFileAtDot() 1218 { 1219 Editor editor = Editor.currentEditor(); 1220 String name = getName(editor.getDotLine()); 1221 if (name == null) 1222 return; 1223 File f = File.getInstance(getFile(), name); 1224 if (!f.exists()) { 1225 editor.status("File not found"); 1226 return; 1227 } 1228 if (f.isFile()) { 1229 String browser = preferences.getStringProperty(Property.BROWSER); 1230 if (browser == null || browser.equals("j")) { 1231 WebBuffer.browse(editor, f, null); 1232 return; 1233 } 1234 try { 1236 String url = "file://".concat(f.canonicalPath()); 1237 String browserOpts = 1238 preferences.getStringProperty(Property.BROWSER_OPTS); 1239 if (browserOpts != null) { 1240 String [] cmdarray = {browser, browserOpts, url}; 1241 Process process = Runtime.getRuntime().exec(cmdarray); 1242 } else { 1243 String [] cmdarray = {browser, url}; 1244 Process process = Runtime.getRuntime().exec(cmdarray); 1245 } 1246 } 1247 catch (Exception e) { 1248 Log.error(e); 1249 } 1250 } 1251 } 1252 1253 public void deleteFiles() 1254 { 1255 if (numMarked > 0) 1256 deleteMarkedFiles(); 1257 else 1258 deleteFileAtDot(); 1259 } 1260 1261 private void showMessageDialog(String message) 1262 { 1263 MessageDialog.showMessageDialog(message, "Error"); 1264 } 1265 1266 private synchronized void deleteMarkedFiles() 1267 { 1268 if (numMarked == 0) 1269 return; 1270 Debug.assertTrue(numMarked > 0); 1271 String message = null; 1272 final Editor editor = Editor.currentEditor(); 1273 if (numMarked > 1) 1274 message = "Delete " + numMarked + " tagged files?"; 1275 else 1276 message = "Delete 1 tagged file?"; 1277 boolean confirmed = editor.confirm("Delete Files", message); 1278 if (!confirmed) 1279 return; 1280 boolean directoryWasDeleted = false; 1281 FtpSession session = null; 1282 for (int i = 0; i < entries.size(); i++) { 1283 DirectoryEntry entry = (DirectoryEntry) entries.get(i); 1284 if (!entry.isMarked()) 1285 continue; 1286 String name = entry.extractName(); 1287 if (name == null) { 1288 Debug.assertTrue(false); 1290 continue; 1291 } 1292 File file = File.getInstance(getFile(), name); 1293 if (!file.isRemote() && !file.exists()) { 1294 showMessageDialog(file.canonicalPath() + " not found"); 1295 return; 1296 } 1297 String displayName = file.canonicalPath(); 1298 boolean isDirectory; 1299 if (file.isRemote()) { 1300 displayName += " on " + file.getHostName(); 1301 isDirectory = entry.isDirectory(); 1302 } 1303 else 1304 isDirectory = file.isDirectory(); 1305 boolean succeeded = false; 1306 if (file instanceof FtpFile) { 1307 if (session == null) 1308 session = FtpSession.getSession((FtpFile)file); 1309 if (session != null) { 1310 if (isDirectory) 1311 succeeded = session.removeDirectory(file.canonicalPath()); 1312 else 1313 succeeded = session.deleteFile(file.canonicalPath()); 1314 } 1315 } else { 1316 file.delete(); 1319 1320 succeeded = !file.exists(); 1322 } 1323 if (succeeded) { 1324 if (isDirectory) 1325 directoryWasDeleted = true; 1326 } else { 1327 if (isDirectory) { 1329 confirmed = editor.confirm("Delete Files", 1330 "Unable to remove directory " + displayName + ". Continue?"); 1331 } else { 1332 confirmed = editor.confirm("Delete Files", 1333 "Unable to delete " + displayName + ". Continue?"); 1334 } 1335 if (!confirmed) 1336 break; 1337 } 1338 } 1339 if (session != null) 1340 session.unlock(); 1341 if (directoryWasDeleted) { 1342 rescan(); 1343 } else { 1344 if (getFile().isRemote()) 1345 DirectoryCache.getDirectoryCache().purge(getFile()); 1346 reload(); 1347 } 1348 } 1349 1350 private void deleteFileAtDot() 1351 { 1352 final Editor editor = Editor.currentEditor(); 1353 String name = getName(editor.getDotLine()); 1354 if (name == null) 1355 return; 1356 if (name.equals(".")) 1357 return; 1358 if (name.equals("..")) 1359 return; 1360 File file = File.getInstance(getFile(), name); 1361 if (!file.isRemote() && !file.exists()) { 1362 showMessageDialog("File not found"); 1363 return; 1364 } 1365 String displayName = file.getName(); 1366 final boolean isDirectory; 1367 if (file.isRemote()) { 1368 displayName += " on " + file.getHostName(); 1369 isDirectory = editor.getDotLine().getText().trim().startsWith("d"); 1370 } else 1371 isDirectory = file.isDirectory(); 1372 final String title, prompt; 1373 if (isDirectory) { 1374 title = "Remove Directory"; 1375 prompt = "Remove directory " + displayName + "?"; 1376 } else { 1377 title = "Delete File"; 1378 prompt = "Delete " + displayName + "?"; 1379 } 1380 if (!editor.confirm(title, prompt)) 1381 return; 1382 boolean succeeded = false; 1383 editor.setWaitCursor(); 1384 if (file instanceof FtpFile) { 1385 FtpSession session = FtpSession.getSession((FtpFile) file); 1386 if (session != null) { 1387 if (isDirectory) 1388 succeeded = session.removeDirectory(file.canonicalPath()); 1389 else 1390 succeeded = session.deleteFile(file.canonicalPath()); 1391 session.unlock(); 1392 } 1393 } else { 1394 file.delete(); 1396 succeeded = !file.exists(); 1397 } 1398 if (succeeded) { 1399 if (isDirectory) { 1400 rescan(); 1401 } else { 1402 if (getFile().isRemote()) 1403 DirectoryCache.getDirectoryCache().purge(getFile()); 1404 reload(); 1405 } 1406 } 1407 editor.setDefaultCursor(); 1408 if (!succeeded) { 1409 if (isDirectory) 1410 showMessageDialog("Unable to remove directory " + displayName); 1411 else 1412 showMessageDialog("Unable to delete " + displayName); 1413 } 1414 } 1415 1416 public static void dirDoShellCommand() 1417 { 1418 if (!Editor.checkExperimental()) 1419 return; 1420 if (!Platform.isPlatformUnix()) 1421 return; 1422 final Editor editor = Editor.currentEditor(); 1423 final Buffer buffer = editor.getBuffer(); 1424 if (buffer instanceof Directory) { 1425 if (buffer.getFile().isRemote()) { 1426 MessageDialog.showMessageDialog(editor, 1427 "Shell commands are not supported in remote directory buffers.", 1428 "Error"); 1429 return; 1430 } 1431 ((Directory)buffer).doShellCommand(editor); 1432 } 1433 } 1434 1435 private void doShellCommand(Editor editor) 1436 { 1437 List names = getMarkedNames(); 1438 if (names == null) { 1439 names = new ArrayList (); 1440 names.add(getName(editor.getDotLine())); 1441 } 1442 String prompt = null; 1443 if (names.size() == 1) 1444 prompt = "Command (on " + (String ) names.get(0) + "):"; 1445 else if (names.size() > 1) 1446 prompt = "Command (on " + names.size() + " tagged files):"; 1447 else 1448 prompt = "Command:"; 1449 InputDialog d = new InputDialog(editor, prompt, "Shell Command", null); 1450 d.setHistory(new History("dirDoShellCommand.command")); 1451 editor.centerDialog(d); 1452 d.show(); 1453 String command = d.getInput(); 1454 if (command == null) 1455 return; 1456 command = command.trim(); 1457 if (command.length() == 0) 1458 return; 1459 editor.setWaitCursor(); 1460 editor.repaintNow(); 1461 String output = null; 1462 if (names != null) { 1463 if (command.indexOf('*') >= 0) { 1464 output = doCommandOnMultipleFiles(command, names); 1465 } else { 1466 FastStringBuffer sb = new FastStringBuffer(); 1467 for (int i = 0; i < names.size(); i++) { 1468 String filename = (String ) names.get(i); 1469 String s = doCommandOnFile(command, filename); 1470 if (s != null && s.length() > 0) 1471 sb.append(s); 1472 } 1473 output = sb.toString(); 1474 } 1475 } 1476 reload(); 1477 if (output != null && output.length() > 0) { 1478 OutputBuffer buf = OutputBuffer.getOutputBuffer(output); 1479 if (buf != null) { 1480 buf.setTitle(command); 1481 editor.makeNext(buf); 1482 editor.displayInOtherWindow(buf); 1483 } 1484 } 1485 editor.setDefaultCursor(); 1486 } 1487 1488 private String doCommandOnFile(String command, String filename) 1489 { 1490 FastStringBuffer sb = new FastStringBuffer(command); 1491 sb.append(' '); 1492 if (filename.indexOf(' ') >= 0) { 1493 sb.append('"'); 1494 sb.append(filename); 1495 sb.append('"'); 1496 } else 1497 sb.append(filename); 1498 ShellCommand shellCommand = new ShellCommand(sb.toString(), getFile()); 1499 shellCommand.run(); 1500 return shellCommand.getOutput(); 1501 } 1502 1503 private String doCommandOnMultipleFiles(String command, List files) 1504 { 1505 if (files.size() < 1) 1506 return null; 1507 String before, after; 1508 int index = command.indexOf('*'); 1509 if (index >= 0) { 1510 before = command.substring(0, index).trim(); 1511 after = command.substring(index + 1).trim(); 1512 } else { 1513 before = command.trim(); 1514 after = ""; 1515 } 1516 if (before.length() == 0) { 1517 showMessageDialog("No command specified"); 1518 return null; 1519 } 1520 FastStringBuffer sb = new FastStringBuffer(before); 1521 for (int i = 0; i < files.size(); i++) { 1522 sb.append(' '); 1523 String filename = (String ) files.get(i); 1524 if (filename.indexOf(' ') >= 0) { 1525 sb.append('"'); 1526 sb.append(filename); 1527 sb.append('"'); 1528 } else 1529 sb.append(filename); 1530 } 1531 if (after.length() > 0) { 1532 sb.append(' '); 1533 sb.append(after); 1534 } 1535 ShellCommand shellCommand = new ShellCommand(sb.toString(), getFile()); 1536 shellCommand.run(); 1537 return shellCommand.getOutput(); 1538 } 1539 1540 private synchronized List getMarkedNames() 1541 { 1542 if (numMarked > 0) { 1543 ArrayList names = new ArrayList (numMarked); 1544 final int size = entries.size(); 1545 for (int i = 0; i < size; i++) { 1546 DirectoryEntry de = (DirectoryEntry) entries.get(i); 1547 if (de.isMarked()) { 1548 String name = de.extractName(); 1549 if (name != null) 1550 names.add(name); 1551 } 1552 } 1553 return names; 1554 } 1555 return null; 1556 } 1557 1558 public void copyFileAtDot() 1559 { 1560 copyFiles(); 1561 } 1562 1563 public void moveFileAtDot() 1564 { 1565 moveFiles(); 1566 } 1567 1568 private List getSourceFiles(Editor editor) 1569 { 1570 ArrayList sources = new ArrayList (); 1571 if (numMarked > 0) { 1572 List names = getMarkedNames(); 1573 for (int i = 0; i < names.size(); i++) { 1574 String name = (String ) names.get(i); 1575 if (name != null) 1576 sources.add(File.getInstance(getFile(), name)); 1577 } 1578 } else if (editor.getDotLine() instanceof DirectoryLine) { 1579 String name = getName(editor.getDotLine()); 1580 if (name != null) 1581 sources.add(File.getInstance(getFile(), name)); 1582 } 1583 return sources; 1584 } 1585 1586 private File getDestinationForCopy(Editor editor, List sources) 1587 { 1588 return getDestination(editor, sources, "Copy"); 1589 } 1590 1591 private File getDestinationForMove(Editor editor, List sources) 1592 { 1593 return getDestination(editor, sources, "Move"); 1594 } 1595 1596 private File getDestination(Editor editor, List sources, String operation) 1597 { 1598 String title = operation + " File"; 1599 String prompt = operation + " "; 1600 String name = null; 1601 if (sources.size() == 1) { 1602 File source = (File) sources.get(0); 1603 name = source.getName(); 1604 prompt += name; 1605 } else 1606 prompt += String.valueOf(sources.size()) + " tagged files"; 1607 prompt += " to: "; 1608 CopyFileDialog d = new CopyFileDialog(editor, title, prompt, name); 1609 editor.centerDialog(d); 1610 d.show(); 1611 editor.repaintNow(); 1612 return d.getDestination(); 1613 } 1614 1615 private void copyFiles() 1616 { 1617 final Editor editor = Editor.currentEditor(); 1618 List sources = getSourceFiles(editor); 1619 File destination = getDestinationForCopy(editor, sources); 1620 if (destination == null) 1621 return; 1622 final String title = "Copy Files"; 1623 if (destination.isLocal()) 1624 copyLocalToLocal(sources, destination, editor, title); 1625 else 1626 MessageDialog.showMessageDialog(editor, "Destination must be local!", title); 1627 } 1628 1629 private void copyLocalToLocal(List sources, File destination, Editor editor, String title) 1630 { 1631 int numFilesCopied = 0; 1632 boolean mustConfirm = true; 1633 boolean cancelled = false; 1634 final int limit = sources.size(); 1635 File destDir = destination.isDirectory() ? destination : destination.getParentFile(); 1636 for (int i = 0; i < limit; i++) { 1637 File from = (File) sources.get(i); 1638 File to; 1639 if (destination.isDirectory()) 1640 to = File.getInstance(destination, from.getName()); 1641 else 1642 to = destination; 1643 if (mustConfirm && to.isFile()) { 1644 String message = "Overwrite existing file " + to.canonicalPath() + "?"; 1645 if (i < limit-1) { 1646 int response = editor.confirmAll(title, message); 1649 switch (response) { 1650 case RESPONSE_YES: 1651 break; 1652 case RESPONSE_NO: 1653 continue; 1654 case RESPONSE_YES_TO_ALL: 1655 mustConfirm = false; 1656 break; 1657 case RESPONSE_CANCEL: 1658 cancelled = true; 1659 break; 1660 default: 1661 break; 1662 } 1663 if (cancelled) 1664 break; 1665 } else if (!editor.confirm(title, message)) { 1666 break; 1668 } 1669 } 1670 if (Utilities.copyFile(from, to)) { 1671 ++numFilesCopied; 1672 } else { 1673 String text = "Unable to copy " + from.getName() + " to " + to.canonicalPath() + "."; 1674 if (i < limit-1) { 1675 text += " Continue?"; 1676 if (!editor.confirm(title, text)) 1677 break; 1678 } else 1679 MessageDialog.showMessageDialog(editor, text, title); 1680 } 1681 } 1682 String statusText = String.valueOf(numFilesCopied) + " file"; 1683 if (numFilesCopied > 1) 1684 statusText += 's'; 1685 statusText += " copied"; 1686 editor.status(statusText); 1687 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1688 Editor ed = it.nextEditor(); 1689 if (destDir.equals(ed.getBuffer().getFile())) { 1690 ((Directory)ed.getBuffer()).reload(); 1691 if (ed != Editor.currentEditor()) 1692 ed.updateDisplay(); 1693 } 1694 } 1695 } 1696 1697 private void moveFiles() 1698 { 1699 final Editor editor = Editor.currentEditor(); 1700 List sources = getSourceFiles(editor); 1701 File destination = getDestinationForMove(editor, sources); 1702 if (destination == null) 1703 return; 1704 Log.debug("ready to move"); 1705 if (destination.isRemote()) { 1706 MessageDialog.showMessageDialog(editor, 1707 "Destination must be local!", "Move Files"); 1708 return; 1709 } 1710 final int count = sources.size(); 1711 for (int i = 0; i < count; i++) { 1712 File source = (File) sources.get(i); 1713 1714 boolean success = source.renameTo(destination); 1716 1717 if (!success) { 1718 Log.warn("renameTo failed; trying copyFile..."); 1719 success = Utilities.copyFile(source, destination); 1720 if (success) { 1721 Log.debug("copyFile succeeded, deleting source..."); 1722 source.delete(); 1723 success = !source.exists(); 1724 } 1725 else 1726 Log.error("copyFile failed"); 1727 } 1728 else 1729 Log.debug("renameTo succeeded"); 1730 1731 if (success) { 1732 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 1735 Buffer buf = it.nextBuffer(); 1736 if (source.equals(buf.getFile())) 1737 buf.changeFile(destination); 1738 } 1739 } else { 1740 MessageDialog.showMessageDialog(editor, "Move failed", "Error"); 1741 break; 1742 } 1743 } 1744 1745 reload(); 1747 } 1748 1749 public void getFileAtDot() 1750 { 1751 final Editor editor = Editor.currentEditor(); 1752 final Line dotLine = editor.getDotLine(); 1753 final String name = getName(dotLine); 1754 if (name == null) 1755 return; 1756 1757 final FtpFile sourceFile = (FtpFile) File.getInstance(getFile(), name); 1758 if (sourceFile == null) 1759 return; 1760 1761 int status = -1; 1762 1763 if (editor.getDotLine().length() >= 3) { 1765 char c = dotLine.charAt(2); 1766 if (c == 'd') { 1767 status = 2; } else if (c == '-') { 1769 status = 1; } 1771 } 1772 1773 if (status == -1) { 1774 MessageDialog.showMessageDialog("Unknown file type", "Get File"); 1776 return; 1777 } 1778 if (status == 2) { 1779 MessageDialog.showMessageDialog( 1780 sourceFile.canonicalPath() + " is a directory", 1781 "Get File"); 1782 return; 1783 } 1784 if (status != 1) { 1785 MessageDialog.showMessageDialog("File not found", "Get File"); 1786 return; 1787 } 1788 1789 CopyFileDialog d = new CopyFileDialog(editor, "Get File", "Destination:", name); 1790 d.setConfirmOverwrite(true); 1791 editor.centerDialog(d); 1792 d.show(); 1793 final File destination = d.getDestination(); 1794 editor.repaintNow(); 1795 if (destination == null) 1796 return; 1797 if (destination.isRemote()) { 1798 MessageDialog.showMessageDialog(editor, "Destination must be local!", title); 1799 return; 1800 } 1801 final File destinationFile = destination.isDirectory() ? File.getInstance(destination, name) : destination; 1802 final FtpSession session = FtpSession.getSession((FtpFile)getFile()); 1803 if (session == null) 1804 return; 1805 final long fileSize = getFileSize(dotLine.getText()); 1806 final FtpLoadProcess loadProcess = new FtpLoadProcess(this, sourceFile, session); 1807 final Runnable successRunnable = new Runnable () { 1808 public void run() 1809 { 1810 File cache = loadProcess.getCache(); 1811 if (cache != null) 1812 Utilities.deleteRename(cache, destination); 1813 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1814 Editor ed = it.nextEditor(); 1815 if (ed.getBuffer() == Directory.this) 1816 ed.setDefaultCursor(); 1817 } 1818 } 1819 }; 1820 final ErrorRunnable errorRunnable = new ErrorRunnable("Operation failed") { 1821 public void run() 1822 { 1823 File cache = loadProcess.getCache(); 1824 if (cache != null && cache.isFile()) 1825 cache.delete(); 1826 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1827 Editor ed = it.nextEditor(); 1828 if (ed.getBuffer() == Directory.this) 1829 ed.setDefaultCursor(); 1830 } 1831 String text = session.getErrorText(); 1832 if (text == null || text.length() == 0) 1833 text = "Unable to retrieve " + name; 1834 MessageDialog.showMessageDialog(text, "Error"); 1835 } 1836 }; 1837 loadProcess.setSuccessRunnable(successRunnable); 1838 loadProcess.setErrorRunnable(errorRunnable); 1839 loadProcess.setProgressNotifier(new StatusBarProgressNotifier(this)); 1840 loadProcess.start(); 1841 } 1842 1843 public boolean isModified() 1844 { 1845 return false; 1846 } 1847 1848 public String getTitle() 1849 { 1850 File dir = getFile(); 1851 title = dir.canonicalPath(); 1852 if (limitPattern != null) { 1853 title += LocalFile.getSeparator(); 1854 title += limitPattern; 1855 } 1856 title += " (sorted by "; 1857 if (sortBy == SORT_BY_NAME) 1858 title += "name)"; 1859 else if (sortBy == SORT_BY_DATE) 1860 title += "date)"; 1861 else if (sortBy == SORT_BY_SIZE) 1862 title += "size)"; 1863 if (dir.isRemote()) 1864 title += " " + dir.getHostName(); 1865 return title; 1866 } 1867 1868 private String getName(Line line) 1869 { 1870 return getName(line.getText()); 1871 } 1872 1873 private String getName(String s) 1874 { 1875 int end = s.indexOf(" ->"); 1877 1878 if (end >= 0) 1879 s = s.substring(0, end); 1880 1881 REMatch match; 1882 1883 if (usingNativeFormat) 1884 match = nativeMoveToFilenameRegExp.getMatch(s); 1885 else 1886 match = internalMoveToFilenameRegExp.getMatch(s); 1887 1888 if (match != null) 1889 return s.substring(match.getEndIndex()); 1890 1891 return null; 1892 } 1893 1894 private long getFileSize(String s) 1895 { 1896 if (usingNativeFormat) { 1897 try { 1898 REMatch match = nativeMoveToFilenameRegExp.getMatch(s); 1899 if (match != null) { 1900 String toBeParsed = s.substring(match.getStartIndex()); 1901 int index = toBeParsed.indexOf(' '); 1902 if (index >= 0) { 1903 toBeParsed = toBeParsed.substring(0, index); 1904 return Long.parseLong(toBeParsed); 1905 } 1906 } 1907 } 1908 catch (Exception e) { 1909 Log.error(e); 1910 } 1911 } 1912 return 0; 1913 } 1914 1915 public void home() 1916 { 1917 final Editor editor = Editor.currentEditor(); 1918 if (editor.getDotOffset() == 0) 1919 return; 1920 editor.addUndo(SimpleEdit.MOVE); 1921 editor.beginningOfBlock(); 1922 int offset = getNameOffset(editor.getDotLine()); 1923 1924 if (editor.getDotOffset() <= offset) 1927 offset = 0; 1928 1929 editor.getDot().setOffset(offset); 1930 editor.moveCaretToDotCol(); 1931 } 1932 1933 public static void chmod() 1934 { 1935 final Editor editor = Editor.currentEditor(); 1936 if (!(editor.getDotLine() instanceof DirectoryLine)) 1937 return; 1938 final Buffer buffer = editor.getBuffer(); 1939 if (!(buffer instanceof Directory)) 1940 return; 1941 final Directory directory = (Directory) buffer; 1942 String name = directory.getName(editor.getDotLine()); 1943 if (name == null) 1944 return; 1945 final File file = File.getInstance(directory.getFile(), name); 1946 if (file == null) 1947 return; 1948 if (file.isLocal()) { 1950 if (!Platform.isPlatformUnix()) 1951 return; 1952 } else if (file.isRemote()) { 1953 int protocol = file.getProtocol(); 1954 if (protocol != File.PROTOCOL_FTP && protocol != File.PROTOCOL_SSH) 1955 return; 1956 } 1957 FastStringBuffer sb = new FastStringBuffer("Change mode of "); 1958 sb.append(file.getName()); 1959 sb.append(" to:"); 1960 final String input = 1961 InputDialog.showInputDialog(editor, sb.toString(), "Change Mode"); 1962 if (input == null || input.length() == 0) 1963 return; 1964 int n = 0; 1965 try { 1966 n = Integer.parseInt(input, 8); 1967 } 1968 catch (NumberFormatException e) { 1969 Log.error(e); 1970 } 1971 if (n == 0) { 1972 MessageDialog.showMessageDialog("Invalid mode string", "Change Mode"); 1973 return; 1974 } 1975 final int permissions = n; 1976 if (file.isLocal()) { 1977 editor.setWaitCursor(); 1978 file.setPermissions(permissions); 1979 editor.setDefaultCursor(); 1980 } else if (file instanceof FtpFile) { 1981 final FtpSession session = FtpSession.getSession((FtpFile)file); 1982 if (session != null) { 1983 final Runnable completionRunnable = new Runnable () { 1984 public void run() 1985 { 1986 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1987 Editor ed = it.nextEditor(); 1988 if (ed.getBuffer() == directory) 1989 ed.setDefaultCursor(); 1990 } 1991 } 1992 }; 1993 final Runnable chmodRunnable = new Runnable () { 1994 public void run() 1995 { 1996 directory.setBusy(true); 1997 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1998 Editor ed = it.nextEditor(); 1999 if (ed.getBuffer() == directory) 2000 ed.setWaitCursor(); 2001 } 2002 if (session.verifyConnected()) { 2003 session.chmod((FtpFile)file, permissions); 2004 session.unlock(); 2005 } 2006 directory.setBusy(false); 2007 SwingUtilities.invokeLater(completionRunnable); 2008 } 2009 }; 2010 new Thread (chmodRunnable).start(); 2011 } 2012 } else if (file instanceof SshFile) { 2013 final SshSession session = SshSession.getSession((SshFile)file); 2014 if (session != null) { 2015 final Runnable completionRunnable = new Runnable () { 2016 public void run() 2017 { 2018 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 2019 Editor ed = it.nextEditor(); 2020 if (ed.getBuffer() == directory) 2021 ed.setDefaultCursor(); 2022 } 2023 } 2024 }; 2025 final Runnable chmodRunnable = new Runnable () { 2026 public void run() 2027 { 2028 directory.setBusy(true); 2029 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 2030 Editor ed = it.nextEditor(); 2031 if (ed.getBuffer() == directory) 2032 ed.setWaitCursor(); 2033 } 2034 if (session.connect()) { 2035 session.chmod((SshFile)file, permissions); 2036 session.unlock(); 2037 } 2038 directory.setBusy(false); 2039 SwingUtilities.invokeLater(completionRunnable); 2040 } 2041 }; 2042 new Thread (chmodRunnable).start(); 2043 } 2044 } 2045 } 2046 2047 private int getNameOffset(Line line) 2048 { 2049 if (line != null) { 2050 REMatch match; 2051 if (usingNativeFormat) 2052 match = nativeMoveToFilenameRegExp.getMatch(line.getText()); 2053 else 2054 match = internalMoveToFilenameRegExp.getMatch(line.getText()); 2055 if (match != null) 2056 return match.getEndIndex(); 2057 } 2058 return 0; 2059 } 2060 2061 private int getNameOffset() 2062 { 2063 return getNameOffset(getFirstLine()); 2064 } 2065 2066 private int getFileSizeEndOffset() 2067 { 2068 Line line = getFirstLine(); 2069 if (line != null) { 2070 final String text = line.getText(); 2071 REMatch match; 2072 if (usingNativeFormat) 2073 match = nativeMoveToFilenameRegExp.getMatch(text); 2074 else 2075 match = internalMoveToFilenameRegExp.getMatch(text); 2076 if (match != null) { 2077 int start = match.getStartIndex(); 2078 return text.indexOf(' ', start); 2080 } 2081 } 2082 return -1; } 2084 2085 private Line findName(String name) 2086 { 2087 if (name != null) { 2088 if (Platform.isPlatformWindows()) { 2089 name = name.toLowerCase(); 2091 for (Line line = getFirstLine(); line != null; line = line.next()) { 2092 String text = line.getText().toLowerCase(); 2093 if (text.indexOf(name) >= 0) if (name.equalsIgnoreCase(getName(line))) 2095 return line; 2096 } 2097 } else { 2098 for (Line line = getFirstLine(); line != null; line = line.next()) { 2099 if (line.getText().indexOf(name) >= 0) if (name.equals(getName(line))) 2101 return line; 2102 } 2103 } 2104 } 2105 return null; 2106 } 2107 2108 public final String toString() 2109 { 2110 File file = getFile(); 2111 if (file.isRemote()) { 2112 FastStringBuffer sb = new FastStringBuffer(file.canonicalPath()); 2113 sb.append(" ["); 2114 sb.append(file.netPath()); 2115 sb.append(']'); 2116 return sb.toString(); 2117 } 2118 if (Platform.isPlatformUnix()) { 2119 String userHome = Utilities.getUserHome(); 2120 if (userHome != null && userHome.length() > 0) { 2121 String s = file.canonicalPath(); 2122 if (s.equals(userHome)) 2123 return "~"; 2124 if (s.startsWith(userHome.concat("/"))) 2125 return "~".concat(s.substring(userHome.length())); 2126 } 2127 } 2128 return file.canonicalPath(); 2129 } 2130 2131 public final Icon getIcon() 2133 { 2134 return Utilities.getIconFromFile("directory.png"); 2135 } 2136} 2137 2138class DirectoryHistory 2139{ 2140 private Vector v = new Vector (); 2141 private int index = -1; 2142 2143 DirectoryHistory() 2144 { 2145 } 2146 2147 boolean atEnd() 2148 { 2149 return index == -1; 2150 } 2151 2152 void truncate() 2153 { 2154 if (index != -1) 2155 v.setSize(index); 2156 } 2157 2158 void append(File file, String name, int offset) 2159 { 2160 v.add(new DirectoryHistoryEntry(file, name, offset)); 2161 } 2162 2163 DirectoryHistoryEntry getPrevious() 2164 { 2165 if (v.size() == 0) 2166 return null; 2167 if (index == -1) 2168 index = v.size(); 2169 if (index > 0) 2170 return (DirectoryHistoryEntry) v.get(--index); 2171 return null; 2172 } 2173 2174 DirectoryHistoryEntry getNext() 2175 { 2176 if (v.size() == 0) 2177 return null; 2178 if (index == -1) 2179 return null; 2180 if (index < v.size()-1) 2181 return (DirectoryHistoryEntry) v.get(++index); 2182 return null; 2183 } 2184 2185 public void reset() 2186 { 2187 index = -1; 2188 } 2189} 2190 2191class DirectoryHistoryEntry 2192{ 2193 File file; 2194 String name; 2195 int offset; 2196 2197 DirectoryHistoryEntry(File file, String name, int offset) 2198 { 2199 this.file = file; 2200 this.name = name; 2201 this.offset = offset; 2202 } 2203} 2204 | Popular Tags |