1 24 package org.gjt.sp.jedit.textarea; 25 26 import org.gjt.sp.jedit.input.InputHandlerProvider; 27 import org.gjt.sp.jedit.input.AbstractInputHandler; 28 import org.gjt.sp.jedit.input.DefaultInputHandlerProvider; 29 import org.gjt.sp.jedit.input.TextAreaInputHandler; 30 import org.gjt.sp.jedit.syntax.Chunk; 31 import org.gjt.sp.jedit.syntax.TokenMarker; 32 import org.gjt.sp.jedit.syntax.ParserRuleSet; 33 import org.gjt.sp.jedit.syntax.SyntaxStyle; 34 import org.gjt.sp.jedit.buffer.JEditBuffer; 35 import org.gjt.sp.jedit.Debug; 36 import org.gjt.sp.jedit.TextUtilities; 37 import org.gjt.sp.util.Log; 38 import org.gjt.sp.util.StandardUtilities; 39 40 import javax.swing.event.EventListenerList ; 41 import javax.swing.event.MouseInputAdapter ; 42 import javax.swing.event.CaretListener ; 43 import javax.swing.event.CaretEvent ; 44 import javax.swing.text.Segment ; 45 import javax.swing.*; 46 import javax.swing.Timer ; 47 import javax.swing.plaf.metal.MetalLookAndFeel ; 48 import java.awt.*; 49 import java.awt.im.InputMethodRequests ; 50 import java.awt.event.*; 51 import java.util.*; 52 53 65 public class TextArea extends JComponent 66 { 67 public TextArea() 69 { 70 this(null); 71 inputHandlerProvider = new DefaultInputHandlerProvider(new TextAreaInputHandler(this)); 72 setMouseHandler(new TextAreaMouseHandler(this)); 73 Font font1 = new Font("Monospaced", Font.PLAIN, 12); 74 painter.setFont(font1); 75 SyntaxStyle[] styles = new SyntaxStyle[1]; 76 styles[0] = new SyntaxStyle(Color.black, Color.white, font1); 77 painter.setStyles(styles); 78 painter.setBlockCaretEnabled(false); 79 80 81 82 painter.setStructureHighlightEnabled(true); 83 painter.setStructureHighlightColor(Color.black); 84 painter.setEOLMarkersPainted(false); 85 painter.setEOLMarkerColor(new Color(255,102,51)); 86 painter.setWrapGuidePainted(true); 87 painter.setWrapGuideColor(new Color(125,125,255)); 88 painter.setCaretColor(Color.red); 89 painter.setSelectionColor(new Color(204,204,255)); 90 painter.setMultipleSelectionColor(new Color(204,255,204)); 91 painter.setBackground(Color.white); 92 painter.setForeground(Color.black); 93 painter.setBlockCaretEnabled(false); 94 painter.setLineHighlightEnabled(true); 95 painter.setLineHighlightColor(new Color(255,204,255)); 96 painter.setAntiAlias(new AntiAlias(0)); 97 painter.setFractionalFontMetricsEnabled(false); 98 99 100 gutter.setExpanded(false); 101 gutter.setHighlightInterval(5); 102 gutter.setCurrentLineHighlightEnabled(true); 103 gutter.setStructureHighlightEnabled(true); 104 gutter.setStructureHighlightColor(new Color(102,102,153)); 105 gutter.setBackground(new Color(219,219,219)); 106 gutter.setForeground(Color.black); 107 gutter.setHighlightedForeground(new Color(153,0,102)); 108 gutter.setFoldColor(new Color(131,131,131)); 109 gutter.setCurrentLineForeground(new Color(255,0,51)); 110 gutter.setLineNumberAlignment(Gutter.RIGHT); 111 gutter.setFont(new Font("Monospaced", Font.PLAIN, 10)); 112 gutter.setBorder(3, new Color(153,0,153), Color.white, painter.getBackground()); 113 114 setCaretBlinkEnabled(true); 115 setElectricScroll(3); 116 117 JEditBuffer buffer = new JEditBuffer(); 118 TokenMarker tokenMarker = new TokenMarker(); 119 tokenMarker.addRuleSet(new ParserRuleSet("text","MAIN")); 120 buffer.setTokenMarker(tokenMarker); 121 buffer.insert(0,"ahaha coucou\ncaca"); 122 setBuffer(buffer); 123 } 125 129 public TextArea(InputHandlerProvider inputHandlerProvider) 130 { 131 this.inputHandlerProvider = inputHandlerProvider; 132 enableEvents(AWTEvent.FOCUS_EVENT_MASK | AWTEvent.KEY_EVENT_MASK); 133 134 selectionManager = new SelectionManager(this); 136 chunkCache = new ChunkCache(this); 137 painter = new TextAreaPainter(this); 138 repaintMgr = new FastRepaintManager(this,painter); 139 gutter = new Gutter(this); 140 gutter.setMouseActionsProvider(new MouseActions("gutter")); 141 listenerList = new EventListenerList (); 142 caretEvent = new MutableCaretEvent(); 143 blink = true; 144 offsetXY = new Point(); 145 structureMatchers = new LinkedList<StructureMatcher>(); 146 structureMatchers.add(new StructureMatcher.BracketMatcher()); 147 149 setLayout(new ScrollLayout()); 151 add(ScrollLayout.CENTER,painter); 152 add(ScrollLayout.LEFT,gutter); 153 154 verticalBox = new Box(BoxLayout.X_AXIS); 156 verticalBox.add(vertical = new JScrollBar(Adjustable.VERTICAL)); 157 vertical.setRequestFocusEnabled(false); 158 add(ScrollLayout.RIGHT,verticalBox); 159 add(ScrollLayout.BOTTOM, 160 horizontal = new JScrollBar(Adjustable.HORIZONTAL)); 161 horizontal.setRequestFocusEnabled(false); 162 163 horizontal.setValues(0,0,0,0); 164 166 if(UIManager.getLookAndFeel() instanceof MetalLookAndFeel ) 172 { 173 setBorder(new TextAreaBorder()); 174 vertical.putClientProperty("JScrollBar.isFreeStanding", 175 Boolean.FALSE); 176 horizontal.putClientProperty("JScrollBar.isFreeStanding", 177 Boolean.FALSE); 178 } 180 182 vertical.addAdjustmentListener(new AdjustHandler()); 184 horizontal.addAdjustmentListener(new AdjustHandler()); 185 186 187 addFocusListener(new FocusHandler()); 188 addMouseWheelListener(new MouseWheelHandler()); 189 190 192 focusedComponent = this; 196 197 } 199 public void setMouseHandler(MouseInputAdapter mouseInputAdapter) 201 { 202 mouseHandler = mouseInputAdapter; 203 painter.addMouseListener(mouseHandler); 204 painter.addMouseMotionListener(mouseHandler); 205 } 207 public void setTransferHandler(TransferHandler newHandler) 209 { 210 super.setTransferHandler(newHandler); 211 try 212 { 213 getDropTarget().addDropTargetListener( 214 new TextAreaDropHandler(this)); 215 } 216 catch(TooManyListenersException e) 217 { 218 Log.log(Log.ERROR,this,e); 219 } 220 } 222 public String toString() { 224 StringBuilder builder = new StringBuilder (); 225 builder.append("caret: ").append(caret).append('\n'); 226 builder.append("caretLine: ").append(caretLine).append('\n'); 227 builder.append("caretScreenLine: ").append(caretScreenLine).append('\n'); 228 builder.append("electricScroll: ").append(electricScroll).append('\n'); 229 builder.append("horizontalOffset: ").append(horizontalOffset).append('\n'); 230 builder.append("magicCaret: ").append(magicCaret).append('\n'); 231 builder.append("offsetXY").append(offsetXY.toString()).append('\n'); 232 builder.append("oldCaretLine: ").append(oldCaretLine).append('\n'); 233 builder.append("screenLastLine: ").append(screenLastLine).append('\n'); 234 builder.append("visibleLines: ").append(visibleLines).append('\n'); 235 builder.append("firstPhysicalLine: ").append(getFirstPhysicalLine()).append('\n'); 236 builder.append("physLastLine: ").append(physLastLine).append('\n'); 237 return builder.toString(); 238 } 240 245 public void dispose() 246 { 247 DisplayManager.textAreaDisposed(this); 248 } 250 254 public AbstractInputHandler getInputHandler() 255 { 256 return inputHandlerProvider.getInputHandler(); 257 } 259 263 public final TextAreaPainter getPainter() 264 { 265 return painter; 266 } 268 273 public final Gutter getGutter() 274 { 275 return gutter; 276 } 278 283 public DisplayManager getDisplayManager() 284 { 285 return displayManager; 286 } 288 292 public final boolean isCaretBlinkEnabled() 293 { 294 return caretBlinks; 295 } 297 302 public void setCaretBlinkEnabled(boolean caretBlinks) 303 { 304 this.caretBlinks = caretBlinks; 305 if(!caretBlinks) 306 blink = false; 307 308 if(buffer != null) 309 invalidateLine(caretLine); 310 } 312 314 319 public final int getElectricScroll() 320 { 321 return electricScroll; 322 } 324 331 public final void setElectricScroll(int electricScroll) 332 { 333 this.electricScroll = electricScroll; 334 } 336 342 public final boolean isQuickCopyEnabled() 343 { 344 return quickCopy; 345 } 347 354 public final void setQuickCopyEnabled(boolean quickCopy) 355 { 356 this.quickCopy = quickCopy; 357 } 359 369 public final JEditBuffer getBuffer() 370 { 371 return buffer; 372 } 374 380 public void setBuffer(JEditBuffer buffer) 381 { 382 if(this.buffer == buffer) 383 return; 384 385 try 386 { 387 bufferChanging = true; 388 389 if(this.buffer != null) 390 { 391 394 if(!buffer.isLoading()) 395 selectNone(); 396 caretLine = caret = caretScreenLine = 0; 397 match = null; 398 } 399 boolean inCompoundEdit = false; 400 if (this.buffer != null) 401 inCompoundEdit = this.buffer.insideCompoundEdit(); 402 if (inCompoundEdit) 403 this.buffer.endCompoundEdit(); 404 this.buffer = buffer; 405 if (inCompoundEdit) 406 this.buffer.beginCompoundEdit(); 407 408 chunkCache.setBuffer(buffer); 409 repaintMgr.setFastScroll(false); 410 propertiesChanged(); 411 412 if(displayManager != null) 413 { 414 DisplayManager.releaseDisplayManager( 415 displayManager); 416 } 417 418 displayManager = DisplayManager.getDisplayManager( 419 buffer,this); 420 421 displayManager.init(); 422 423 if(buffer.isLoading()) 424 updateScrollBar(); 425 426 repaint(); 427 428 fireScrollEvent(true); 429 } 430 finally 431 { 432 bufferChanging = false; 433 } 434 } 436 440 public final boolean isEditable() 441 { 442 return buffer.isEditable(); 443 } 445 454 public boolean isDragInProgress() 455 { 456 return dndInProgress; 457 } 459 468 public void setDragInProgress(boolean dndInProgress) 469 { 470 this.dndInProgress = dndInProgress; 471 } 473 478 public boolean isDragEnabled() 479 { 480 return dndEnabled; 481 } 483 488 public void setDragEnabled(boolean dndEnabled) 489 { 490 this.dndEnabled = dndEnabled; 491 } 493 498 public boolean getJoinNonWordChars() 499 { 500 return joinNonWordChars; 501 } 503 508 public void setJoinNonWordChars(boolean joinNonWordChars) 509 { 510 this.joinNonWordChars = joinNonWordChars; 511 } 513 515 520 public final int getFirstLine() 521 { 522 return displayManager.firstLine.scrollLine 523 + displayManager.firstLine.skew; 524 } 526 532 public void setFirstLine(int firstLine) 533 { 534 int max = displayManager.getScrollLineCount() - visibleLines 536 + (lastLinePartial ? 1 : 0); 537 if(firstLine > max) 538 firstLine = max; 539 if(firstLine < 0) 540 firstLine = 0; 541 543 if(Debug.SCROLL_DEBUG) 544 { 545 Log.log(Log.DEBUG,this,"setFirstLine() from " 546 + getFirstLine() + " to " + firstLine); 547 } 548 549 int oldFirstLine = getFirstLine(); 550 if(firstLine == oldFirstLine) 551 return; 552 553 displayManager.setFirstLine(oldFirstLine,firstLine); 554 555 repaint(); 556 557 fireScrollEvent(true); 558 } 560 565 public final int getFirstPhysicalLine() 566 { 567 return displayManager.firstLine.physicalLine; 568 } 570 576 public void setFirstPhysicalLine(int physFirstLine) 577 { 578 setFirstPhysicalLine(physFirstLine,0); 579 } 581 588 public void setFirstPhysicalLine(int physFirstLine, int skew) 589 { 590 if(Debug.SCROLL_DEBUG) 591 { 592 Log.log(Log.DEBUG,this,"setFirstPhysicalLine(" 593 + physFirstLine + ',' + skew + ')'); 594 } 595 596 int amount = physFirstLine - displayManager.firstLine.physicalLine; 597 598 displayManager.setFirstPhysicalLine(amount,skew); 599 600 repaint(); 601 602 fireScrollEvent(true); 603 } 605 610 public final int getLastPhysicalLine() 611 { 612 return physLastLine; 613 } 615 619 public int getLastScreenLine() 620 { 621 return screenLastLine; 622 } 624 628 public final int getVisibleLines() 629 { 630 return visibleLines; 631 } 633 637 public final int getHorizontalOffset() 638 { 639 return horizontalOffset; 640 } 642 648 public void setHorizontalOffset(int horizontalOffset) 649 { 650 if(horizontalOffset > 0) 651 horizontalOffset = 0; 652 653 if(horizontalOffset == this.horizontalOffset) 654 return; 655 656 this.horizontalOffset = horizontalOffset; 657 painter.repaint(); 658 659 fireScrollEvent(false); 660 } 662 667 public void scrollUpLine() 668 { 669 setFirstLine(getFirstLine() - 1); 670 } 672 677 public void scrollUpPage() 678 { 679 setFirstLine(getFirstLine() - getVisibleLines() 680 + (lastLinePartial ? 1 : 0)); 681 } 683 688 public void scrollDownLine() 689 { 690 setFirstLine(getFirstLine() + 1); 691 } 693 698 public void scrollDownPage() 699 { 700 setFirstLine(getFirstLine() + getVisibleLines() 701 - (lastLinePartial ? 1 : 0)); 702 } 704 710 public void scrollToCaret(boolean doElectricScroll) 711 { 712 scrollTo(caretLine,caret - buffer.getLineStartOffset(caretLine), 713 doElectricScroll); 714 } 716 723 public void scrollTo(int offset, boolean doElectricScroll) 724 { 725 int line = buffer.getLineOfOffset(offset); 726 scrollTo(line,offset - buffer.getLineStartOffset(line), 727 doElectricScroll); 728 } 730 738 public void scrollTo(int line, int offset, boolean doElectricScroll) 739 { 740 if(Debug.SCROLL_TO_DEBUG) 741 Log.log(Log.DEBUG,this,"scrollTo(), lineCount=" 742 + getLineCount()); 743 744 int extraEndVirt; 746 int lineLength = buffer.getLineLength(line); 747 if(offset > lineLength) 748 { 749 extraEndVirt = charWidth * (offset - lineLength); 750 offset = lineLength; 751 } 752 else 753 extraEndVirt = 0; 754 755 int _electricScroll = doElectricScroll 756 && visibleLines - 1 > (electricScroll << 1) 757 ? electricScroll : 0; 758 760 if(visibleLines <= 1) 761 { 762 if(Debug.SCROLL_TO_DEBUG) 763 Log.log(Log.DEBUG,this,"visibleLines <= 0"); 764 setFirstPhysicalLine(line,_electricScroll); 765 return; 766 } 767 768 int screenLine = chunkCache.getScreenLineOfOffset(line,offset); 770 int visibleLines = getVisibleLines(); 771 if(screenLine == -1) 772 { 773 if(Debug.SCROLL_TO_DEBUG) 774 Log.log(Log.DEBUG,this,"screenLine == -1"); 775 ChunkCache.LineInfo[] infos = chunkCache 776 .getLineInfosForPhysicalLine(line); 777 int subregion = ChunkCache.getSubregionOfOffset( 778 offset,infos); 779 int prevLine = displayManager.getPrevVisibleLine(getFirstPhysicalLine()); 780 int nextLine = displayManager.getNextVisibleLine(getLastPhysicalLine()); 781 if(line == getFirstPhysicalLine()) 782 { 783 if(Debug.SCROLL_TO_DEBUG) 784 Log.log(Log.DEBUG,this,line + " == " + getFirstPhysicalLine()); 785 setFirstPhysicalLine(line,subregion 786 - _electricScroll); 787 } 788 else if(line == prevLine) 789 { 790 if(Debug.SCROLL_TO_DEBUG) 791 Log.log(Log.DEBUG,this,line + " == " + prevLine); 792 setFirstPhysicalLine(prevLine,subregion 793 - _electricScroll); 794 } 795 else if(line == getLastPhysicalLine()) 796 { 797 if(Debug.SCROLL_TO_DEBUG) 798 Log.log(Log.DEBUG,this,line + " == " + getLastPhysicalLine()); 799 setFirstPhysicalLine(line, 800 subregion + _electricScroll 801 - visibleLines 802 + (lastLinePartial ? 2 : 1)); 803 } 804 else if(line == nextLine) 805 { 806 if(Debug.SCROLL_TO_DEBUG) 807 Log.log(Log.DEBUG,this,line + " == " + nextLine); 808 setFirstPhysicalLine(nextLine, 809 subregion + electricScroll 810 - visibleLines 811 + (lastLinePartial ? 2 : 1)); 812 } 813 else 814 { 815 if(Debug.SCROLL_TO_DEBUG) 816 { 817 Log.log(Log.DEBUG,this,"neither"); 818 Log.log(Log.DEBUG,this,"Last physical line is " + getLastPhysicalLine()); 819 } 820 setFirstPhysicalLine(line,subregion 821 - (visibleLines >> 1)); 822 if(Debug.SCROLL_TO_DEBUG) 823 { 824 Log.log(Log.DEBUG,this,"Last physical line is " + getLastPhysicalLine()); 825 } 826 } 827 } 828 else if(screenLine < _electricScroll) 829 { 830 if(Debug.SCROLL_TO_DEBUG) 831 Log.log(Log.DEBUG,this,"electric up"); 832 setFirstLine(getFirstLine() - _electricScroll + screenLine); 833 } 834 else if(screenLine > visibleLines - _electricScroll 835 - (lastLinePartial ? 2 : 1)) 836 { 837 if(Debug.SCROLL_TO_DEBUG) 838 Log.log(Log.DEBUG,this,"electric down"); 839 setFirstLine(getFirstLine() + _electricScroll - visibleLines + screenLine + (lastLinePartial ? 2 : 1)); 840 } 842 if(!displayManager.isLineVisible(line)) 844 return; 845 846 Point point = offsetToXY(line,offset,offsetXY); 847 if(point == null) 848 { 851 852 Log.log(Log.ERROR,this,"BUG: screenLine=" + screenLine 853 + ",visibleLines=" + visibleLines 854 + ",physicalLine=" + line 855 + ",offset=" + offset 856 + ",firstPhysicalLine=" + getFirstPhysicalLine() 857 + ",lastPhysicalLine=" + getLastPhysicalLine()); 858 859 } 860 point.x += extraEndVirt; 861 862 if(point.x < 0) 863 { 864 setHorizontalOffset(horizontalOffset 865 - point.x + charWidth + 5); 866 } 867 else if(point.x >= painter.getWidth() - charWidth - 5) 868 { 869 setHorizontalOffset(horizontalOffset + 870 (painter.getWidth() - point.x) 871 - charWidth - 5); 872 } } 875 881 public final void addScrollListener(ScrollListener listener) 882 { 883 listenerList.add(ScrollListener.class,listener); 884 } 886 892 public final void removeScrollListener(ScrollListener listener) 893 { 894 listenerList.remove(ScrollListener.class,listener); 895 } 897 899 901 908 public int getPhysicalLineOfScreenLine(int screenLine) 909 { 910 return chunkCache.getLineInfo(screenLine).physicalLine; 911 } 913 920 public int getScreenLineOfOffset(int offset) 921 { 922 int line = buffer.getLineOfOffset(offset); 923 offset -= buffer.getLineStartOffset(line); 924 return chunkCache.getScreenLineOfOffset(line,offset); 925 } 927 933 public int getScreenLineStartOffset(int line) 934 { 935 ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line); 936 if(lineInfo.physicalLine == -1) 937 return -1; 938 939 return buffer.getLineStartOffset(lineInfo.physicalLine) 940 + lineInfo.offset; 941 } 943 949 public int getScreenLineEndOffset(int line) 950 { 951 ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line); 952 if(lineInfo.physicalLine == -1) 953 return -1; 954 955 return buffer.getLineStartOffset(lineInfo.physicalLine) 956 + lineInfo.offset + lineInfo.length; 957 } 959 961 963 972 public int xyToOffset(int x, int y) 973 { 974 return xyToOffset(x,y,true); 975 } 977 988 public int xyToOffset(int x, int y, boolean round) 989 { 990 FontMetrics fm = painter.getFontMetrics(); 991 int height = fm.getHeight(); 992 int line = y / height; 993 994 if(line < 0 || line >= visibleLines) 995 return -1; 996 997 return xToScreenLineOffset(line,x,round); 998 } 1000 1011 public int xToScreenLineOffset(int screenLine, int x, boolean round) 1012 { 1013 ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(screenLine); 1014 if(lineInfo.physicalLine == -1) 1015 { 1016 return getLineEndOffset(displayManager 1017 .getLastVisibleLine()) - 1; 1018 } 1019 else 1020 { 1021 int offset = Chunk.xToOffset(lineInfo.chunks, 1022 x - horizontalOffset,round); 1023 if(offset == -1 || offset == lineInfo.offset + lineInfo.length) 1024 offset = lineInfo.offset + lineInfo.length - 1; 1025 1026 return getLineStartOffset(lineInfo.physicalLine) + offset; 1027 } 1028 } 1030 1038 public Point offsetToXY(int offset) 1039 { 1040 int line = buffer.getLineOfOffset(offset); 1041 offset -= buffer.getLineStartOffset(line); 1042 Point retVal = new Point(); 1043 return offsetToXY(line,offset,retVal); 1044 } 1046 1055 public Point offsetToXY(int line, int offset) 1056 { 1057 return offsetToXY(line,offset,new Point()); 1058 } 1060 1072 public Point offsetToXY(int line, int offset, Point retVal) 1073 { 1074 if(!displayManager.isLineVisible(line)) 1075 return null; 1076 int screenLine = chunkCache.getScreenLineOfOffset(line,offset); 1077 if(screenLine == -1) 1078 return null; 1079 1080 FontMetrics fm = painter.getFontMetrics(); 1081 1082 retVal.y = screenLine * fm.getHeight(); 1083 1084 ChunkCache.LineInfo info = chunkCache.getLineInfo(screenLine); 1085 1086 retVal.x = (int)(horizontalOffset + Chunk.offsetToX( 1087 info.chunks,offset)); 1088 1089 return retVal; 1090 } 1092 1094 1096 1103 public void invalidateScreenLineRange(int start, int end) 1104 { 1105 if(buffer.isLoading()) 1106 return; 1107 1108 if(start > end) 1109 { 1110 int tmp = end; 1111 end = start; 1112 start = tmp; 1113 } 1114 1115 if(chunkCache.needFullRepaint()) 1116 end = visibleLines; 1117 1118 FontMetrics fm = painter.getFontMetrics(); 1119 int y = start * fm.getHeight(); 1120 int height = (end - start + 1) * fm.getHeight(); 1121 painter.repaint(0,y,painter.getWidth(),height); 1122 gutter.repaint(0,y,gutter.getWidth(),height); 1123 } 1125 1130 public void invalidateLine(int line) 1131 { 1132 if(!isShowing() 1133 || buffer.isLoading() 1134 || line < getFirstPhysicalLine() 1135 || line > physLastLine 1136 || !displayManager.isLineVisible(line)) 1137 return; 1138 1139 int startLine = -1; 1140 int endLine = -1; 1141 1142 for(int i = 0; i < visibleLines; i++) 1143 { 1144 ChunkCache.LineInfo info = chunkCache.getLineInfo(i); 1145 1146 if((info.physicalLine >= line || info.physicalLine == -1) 1147 && startLine == -1) 1148 { 1149 startLine = i; 1150 } 1151 1152 if((info.physicalLine >= line && info.lastSubregion) 1153 || info.physicalLine == -1) 1154 { 1155 endLine = i; 1156 break; 1157 } 1158 } 1159 1160 if(chunkCache.needFullRepaint() || endLine == -1) 1161 endLine = visibleLines; 1162 1163 invalidateScreenLineRange(startLine,endLine); 1164 } 1166 1172 public void invalidateLineRange(int start, int end) 1173 { 1174 if(!isShowing() || buffer.isLoading()) 1175 return; 1176 1177 if(end < start) 1178 { 1179 int tmp = end; 1180 end = start; 1181 start = tmp; 1182 } 1183 1184 if(end < getFirstPhysicalLine() || start > getLastPhysicalLine()) 1185 return; 1186 1187 int startScreenLine = -1; 1188 int endScreenLine = -1; 1189 1190 for(int i = 0; i < visibleLines; i++) 1191 { 1192 ChunkCache.LineInfo info = chunkCache.getLineInfo(i); 1193 1194 if((info.physicalLine >= start || info.physicalLine == -1) 1195 && startScreenLine == -1) 1196 { 1197 startScreenLine = i; 1198 } 1199 1200 if((info.physicalLine >= end && info.lastSubregion) 1201 || info.physicalLine == -1) 1202 { 1203 endScreenLine = i; 1204 break; 1205 } 1206 } 1207 1208 if(startScreenLine == -1) 1209 startScreenLine = 0; 1210 1211 if(chunkCache.needFullRepaint() || endScreenLine == -1) 1212 endScreenLine = visibleLines; 1213 1214 invalidateScreenLineRange(startScreenLine,endScreenLine); 1215 } 1217 1219 1221 1225 public final int getBufferLength() 1226 { 1227 return buffer.getLength(); 1228 } 1230 1234 public final int getLineCount() 1235 { 1236 return buffer.getLineCount(); 1237 } 1239 1244 public final int getLineOfOffset(int offset) 1245 { 1246 return buffer.getLineOfOffset(offset); 1247 } 1249 1256 public int getLineStartOffset(int line) 1257 { 1258 return buffer.getLineStartOffset(line); 1259 } 1261 1268 public int getLineEndOffset(int line) 1269 { 1270 return buffer.getLineEndOffset(line); 1271 } 1273 1278 public int getLineLength(int line) 1279 { 1280 return buffer.getLineLength(line); 1281 } 1283 1290 public final String getText(int start, int len) 1291 { 1292 return buffer.getText(start,len); 1293 } 1295 1302 public final void getText(int start, int len, Segment segment) 1303 { 1304 buffer.getText(start,len,segment); 1305 } 1307 1313 public final String getLineText(int lineIndex) 1314 { 1315 return buffer.getLineText(lineIndex); 1316 } 1318 1324 public final void getLineText(int lineIndex, Segment segment) 1325 { 1326 buffer.getLineText(lineIndex,segment); 1327 } 1329 1333 public String getText() 1334 { 1335 return buffer.getText(0,buffer.getLength()); 1336 } 1338 1342 public void setText(String text) 1343 { 1344 try 1345 { 1346 buffer.beginCompoundEdit(); 1347 buffer.remove(0,buffer.getLength()); 1348 buffer.insert(0,text); 1349 } 1350 finally 1351 { 1352 buffer.endCompoundEdit(); 1353 } 1354 } 1356 1358 1360 1364 public final void selectAll() 1365 { 1366 int firstLine = getFirstLine(); 1367 int horizOffset = getHorizontalOffset(); 1368 1369 setSelection(new Selection.Range(0,buffer.getLength())); 1370 moveCaretPosition(buffer.getLength(),true); 1371 1372 setFirstLine(firstLine); 1373 setHorizontalOffset(horizOffset); 1374 } 1376 1381 public void selectLine() 1382 { 1383 int caretLine = getCaretLine(); 1384 int start = getLineStartOffset(caretLine); 1385 int end = getLineEndOffset(caretLine) - 1; 1386 Selection s = new Selection.Range(start,end); 1387 if(multi) 1388 addToSelection(s); 1389 else 1390 setSelection(s); 1391 moveCaretPosition(end); 1392 } 1394 1399 public void selectParagraph() 1400 { 1401 int caretLine = getCaretLine(); 1402 1403 if(getLineLength(caretLine) == 0) 1404 { 1405 getToolkit().beep(); 1406 return; 1407 } 1408 1409 int start = caretLine; 1410 int end = caretLine; 1411 1412 while(start >= 0) 1413 { 1414 if(getLineLength(start) == 0) 1415 break; 1416 else 1417 start--; 1418 } 1419 1420 while(end < getLineCount()) 1421 { 1422 if(getLineLength(end) == 0) 1423 break; 1424 else 1425 end++; 1426 } 1427 1428 int selectionStart = getLineStartOffset(start + 1); 1429 int selectionEnd = getLineEndOffset(end - 1) - 1; 1430 Selection s = new Selection.Range(selectionStart,selectionEnd); 1431 if(multi) 1432 addToSelection(s); 1433 else 1434 setSelection(s); 1435 moveCaretPosition(selectionEnd); 1436 } 1438 1443 public void selectWord() 1444 { 1445 int line = getCaretLine(); 1446 int lineStart = getLineStartOffset(line); 1447 int offset = getCaretPosition() - lineStart; 1448 1449 if(getLineLength(line) == 0) 1450 return; 1451 1452 String lineText = getLineText(line); 1453 String noWordSep = buffer.getStringProperty("noWordSep"); 1454 1455 if(offset == getLineLength(line)) 1456 offset--; 1457 1458 int wordStart = TextUtilities.findWordStart(lineText,offset,noWordSep); 1459 int wordEnd = TextUtilities.findWordEnd(lineText,offset+1,noWordSep); 1460 1461 Selection s = new Selection.Range(lineStart + wordStart, 1462 lineStart + wordEnd); 1463 if(multi) 1464 addToSelection(s); 1465 else 1466 setSelection(s); 1467 moveCaretPosition(lineStart + wordEnd); 1468 } 1470 1476 public Selection selectToMatchingBracket(int position, 1477 boolean quickCopy) 1478 { 1479 int positionLine = buffer.getLineOfOffset(position); 1480 int lineOffset = position - buffer.getLineStartOffset(positionLine); 1481 if(getLineLength(positionLine) != 0) 1482 { 1483 int bracket = TextUtilities.findMatchingBracket(buffer, 1484 positionLine,Math.max(0,lineOffset - 1)); 1485 1486 if(bracket != -1) 1487 { 1488 Selection s; 1489 1490 if(bracket < position) 1491 { 1492 if(!quickCopy) 1493 moveCaretPosition(position,false); 1494 s = new Selection.Range(bracket,position); 1495 } 1496 else 1497 { 1498 if(!quickCopy) 1499 moveCaretPosition(bracket + 1,false); 1500 s = new Selection.Range(position - 1,bracket + 1); 1501 } 1502 1503 if(!multi && !quickCopy) 1504 selectNone(); 1505 1506 addToSelection(s); 1507 return s; 1508 } 1509 } 1510 1511 return null; 1512 } 1514 1520 public void selectToMatchingBracket() 1521 { 1522 selectToMatchingBracket(caret,false); 1523 } 1525 1530 public void selectBlock() 1531 { 1532 1533 Selection s = getSelectionAtOffset(caret); 1534 int start, end; 1535 if(s == null) 1536 start = end = caret; 1537 else 1538 { 1539 start = s.start; 1540 end = s.end; 1541 } 1542 1543 String text = getText(0,buffer.getLength()); 1544 1545 if(start == 0) 1547 { 1548 getToolkit().beep(); 1549 return; 1550 } 1551 1552 String openBrackets = "([{"; 1554 String closeBrackets = ")]}"; 1555 int count = 1; 1556 char openBracket = '\0'; 1557 char closeBracket = '\0'; 1558 1559backward_scan: while(--start > 0) 1560 { 1561 char c = text.charAt(start); 1562 int index = openBrackets.indexOf(c); 1563 if(index != -1) 1564 { 1565 if(--count == 0) 1566 { 1567 openBracket = c; 1568 closeBracket = closeBrackets.charAt(index); 1569 break backward_scan; 1570 } 1571 } 1572 else if(closeBrackets.indexOf(c) != -1) 1573 count++; 1574 } 1575 1576 count = 1; 1578 1579 if(openBracket == '\0') 1581 { 1582 getToolkit().beep(); 1583 return; 1584 } 1585forward_scan: do 1586 { 1587 char c = text.charAt(end); 1588 if(c == closeBracket) 1589 { 1590 if(--count == 0) 1591 { 1592 end++; 1593 break forward_scan; 1594 } 1595 } 1596 else if(c == openBracket) 1597 count++; 1598 } 1599 while(++end < buffer.getLength()); 1600 1601 s = new Selection.Range(start,end); 1602 if(multi) 1603 addToSelection(s); 1604 else 1605 setSelection(s); 1606 moveCaretPosition(end); 1607 } 1609 1615 public boolean lineInStructureScope(int line) 1616 { 1617 if(match == null) 1618 return false; 1619 1620 if(match.startLine < caretLine) 1621 return line >= match.startLine && line <= caretLine; 1622 else 1623 return line <= match.endLine && line >= caretLine; 1624 } 1626 1631 public final void invertSelection() 1632 { 1633 selectionManager.invertSelection(); 1634 } 1636 1642 public int getSelectionCount() 1643 { 1644 return selectionManager.getSelectionCount(); 1645 } 1647 1652 public Selection[] getSelection() 1653 { 1654 return selectionManager.getSelection(); 1655 } 1657 1662 public Iterator<Selection> getSelectionIterator() 1663 { 1664 return selectionManager.selection.iterator(); 1665 } 1667 1674 public Selection getSelection(int index) 1675 { 1676 return selectionManager.selection.get(index); 1677 } 1679 1683 public void selectNone() 1684 { 1685 invalidateSelectedLines(); 1686 setSelection((Selection)null); 1687 } 1689 1696 public void setSelection(Selection[] selection) 1697 { 1698 invalidateSelectedLines(); 1700 selectionManager.setSelection(selection); 1701 finishCaretUpdate(caretLine,NO_SCROLL,true); 1702 } 1704 1711 public void setSelection(Selection selection) 1712 { 1713 invalidateSelectedLines(); 1714 selectionManager.setSelection(selection); 1715 finishCaretUpdate(caretLine,NO_SCROLL,true); 1716 } 1718 1725 public void addToSelection(Selection[] selection) 1726 { 1727 invalidateSelectedLines(); 1728 selectionManager.addToSelection(selection); 1729 finishCaretUpdate(caretLine,NO_SCROLL,true); 1730 } 1732 1739 public void addToSelection(Selection selection) 1740 { 1741 invalidateSelectedLines(); 1742 selectionManager.addToSelection(selection); 1743 finishCaretUpdate(caretLine,NO_SCROLL,true); 1744 } 1746 1753 public Selection getSelectionAtOffset(int offset) 1754 { 1755 return selectionManager.getSelectionAtOffset(offset); 1756 } 1758 1764 public void removeFromSelection(Selection sel) 1765 { 1766 invalidateSelectedLines(); 1767 selectionManager.removeFromSelection(sel); 1768 finishCaretUpdate(caretLine,NO_SCROLL,true); 1769 } 1771 1778 public void removeFromSelection(int offset) 1779 { 1780 Selection sel = getSelectionAtOffset(offset); 1781 if(sel == null) 1782 return; 1783 1784 invalidateSelectedLines(); 1785 selectionManager.removeFromSelection(sel); 1786 finishCaretUpdate(caretLine,NO_SCROLL,true); 1787 } 1789 1803 public void resizeSelection(int offset, int end, int extraEndVirt, 1804 boolean rect) 1805 { 1806 Selection s = selectionManager.getSelectionAtOffset(offset); 1807 if(s != null) 1808 { 1809 invalidateLineRange(s.startLine,s.endLine); 1810 selectionManager.removeFromSelection(s); 1811 } 1812 1813 selectionManager.resizeSelection(offset,end,extraEndVirt,rect); 1814 fireCaretEvent(); 1815 } 1817 1827 public void extendSelection(int offset, int end) 1828 { 1829 extendSelection(offset,end,0,0); 1830 } 1832 1844 public void extendSelection(int offset, int end, 1845 int extraStartVirt, int extraEndVirt) 1846 { 1847 Selection s = getSelectionAtOffset(offset); 1848 if(s != null) 1849 { 1850 invalidateLineRange(s.startLine,s.endLine); 1851 selectionManager.removeFromSelection(s); 1852 1853 if(offset == s.start) 1854 { 1855 offset = end; 1856 end = s.end; 1857 } 1858 else if(offset == s.end) 1859 { 1860 offset = s.start; 1861 } 1862 } 1863 1864 if(end < offset) 1865 { 1866 int tmp = end; 1867 end = offset; 1868 offset = tmp; 1869 } 1870 1871 if(rectangularSelectionMode) 1872 { 1873 s = new Selection.Rect(offset,end); 1874 ((Selection.Rect)s).extraStartVirt = extraStartVirt; 1875 ((Selection.Rect)s).extraEndVirt = extraEndVirt; 1876 } 1877 else 1878 s = new Selection.Range(offset,end); 1879 1880 selectionManager.addToSelection(s); 1881 fireCaretEvent(); 1882 1883 if(rectangularSelectionMode && extraEndVirt != 0) 1884 { 1885 int line = getLineOfOffset(end); 1886 scrollTo(line,getLineLength(line) + extraEndVirt,false); 1887 } 1888 } 1890 1896 public String getSelectedText(Selection s) 1897 { 1898 StringBuffer buf = new StringBuffer (s.end - s.start); 1899 s.getText(buffer,buf); 1900 return buf.toString(); 1901 } 1903 1910 public String getSelectedText(String separator) 1911 { 1912 Selection[] sel = selectionManager.getSelection(); 1913 if(sel.length == 0) 1914 return null; 1915 1916 StringBuffer buf = new StringBuffer (); 1917 for(int i = 0; i < sel.length; i++) 1918 { 1919 if(i != 0) 1920 buf.append(separator); 1921 1922 sel[i].getText(buffer,buf); 1923 } 1924 1925 return buf.toString(); 1926 } 1928 1933 public String getSelectedText() 1934 { 1935 return getSelectedText("\n"); 1936 } 1938 1945 public void setSelectedText(Selection s, String selectedText) 1946 { 1947 if(!isEditable()) 1948 { 1949 throw new InternalError ("Text component" 1950 + " read only"); 1951 } 1952 1953 try 1954 { 1955 buffer.beginCompoundEdit(); 1956 1957 moveCaretPosition(s.setText(buffer,selectedText)); 1958 } 1959 finally 1962 { 1963 buffer.endCompoundEdit(); 1964 } 1965 1966 } 1970 1976 public void setSelectedText(String selectedText) 1977 { 1978 int newCaret = replaceSelection(selectedText); 1979 if(newCaret != -1) 1980 moveCaretPosition(newCaret); 1981 selectNone(); 1982 } 1984 1993 public void setSelectedText(String selectedText, boolean moveCaret) 1994 { 1995 int newCaret = replaceSelection(selectedText); 1996 if(moveCaret && newCaret != -1) 1997 moveCaretPosition(newCaret); 1998 selectNone(); 1999 } 2001 2012 public int replaceSelection(String selectedText) 2013 { 2014 if(!isEditable()) 2015 throw new RuntimeException ("Text component read only"); 2016 2017 int newCaret = -1; 2018 2019 if(getSelectionCount() == 0) 2020 { 2021 buffer.insert(caret,selectedText); 2023 } 2024 else 2025 { 2026 try 2027 { 2028 2029 buffer.beginCompoundEdit(); 2030 2031 Selection[] selection = getSelection(); 2032 for(int i = 0; i < selection.length; i++) 2033 newCaret = selection[i].setText(buffer,selectedText); 2034 } 2035 finally 2036 { 2037 buffer.endCompoundEdit(); 2038 } 2039 } 2040 2041 return newCaret; 2042 } 2044 2056 public int[] getSelectedLines() 2057 { 2058 if(selectionManager.getSelectionCount() == 0) 2059 return new int[] { caretLine }; 2060 2061 return selectionManager.getSelectedLines(); 2062 } 2064 2066 2068 2073 public boolean caretAutoScroll() 2074 { 2075 return focusedComponent == this; 2076 } 2078 2083 public void addStructureMatcher(StructureMatcher matcher) 2084 { 2085 structureMatchers.add(matcher); 2086 } 2088 2093 public void removeStructureMatcher(StructureMatcher matcher) 2094 { 2095 structureMatchers.remove(matcher); 2096 } 2098 2104 public StructureMatcher.Match getStructureMatch() 2105 { 2106 return match; 2107 } 2109 2113 public final void blinkCaret() 2114 { 2115 if(caretBlinks) 2116 { 2117 blink = !blink; 2118 invalidateLine(caretLine); 2119 } 2120 else 2121 blink = true; 2122 } 2124 2129 public void centerCaret() 2130 { 2131 int offset = getScreenLineStartOffset(visibleLines >> 1); 2132 if(offset == -1) 2133 getToolkit().beep(); 2134 else 2135 setCaretPosition(offset); 2136 } 2138 2143 public void setCaretPosition(int newCaret) 2144 { 2145 selectNone(); 2146 moveCaretPosition(newCaret,true); 2147 } 2149 2155 public void setCaretPosition(int newCaret, boolean doElectricScroll) 2156 { 2157 selectNone(); 2158 moveCaretPosition(newCaret,doElectricScroll); 2159 } 2161 2166 public void moveCaretPosition(int newCaret) 2167 { 2168 moveCaretPosition(newCaret,true); 2169 } 2171 2177 public void moveCaretPosition(int newCaret, boolean doElectricScroll) 2178 { 2179 moveCaretPosition(newCaret,doElectricScroll ? ELECTRIC_SCROLL 2180 : NORMAL_SCROLL); 2181 } 2183 public static final int NO_SCROLL = 0; 2185 public static final int NORMAL_SCROLL = 1; 2186 public static final int ELECTRIC_SCROLL = 2; 2187 2194 public void moveCaretPosition(int newCaret, int scrollMode) 2195 { 2196 if(newCaret < 0 || newCaret > buffer.getLength()) 2197 { 2198 throw new IllegalArgumentException ("caret out of bounds: " 2199 + newCaret); 2200 } 2201 2202 int oldCaretLine = caretLine; 2203 2204 if(caret == newCaret) 2205 finishCaretUpdate(oldCaretLine,scrollMode,false); 2206 else 2207 { 2208 caret = newCaret; 2209 caretLine = getLineOfOffset(newCaret); 2210 2211 magicCaret = -1; 2212 2213 finishCaretUpdate(oldCaretLine,scrollMode,true); 2214 } 2215 } 2217 2221 public int getCaretPosition() 2222 { 2223 return caret; 2224 } 2226 2230 public int getCaretLine() 2231 { 2232 return caretLine; 2233 } 2235 2241 public int getMagicCaretPosition() 2242 { 2243 if(magicCaret == -1) 2244 { 2245 magicCaret = chunkCache.subregionOffsetToX( 2246 caretLine,caret - getLineStartOffset(caretLine)); 2247 } 2248 2249 return magicCaret; 2250 } 2252 2259 public void setMagicCaretPosition(int magicCaret) 2260 { 2261 this.magicCaret = magicCaret; 2262 } 2264 2269 public final void addCaretListener(CaretListener listener) 2270 { 2271 listenerList.add(CaretListener .class,listener); 2272 } 2274 2279 public final void removeCaretListener(CaretListener listener) 2280 { 2281 listenerList.remove(CaretListener .class,listener); 2282 } 2284 2290 public void goToNextBracket(boolean select) 2291 { 2292 int newCaret = -1; 2293 2294 if(caret != buffer.getLength()) 2295 { 2296 String text = getText(caret,buffer.getLength() 2297 - caret - 1); 2298 2299loop: for(int i = 0; i < text.length(); i++) 2300 { 2301 switch(text.charAt(i)) 2302 { 2303 case ')': case ']': case '}': 2304 newCaret = caret + i + 1; 2305 break loop; 2306 } 2307 } 2308 } 2309 2310 if(newCaret == -1) 2311 getToolkit().beep(); 2312 else 2313 { 2314 if(select) 2315 extendSelection(caret,newCaret); 2316 else if(!multi) 2317 selectNone(); 2318 moveCaretPosition(newCaret); 2319 } 2320 } 2322 2328 public void goToNextCharacter(boolean select) 2329 { 2330 Selection s = getSelectionAtOffset(caret); 2331 2332 if(!select && s instanceof Selection.Range) 2333 { 2334 if(multi) 2335 { 2336 if(caret != s.end) 2337 { 2338 moveCaretPosition(s.end); 2339 return; 2340 } 2341 } 2342 else 2343 { 2344 setCaretPosition(s.end); 2345 return; 2346 } 2347 } 2348 2349 int extraStartVirt, extraEndVirt; 2350 if(s instanceof Selection.Rect) 2351 { 2352 extraStartVirt = ((Selection.Rect)s).extraStartVirt; 2353 extraEndVirt = ((Selection.Rect)s).extraEndVirt; 2354 } 2355 else 2356 { 2357 extraStartVirt = 0; 2358 extraEndVirt = 0; 2359 } 2360 2361 int newCaret = caret; 2362 2363 if(caret == buffer.getLength()) 2364 { 2365 if(select && (rectangularSelectionMode || s instanceof Selection.Rect)) 2366 { 2367 if(s != null && caret == s.start) 2368 extraStartVirt++; 2369 else 2370 extraEndVirt++; 2371 } 2372 else 2373 { 2374 getToolkit().beep(); 2375 return; 2376 } 2377 } 2378 else if(caret == getLineEndOffset(caretLine) - 1) 2379 { 2380 if(select && (rectangularSelectionMode || s instanceof Selection.Rect)) 2381 { 2382 if(s != null && caret == s.start) 2383 extraStartVirt++; 2384 else 2385 extraEndVirt++; 2386 } 2387 else 2388 { 2389 int line = displayManager.getNextVisibleLine(caretLine); 2390 if(line == -1) 2391 { 2392 getToolkit().beep(); 2393 return; 2394 } 2395 else 2396 newCaret = getLineStartOffset(line); 2397 } 2398 } 2399 else 2400 newCaret = caret + 1; 2401 2402 if(select) 2403 extendSelection(caret,newCaret,extraStartVirt,extraEndVirt); 2404 else if(!multi) 2405 selectNone(); 2406 2407 moveCaretPosition(newCaret); 2408 } 2410 2416 public void goToNextLine(boolean select) 2417 { 2418 Selection s = getSelectionAtOffset(caret); 2419 boolean rectSelect = s == null ? rectangularSelectionMode 2420 : s instanceof Selection.Rect; 2421 int magic = getMagicCaretPosition(); 2422 int newCaret = chunkCache.getBelowPosition(caretLine, 2423 caret - buffer.getLineStartOffset(caretLine),magic + 1, 2424 rectSelect && select); 2425 if(newCaret == -1) 2426 { 2427 int end = getLineEndOffset(caretLine) - 1; 2428 if(caret == end) 2429 { 2430 getToolkit().beep(); 2431 return; 2432 } 2433 else 2434 newCaret = end; 2435 } 2436 2437 _changeLine(select, newCaret); 2438 2439 setMagicCaretPosition(magic); 2440 } 2442 2448 public void goToNextPage(boolean select) 2449 { 2450 scrollToCaret(false); 2451 int magic = getMagicCaretPosition(); 2452 if(caretLine < displayManager.getFirstVisibleLine()) 2453 { 2454 caretLine = displayManager.getNextVisibleLine( 2455 caretLine); 2456 } 2457 2458 int newCaret; 2459 2460 if(getFirstLine() + getVisibleLines() >= displayManager 2461 .getScrollLineCount()) 2462 { 2463 int lastVisibleLine = displayManager 2464 .getLastVisibleLine(); 2465 newCaret = getLineEndOffset(lastVisibleLine) - 1; 2466 } 2467 else 2468 { 2469 int caretScreenLine = getScreenLineOfOffset(caret); 2470 2471 scrollDownPage(); 2472 2473 newCaret = xToScreenLineOffset(caretScreenLine, 2474 magic,true); 2475 } 2476 2477 if(select) 2478 extendSelection(caret,newCaret); 2479 else if(!multi) 2480 selectNone(); 2481 2482 moveCaretPosition(newCaret,false); 2483 2484 setMagicCaretPosition(magic); 2485 } 2487 2493 public void goToNextParagraph(boolean select) 2494 { 2495 int lineNo = getCaretLine(); 2496 2497 int newCaret = getBufferLength(); 2498 2499 boolean foundBlank = false; 2500 2501loop: for(int i = lineNo + 1; i < getLineCount(); i++) 2502 { 2503 if(!displayManager.isLineVisible(i)) 2504 continue; 2505 2506 getLineText(i,lineSegment); 2507 2508 for(int j = 0; j < lineSegment.count; j++) 2509 { 2510 switch(lineSegment.array[lineSegment.offset + j]) 2511 { 2512 case ' ': 2513 case '\t': 2514 break; 2515 default: 2516 if(foundBlank) 2517 { 2518 newCaret = getLineStartOffset(i); 2519 break loop; 2520 } 2521 else 2522 continue loop; 2523 } 2524 } 2525 2526 foundBlank = true; 2527 } 2528 2529 if(select) 2530 extendSelection(caret,newCaret); 2531 else if(!multi) 2532 selectNone(); 2533 moveCaretPosition(newCaret); 2534 } 2536 2544 public void goToNextWord(boolean select) 2545 { 2546 goToNextWord(select,false); 2547 } 2549 2554 public void goToNextWord(boolean select, boolean eatWhitespace) 2555 { 2556 int lineStart = getLineStartOffset(caretLine); 2557 int newCaret = caret - lineStart; 2558 String lineText = getLineText(caretLine); 2559 2560 if(newCaret == lineText.length()) 2561 { 2562 int nextLine = displayManager.getNextVisibleLine(caretLine); 2563 if(nextLine == -1) 2564 { 2565 getToolkit().beep(); 2566 return; 2567 } 2568 2569 newCaret = getLineStartOffset(nextLine); 2570 } 2571 else 2572 { 2573 String noWordSep = buffer.getStringProperty("noWordSep"); 2574 newCaret = TextUtilities.findWordEnd(lineText, 2575 newCaret + 1,noWordSep,true,eatWhitespace); 2576 2577 newCaret += lineStart; 2578 } 2579 2580 if(select) 2581 extendSelection(caret,newCaret); 2582 else if(!multi) 2583 selectNone(); 2584 moveCaretPosition(newCaret); 2585 } 2587 2593 public void goToPrevBracket(boolean select) 2594 { 2595 String text = getText(0,caret); 2596 2597 int newCaret = -1; 2598 2599loop: for(int i = getCaretPosition() - 1; i >= 0; i--) 2600 { 2601 switch(text.charAt(i)) 2602 { 2603 case '(': case '[': case '{': 2604 newCaret = i; 2605 break loop; 2606 } 2607 } 2608 2609 if(newCaret == -1) 2610 getToolkit().beep(); 2611 else 2612 { 2613 if(select) 2614 extendSelection(caret,newCaret); 2615 else if(!multi) 2616 selectNone(); 2617 moveCaretPosition(newCaret); 2618 } 2619 } 2621 2627 public void goToPrevCharacter(boolean select) 2628 { 2629 Selection s = getSelectionAtOffset(caret); 2630 2631 if(caret == 0) 2632 { 2633 getToolkit().beep(); 2634 return; 2635 } 2636 2637 if(!select && s instanceof Selection.Range) 2638 { 2639 if(multi) 2640 { 2641 if(caret != s.start) 2642 { 2643 moveCaretPosition(s.start); 2644 return; 2645 } 2646 } 2647 else 2648 { 2649 setCaretPosition(s.start); 2650 return; 2651 } 2652 } 2653 2654 int extraStartVirt = 0; 2655 int extraEndVirt = 0; 2656 int newCaret = caret; 2657 2658 if(select && caret == getLineEndOffset(caretLine) - 1) 2659 { 2660 if(s instanceof Selection.Rect) 2661 { 2662 extraStartVirt = ((Selection.Rect)s).extraStartVirt; 2663 extraEndVirt = ((Selection.Rect)s).extraEndVirt; 2664 if(caret == s.start) 2665 { 2666 if(extraStartVirt == 0) 2667 newCaret = caret - 1; 2668 else 2669 extraStartVirt--; 2670 } 2671 else 2672 { 2673 if(extraEndVirt == 0) 2674 newCaret = caret - 1; 2675 else 2676 extraEndVirt--; 2677 } 2678 } 2679 else 2680 newCaret = caret - 1; 2681 } 2682 else if(caret == getLineStartOffset(caretLine)) 2683 { 2684 int line = displayManager.getPrevVisibleLine(caretLine); 2685 if(line == -1) 2686 { 2687 getToolkit().beep(); 2688 return; 2689 } 2690 newCaret = getLineEndOffset(line) - 1; 2691 } 2692 else 2693 newCaret = caret - 1; 2694 2695 if(select) 2696 extendSelection(caret,newCaret,extraStartVirt,extraEndVirt); 2697 else if(!multi) 2698 selectNone(); 2699 moveCaretPosition(newCaret); 2700 } 2702 2708 public void goToPrevLine(boolean select) 2709 { 2710 Selection s = getSelectionAtOffset(caret); 2711 boolean rectSelect = s == null ? rectangularSelectionMode 2712 : s instanceof Selection.Rect; 2713 int magic = getMagicCaretPosition(); 2714 2715 int newCaret = chunkCache.getAbovePosition(caretLine, 2716 caret - buffer.getLineStartOffset(caretLine),magic + 1, 2717 rectSelect && select); 2718 if(newCaret == -1) 2719 { 2720 int start = getLineStartOffset(caretLine); 2721 if(caret == start) 2722 { 2723 getToolkit().beep(); 2724 return; 2725 } 2726 else 2727 newCaret = start; 2728 } 2729 2730 _changeLine(select, newCaret); 2731 2732 setMagicCaretPosition(magic); 2733 } 2735 2741 public void goToPrevPage(boolean select) 2742 { 2743 scrollToCaret(false); 2744 int magic = getMagicCaretPosition(); 2745 2746 if(caretLine < displayManager.getFirstVisibleLine()) 2747 { 2748 caretLine = displayManager.getNextVisibleLine( 2749 caretLine); 2750 } 2751 2752 int newCaret; 2753 2754 if(getFirstLine() == 0) 2755 { 2756 int firstVisibleLine = displayManager 2757 .getFirstVisibleLine(); 2758 newCaret = getLineStartOffset(firstVisibleLine); 2759 } 2760 else 2761 { 2762 int caretScreenLine = getScreenLineOfOffset(caret); 2763 2764 scrollUpPage(); 2765 2766 newCaret = xToScreenLineOffset(caretScreenLine, 2767 magic,true); 2768 } 2769 2770 if(select) 2771 extendSelection(caret,newCaret); 2772 else if(!multi) 2773 selectNone(); 2774 moveCaretPosition(newCaret,false); 2775 2776 setMagicCaretPosition(magic); 2777 } 2779 2785 public void goToPrevParagraph(boolean select) 2786 { 2787 int lineNo = caretLine; 2788 int newCaret = 0; 2789 2790 boolean foundBlank = false; 2791 2792loop: for(int i = lineNo - 1; i >= 0; i--) 2793 { 2794 if(!displayManager.isLineVisible(i)) 2795 continue; 2796 2797 getLineText(i,lineSegment); 2798 2799 for(int j = 0; j < lineSegment.count; j++) 2800 { 2801 switch(lineSegment.array[lineSegment.offset + j]) 2802 { 2803 case ' ': 2804 case '\t': 2805 break; 2806 default: 2807 if(foundBlank) 2808 { 2809 newCaret = getLineEndOffset(i) - 1; 2810 break loop; 2811 } 2812 else 2813 continue loop; 2814 } 2815 } 2816 2817 foundBlank = true; 2818 } 2819 2820 if(select) 2821 extendSelection(caret,newCaret); 2822 else if(!multi) 2823 selectNone(); 2824 moveCaretPosition(newCaret); 2825 } 2827 2833 public void goToPrevWord(boolean select) 2834 { 2835 goToPrevWord(select,false); 2836 } 2838 2843 public void goToPrevWord(boolean select, boolean eatWhitespace) 2844 { 2845 int lineStart = getLineStartOffset(caretLine); 2846 int newCaret = caret - lineStart; 2847 String lineText = getLineText(caretLine); 2848 2849 if(newCaret == 0) 2850 { 2851 if(lineStart == 0) 2852 { 2853 getToolkit().beep(); 2854 return; 2855 } 2856 else 2857 { 2858 int prevLine = displayManager.getPrevVisibleLine(caretLine); 2859 if(prevLine == -1) 2860 { 2861 getToolkit().beep(); 2862 return; 2863 } 2864 2865 newCaret = getLineEndOffset(prevLine) - 1; 2866 } 2867 } 2868 else 2869 { 2870 String noWordSep = buffer.getStringProperty("noWordSep"); 2871 newCaret = TextUtilities.findWordStart(lineText, 2872 newCaret - 1,noWordSep,true,eatWhitespace); 2873 2874 newCaret += lineStart; 2875 } 2876 2877 if(select) 2878 extendSelection(caret,newCaret); 2879 else if(!multi) 2880 selectNone(); 2881 moveCaretPosition(newCaret); 2882 } 2884 2892 public void smartHome(boolean select) 2893 { 2894 switch(getInputHandler().getLastActionCount()) 2895 { 2896 case 1: 2897 goToStartOfWhiteSpace(select); 2898 break; 2899 case 2: 2900 goToStartOfLine(select); 2901 break; 2902 default: goToFirstVisibleLine(select); 2904 break; 2905 } 2906 } 2908 2916 public void smartEnd(boolean select) 2917 { 2918 switch(getInputHandler().getLastActionCount()) 2919 { 2920 case 1: 2921 goToEndOfWhiteSpace(select); 2922 break; 2923 case 2: 2924 goToEndOfLine(select); 2925 break; 2926 default: goToLastVisibleLine(select); 2928 break; 2929 } 2930 } 2932 2938 public void goToStartOfLine(boolean select) 2939 { 2940 Selection s = getSelectionAtOffset(caret); 2941 int line = select || s == null ? caretLine : s.startLine; 2942 int newCaret = getLineStartOffset(line); 2943 if(select) 2944 extendSelection(caret,newCaret); 2945 else if(!multi) 2946 selectNone(); 2947 moveCaretPosition(newCaret); 2948 } 2950 2956 public void goToEndOfLine(boolean select) 2957 { 2958 Selection s = getSelectionAtOffset(caret); 2959 int line = select || s == null ? caretLine : s.endLine; 2960 int newCaret = getLineEndOffset(line) - 1; 2961 if(select) 2962 extendSelection(caret,newCaret); 2963 else if(!multi) 2964 selectNone(); 2965 moveCaretPosition(newCaret); 2966 2967 } 2972 2979 public void goToStartOfWhiteSpace(boolean select) 2980 { 2981 Selection s = getSelectionAtOffset(caret); 2982 int line, offset; 2983 if(select || s == null) 2984 { 2985 line = caretLine; 2986 offset = caret - buffer.getLineStartOffset(line); 2987 } 2988 else 2989 { 2990 line = s.startLine; 2991 offset = s.start - buffer.getLineStartOffset(line); 2992 } 2993 2994 int firstIndent = chunkCache.getSubregionStartOffset(line,offset); 2995 if(firstIndent == getLineStartOffset(line)) 2996 { 2997 firstIndent = StandardUtilities.getLeadingWhiteSpace(getLineText(line)); 2998 if(firstIndent == getLineLength(line)) 2999 firstIndent = 0; 3000 firstIndent += getLineStartOffset(line); 3001 } 3002 3003 if(select) 3004 extendSelection(caret,firstIndent); 3005 else if(!multi) 3006 selectNone(); 3007 moveCaretPosition(firstIndent); 3008 } 3010 3017 public void goToEndOfWhiteSpace(boolean select) 3018 { 3019 Selection s = getSelectionAtOffset(caret); 3020 int line, offset; 3021 if(select || s == null) 3022 { 3023 line = caretLine; 3024 offset = caret - getLineStartOffset(line); 3025 } 3026 else 3027 { 3028 line = s.endLine; 3029 offset = s.end - getLineStartOffset(line); 3030 } 3031 3032 int lastIndent = chunkCache.getSubregionEndOffset(line,offset); 3033 3034 if(lastIndent == getLineEndOffset(line)) 3035 { 3036 lastIndent = getLineLength(line) - StandardUtilities.getTrailingWhiteSpace(getLineText(line)); 3037 if(lastIndent == 0) 3038 lastIndent = getLineLength(line); 3039 lastIndent += getLineStartOffset(line); 3040 } 3041 else 3042 { 3043 lastIndent--; 3044 } 3045 3046 if(select) 3047 extendSelection(caret,lastIndent); 3048 else if(!multi) 3049 selectNone(); 3050 moveCaretPosition(lastIndent); 3051 } 3053 3059 public void goToFirstVisibleLine(boolean select) 3060 { 3061 int firstVisibleLine = getFirstLine() == 0 ? 0 : electricScroll; 3062 int firstVisible = getScreenLineStartOffset(firstVisibleLine); 3063 if(firstVisible == -1) 3064 { 3065 firstVisible = getLineStartOffset(displayManager 3066 .getFirstVisibleLine()); 3067 } 3068 3069 if(select) 3070 extendSelection(caret,firstVisible); 3071 else if(!multi) 3072 selectNone(); 3073 moveCaretPosition(firstVisible); 3074 } 3076 3082 public void goToLastVisibleLine(boolean select) 3083 { 3084 int lastVisible; 3085 3086 if(getFirstLine() + visibleLines >= 3087 displayManager.getScrollLineCount()) 3088 { 3089 lastVisible = getLineEndOffset(displayManager 3090 .getLastVisibleLine()) - 1; 3091 } 3092 else 3093 { 3094 lastVisible = visibleLines - electricScroll - 1; 3095 if(lastLinePartial) 3096 lastVisible--; 3097 if(lastVisible < 0) 3098 lastVisible = 0; 3099 lastVisible = getScreenLineEndOffset(lastVisible) - 1; 3100 if(lastVisible == -1) 3101 { 3102 lastVisible = getLineEndOffset(displayManager 3103 .getLastVisibleLine()) - 1; 3104 } 3105 } 3106 3107 if(select) 3108 extendSelection(caret,lastVisible); 3109 else if(!multi) 3110 selectNone(); 3111 moveCaretPosition(lastVisible); 3112 } 3114 3120 public void goToBufferStart(boolean select) 3121 { 3122 int start = buffer.getLineStartOffset( 3123 displayManager.getFirstVisibleLine()); 3124 if(select) 3125 extendSelection(caret,start); 3126 else if(!multi) 3127 selectNone(); 3128 moveCaretPosition(start); 3129 } 3131 3137 public void goToBufferEnd(boolean select) 3138 { 3139 int end = buffer.getLineEndOffset( 3140 displayManager.getLastVisibleLine()) - 1; 3141 if(select) 3142 extendSelection(caret,end); 3143 else if(!multi) 3144 selectNone(); 3145 moveCaretPosition(end); 3146 } 3148 3153 public void goToMatchingBracket() 3154 { 3155 if(getLineLength(caretLine) != 0) 3156 { 3157 int dot = caret - getLineStartOffset(caretLine); 3158 3159 int bracket = TextUtilities.findMatchingBracket( 3160 buffer,caretLine,Math.max(0,dot - 1)); 3161 if(bracket != -1) 3162 { 3163 selectNone(); 3164 moveCaretPosition(bracket + 1,false); 3165 return; 3166 } 3167 } 3168 3169 getToolkit().beep(); 3170 } 3172 3174 3176 3193 public void userInput(char ch) 3194 { 3195 if(!isEditable()) 3196 { 3197 getToolkit().beep(); 3198 return; 3199 } 3200 3201 3202 if(hiddenCursor != null) 3203 getPainter().setCursor(hiddenCursor); 3204 3205 if(ch == '\t') 3206 userInputTab(); 3207 else 3208 { 3209 boolean indent = buffer.isElectricKey(ch, caretLine); 3210 String str = String.valueOf(ch); 3211 if(getSelectionCount() == 0) 3212 { 3213 if(!doWordWrap(ch == ' ')) 3214 insert(str,indent); 3215 } 3216 else 3217 replaceSelection(str); 3218 } 3219 } 3221 3225 public final boolean isOverwriteEnabled() 3226 { 3227 return overwrite; 3228 } 3230 3234 public final void setOverwriteEnabled(boolean overwrite) 3235 { 3236 blink = true; 3237 caretTimer.restart(); 3238 3239 this.overwrite = overwrite; 3240 invalidateLine(caretLine); 3241 fireStatusChanged(StatusListener.OVERWRITE_CHANGED,overwrite); 3242 } 3244 3249 public final void toggleOverwriteEnabled() 3250 { 3251 setOverwriteEnabled(!overwrite); 3252 } 3254 3260 public void backspace() 3261 { 3262 delete(false); 3263 } 3265 3270 public void backspaceWord() 3271 { 3272 backspaceWord(false); 3273 } 3275 3281 public void backspaceWord(boolean eatWhitespace) 3282 { 3283 if(!buffer.isEditable()) 3284 { 3285 getToolkit().beep(); 3286 return; 3287 } 3288 3289 if(getSelectionCount() != 0) 3290 { 3291 setSelectedText(""); 3292 return; 3293 } 3294 3295 int lineStart = getLineStartOffset(caretLine); 3296 int _caret = caret - lineStart; 3297 3298 String lineText = getLineText(caretLine); 3299 3300 if(_caret == 0) 3301 { 3302 if(lineStart == 0) 3303 { 3304 getToolkit().beep(); 3305 return; 3306 } 3307 _caret--; 3308 } 3309 else 3310 { 3311 String noWordSep = buffer.getStringProperty("noWordSep"); 3312 _caret = TextUtilities.findWordStart(lineText,_caret-1, 3313 noWordSep,true,eatWhitespace); 3314 } 3315 3316 buffer.remove(_caret + lineStart, 3317 caret - (_caret + lineStart)); 3318 } 3320 3325 public void delete() 3326 { 3327 delete(true); 3328 } 3330 3335 public void deleteToEndOfLine() 3336 { 3337 if(!buffer.isEditable()) 3338 { 3339 getToolkit().beep(); 3340 return; 3341 } 3342 3343 buffer.remove(caret,getLineEndOffset(caretLine) 3344 - caret - 1); 3345 } 3347 3352 public void deleteLine() 3353 { 3354 if(!buffer.isEditable()) 3355 { 3356 getToolkit().beep(); 3357 return; 3358 } 3359 3360 int x = chunkCache.subregionOffsetToX(caretLine,caret - getLineStartOffset(caretLine)); 3361 int[] lines = getSelectedLines(); 3362 3363 try 3364 { 3365 buffer.beginCompoundEdit(); 3366 3367 for (int i = lines.length - 1; i >= 0; i--) 3368 { 3369 int start = getLineStartOffset(lines[i]); 3370 int end = getLineEndOffset(lines[i]); 3371 if (end > buffer.getLength()) 3372 { 3373 if (start != 0) 3374 start--; 3375 end--; 3376 } 3377 buffer.remove(start,end - start); 3378 } 3379 } 3380 finally 3381 { 3382 buffer.endCompoundEdit(); 3383 } 3384 3385 int lastLine = displayManager.getLastVisibleLine(); 3386 3387 if(caretLine == lastLine) 3388 { 3389 int offset = chunkCache.xToSubregionOffset(lastLine,0,x,true); 3390 setCaretPosition(buffer.getLineStartOffset(lastLine) 3391 + offset); 3392 } 3393 else 3394 { 3395 int offset = chunkCache.xToSubregionOffset(caretLine,0,x,true); 3396 setCaretPosition(getLineStartOffset(caretLine) + offset); 3397 } 3398 } 3400 3405 public void deleteParagraph() 3406 { 3407 if(!buffer.isEditable()) 3408 { 3409 getToolkit().beep(); 3410 return; 3411 } 3412 3413 int start = 0; 3415 for(int i = caretLine - 1; i >= 0; i--) 3416 { 3417 if (lineContainsSpaceAndTabs(i)) 3418 { 3419 start = getLineStartOffset(i); 3420 break; 3421 } 3422 } 3423 3424 int end = buffer.getLength(); 3426 for(int i = caretLine + 1; i < getLineCount(); i++) 3427 { 3428 3431 if (lineContainsSpaceAndTabs(i)) 3432 { 3433 end = getLineEndOffset(i) - 1; 3434 break; 3435 } 3436 } 3437 3438 buffer.remove(start,end - start); 3439 } 3441 3446 public void deleteToStartOfLine() 3447 { 3448 if(!buffer.isEditable()) 3449 { 3450 getToolkit().beep(); 3451 return; 3452 } 3453 3454 buffer.remove(getLineStartOffset(caretLine), 3455 caret - getLineStartOffset(caretLine)); 3456 } 3458 3463 public void deleteWord() 3464 { 3465 deleteWord(false); 3466 } 3468 3475 public void deleteWord(boolean eatWhitespace) 3476 { 3477 if(!buffer.isEditable()) 3478 { 3479 getToolkit().beep(); 3480 return; 3481 } 3482 3483 if(getSelectionCount() != 0) 3484 { 3485 setSelectedText(""); 3486 return; 3487 } 3488 3489 int lineStart = getLineStartOffset(caretLine); 3490 int _caret = caret - lineStart; 3491 3492 String lineText = getLineText(caretLine); 3493 3494 if(_caret == lineText.length()) 3495 { 3496 if(lineStart + _caret == buffer.getLength()) 3497 { 3498 getToolkit().beep(); 3499 return; 3500 } 3501 _caret++; 3502 } 3503 else 3504 { 3505 String noWordSep = buffer.getStringProperty("noWordSep"); 3506 _caret = TextUtilities.findWordEnd(lineText, 3507 _caret+1,noWordSep,true,eatWhitespace); 3508 } 3509 3510 buffer.remove(caret,(_caret + lineStart) - caret); 3511 } 3513 3518 public final boolean isMultipleSelectionEnabled() 3519 { 3520 return multi; 3521 } 3523 3528 public final void toggleMultipleSelectionEnabled() 3529 { 3530 setMultipleSelectionEnabled(!multi); 3531 } 3533 3544 public final void setMultipleSelectionEnabled(boolean multi) 3545 { 3546 this.multi = multi; 3547 fireStatusChanged(StatusListener.MULTI_SELECT_CHANGED,multi); 3548 painter.repaint(); 3549 } 3551 3556 public final boolean isRectangularSelectionEnabled() 3557 { 3558 return rectangularSelectionMode; 3559 } 3561 3566 public final void toggleRectangularSelectionEnabled() 3567 { 3568 setRectangularSelectionEnabled(!rectangularSelectionMode); 3569 3570 if(getSelectionCount() == 1) 3571 { 3572 Selection s = getSelection(0); 3573 removeFromSelection(s); 3574 if(rectangularSelectionMode) 3575 { 3576 addToSelection(new Selection.Rect( 3577 s.getStart(),s.getEnd())); 3578 } 3579 else 3580 { 3581 addToSelection(new Selection.Range( 3582 s.getStart(),s.getEnd())); 3583 } 3584 } 3585 } 3587 3599 public final void setRectangularSelectionEnabled( 3600 boolean rectangularSelectionMode) 3601 { 3602 this.rectangularSelectionMode = rectangularSelectionMode; 3603 fireStatusChanged(StatusListener.RECT_SELECT_CHANGED, 3604 rectangularSelectionMode); 3605 painter.repaint(); 3606 } 3608 3610 3612 3618 public void goToParentFold() 3619 { 3620 int line = -1; 3621 int level = buffer.getFoldLevel(caretLine); 3622 for(int i = caretLine - 1; i >= 0; i--) 3623 { 3624 if(buffer.getFoldLevel(i) < level) 3625 { 3626 line = i; 3627 break; 3628 } 3629 } 3630 3631 if(line == -1) 3632 { 3633 getToolkit().beep(); 3634 return; 3635 } 3636 3637 int magic = getMagicCaretPosition(); 3638 3639 int newCaret = buffer.getLineStartOffset(line) 3640 + chunkCache.xToSubregionOffset(line,0,magic + 1,true); 3641 if(!multi) 3642 selectNone(); 3643 3644 moveCaretPosition(newCaret); 3645 setMagicCaretPosition(magic); 3646 } 3648 3654 public void goToNextFold(boolean select) 3655 { 3656 int nextFold = -1; 3657 for(int i = caretLine + 1; i < buffer.getLineCount(); i++) 3658 { 3659 if(buffer.isFoldStart(i) 3660 && displayManager.isLineVisible(i)) 3661 { 3662 nextFold = i; 3663 break; 3664 } 3665 } 3666 3667 if(nextFold == -1) 3668 { 3669 getToolkit().beep(); 3670 return; 3671 } 3672 3673 int magic = getMagicCaretPosition(); 3674 3675 int newCaret = buffer.getLineStartOffset(nextFold) 3676 + chunkCache.xToSubregionOffset(nextFold,0,magic + 1,true); 3677 if(select) 3678 extendSelection(caret,newCaret); 3679 else if(!multi) 3680 selectNone(); 3681 3682 moveCaretPosition(newCaret); 3683 setMagicCaretPosition(magic); 3684 } 3686 3692 public void goToPrevFold(boolean select) 3693 { 3694 int prevFold = -1; 3695 for(int i = caretLine - 1; i >= 0; i--) 3696 { 3697 if(buffer.isFoldStart(i) 3698 && displayManager.isLineVisible(i)) 3699 { 3700 prevFold = i; 3701 break; 3702 } 3703 } 3704 3705 if(prevFold == -1) 3706 { 3707 getToolkit().beep(); 3708 return; 3709 } 3710 3711 int magic = getMagicCaretPosition(); 3712 3713 int newCaret = buffer.getLineStartOffset(prevFold) 3714 + chunkCache.xToSubregionOffset(prevFold,0,magic + 1,true); 3715 if(select) 3716 extendSelection(caret,newCaret); 3717 else if(!multi) 3718 selectNone(); 3719 3720 moveCaretPosition(newCaret); 3721 setMagicCaretPosition(magic); 3722 } 3724 3730 public void collapseFold() 3731 { 3732 collapseFold(caretLine); 3733 } 3735 3741 public void collapseFold(int line) 3742 { 3743 int x = chunkCache.subregionOffsetToX(caretLine, 3744 caret - getLineStartOffset(caretLine)); 3745 3746 displayManager.collapseFold(line); 3747 3748 if(displayManager.isLineVisible(caretLine)) 3749 return; 3750 3751 line = displayManager.getPrevVisibleLine(caretLine); 3752 3753 if(!multi) 3754 { 3755 invalidateSelectedLines(); 3757 selectionManager.setSelection((Selection) null); 3758 } 3759 moveCaretPosition(buffer.getLineStartOffset(line) 3760 + chunkCache.xToSubregionOffset(line,0,x,true)); 3761 } 3763 3769 public void expandFold(boolean fully) 3770 { 3771 int x = chunkCache.subregionOffsetToX(caretLine, 3772 caret - getLineStartOffset(caretLine)); 3773 3774 int line = displayManager.expandFold(caretLine,fully); 3775 3776 if(!fully && line != -1) 3777 { 3778 if(!multi) 3779 selectNone(); 3780 moveCaretPosition(getLineStartOffset(line) 3781 + chunkCache.xToSubregionOffset(line,0,x,true)); 3782 } 3783 } 3785 3790 public void selectFold() 3791 { 3792 selectFold(caretLine); 3793 } 3795 3801 public void selectFold(int line) 3802 { 3803 int[] lines = buffer.getFoldAtLine(line); 3804 3805 int newCaret = getLineEndOffset(lines[1]) - 1; 3806 Selection s = new Selection.Range(getLineStartOffset(lines[0]),newCaret); 3807 if(multi) 3808 addToSelection(s); 3809 else 3810 setSelection(s); 3811 moveCaretPosition(newCaret); 3812 } 3814 3819 public void narrowToFold() 3820 { 3821 int[] lines = buffer.getFoldAtLine(caretLine); 3822 if(lines[0] == 0 && lines[1] == buffer.getLineCount() - 1) 3823 getToolkit().beep(); 3824 else 3825 displayManager.narrow(lines[0],lines[1]); 3826 } 3828 3833 public void narrowToSelection() 3834 { 3835 if(getSelectionCount() != 1) 3836 { 3837 getToolkit().beep(); 3838 return; 3839 } 3840 3841 Selection sel = getSelection(0); 3842 displayManager.narrow(sel.getStartLine(),sel.getEndLine()); 3843 3844 selectNone(); 3845 } 3847 3852 public void addExplicitFold() throws TextAreaException 3853 { 3854 if(!buffer.isEditable()) 3855 { 3856 getToolkit().beep(); 3857 return; 3858 } 3859 if(!buffer.getStringProperty("folding").equals("explicit")) 3860 { 3861 throw new TextAreaException("folding-not-explicit"); 3862 } 3863 3864 try 3865 { 3866 buffer.beginCompoundEdit(); 3867 3868 if (getSelectionCount() == 0) 3869 { 3870 addExplicitFold(caret, caret, caretLine, caretLine); 3871 } 3872 else 3873 { 3874 Selection[] selections = getSelection(); 3875 Selection selection = null; 3876 int caretBack = 0; 3877 for (int i = 0; i < selections.length; i++) 3878 { 3879 selection = selections[i]; 3880 caretBack = addExplicitFold(selection.start, selection.end, selection.startLine,selection.endLine); 3881 } 3882 assert selection != null; 3884 setCaretPosition(selection.start - caretBack, false); 3885 } 3886 } 3887 finally 3888 { 3889 buffer.endCompoundEdit(); 3890 } 3891 } 3894 3896 3901 public void lineComment() 3902 { 3903 String comment = buffer.getContextSensitiveProperty(caret,"lineComment"); 3904 if(!buffer.isEditable() || comment == null || comment.length() == 0) 3905 { 3906 getToolkit().beep(); 3907 return; 3908 } 3909 3910 comment += ' '; 3911 3912 buffer.beginCompoundEdit(); 3913 3914 int[] lines = getSelectedLines(); 3915 3916 try 3917 { 3918 for(int i = 0; i < lines.length; i++) 3919 { 3920 String text = getLineText(lines[i]); 3921 buffer.insert(getLineStartOffset(lines[i]) 3922 + StandardUtilities.getLeadingWhiteSpace(text), 3923 comment); 3924 } 3925 } 3926 finally 3927 { 3928 buffer.endCompoundEdit(); 3929 } 3930 3931 selectNone(); 3932 } 3934 3940 public void rangeComment() 3941 { 3942 String commentStart = buffer.getContextSensitiveProperty(caret,"commentStart"); 3943 String commentEnd = buffer.getContextSensitiveProperty(caret,"commentEnd"); 3944 if(!buffer.isEditable() || commentStart == null || commentEnd == null 3945 || commentStart.length() == 0 || commentEnd.length() == 0) 3946 { 3947 getToolkit().beep(); 3948 return; 3949 } 3950 3951 commentStart += ' '; 3952 commentEnd = ' ' + commentEnd; 3953 3954 try 3955 { 3956 buffer.beginCompoundEdit(); 3957 3958 Selection[] selection = getSelection(); 3959 3960 if(selection.length == 0) 3961 { 3962 int oldCaret = caret; 3963 buffer.insert(caret,commentStart); 3964 buffer.insert(caret,commentEnd); 3965 setCaretPosition(oldCaret + commentStart.length()); 3966 } 3967 3968 for(int i = 0; i < selection.length; i++) 3969 { 3970 Selection s = selection[i]; 3971 if(s instanceof Selection.Range) 3972 { 3973 buffer.insert(s.start,commentStart); 3974 buffer.insert(s.end,commentEnd); 3975 } 3976 else if(s instanceof Selection.Rect) 3977 { 3978 Selection.Rect rect = (Selection.Rect)s; 3979 int start = rect.getStartColumn(buffer); 3980 int end = rect.getEndColumn(buffer); 3981 3982 for(int j = s.startLine; j <= s.endLine; j++) 3983 { 3984 buffer.insertAtColumn(j,end, 3985 commentEnd); 3986 buffer.insertAtColumn(j,start, 3987 commentStart); 3988 } 3989 } 3990 } 3991 3992 selectNone(); 3993 } 3994 finally 3995 { 3996 buffer.endCompoundEdit(); 3997 } 3998 } 4000 4005 public void formatParagraph() throws TextAreaException 4006 { 4007 if(!buffer.isEditable()) 4008 { 4009 getToolkit().beep(); 4010 return; 4011 } 4012 4013 if(maxLineLen <= 0) 4014 { 4015 throw new TextAreaException("format-maxlinelen"); 4016 } 4017 4018 Selection[] selection = getSelection(); 4019 if(selection.length != 0) 4020 { 4021 buffer.beginCompoundEdit(); 4022 4023 for(int i = 0; i < selection.length; i++) 4024 { 4025 Selection s = selection[i]; 4026 setSelectedText(s,TextUtilities.format( 4027 getSelectedText(s),maxLineLen, 4028 buffer.getTabSize())); 4029 } 4030 4031 buffer.endCompoundEdit(); 4032 } 4033 else 4034 { 4035 int lineNo = getCaretLine(); 4036 4037 int start = 0, end = buffer.getLength(); 4038 4039 for(int i = lineNo - 1; i >= 0; i--) 4040 { 4041 if (lineContainsSpaceAndTabs(i)) 4042 { 4043 start = getLineEndOffset(i); 4044 break; 4045 } 4046 } 4047 4048 for(int i = lineNo + 1; i < getLineCount(); i++) 4049 { 4050 if (lineContainsSpaceAndTabs(i)) 4051 { 4052 end = getLineStartOffset(i) - 1; 4053 break; 4054 } 4055 } 4056 4057 try 4058 { 4059 buffer.beginCompoundEdit(); 4060 4061 String text = buffer.getText(start,end - start); 4062 int offset = getCaretPosition() - start; 4063 int noSpaceOffset = TextUtilities.indexIgnoringWhitespace( 4064 text,offset); 4065 buffer.remove(start,end - start); 4066 text = TextUtilities.format( 4067 text,maxLineLen,buffer.getTabSize()); 4068 buffer.insert(start,text); 4069 int caretPos = start; 4070 if (text.length() != 0) 4071 { 4072 caretPos += Math.min(text.length(), 4073 TextUtilities.ignoringWhitespaceIndex( 4074 text,noSpaceOffset)); 4075 } 4076 moveCaretPosition(caretPos); 4077 } 4078 finally 4079 { 4080 buffer.endCompoundEdit(); 4081 } 4082 } 4083 } 4085 4090 public void spacesToTabs() 4091 { 4092 Selection[] selection = getSelection(); 4093 4094 if(!buffer.isEditable()) 4095 { 4096 getToolkit().beep(); 4097 return; 4098 } 4099 4100 buffer.beginCompoundEdit(); 4101 4102 if(selection.length == 0) 4103 { 4104 setText(TextUtilities.spacesToTabs( 4105 getText(), buffer.getTabSize())); 4106 } 4107 else 4108 { 4109 for(int i = 0; i < selection.length; i++) 4110 { 4111 Selection s = selection[i]; 4112 setSelectedText(s,TextUtilities.spacesToTabs( 4113 getSelectedText(s),buffer.getTabSize())); 4114 } 4115 } 4116 4117 buffer.endCompoundEdit(); 4118 } 4120 4125 public void tabsToSpaces() 4126 { 4127 Selection[] selection = getSelection(); 4128 4129 if(!buffer.isEditable()) 4130 { 4131 getToolkit().beep(); 4132 return; 4133 } 4134 4135 buffer.beginCompoundEdit(); 4136 4137 if(selection.length == 0) 4138 { 4139 setText(TextUtilities.tabsToSpaces( 4140 getText(), buffer.getTabSize())); 4141 } 4142 else 4143 { 4144 for(int i = 0; i < selection.length; i++) 4145 { 4146 Selection s = selection[i]; 4147 setSelectedText(s,TextUtilities.tabsToSpaces( 4148 getSelectedText(s),buffer.getTabSize())); 4149 } 4150 } 4151 4152 buffer.endCompoundEdit(); 4153 } 4155 4160 public void toUpperCase() 4161 { 4162 if(!buffer.isEditable()) 4163 { 4164 getToolkit().beep(); 4165 return; 4166 } 4167 4168 Selection[] selection = getSelection(); 4169 int caret = -1; 4170 if (selection.length == 0) 4171 { 4172 caret = getCaretPosition(); 4173 selectWord(); 4174 selection = getSelection(); 4175 } 4176 if (selection.length == 0) 4177 { 4178 if (caret != -1) 4179 setCaretPosition(caret); 4180 getToolkit().beep(); 4181 return; 4182 } 4183 4184 buffer.beginCompoundEdit(); 4185 4186 for(int i = 0; i < selection.length; i++) 4187 { 4188 Selection s = selection[i]; 4189 setSelectedText(s,getSelectedText(s).toUpperCase()); 4190 } 4191 4192 buffer.endCompoundEdit(); 4193 if (caret != -1) 4194 setCaretPosition(caret); 4195 } 4197 4202 public void toLowerCase() 4203 { 4204 if(!buffer.isEditable()) 4205 { 4206 getToolkit().beep(); 4207 return; 4208 } 4209 4210 Selection[] selection = getSelection(); 4211 int caret = -1; 4212 if (selection.length == 0) 4213 { 4214 caret = getCaretPosition(); 4215 selectWord(); 4216 selection = getSelection(); 4217 } 4218 if (selection.length == 0) 4219 { 4220 if (caret != -1) 4221 setCaretPosition(caret); 4222 getToolkit().beep(); 4223 return; 4224 } 4225 4226 buffer.beginCompoundEdit(); 4227 4228 for (int i = 0; i < selection.length; i++) 4229 { 4230 Selection s = selection[i]; 4231 setSelectedText(s,getSelectedText(s).toLowerCase()); 4232 } 4233 4234 buffer.endCompoundEdit(); 4235 if (caret != -1) 4236 setCaretPosition(caret); 4237 } 4239 4244 public void removeTrailingWhiteSpace() 4245 { 4246 if(!buffer.isEditable()) 4247 getToolkit().beep(); 4248 else 4249 { 4250 buffer.removeTrailingWhiteSpace(getSelectedLines()); 4251 } 4252 } 4254 public void insertEnterAndIndent() 4256 { 4257 if(!isEditable()) 4258 getToolkit().beep(); 4259 else 4260 { 4261 try 4262 { 4263 buffer.beginCompoundEdit(); 4264 setSelectedText("\n"); 4265 buffer.indentLine(caretLine,true); 4266 } 4267 finally 4268 { 4269 buffer.endCompoundEdit(); 4270 } 4271 } 4272 } 4274 public void insertTabAndIndent() 4276 { 4277 if(!isEditable()) 4278 { 4279 getToolkit().beep(); 4280 return; 4281 } 4282 4283 if(getSelectionCount() == 0) 4284 { 4285 String text = buffer.getLineText(caretLine); 4287 int start = buffer.getLineStartOffset(caretLine); 4288 int whiteSpace = StandardUtilities.getLeadingWhiteSpace(text); 4289 4290 if(caret - start <= whiteSpace 4291 && buffer.indentLine(caretLine,false)) 4292 return; 4293 } 4294 4295 userInput('\t'); 4296 } 4298 4303 public void indentSelectedLines() 4304 { 4305 if(!buffer.isEditable()) 4306 getToolkit().beep(); 4307 else 4308 { 4309 buffer.indentLines(getSelectedLines()); 4310 selectNone(); 4311 } 4312 } 4314 4319 public void shiftIndentLeft() 4320 { 4321 if(!buffer.isEditable()) 4322 getToolkit().beep(); 4323 else 4324 { 4325 buffer.shiftIndentLeft(getSelectedLines()); 4326 } 4327 } 4329 4334 public void shiftIndentRight() 4335 { 4336 if(!buffer.isEditable()) 4337 getToolkit().beep(); 4338 else 4339 buffer.shiftIndentRight(getSelectedLines()); 4340 } 4342 4347 public void joinLines() 4348 { 4349 if (getSelectionCount() == 0) 4350 { 4351 int end = getLineEndOffset(caretLine); 4352 if(!buffer.isEditable() || end > buffer.getLength()) 4353 { 4354 getToolkit().beep(); 4355 return; 4356 } 4357 4358 try 4359 { 4360 buffer.beginCompoundEdit(); 4361 String nextLineText = buffer.getLineText(caretLine + 1); 4362 buffer.remove(end - 1,StandardUtilities.getLeadingWhiteSpace( 4363 nextLineText) + 1); 4364 if (nextLineText.length() != 0) 4365 buffer.insert(end - 1, " "); 4366 } 4367 finally 4368 { 4369 buffer.endCompoundEdit(); 4370 } 4371 setCaretPosition(end - 1); 4372 } 4373 else 4374 { 4375 try 4376 { 4377 buffer.beginCompoundEdit(); 4378 Selection[] selections = selectionManager.getSelection(); 4379 for (int i = 0; i < selections.length; i++) 4380 { 4381 Selection selection = selections[i]; 4382 joinLines(selection); 4383 } 4384 } 4385 finally 4386 { 4387 buffer.endCompoundEdit(); 4388 } 4389 } 4390 } 4392 4400 private void joinLines(Selection selection) 4401 { 4402 do 4403 { 4404 if (selection.startLine == buffer.getLineCount() - 1) 4405 return; 4406 int end = getLineEndOffset(selection.startLine); 4407 String nextLineText = buffer.getLineText(selection.startLine + 1); 4408 buffer.remove(end - 1,StandardUtilities.getLeadingWhiteSpace( 4409 nextLineText) + 1); 4410 if (nextLineText.length() != 0) 4411 buffer.insert(end - 1, " "); 4412 } 4413 while (selection.startLine < selection.endLine); 4414 } 4417 4419 4428 public void addLeftOfScrollBar(Component comp) 4429 { 4430 verticalBox.add(comp,verticalBox.getComponentCount() - 1); 4431 } 4433 4440 public void removeLeftOfScrollBar(Component comp) 4441 { 4442 verticalBox.remove(comp); 4443 } 4445 4450 public void addNotify() 4451 { 4452 super.addNotify(); 4453 4454 ToolTipManager.sharedInstance().registerComponent(painter); 4455 ToolTipManager.sharedInstance().registerComponent(gutter); 4456 4457 recalculateVisibleLines(); 4458 if(!buffer.isLoading()) 4459 recalculateLastPhysicalLine(); 4460 propertiesChanged(); 4461 4462 hiddenCursor = getToolkit().createCustomCursor( 4463 getGraphicsConfiguration() 4464 .createCompatibleImage(16,16, 4465 Transparency.BITMASK), 4466 new Point(0,0),"Hidden"); 4467 } 4469 4475 public void removeNotify() 4476 { 4477 super.removeNotify(); 4478 4479 ToolTipManager.sharedInstance().unregisterComponent(painter); 4480 ToolTipManager.sharedInstance().unregisterComponent(gutter); 4481 4482 if(focusedComponent == this) 4483 focusedComponent = null; 4484 } 4486 4491 public boolean getFocusTraversalKeysEnabled() 4492 { 4493 return false; 4494 } 4496 4502 public boolean getFocusCycleRoot() 4503 { 4504 return true; 4505 } 4507 public void processKeyEvent(KeyEvent evt) 4509 { 4510 getInputHandler().processKeyEvent(evt,1, false); 4511 if(!evt.isConsumed()) 4512 super.processKeyEvent(evt); 4513 4514 } 4516 4522 public void addTopComponent(Component comp) 4523 { 4524 add(ScrollLayout.TOP,comp); 4525 } 4527 4533 public void removeTopComponent(Component comp) 4534 { 4535 remove(comp); 4536 } 4538 private InputMethodSupport inputMethodSupport; 4540 public InputMethodRequests getInputMethodRequests() 4541 { 4542 if(inputMethodSupport == null) 4543 { 4544 inputMethodSupport = new InputMethodSupport(this); 4545 Log.log(Log.DEBUG, this, "InputMethodSupport is activated"); 4546 } 4547 return inputMethodSupport; 4548 } 4551 4557 public final void addStatusListener(StatusListener listener) 4558 { 4559 listenerList.add(StatusListener.class,listener); 4560 } 4562 4568 public final void removeStatusListener(StatusListener listener) 4569 { 4570 listenerList.remove(StatusListener.class,listener); 4571 } 4573 4577 public void propertiesChanged() 4578 { 4579 if(buffer == null) 4580 return; 4581 4582 int _tabSize = buffer.getTabSize(); 4583 char[] foo = new char[_tabSize]; 4584 for(int i = 0; i < foo.length; i++) 4585 foo[i] = ' '; 4586 4587 tabSize = painter.getStringWidth(new String (foo)); 4588 4589 charWidth = (int)Math.round( 4590 painter.getFont().getStringBounds(foo,0,1, 4591 painter.getFontRenderContext()).getWidth()); 4592 4593 String oldWrap = wrap; 4594 wrap = buffer.getStringProperty("wrap"); 4595 hardWrap = wrap.equals("hard"); 4596 softWrap = wrap.equals("soft"); 4597 boolean oldWrapToWidth = wrapToWidth; 4598 int oldWrapMargin = wrapMargin; 4599 setMaxLineLength(buffer.getIntegerProperty("maxLineLen",0)); 4600 4601 boolean wrapSettingsChanged = !(wrap.equals(oldWrap) 4602 && oldWrapToWidth == wrapToWidth 4603 && oldWrapMargin == wrapMargin); 4604 4605 if(displayManager != null && !bufferChanging 4606 && !buffer.isLoading() && wrapSettingsChanged) 4607 { 4608 displayManager.invalidateScreenLineCounts(); 4609 displayManager.notifyScreenLineChanges(); 4610 } 4611 4612 repaintMgr.setFastScroll(false); 4613 chunkCache.invalidateAll(); 4614 gutter.repaint(); 4615 painter.repaint(); 4616 } 4618 4620 4625 public final int getSelectionStart() 4626 { 4627 if(getSelectionCount() != 1) 4628 return caret; 4629 4630 return getSelection(0).getStart(); 4631 } 4633 4638 public int getSelectionStart(int line) 4639 { 4640 if(getSelectionCount() != 1) 4641 return caret; 4642 4643 return getSelection(0).getStart(buffer,line); 4644 } 4646 4651 public final int getSelectionStartLine() 4652 { 4653 if(getSelectionCount() != 1) 4654 return caret; 4655 4656 return getSelection(0).getStartLine(); 4657 } 4659 4663 public final void setSelectionStart(int selectionStart) 4664 { 4665 int selectionEnd = getSelectionCount() == 1 ? getSelection(0).getEnd() : caret; 4666 select(selectionStart,selectionEnd,true); 4667 } 4669 4674 public final int getSelectionEnd() 4675 { 4676 return getSelectionCount() == 1 ? getSelection(0).getEnd() : caret; 4677 4678 } 4680 4685 public int getSelectionEnd(int line) 4686 { 4687 if(getSelectionCount() != 1) 4688 return caret; 4689 4690 return getSelection(0).getEnd(buffer,line); 4691 } 4693 4698 public final int getSelectionEndLine() 4699 { 4700 if(getSelectionCount() != 1) 4701 return caret; 4702 4703 return getSelection(0).getEndLine(); 4704 } 4706 4710 public final void setSelectionEnd(int selectionEnd) 4711 { 4712 select(getSelectionStart(),selectionEnd,true); 4713 } 4715 4719 public final int getMarkPosition() 4720 { 4721 Selection s = getSelectionAtOffset(caret); 4722 if(s == null) 4723 return caret; 4724 4725 if(s.start == caret) 4726 return s.end; 4727 else if(s.end == caret) 4728 return s.start; 4729 else 4730 return caret; 4731 } 4733 4737 public final int getMarkLine() 4738 { 4739 if(getSelectionCount() != 1) 4740 return caretLine; 4741 4742 Selection s = getSelection(0); 4743 if(s.start == caret) 4744 return s.endLine; 4745 else if(s.end == caret) 4746 return s.startLine; 4747 else 4748 return caretLine; 4749 } 4751 4756 public void select(int start, int end) 4757 { 4758 select(start,end,true); 4759 } 4761 4766 public void select(int start, int end, boolean doElectricScroll) 4767 { 4768 selectNone(); 4769 4770 int newStart, newEnd; 4771 if(start < end) 4772 { 4773 newStart = start; 4774 newEnd = end; 4775 } 4776 else 4777 { 4778 newStart = end; 4779 newEnd = start; 4780 } 4781 4782 setSelection(new Selection.Range(newStart,newEnd)); 4783 moveCaretPosition(end,doElectricScroll); 4784 } 4786 4791 public boolean isSelectionRectangular() 4792 { 4793 Selection s = getSelectionAtOffset(caret); 4794 return s != null && s instanceof Selection.Rect; 4795 } 4797 4799 4801 static TextArea focusedComponent; 4802 4803 final Segment lineSegment = new Segment (); 4805 MouseInputAdapter mouseHandler; 4806 final ChunkCache chunkCache; 4807 final FastRepaintManager repaintMgr; 4808 DisplayManager displayManager; 4809 final SelectionManager selectionManager; 4810 boolean bufferChanging; 4811 4812 int maxHorizontalScrollWidth; 4813 4814 String wrap; 4815 boolean hardWrap; 4816 boolean softWrap; 4817 boolean wrapToWidth; 4818 int maxLineLen; 4819 int wrapMargin; 4820 float tabSize; 4821 int charWidth; 4822 4823 boolean scrollBarsInitialized; 4824 4825 4829 final Point offsetXY; 4830 4831 boolean lastLinePartial; 4832 4833 boolean blink; 4834 4836 4840 final boolean isCaretVisible() 4841 { 4842 return blink && hasFocus(); 4843 } 4845 4850 final boolean isStructureHighlightVisible() 4851 { 4852 return match != null 4853 && hasFocus() 4854 && displayManager.isLineVisible(match.startLine) 4855 && displayManager.isLineVisible(match.endLine); 4856 } 4858 void updateMaxHorizontalScrollWidth() 4860 { 4861 int max = chunkCache.getMaxHorizontalScrollWidth(); 4862 4863 if(max != maxHorizontalScrollWidth) 4864 { 4865 maxHorizontalScrollWidth = max; 4866 horizontal.setValues(Math.max(0, 4867 Math.min(maxHorizontalScrollWidth + charWidth 4868 - painter.getWidth(), 4869 -horizontalOffset)), 4870 painter.getWidth(), 4871 0,maxHorizontalScrollWidth 4872 + charWidth); 4873 horizontal.setUnitIncrement(10); 4874 horizontal.setBlockIncrement(painter.getWidth()); 4875 } 4876 else if (horizontal.getValue() != -horizontalOffset) 4877 { 4878 horizontal.setValue(-horizontalOffset); 4879 } 4880 } 4882 void recalculateVisibleLines() 4884 { 4885 if(painter == null) 4886 return; 4887 int height = painter.getHeight(); 4888 int lineHeight = painter.getFontMetrics().getHeight(); 4889 if(lineHeight == 0) 4890 visibleLines = 0; 4891 else if(height <= 0) 4892 { 4893 visibleLines = 0; 4894 lastLinePartial = false; 4895 } 4896 else 4897 { 4898 visibleLines = height / lineHeight; 4899 lastLinePartial = (height % lineHeight != 0); 4900 if(lastLinePartial) 4901 visibleLines++; 4902 } 4903 4904 chunkCache.recalculateVisibleLines(); 4905 4906 if(displayManager != null && buffer != null && !buffer.isLoading()) 4908 setFirstLine(getFirstLine()); 4909 4910 updateScrollBar(); 4911 } 4913 void foldStructureChanged() 4915 { 4916 repaintMgr.setFastScroll(false); 4917 chunkCache.invalidateAll(); 4918 recalculateLastPhysicalLine(); 4919 repaint(); 4920 } 4922 4928 void updateScrollBar() 4929 { 4930 if(buffer == null) 4931 return; 4932 4933 if(Debug.SCROLL_DEBUG) 4934 Log.log(Log.DEBUG,this,"updateScrollBar(), slc=" 4935 + displayManager.getScrollLineCount()); 4936 4937 if(vertical != null && visibleLines != 0) 4938 { 4939 if(Debug.SCROLL_DEBUG) 4940 Log.log(Log.DEBUG,this,"Vertical ok"); 4941 int lineCount = displayManager.getScrollLineCount(); 4942 int firstLine = getFirstLine(); 4943 int visible = visibleLines - (lastLinePartial ? 1 : 0); 4944 4945 vertical.setValues(firstLine,visible,0,lineCount); 4946 vertical.setUnitIncrement(2); 4947 vertical.setBlockIncrement(visible); 4948 } 4949 } 4951 4953 void _finishCaretUpdate() 4954 { 4955 if(!queuedCaretUpdate) 4956 return; 4957 4958 try 4959 { 4960 if(match != null) 4961 { 4962 if(oldCaretLine < match.startLine) 4963 invalidateLineRange(oldCaretLine,match.endLine); 4964 else 4965 invalidateLineRange(match.startLine,oldCaretLine); 4966 match = null; 4967 } 4968 4969 int newCaretScreenLine = chunkCache.getScreenLineOfOffset(caretLine, 4970 caret - buffer.getLineStartOffset(caretLine)); 4971 if(caretScreenLine == -1) 4972 invalidateScreenLineRange(newCaretScreenLine,newCaretScreenLine); 4973 else 4974 invalidateScreenLineRange(caretScreenLine,newCaretScreenLine); 4975 caretScreenLine = newCaretScreenLine; 4976 4977 invalidateSelectedLines(); 4978 4979 blink = true; 4982 caretTimer.restart(); 4983 4984 if(!displayManager.isLineVisible(caretLine)) 4985 { 4986 if(caretLine < displayManager.getFirstVisibleLine() 4987 || caretLine > displayManager.getLastVisibleLine()) 4988 { 4989 int collapseFolds = buffer.getIntegerProperty( 4990 "collapseFolds",0); 4991 if(collapseFolds != 0) 4992 { 4993 displayManager.expandFolds(collapseFolds); 4994 displayManager.expandFold(caretLine,false); 4995 } 4996 else 4997 displayManager.expandAllFolds(); 4998 } 4999 else 5000 displayManager.expandFold(caretLine,false); 5001 } 5002 5003 if(queuedScrollMode == ELECTRIC_SCROLL) 5004 scrollToCaret(true); 5005 else if(queuedScrollMode == NORMAL_SCROLL) 5006 scrollToCaret(false); 5007 5008 updateBracketHighlightWithDelay(); 5009 if(queuedFireCaretEvent) 5010 fireCaretEvent(); 5011 } 5012 finally 5015 { 5016 queuedCaretUpdate = queuedFireCaretEvent = false; 5017 queuedScrollMode = NO_SCROLL; 5018 } 5019 } 5021 void invalidateStructureMatch() 5023 { 5024 if(match != null) 5025 invalidateLineRange(match.startLine,match.endLine); 5026 } 5028 void startDragAndDrop(InputEvent evt, boolean copy) 5030 { 5031 TransferHandler transferHandler = getTransferHandler(); 5032 if (transferHandler != null) 5033 { 5034 Log.log(Log.DEBUG,this,"Drag and drop callback"); 5035 transferHandler.exportAsDrag(this,evt, 5036 copy ? TransferHandler.COPY 5037 : TransferHandler.MOVE); 5038 } 5039 } 5041 void fireNarrowActive() 5043 { 5044 Object [] listeners = listenerList.getListenerList(); 5045 for(int i = listeners.length - 2; i >= 0; i--) 5046 { 5047 if(listeners[i] == StatusListener.class) 5048 { 5049 try 5050 { 5051 ((StatusListener)listeners[i+1]) 5052 .narrowActive(this); 5053 } 5054 catch(Throwable t) 5055 { 5056 Log.log(Log.ERROR,this,t); 5057 } 5058 } 5059 } 5060 } 5062 5064 5066 private static final Timer caretTimer; 5068 private static final Timer structureTimer; 5069 5071 protected Cursor hiddenCursor; 5073 5074 private final Gutter gutter; 5075 protected final TextAreaPainter painter; 5076 5077 private final EventListenerList listenerList; 5078 private final MutableCaretEvent caretEvent; 5079 5080 private boolean caretBlinks; 5081 private InputHandlerProvider inputHandlerProvider; 5082 5083 private int physLastLine; 5084 private int screenLastLine; 5085 5086 private int visibleLines; 5087 private int electricScroll; 5088 5089 private int horizontalOffset; 5090 5091 private boolean quickCopy; 5092 5093 private final Box verticalBox; 5095 private final JScrollBar vertical; 5096 private final JScrollBar horizontal; 5097 5098 protected JEditBuffer buffer; 5099 5100 protected int caret; 5101 protected int caretLine; 5102 private int caretScreenLine; 5103 5104 private final java.util.List <StructureMatcher> structureMatchers; 5105 private StructureMatcher.Match match; 5106 5107 private int magicCaret; 5108 5109 protected boolean multi; 5110 private boolean overwrite; 5111 private boolean rectangularSelectionMode; 5112 5113 private boolean dndEnabled; 5114 private boolean dndInProgress; 5115 5116 private boolean queuedCaretUpdate; 5118 private int queuedScrollMode; 5119 private boolean queuedFireCaretEvent; 5120 private int oldCaretLine; 5121 5122 private boolean joinNonWordChars; 5123 5125 5129 private void invalidateSelectedLines() 5130 { 5131 invalidateLine(caretLine); 5133 5134 for (Selection s : selectionManager.selection) 5135 invalidateLineRange(s.startLine,s.endLine); 5136 } 5138 5143 private void finishCaretUpdate(int oldCaretLine, 5144 int scrollMode, boolean fireCaretEvent) 5145 { 5146 queuedFireCaretEvent |= fireCaretEvent; 5147 queuedScrollMode = Math.max(scrollMode,queuedScrollMode); 5148 5149 if(queuedCaretUpdate) 5150 return; 5151 5152 this.oldCaretLine = oldCaretLine; 5153 queuedCaretUpdate = true; 5154 5155 if(!buffer.isTransactionInProgress()) 5156 _finishCaretUpdate(); 5157 5158 5159 repaintMgr.setFastScroll(false); 5160 } 5162 private void fireCaretEvent() 5164 { 5165 Object [] listeners = listenerList.getListenerList(); 5166 for(int i = listeners.length - 2; i >= 0; i--) 5167 { 5168 if(listeners[i] == CaretListener .class) 5169 { 5170 try 5171 { 5172 ((CaretListener )listeners[i+1]).caretUpdate(caretEvent); 5173 } 5174 catch(Throwable t) 5175 { 5176 Log.log(Log.ERROR,this,t); 5177 } 5178 } 5179 } 5180 } 5182 private void fireScrollEvent(boolean vertical) 5184 { 5185 Object [] listeners = listenerList.getListenerList(); 5186 for(int i = listeners.length - 2; i >= 0; i--) 5187 { 5188 if(listeners[i] == ScrollListener.class) 5189 { 5190 try 5191 { 5192 if(vertical) 5193 ((ScrollListener)listeners[i+1]).scrolledVertically(this); 5194 else 5195 ((ScrollListener)listeners[i+1]).scrolledHorizontally(this); 5196 } 5197 catch(Throwable t) 5198 { 5199 Log.log(Log.ERROR,this,t); 5200 } 5201 } 5202 } 5203 } 5205 private void fireStatusChanged(int flag, boolean value) 5207 { 5208 Object [] listeners = listenerList.getListenerList(); 5209 for(int i = listeners.length - 2; i >= 0; i--) 5210 { 5211 if(listeners[i] == StatusListener.class) 5212 { 5213 try 5214 { 5215 ((StatusListener)listeners[i+1]) 5216 .statusChanged(this,flag,value); 5217 } 5218 catch(Throwable t) 5219 { 5220 Log.log(Log.ERROR,this,t); 5221 } 5222 } 5223 } 5224 } 5226 private void fireBracketSelected(int line, String text) 5228 { 5229 Object [] listeners = listenerList.getListenerList(); 5230 for(int i = listeners.length - 2; i >= 0; i--) 5231 { 5232 if(listeners[i] == StatusListener.class) 5233 { 5234 try 5235 { 5236 ((StatusListener)listeners[i+1]) 5237 .bracketSelected(this,line,text); 5238 } 5239 catch(Throwable t) 5240 { 5241 Log.log(Log.ERROR,this,t); 5242 } 5243 } 5244 } 5245 } 5247 private void _changeLine(boolean select, int newCaret) 5249 { 5250 if(select) 5251 { 5252 RectParams params = getRectParams(caret,newCaret); 5253 int extraStartVirt; 5254 int extraEndVirt; 5255 if(params == null) 5256 { 5257 extraStartVirt = 0; 5258 extraEndVirt = 0; 5259 } 5260 else 5261 { 5262 extraStartVirt = params.extraStartVirt; 5263 extraEndVirt = params.extraEndVirt; 5264 newCaret = params.newCaret; 5265 } 5266 extendSelection(caret,newCaret,extraStartVirt,extraEndVirt); 5267 } 5268 else if(!multi) 5269 selectNone(); 5270 5271 moveCaretPosition(newCaret); 5272 } 5274 5275 5281 private boolean lineContainsSpaceAndTabs(int lineIndex) 5282 { 5283 getLineText(lineIndex,lineSegment); 5284 5285 for(int j = 0; j < lineSegment.count; j++) 5286 { 5287 switch(lineSegment.array[lineSegment.offset + j]) 5288 { 5289 case ' ': 5290 case '\t': 5291 break; 5292 default: 5293 return false; 5294 } 5295 } 5296 return true; 5297 } 5298 5299 protected void insert(String str, boolean indent) 5301 { 5302 try 5303 { 5304 if(overwrite || indent) 5307 buffer.beginCompoundEdit(); 5308 5309 if(overwrite) 5310 { 5311 int caretLineEnd = getLineEndOffset(caretLine); 5312 if(caretLineEnd - caret > 1) 5313 buffer.remove(caret,1); 5314 } 5315 5316 buffer.insert(caret,str); 5317 5318 if(indent) 5319 buffer.indentLine(caretLine,true); 5320 } 5321 finally 5322 { 5323 if(overwrite || indent) 5324 buffer.endCompoundEdit(); 5325 } 5326 } 5328 private void insertTab() 5330 { 5331 int tabSize = buffer.getTabSize(); 5332 if(buffer.getBooleanProperty("noTabs")) 5333 { 5334 int lineStart = getLineStartOffset(caretLine); 5335 5336 String line = getText(lineStart,caret - lineStart); 5337 5338 int pos = 0; 5339 5340 for(int i = 0; i < line.length(); i++) 5341 { 5342 switch(line.charAt(pos)) 5343 { 5344 case '\t': 5345 pos = 0; 5346 break; 5347 default: 5348 if(++pos >= tabSize) 5349 pos = 0; 5350 break; 5351 } 5352 } 5353 5354 replaceSelection(StandardUtilities.createWhiteSpace( 5355 tabSize - pos,0)); 5356 } 5357 else 5358 replaceSelection("\t"); 5359 } 5361 protected void userInputTab() 5363 { 5364 if(getSelectionCount() == 1) 5365 { 5366 Selection sel = getSelection(0); 5367 if(sel instanceof Selection.Rect || 5368 (sel.startLine == sel.endLine 5369 && (sel.start != buffer.getLineStartOffset(sel.startLine) 5370 || sel.end != buffer.getLineEndOffset(sel.startLine) - 1))) 5371 { 5372 insertTab(); 5373 } 5374 else 5375 shiftIndentRight(); 5376 } 5377 else if(getSelectionCount() != 0) 5378 shiftIndentRight(); 5379 else 5380 insertTab(); 5381 } 5383 5387 protected boolean doWordWrap(boolean spaceInserted) 5388 { 5389 if(!hardWrap || maxLineLen <= 0) 5390 return false; 5391 5392 buffer.getLineText(caretLine,lineSegment); 5393 5394 int start = getLineStartOffset(caretLine); 5395 int end = getLineEndOffset(caretLine); 5396 int len = end - start - 1; 5397 5398 int caretPos = caret - start; 5399 5400 for(int i = caretPos; i < len; i++) 5403 { 5404 char ch = lineSegment.array[lineSegment.offset + i]; 5405 if(ch != ' ' && ch != '\t') 5406 return false; 5407 } 5408 5409 int tabSize = buffer.getTabSize(); 5410 5411 String wordBreakChars = buffer.getStringProperty("wordBreakChars"); 5412 5413 int lastInLine = 0; int logicalLength = 0; int lastWordOffset = -1; 5416 boolean lastWasSpace = true; 5417 for(int i = 0; i < caretPos; i++) 5418 { 5419 char ch = lineSegment.array[lineSegment.offset + i]; 5420 if(ch == '\t') 5421 { 5422 logicalLength += tabSize - (logicalLength % tabSize); 5423 if(!lastWasSpace && logicalLength <= maxLineLen) 5424 { 5425 lastInLine = i; 5426 lastWordOffset = i; 5427 lastWasSpace = true; 5428 } 5429 } 5430 else if(ch == ' ') 5431 { 5432 logicalLength++; 5433 if(!lastWasSpace && 5434 logicalLength <= maxLineLen + 1) 5435 { 5436 lastInLine = i; 5437 lastWordOffset = i; 5438 lastWasSpace = true; 5439 } 5440 } 5441 else if(wordBreakChars != null && wordBreakChars.indexOf(ch) != -1) 5442 { 5443 logicalLength++; 5444 if(!lastWasSpace && logicalLength <= maxLineLen) 5445 { 5446 lastInLine = i; 5447 lastWordOffset = i; 5448 lastWasSpace = true; 5449 } 5450 } 5451 else 5452 { 5453 lastInLine = i; 5454 logicalLength++; 5455 lastWasSpace = false; 5456 } 5457 } 5458 5459 boolean returnValue; 5460 5461 int insertNewLineAt; 5462 if(spaceInserted && logicalLength == maxLineLen 5463 && lastInLine == caretPos - 1) 5464 { 5465 insertNewLineAt = caretPos; 5466 returnValue = true; 5467 } 5468 else if(logicalLength >= maxLineLen && lastWordOffset != -1) 5469 { 5470 insertNewLineAt = lastWordOffset; 5471 returnValue = false; 5472 } 5473 else 5474 return false; 5475 5476 try 5477 { 5478 buffer.beginCompoundEdit(); 5479 buffer.insert(start + insertNewLineAt,"\n"); 5480 buffer.indentLine(caretLine,true); 5483 } 5484 finally 5485 { 5486 buffer.endCompoundEdit(); 5487 } 5488 5489 5491 return returnValue; 5492 } 5494 private static void updateBracketHighlightWithDelay() 5496 { 5497 structureTimer.stop(); 5498 structureTimer.start(); 5499 } 5501 private void updateStructureHighlight() 5503 { 5504 if(!painter.isStructureHighlightEnabled() 5505 && !gutter.isStructureHighlightEnabled()) 5506 return; 5507 5508 for (StructureMatcher matcher : structureMatchers) 5509 { 5510 match = matcher.getMatch(this); 5511 if(match != null) 5512 break; 5513 } 5514 5515 if(match != null) 5516 { 5517 if(caretLine < match.startLine) 5518 invalidateLineRange(caretLine,match.endLine); 5519 else 5520 invalidateLineRange(match.startLine,caretLine); 5521 5522 if(!displayManager.isLineVisible(match.startLine) 5523 || chunkCache.getScreenLineOfOffset( 5524 match.startLine,match.start - getLineStartOffset(match.startLine)) 5525 == -1) 5526 { 5527 showStructureStatusMessage(match.startLine < caretLine); 5528 } 5529 } 5530 } 5532 private void showStructureStatusMessage(boolean backward) 5534 { 5535 String text = buffer.getLineText(match.startLine).trim(); 5536 if(backward && match.startLine != 0 && text.length() == 1) 5537 { 5538 switch(text.charAt(0)) 5539 { 5540 case '{': case '}': 5541 case '[': case ']': 5542 case '(': case ')': 5543 text = buffer.getLineText(match.startLine - 1) 5544 .trim() + ' ' + text; 5545 break; 5546 } 5547 } 5548 5549 fireBracketSelected(match.startLine + 1,text.replace('\t',' ')); 5551 } 5553 void recalculateLastPhysicalLine() 5555 { 5556 int oldScreenLastLine = screenLastLine; 5557 for(int i = visibleLines - 1; i >= 0; i--) 5558 { 5559 ChunkCache.LineInfo info = chunkCache.getLineInfo(i); 5560 if(info.physicalLine != -1) 5561 { 5562 physLastLine = info.physicalLine; 5563 screenLastLine = i; 5564 break; 5565 } 5566 } 5567 invalidateScreenLineRange(oldScreenLastLine,screenLastLine); 5568 } 5570 static class RectParams 5572 { 5573 final int extraStartVirt; 5574 final int extraEndVirt; 5575 final int newCaret; 5576 5577 RectParams(int extraStartVirt, int extraEndVirt, int newCaret) 5578 { 5579 this.extraStartVirt = extraStartVirt; 5580 this.extraEndVirt = extraEndVirt; 5581 this.newCaret = newCaret; 5582 } 5583 } 5584 5585 5588 private RectParams getRectParams(int caret, int newCaret) 5589 { 5590 Selection s = getSelectionAtOffset(caret); 5591 int virtualWidth; 5592 if(s instanceof Selection.Rect) 5593 { 5594 if(caret == s.end) 5595 { 5596 virtualWidth = buffer.getVirtualWidth( 5597 s.endLine,s.end - getLineStartOffset( 5598 s.endLine)) + ((Selection.Rect)s).extraEndVirt; 5599 } 5600 else 5601 { 5602 virtualWidth = buffer.getVirtualWidth( 5603 s.startLine,s.start - getLineStartOffset( 5604 s.startLine)) + ((Selection.Rect)s).extraStartVirt; 5605 } 5606 } 5607 else if(rectangularSelectionMode) 5608 { 5609 virtualWidth = buffer.getVirtualWidth( 5610 caretLine,caret - buffer.getLineStartOffset(caretLine)); 5611 } 5612 else 5613 return null; 5614 5615 int newLine = getLineOfOffset(newCaret); 5616 int[] totalVirtualWidth = new int[1]; 5617 int newOffset = buffer.getOffsetOfVirtualColumn(newLine, 5618 virtualWidth,totalVirtualWidth); 5619 if(newOffset == -1) 5620 { 5621 int extraVirt = virtualWidth - totalVirtualWidth[0]; 5622 newCaret = getLineEndOffset(newLine) - 1; 5623 5624 boolean bias; 5625 if(s == null) 5626 bias = newCaret < caret; 5627 else if(s.start == caret) 5628 bias = newCaret <= s.end; 5629 else if(s.end == caret) 5630 bias = newCaret <= s.start; 5631 else 5632 bias = false; 5633 5634 RectParams returnValue; 5635 if(bias) 5636 returnValue = new RectParams(extraVirt,0,newCaret); 5637 else 5638 returnValue = new RectParams(0,extraVirt,newCaret); 5639 return returnValue; 5640 } 5641 else 5642 { 5643 return new RectParams(0,0,getLineStartOffset(newLine) 5644 + newOffset); 5645 } 5646 } 5648 private void delete(boolean forward) 5650 { 5651 if(!buffer.isEditable()) 5652 { 5653 getToolkit().beep(); 5654 return; 5655 } 5656 5657 if(getSelectionCount() != 0) 5658 { 5659 Selection[] selections = getSelection(); 5660 for(int i = 0; i < selections.length; i++) 5661 { 5662 Selection s = selections[i]; 5663 if(s instanceof Selection.Rect) 5664 { 5665 Selection.Rect r = (Selection.Rect)s; 5666 int startColumn = r.getStartColumn(buffer); 5667 if(startColumn == r.getEndColumn(buffer)) 5668 { 5669 if(!forward && startColumn == 0) 5670 getToolkit().beep(); 5671 else 5672 tallCaretDelete(r,forward); 5673 } 5674 else 5675 setSelectedText(s,null); 5676 } 5677 else 5678 setSelectedText(s,null); 5679 } 5680 } 5681 else if(forward) 5682 { 5683 if(caret == buffer.getLength()) 5684 { 5685 getToolkit().beep(); 5686 return; 5687 } 5688 5689 buffer.remove(caret,1); 5690 } 5691 else 5692 { 5693 if(caret == 0) 5694 { 5695 getToolkit().beep(); 5696 return; 5697 } 5698 5699 buffer.remove(caret - 1,1); 5700 } 5701 } 5703 private void tallCaretDelete(Selection.Rect s, boolean forward) 5705 { 5706 try 5707 { 5708 buffer.beginCompoundEdit(); 5709 5710 int[] width = new int[1]; 5711 5712 int startCol = s.getStartColumn(buffer); 5713 int startLine = s.startLine; 5714 int endLine = s.endLine; 5715 for(int i = startLine; i <= endLine; i++) 5716 { 5717 int offset = buffer.getOffsetOfVirtualColumn( 5718 i,startCol,width); 5719 if(offset == -1) 5720 { 5721 if(width[0] == startCol) 5722 offset = getLineLength(i); 5723 else 5724 { 5725 if(i == startLine && !forward) 5726 shiftTallCaretLeft(s); 5727 continue; 5728 } 5729 } 5730 offset += buffer.getLineStartOffset(i); 5731 if(forward) 5732 { 5733 if(offset != buffer.getLineEndOffset(i) - 1) 5734 buffer.remove(offset,1); 5735 } 5736 else 5737 buffer.remove(offset-1,1); 5738 } 5739 } 5740 finally 5741 { 5742 buffer.endCompoundEdit(); 5743 } 5744 } 5746 private void shiftTallCaretLeft(Selection.Rect s) 5748 { 5749 removeFromSelection(s); 5750 addToSelection(new Selection.Rect( 5751 buffer, 5752 s.getStartLine(),s.getStartColumn(buffer) - 1, 5753 s.getEndLine(),s.getEndColumn(buffer) - 1)); 5754 } 5756 private void setMaxLineLength(int maxLineLen) 5758 { 5759 this.maxLineLen = maxLineLen; 5760 5761 if(maxLineLen <= 0) 5762 { 5763 if(softWrap) 5764 { 5765 wrapToWidth = true; 5766 wrapMargin = painter.getWidth() - charWidth * 3; 5767 } 5768 else 5769 { 5770 wrapToWidth = false; 5771 wrapMargin = 0; 5772 } 5773 } 5774 else 5775 { 5776 char[] foo = new char[maxLineLen]; 5778 for(int i = 0; i < foo.length; i++) 5779 { 5780 foo[i] = ' '; 5781 } 5782 wrapToWidth = false; 5783 wrapMargin = (int)painter.getFont().getStringBounds( 5784 foo,0,foo.length, 5785 painter.getFontRenderContext()) 5786 .getWidth(); 5787 } 5788 } 5790 5803 protected int addExplicitFold(int caretStart, int caretEnd, int lineStart, int lineEnd) 5804 { 5805 int startCaret = caretStart < buffer.getLength() ? caretStart + 1 : caretStart; 5811 int endCaret = caretEnd > 0 ? caretEnd - 1 : caretEnd; 5812 5813 String startLineComment = buffer.getContextSensitiveProperty(startCaret,"lineComment"); 5814 String startCommentStart = buffer.getContextSensitiveProperty(startCaret,"commentStart"); 5815 String startCommentEnd = buffer.getContextSensitiveProperty(startCaret,"commentEnd"); 5816 String endLineComment = buffer.getContextSensitiveProperty(endCaret,"lineComment"); 5817 String endCommentStart = buffer.getContextSensitiveProperty(endCaret,"commentStart"); 5818 String endCommentEnd = buffer.getContextSensitiveProperty(endCaret,"commentEnd"); 5819 5820 String start; 5821 int caretBack = 1; 5822 if(startLineComment != null) 5823 start = startLineComment + "{{{ "; 5824 else if(startCommentStart != null && startCommentEnd != null) 5825 { 5826 start = startCommentStart + "{{{ " + startCommentEnd; 5827 caretBack = 1 + startCommentStart.length(); 5828 } 5829 else 5830 start = "{{{ "; 5831 5832 if (startLineComment != null) { 5833 int nextLineOffset = buffer.getLineStartOffset(lineStart+1); 5836 if (nextLineOffset - caretStart != 1) 5837 start += "\n"; 5838 } 5839 else 5840 { 5841 start += "\n"; 5843 } 5844 5845 String end; 5846 if(endLineComment != null) 5847 end = endLineComment + "}}}"; 5848 else if(endCommentStart != null && endCommentEnd != null) 5849 end = endCommentStart + "}}}" + endCommentEnd; 5850 else 5851 end = "}}}"; 5852 5853 String line = buffer.getLineText(lineStart); 5854 String whitespace = line.substring(0, 5855 StandardUtilities.getLeadingWhiteSpace(line)); 5856 5857 if (endLineComment != null) 5858 { 5859 int nextLineOffset = buffer.getLineStartOffset(lineEnd+1); 5863 if (nextLineOffset - caretEnd != 1) 5864 end += "\n"; 5865 } 5866 else 5867 { 5868 end += "\n"; 5870 } 5871 5872 if(caretEnd == buffer.getLineStartOffset(lineEnd)) 5873 buffer.insert(caretEnd,end); 5874 else 5875 { 5876 String lineText = buffer.getText(caretEnd - 1, 1); 5877 if (Character.isWhitespace(lineText.charAt(0))) 5878 buffer.insert(caretEnd, end); 5879 else 5880 buffer.insert(caretEnd,' ' + end); 5881 } 5882 5883 buffer.insert(caretStart,start + whitespace); 5884 5885 return caretBack; 5886 } 5889 5891 static class CaretBlinker implements ActionListener 5893 { 5894 public void actionPerformed(ActionEvent evt) 5896 { 5897 if(focusedComponent != null && focusedComponent.hasFocus()) 5898 focusedComponent.blinkCaret(); 5899 } } 5902 class MutableCaretEvent extends CaretEvent 5904 { 5905 MutableCaretEvent() 5907 { 5908 super(TextArea.this); 5909 } 5911 public int getDot() 5913 { 5914 return getCaretPosition(); 5915 } 5917 public int getMark() 5919 { 5920 return getMarkPosition(); 5921 } } 5924 class AdjustHandler implements AdjustmentListener 5926 { 5927 public void adjustmentValueChanged(AdjustmentEvent evt) 5929 { 5930 if(!scrollBarsInitialized) 5931 return; 5932 5933 if(evt.getAdjustable() == vertical) 5934 setFirstLine(vertical.getValue()); 5935 else 5936 setHorizontalOffset(-horizontal.getValue()); 5937 } } 5940 class FocusHandler implements FocusListener 5942 { 5943 public void focusGained(FocusEvent evt) 5945 { 5946 if(bufferChanging) 5947 return; 5948 5949 if(match != null) 5950 { 5951 if(caretLine < match.startLine) 5952 invalidateLineRange(caretLine,match.endLine); 5953 else 5954 invalidateLineRange(match.startLine,caretLine); 5955 } 5956 else 5957 invalidateLine(caretLine); 5958 5959 focusedComponent = TextArea.this; 5960 } 5962 public void focusLost(FocusEvent evt) 5964 { 5965 if(!isShowing()) 5966 return; 5967 5968 if(match != null) 5969 { 5970 if(caretLine < match.startLine) 5971 invalidateLineRange(caretLine,match.endLine); 5972 else 5973 invalidateLineRange(match.startLine,caretLine); 5974 } 5975 else 5976 invalidateLine(caretLine); 5977 } } 5980 class MouseWheelHandler implements MouseWheelListener 5982 { 5983 public void mouseWheelMoved(MouseWheelEvent e) 5984 { 5985 5993 if(e.isAltDown()) 5994 { 5995 boolean select = e.isShiftDown() 5996 || e.isControlDown(); 5997 if(e.getWheelRotation() < 0) 5998 goToPrevLine(select); 5999 else 6000 goToNextLine(select); 6001 } 6002 else if(e.isShiftDown()) 6003 { 6004 if(e.getWheelRotation() > 0) 6005 scrollDownPage(); 6006 else 6007 scrollUpPage(); 6008 } 6009 else if(e.isControlDown()) 6010 { 6011 setFirstLine(getFirstLine() 6012 + e.getWheelRotation()); 6013 } 6014 else if(e.getScrollType() 6015 == MouseWheelEvent.WHEEL_UNIT_SCROLL) 6016 { 6017 setFirstLine(getFirstLine() 6018 + e.getUnitsToScroll()); 6019 } 6020 else 6021 { 6022 setFirstLine(getFirstLine() 6023 + 3 * e.getWheelRotation()); 6024 } 6025 } 6026 } 6028 6030 static 6032 { 6033 caretTimer = new Timer (500,new CaretBlinker()); 6034 caretTimer.setInitialDelay(500); 6035 caretTimer.start(); 6036 6037 structureTimer = new Timer (100,new ActionListener() 6038 { 6039 public void actionPerformed(ActionEvent evt) 6040 { 6041 if(focusedComponent != null) 6042 focusedComponent.updateStructureHighlight(); 6043 } 6044 }); 6045 structureTimer.setInitialDelay(100); 6046 structureTimer.setRepeats(false); 6047 } 6049 public static void main(String [] args) 6051 { 6052 JFrame frame = new JFrame(); 6053 TextArea text = new TextArea(); 6054 frame.getContentPane().add(text); 6055 frame.pack(); 6056 frame.setVisible(true); 6057 } } 6059 | Popular Tags |