Source Code Cross Referenced for TextArea.java in  » Swing-Library » jEdit » org » gjt » sp » jedit » textarea » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Swing Library » jEdit » org.gjt.sp.jedit.textarea 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * TextArea.java - Handles services.xml files in plugins
0003:         * :tabSize=8:indentSize=8:noTabs=false:
0004:         * :folding=explicit:collapseFolds=1:
0005:         *
0006:         * Copyright (C) 1999, 2005 Slava Pestov
0007:         * Portions copyright (C) 2000 Ollie Rutherfurd
0008:         * Portions copyright (C) 2006 Matthieu Casanova
0009:         *
0010:         * This program is free software; you can redistribute it and/or
0011:         * modify it under the terms of the GNU General Public License
0012:         * as published by the Free Software Foundation; either version 2
0013:         * of the License, or any later version.
0014:         *
0015:         * This program is distributed in the hope that it will be useful,
0016:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018:         * GNU General Public License for more details.
0019:         *
0020:         * You should have received a copy of the GNU General Public License
0021:         * along with this program; if not, write to the Free Software
0022:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0023:         */
0024:        package org.gjt.sp.jedit.textarea;
0025:
0026:        //{{{ Imports
0027:        import org.gjt.sp.jedit.Debug;
0028:        import org.gjt.sp.jedit.Mode;
0029:        import org.gjt.sp.jedit.TextUtilities;
0030:        import org.gjt.sp.jedit.buffer.*;
0031:        import org.gjt.sp.jedit.input.AbstractInputHandler;
0032:        import org.gjt.sp.jedit.input.DefaultInputHandlerProvider;
0033:        import org.gjt.sp.jedit.input.InputHandlerProvider;
0034:        import org.gjt.sp.jedit.input.TextAreaInputHandler;
0035:        import org.gjt.sp.jedit.syntax.*;
0036:        import org.gjt.sp.util.Log;
0037:        import org.gjt.sp.util.StandardUtilities;
0038:
0039:        import javax.swing.*;
0040:        import javax.swing.event.CaretEvent;
0041:        import javax.swing.event.CaretListener;
0042:        import javax.swing.event.EventListenerList;
0043:        import javax.swing.event.MouseInputAdapter;
0044:        import javax.swing.plaf.metal.MetalLookAndFeel;
0045:        import javax.swing.text.Segment;
0046:        import java.awt.*;
0047:        import java.awt.event.*;
0048:        import java.awt.im.InputMethodRequests;
0049:        import java.util.Iterator;
0050:        import java.util.LinkedList;
0051:        import java.util.TooManyListenersException;
0052:
0053:        //}}}
0054:
0055:        /**
0056:         * jEdit's text component.<p>
0057:         *
0058:         * Unlike most other text editors, the selection API permits selection and
0059:         * concurrent manipulation of multiple, non-contiguous regions of text.
0060:         * Methods in this class that deal with selecting text rely upon classes derived
0061:         * the {@link Selection} class.
0062:         *
0063:         * @author Slava Pestov
0064:         * @author John Gellene (API documentation)
0065:         * @version $Id: JEditTextArea.java 7148 2006-09-29 23:09:06 +0200 (ven., 29 sept. 2006) kpouer $
0066:         */
0067:        public class TextArea extends JComponent {
0068:            //{{{ TextArea constructor
0069:            public TextArea() {
0070:                this (false);
0071:            } //}}}
0072:
0073:            //{{{ TextArea constructor
0074:            /**
0075:             * Instantiate a TextArea.
0076:             * @param insideJEdit must be set to true if the textarea is embedded in jEdit
0077:             */
0078:            public TextArea(boolean insideJEdit) {
0079:                this (null);
0080:                inputHandlerProvider = new DefaultInputHandlerProvider(
0081:                        new TextAreaInputHandler(this ));
0082:                setMouseHandler(new TextAreaMouseHandler(this ));
0083:                if (insideJEdit) {
0084:                    return;
0085:                }
0086:
0087:                Font font1 = new Font("Monospaced", Font.PLAIN, 12);
0088:                painter.setFont(font1);
0089:                SyntaxStyle[] styles = new SyntaxStyle[1];
0090:                styles[0] = new SyntaxStyle(Color.black, Color.white, font1);
0091:                painter.setStyles(styles);
0092:                painter.setBlockCaretEnabled(false);
0093:
0094:                painter.setStructureHighlightEnabled(true);
0095:                painter.setStructureHighlightColor(Color.black);
0096:                painter.setEOLMarkersPainted(false);
0097:                painter.setEOLMarkerColor(new Color(255, 102, 51));
0098:                painter.setWrapGuidePainted(true);
0099:                painter.setWrapGuideColor(new Color(125, 125, 255));
0100:                painter.setCaretColor(Color.red);
0101:                painter.setSelectionColor(new Color(204, 204, 255));
0102:                painter.setMultipleSelectionColor(new Color(204, 255, 204));
0103:                painter.setBackground(Color.white);
0104:                painter.setForeground(Color.black);
0105:                painter.setBlockCaretEnabled(false);
0106:                painter.setLineHighlightEnabled(true);
0107:                painter.setLineHighlightColor(new Color(255, 204, 255));
0108:                painter.setAntiAlias(new AntiAlias(0));
0109:                painter.setFractionalFontMetricsEnabled(false);
0110:
0111:                gutter.setExpanded(false);
0112:                gutter.setHighlightInterval(5);
0113:                gutter.setCurrentLineHighlightEnabled(true);
0114:                gutter.setStructureHighlightEnabled(true);
0115:                gutter.setStructureHighlightColor(new Color(102, 102, 153));
0116:                gutter.setBackground(new Color(219, 219, 219));
0117:                gutter.setForeground(Color.black);
0118:                gutter.setHighlightedForeground(new Color(153, 0, 102));
0119:                gutter.setFoldColor(new Color(131, 131, 131));
0120:                gutter.setCurrentLineForeground(new Color(255, 0, 51));
0121:                gutter.setLineNumberAlignment(Gutter.RIGHT);
0122:                gutter.setFont(new Font("Monospaced", Font.PLAIN, 10));
0123:                gutter.setBorder(3, new Color(153, 0, 153), Color.white,
0124:                        painter.getBackground());
0125:
0126:                setCaretBlinkEnabled(true);
0127:                setElectricScroll(3);
0128:
0129:                FoldHandler.foldHandlerProvider = new DefaultFoldHandlerProvider();
0130:                JEditBuffer buffer = new JEditBuffer();
0131:                TokenMarker tokenMarker = new TokenMarker();
0132:                tokenMarker.addRuleSet(new ParserRuleSet("text", "MAIN"));
0133:                buffer.setTokenMarker(tokenMarker);
0134:                setBuffer(buffer);
0135:                Mode mode = new Mode("text");
0136:                mode.setTokenMarker(tokenMarker);
0137:                ModeProvider.instance.addMode(mode);
0138:                KillRing.setInstance(new KillRing());
0139:                KillRing.getInstance().propertiesChanged(100);
0140:            } //}}}
0141:
0142:            //{{{ TextArea constructor
0143:            /**
0144:             * Creates a new JEditTextArea.
0145:             */
0146:            public TextArea(InputHandlerProvider inputHandlerProvider) {
0147:                this .inputHandlerProvider = inputHandlerProvider;
0148:                enableEvents(AWTEvent.FOCUS_EVENT_MASK
0149:                        | AWTEvent.KEY_EVENT_MASK);
0150:
0151:                //{{{ Initialize some misc. stuff
0152:                selectionManager = new SelectionManager(this );
0153:                chunkCache = new ChunkCache(this );
0154:                painter = new TextAreaPainter(this );
0155:                repaintMgr = new FastRepaintManager(this , painter);
0156:                gutter = new Gutter(this );
0157:                gutter.setMouseActionsProvider(new MouseActions("gutter"));
0158:                listenerList = new EventListenerList();
0159:                caretEvent = new MutableCaretEvent();
0160:                blink = true;
0161:                offsetXY = new Point();
0162:                structureMatchers = new LinkedList<StructureMatcher>();
0163:                structureMatchers.add(new StructureMatcher.BracketMatcher());
0164:                //}}}
0165:
0166:                //{{{ Initialize the GUI
0167:                setLayout(new ScrollLayout());
0168:                add(ScrollLayout.CENTER, painter);
0169:                add(ScrollLayout.LEFT, gutter);
0170:
0171:                // some plugins add stuff in a "right-hand" gutter
0172:                verticalBox = new Box(BoxLayout.X_AXIS);
0173:                verticalBox.add(vertical = new JScrollBar(Adjustable.VERTICAL));
0174:                vertical.setRequestFocusEnabled(false);
0175:                add(ScrollLayout.RIGHT, verticalBox);
0176:                add(ScrollLayout.BOTTOM, horizontal = new JScrollBar(
0177:                        Adjustable.HORIZONTAL));
0178:                horizontal.setRequestFocusEnabled(false);
0179:
0180:                horizontal.setValues(0, 0, 0, 0);
0181:                //}}}
0182:
0183:                //{{{ this ensures that the text area's look is slightly
0184:                // more consistent with the rest of the metal l&f.
0185:                // while it depends on not-so-well-documented portions
0186:                // of Swing, it only affects appearance, so future
0187:                // breakage shouldn't matter
0188:                if (UIManager.getLookAndFeel() instanceof  MetalLookAndFeel) {
0189:                    setBorder(new TextAreaBorder());
0190:                    vertical.putClientProperty("JScrollBar.isFreeStanding",
0191:                            Boolean.FALSE);
0192:                    horizontal.putClientProperty("JScrollBar.isFreeStanding",
0193:                            Boolean.FALSE);
0194:                    //horizontal.setBorder(null);
0195:                }
0196:                //}}}
0197:
0198:                //{{{ Add some event listeners
0199:                vertical.addAdjustmentListener(new AdjustHandler());
0200:                horizontal.addAdjustmentListener(new AdjustHandler());
0201:
0202:                addFocusListener(new FocusHandler());
0203:                addMouseWheelListener(new MouseWheelHandler());
0204:
0205:                //}}}
0206:
0207:                // This doesn't seem very correct, but it fixes a problem
0208:                // when setting the initial caret position for a buffer
0209:                // (eg, from the recent file list)
0210:                focusedComponent = this ;
0211:
0212:            } //}}}
0213:
0214:            //{{{ setMouseHandler() method
0215:            public void setMouseHandler(MouseInputAdapter mouseInputAdapter) {
0216:                mouseHandler = mouseInputAdapter;
0217:                painter.addMouseListener(mouseHandler);
0218:                painter.addMouseMotionListener(mouseHandler);
0219:            } //}}}
0220:
0221:            //{{{ setTransferHandler() method
0222:            public void setTransferHandler(TransferHandler newHandler) {
0223:                super .setTransferHandler(newHandler);
0224:                try {
0225:                    getDropTarget().addDropTargetListener(
0226:                            new TextAreaDropHandler(this ));
0227:                } catch (TooManyListenersException e) {
0228:                    Log.log(Log.ERROR, this , e);
0229:                }
0230:            } //}}}
0231:
0232:            //{{{ toString() method
0233:            public String toString() {
0234:                StringBuilder builder = new StringBuilder();
0235:                builder.append("caret: ").append(caret).append('\n');
0236:                builder.append("caretLine: ").append(caretLine).append('\n');
0237:                builder.append("caretScreenLine: ").append(caretScreenLine)
0238:                        .append('\n');
0239:                builder.append("electricScroll: ").append(electricScroll)
0240:                        .append('\n');
0241:                builder.append("horizontalOffset: ").append(horizontalOffset)
0242:                        .append('\n');
0243:                builder.append("magicCaret: ").append(magicCaret).append('\n');
0244:                builder.append("offsetXY").append(offsetXY.toString()).append(
0245:                        '\n');
0246:                builder.append("oldCaretLine: ").append(oldCaretLine).append(
0247:                        '\n');
0248:                builder.append("screenLastLine: ").append(screenLastLine)
0249:                        .append('\n');
0250:                builder.append("visibleLines: ").append(visibleLines).append(
0251:                        '\n');
0252:                builder.append("firstPhysicalLine: ").append(
0253:                        getFirstPhysicalLine()).append('\n');
0254:                builder.append("physLastLine: ").append(physLastLine).append(
0255:                        '\n');
0256:                return builder.toString();
0257:            } //}}}
0258:
0259:            //{{{ dispose() method
0260:            /**
0261:             * Plugins and macros should not call this method.
0262:             * @since jEdit 4.2pre1
0263:             */
0264:            public void dispose() {
0265:                DisplayManager.textAreaDisposed(this );
0266:            } //}}}
0267:
0268:            //{{{ getInputHandler() method
0269:            /**
0270:             * @since jEdit 4.3pre1
0271:             */
0272:            public AbstractInputHandler getInputHandler() {
0273:                return inputHandlerProvider.getInputHandler();
0274:            } //}}}
0275:
0276:            //{{{ getPainter() method
0277:            /**
0278:             * Returns the object responsible for painting this text area.
0279:             */
0280:            public final TextAreaPainter getPainter() {
0281:                return painter;
0282:            } //}}}
0283:
0284:            //{{{ getGutter() method
0285:            /**
0286:             * Returns the gutter to the left of the text area or null if the gutter
0287:             * is disabled
0288:             */
0289:            public final Gutter getGutter() {
0290:                return gutter;
0291:            } //}}}
0292:
0293:            //{{{ getDisplayManager() method
0294:            /**
0295:             * @return the display manager used by this text area.
0296:             * @since jEdit 4.2pre1
0297:             */
0298:            public DisplayManager getDisplayManager() {
0299:                return displayManager;
0300:            } //}}}
0301:
0302:            //{{{ isCaretBlinkEnabled() method
0303:            /**
0304:             * @return true if the caret is blinking, false otherwise.
0305:             */
0306:            public final boolean isCaretBlinkEnabled() {
0307:                return caretBlinks;
0308:            } //}}}
0309:
0310:            //{{{ setCaretBlinkEnabled() method
0311:            /**
0312:             * Toggles caret blinking.
0313:             * @param caretBlinks True if the caret should blink, false otherwise
0314:             */
0315:            public void setCaretBlinkEnabled(boolean caretBlinks) {
0316:                this .caretBlinks = caretBlinks;
0317:                if (!caretBlinks)
0318:                    blink = false;
0319:
0320:                if (buffer != null)
0321:                    invalidateLine(caretLine);
0322:            } //}}}
0323:
0324:            //{{{ getElectricScroll() method
0325:
0326:            /**
0327:             * @return the minimum distance (in number of lines)
0328:             * from the caret to the nearest edge of the screen
0329:             * (top or bottom edge).
0330:             */
0331:            public final int getElectricScroll() {
0332:                return electricScroll;
0333:            } //}}}
0334:
0335:            //{{{ setElectricScroll() method
0336:            /**
0337:             * Sets the number of lines from the top and bottom of the text
0338:             * area that are always visible
0339:             * @param electricScroll The number of lines always visible from
0340:             * the top or bottom
0341:             */
0342:            public final void setElectricScroll(int electricScroll) {
0343:                this .electricScroll = electricScroll;
0344:            } //}}}
0345:
0346:            //{{{ isQuickCopyEnabled() method
0347:            /**
0348:             * Returns if clicking the middle mouse button pastes the most
0349:             * recent selection (% register), and if Control-dragging inserts
0350:             * the selection at the caret.
0351:             */
0352:            public final boolean isQuickCopyEnabled() {
0353:                return quickCopy;
0354:            } //}}}
0355:
0356:            //{{{ setQuickCopyEnabled() method
0357:            /**
0358:             * Sets if clicking the middle mouse button pastes the most
0359:             * recent selection (% register), and if Control-dragging inserts
0360:             * the selection at the caret.
0361:             * @param quickCopy A boolean flag
0362:             */
0363:            public final void setQuickCopyEnabled(boolean quickCopy) {
0364:                this .quickCopy = quickCopy;
0365:            } //}}}
0366:
0367:            //{{{ getBuffer() method
0368:            /**
0369:             * Returns the buffer this text area is editing.
0370:             * @since jedit 4.3pre3
0371:             *
0372:             *  Prior to 4.3pre3, this function returned a "Buffer" type.
0373:             *  If this causes your code to break, try calling view.getBuffer() instead of
0374:             *  view.getTextArea().getBuffer().
0375:             *
0376:             */
0377:            public final JEditBuffer getBuffer() {
0378:                return buffer;
0379:            } //}}}
0380:
0381:            //{{{ setBuffer() method
0382:            /**
0383:             * Sets the buffer this text area is editing.
0384:             * If you don't run a standalone textarea in jEdit please do not call this method -
0385:             * use {@link org.gjt.sp.jedit.EditPane#setBuffer(org.gjt.sp.jedit.Buffer)} instead.
0386:             * @param buffer The buffer
0387:             */
0388:            public void setBuffer(JEditBuffer buffer) {
0389:                if (this .buffer == buffer)
0390:                    return;
0391:
0392:                try {
0393:                    bufferChanging = true;
0394:
0395:                    if (this .buffer != null) {
0396:                        // dubious?
0397:                        //setFirstLine(0);
0398:
0399:                        if (!buffer.isLoading())
0400:                            selectNone();
0401:                        caretLine = caret = caretScreenLine = 0;
0402:                        match = null;
0403:                    }
0404:                    boolean inCompoundEdit = false;
0405:                    if (this .buffer != null)
0406:                        inCompoundEdit = this .buffer.insideCompoundEdit();
0407:                    if (inCompoundEdit)
0408:                        this .buffer.endCompoundEdit();
0409:                    this .buffer = buffer;
0410:                    if (inCompoundEdit)
0411:                        this .buffer.beginCompoundEdit();
0412:
0413:                    chunkCache.setBuffer(buffer);
0414:                    repaintMgr.setFastScroll(false);
0415:                    propertiesChanged();
0416:
0417:                    if (displayManager != null) {
0418:                        DisplayManager.releaseDisplayManager(displayManager);
0419:                    }
0420:
0421:                    displayManager = DisplayManager.getDisplayManager(buffer,
0422:                            this );
0423:
0424:                    displayManager.init();
0425:
0426:                    if (buffer.isLoading())
0427:                        updateScrollBar();
0428:
0429:                    repaint();
0430:
0431:                    fireScrollEvent(true);
0432:                } finally {
0433:                    bufferChanging = false;
0434:                }
0435:            } //}}}
0436:
0437:            //{{{ isEditable() method
0438:            /**
0439:             * Returns true if this text area is editable, false otherwise.
0440:             */
0441:            public final boolean isEditable() {
0442:                return buffer.isEditable();
0443:            } //}}}
0444:
0445:            //{{{ isDragInProgress() method
0446:            /**
0447:             * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs,
0448:             * however since jEdit must run with Java 1.3, this class only has the
0449:             * necessary support to call a hook method via reflection. This method
0450:             * is called by the {@link org.gjt.sp.jedit.Java14} class to signal that
0451:             * a drag is in progress.
0452:             * @since jEdit 4.2pre5
0453:             */
0454:            public boolean isDragInProgress() {
0455:                return dndInProgress;
0456:            } //}}}
0457:
0458:            //{{{ setDragInProgress() method
0459:            /**
0460:             * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs,
0461:             * however since jEdit must run with Java 1.3, this class only has the
0462:             * necessary support to call a hook method via reflection. This method
0463:             * is called by the {@link org.gjt.sp.jedit.Java14} class to signal that
0464:             * a drag is in progress.
0465:             * @since jEdit 4.2pre5
0466:             */
0467:            public void setDragInProgress(boolean dndInProgress) {
0468:                this .dndInProgress = dndInProgress;
0469:            } //}}}
0470:
0471:            //{{{ isDragEnabled() method
0472:            /**
0473:             * Returns if drag and drop of text is enabled.
0474:             * @since jEdit 4.2pre5
0475:             */
0476:            public boolean isDragEnabled() {
0477:                return dndEnabled;
0478:            } //}}}
0479:
0480:            //{{{ setDragEnabled() method
0481:            /**
0482:             * Sets if drag and drop of text is enabled.
0483:             * @since jEdit 4.2pre5
0484:             */
0485:            public void setDragEnabled(boolean dndEnabled) {
0486:                this .dndEnabled = dndEnabled;
0487:            } //}}}
0488:
0489:            //{{{ getJoinNonWordChars() method
0490:            /**
0491:             * If set, double clicking will join non-word characters to form one "word".
0492:             * @since jEdit 4.3pre2
0493:             */
0494:            public boolean getJoinNonWordChars() {
0495:                return joinNonWordChars;
0496:            } //}}}
0497:
0498:            //{{{ setJoinNonWordChars() method
0499:            /**
0500:             * If set, double clicking will join non-word characters to form one "word".
0501:             * @since jEdit 4.3pre2
0502:             */
0503:            public void setJoinNonWordChars(boolean joinNonWordChars) {
0504:                this .joinNonWordChars = joinNonWordChars;
0505:            } //}}}
0506:
0507:            //{{{ getCtrlForRectangularSelection() method
0508:            /**
0509:             * If set, CTRL enables rectangular selection mode while pressed.
0510:             * @since jEdit 4.3pre10
0511:             */
0512:            public boolean isCtrlForRectangularSelection() {
0513:                return ctrlForRectangularSelection;
0514:            } //}}}
0515:
0516:            //{{{ setCtrlForRectangularSelection() method
0517:            /**
0518:             * If set, CTRL enables rectangular selection mode while pressed.
0519:             * @since jEdit 4.3pre10
0520:             */
0521:            public void setCtrlForRectangularSelection(
0522:                    boolean ctrlForRectangularSelection) {
0523:                this .ctrlForRectangularSelection = ctrlForRectangularSelection;
0524:            } //}}}
0525:
0526:            //{{{ Scrolling
0527:
0528:            //{{{ getFirstLine() method
0529:            /**
0530:             * Returns the vertical scroll bar position.
0531:             * @since jEdit 4.2pre1
0532:             */
0533:            public final int getFirstLine() {
0534:                return displayManager.firstLine.scrollLine
0535:                        + displayManager.firstLine.skew;
0536:            } //}}}
0537:
0538:            //{{{ setFirstLine() method
0539:            /**
0540:             * Sets the vertical scroll bar position
0541:             *
0542:             * @param firstLine The scroll bar position
0543:             */
0544:            public void setFirstLine(int firstLine) {
0545:                //{{{ ensure we don't have empty space at the bottom or top, etc
0546:                int max = displayManager.getScrollLineCount() - visibleLines
0547:                        + (lastLinePartial ? 1 : 0);
0548:                if (firstLine > max)
0549:                    firstLine = max;
0550:                if (firstLine < 0)
0551:                    firstLine = 0;
0552:                //}}}
0553:
0554:                if (Debug.SCROLL_DEBUG) {
0555:                    Log.log(Log.DEBUG, this , "setFirstLine() from "
0556:                            + getFirstLine() + " to " + firstLine);
0557:                }
0558:
0559:                int oldFirstLine = getFirstLine();
0560:                if (firstLine == oldFirstLine)
0561:                    return;
0562:
0563:                displayManager.setFirstLine(oldFirstLine, firstLine);
0564:
0565:                repaint();
0566:
0567:                fireScrollEvent(true);
0568:            } //}}}
0569:
0570:            //{{{ getFirstPhysicalLine() method
0571:            /**
0572:             * Returns the first visible physical line index.
0573:             * @since jEdit 4.0pre4
0574:             */
0575:            public final int getFirstPhysicalLine() {
0576:                return displayManager.firstLine.physicalLine;
0577:            } //}}}
0578:
0579:            //{{{ setFirstPhysicalLine() method
0580:            /**
0581:             * Sets the vertical scroll bar position.
0582:             * @param physFirstLine The first physical line to display
0583:             * @since jEdit 4.2pre1
0584:             */
0585:            public void setFirstPhysicalLine(int physFirstLine) {
0586:                setFirstPhysicalLine(physFirstLine, 0);
0587:            } //}}}
0588:
0589:            //{{{ setFirstPhysicalLine() method
0590:            /**
0591:             * Sets the vertical scroll bar position.
0592:             * @param physFirstLine The first physical line to display
0593:             * @param skew A local screen line delta
0594:             * @since jEdit 4.2pre1
0595:             */
0596:            public void setFirstPhysicalLine(int physFirstLine, int skew) {
0597:                if (Debug.SCROLL_DEBUG) {
0598:                    Log.log(Log.DEBUG, this , "setFirstPhysicalLine("
0599:                            + physFirstLine + ',' + skew + ')');
0600:                }
0601:
0602:                int amount = physFirstLine
0603:                        - displayManager.firstLine.physicalLine;
0604:
0605:                displayManager.setFirstPhysicalLine(amount, skew);
0606:
0607:                repaint();
0608:
0609:                fireScrollEvent(true);
0610:            } //}}}
0611:
0612:            //{{{ getLastPhysicalLine() method
0613:            /**
0614:             * Returns the last visible physical line index.
0615:             * @since jEdit 4.0pre4
0616:             */
0617:            public final int getLastPhysicalLine() {
0618:                return physLastLine;
0619:            } //}}}
0620:
0621:            //{{{ getLastScreenLine() method
0622:            /**
0623:             * Returns the last screen line index, it is different from
0624:             * {@link #getVisibleLines()} because the buffer can have less lines than
0625:             * the visible lines
0626:             * @return the last screen line index.
0627:             * @since jEdit 4.3pre1
0628:             */
0629:            public int getLastScreenLine() {
0630:                return screenLastLine;
0631:            } //}}}
0632:
0633:            //{{{ getVisibleLines() method
0634:            /**
0635:             * Returns the number of lines visible in this text area.
0636:             * @return the number of visible lines in the textarea
0637:             */
0638:            public final int getVisibleLines() {
0639:                return visibleLines;
0640:            } //}}}
0641:
0642:            //{{{ getHorizontalOffset() method
0643:            /**
0644:             * Returns the horizontal offset of drawn lines.
0645:             */
0646:            public final int getHorizontalOffset() {
0647:                return horizontalOffset;
0648:            } //}}}
0649:
0650:            //{{{ setHorizontalOffset() method
0651:            /**
0652:             * Sets the horizontal offset of drawn lines. This can be used to
0653:             * implement horizontal scrolling.
0654:             * @param horizontalOffset offset The new horizontal offset
0655:             */
0656:            public void setHorizontalOffset(int horizontalOffset) {
0657:                if (horizontalOffset > 0)
0658:                    horizontalOffset = 0;
0659:
0660:                if (horizontalOffset == this .horizontalOffset)
0661:                    return;
0662:
0663:                this .horizontalOffset = horizontalOffset;
0664:                painter.repaint();
0665:
0666:                fireScrollEvent(false);
0667:            } //}}}
0668:
0669:            //{{{ scrollUpLine() method
0670:            /**
0671:             * Scrolls up by one line.
0672:             * @since jEdit 2.7pre2
0673:             */
0674:            public void scrollUpLine() {
0675:                setFirstLine(getFirstLine() - 1);
0676:            } //}}}
0677:
0678:            //{{{ scrollUpPage() method
0679:            /**
0680:             * Scrolls up by one page.
0681:             * @since jEdit 2.7pre2
0682:             */
0683:            public void scrollUpPage() {
0684:                setFirstLine(getFirstLine() - getVisibleLines()
0685:                        + (lastLinePartial ? 1 : 0));
0686:            } //}}}
0687:
0688:            //{{{ scrollDownLine() method
0689:            /**
0690:             * Scrolls down by one line.
0691:             * @since jEdit 2.7pre2
0692:             */
0693:            public void scrollDownLine() {
0694:                setFirstLine(getFirstLine() + 1);
0695:            } //}}}
0696:
0697:            //{{{ scrollDownPage() method
0698:            /**
0699:             * Scrolls down by one page.
0700:             * @since jEdit 2.7pre2
0701:             */
0702:            public void scrollDownPage() {
0703:                setFirstLine(getFirstLine() + getVisibleLines()
0704:                        - (lastLinePartial ? 1 : 0));
0705:            } //}}}
0706:
0707:            //{{{ scrollToCaret() method
0708:            /**
0709:             * Ensures that the caret is visible by scrolling the text area if
0710:             * necessary.
0711:             * @param doElectricScroll If true, electric scrolling will be performed
0712:             */
0713:            public void scrollToCaret(boolean doElectricScroll) {
0714:                scrollTo(caretLine, caret
0715:                        - buffer.getLineStartOffset(caretLine),
0716:                        doElectricScroll);
0717:            } //}}}
0718:
0719:            //{{{ scrollTo() method
0720:            /**
0721:             * Ensures that the specified location in the buffer is visible.
0722:             * @param offset The offset from the start of the buffer
0723:             * @param doElectricScroll If true, electric scrolling will be performed
0724:             * @since jEdit 4.2pre3
0725:             */
0726:            public void scrollTo(int offset, boolean doElectricScroll) {
0727:                int line = buffer.getLineOfOffset(offset);
0728:                scrollTo(line, offset - buffer.getLineStartOffset(line),
0729:                        doElectricScroll);
0730:            } //}}}
0731:
0732:            //{{{ scrollTo() method
0733:            /**
0734:             * Ensures that the specified location in the buffer is visible.
0735:             * @param line The line number
0736:             * @param offset The offset from the start of the line
0737:             * @param doElectricScroll If true, electric scrolling will be performed
0738:             * @since jEdit 4.0pre6
0739:             */
0740:            public void scrollTo(int line, int offset, boolean doElectricScroll) {
0741:                if (Debug.SCROLL_TO_DEBUG)
0742:                    Log.log(Log.DEBUG, this , "scrollTo(), lineCount="
0743:                            + getLineCount());
0744:
0745:                //{{{ Get ready
0746:                int extraEndVirt;
0747:                int lineLength = buffer.getLineLength(line);
0748:                if (offset > lineLength) {
0749:                    extraEndVirt = charWidth * (offset - lineLength);
0750:                    offset = lineLength;
0751:                } else
0752:                    extraEndVirt = 0;
0753:
0754:                int _electricScroll = doElectricScroll
0755:                        && visibleLines - 1 > (electricScroll << 1) ? electricScroll
0756:                        : 0;
0757:                //}}}
0758:
0759:                if (visibleLines <= 1) {
0760:                    if (Debug.SCROLL_TO_DEBUG)
0761:                        Log.log(Log.DEBUG, this , "visibleLines <= 0");
0762:                    setFirstPhysicalLine(line, _electricScroll);
0763:                    return;
0764:                }
0765:
0766:                //{{{ Scroll vertically
0767:                int screenLine = chunkCache.getScreenLineOfOffset(line, offset);
0768:                int visibleLines = getVisibleLines();
0769:                if (screenLine == -1) {
0770:                    if (Debug.SCROLL_TO_DEBUG)
0771:                        Log.log(Log.DEBUG, this , "screenLine == -1");
0772:                    ChunkCache.LineInfo[] infos = chunkCache
0773:                            .getLineInfosForPhysicalLine(line);
0774:                    int subregion = ChunkCache.getSubregionOfOffset(offset,
0775:                            infos);
0776:                    int prevLine = displayManager
0777:                            .getPrevVisibleLine(getFirstPhysicalLine());
0778:                    int nextLine = displayManager
0779:                            .getNextVisibleLine(getLastPhysicalLine());
0780:                    if (line == getFirstPhysicalLine()) {
0781:                        if (Debug.SCROLL_TO_DEBUG)
0782:                            Log.log(Log.DEBUG, this , line + " == "
0783:                                    + getFirstPhysicalLine());
0784:                        setFirstPhysicalLine(line, subregion - _electricScroll);
0785:                    } else if (line == prevLine) {
0786:                        if (Debug.SCROLL_TO_DEBUG)
0787:                            Log.log(Log.DEBUG, this , line + " == " + prevLine);
0788:                        setFirstPhysicalLine(prevLine, subregion
0789:                                - _electricScroll);
0790:                    } else if (line == getLastPhysicalLine()) {
0791:                        if (Debug.SCROLL_TO_DEBUG)
0792:                            Log.log(Log.DEBUG, this , line + " == "
0793:                                    + getLastPhysicalLine());
0794:                        setFirstPhysicalLine(line, subregion + _electricScroll
0795:                                - visibleLines + (lastLinePartial ? 2 : 1));
0796:                    } else if (line == nextLine) {
0797:                        if (Debug.SCROLL_TO_DEBUG)
0798:                            Log.log(Log.DEBUG, this , line + " == " + nextLine);
0799:                        setFirstPhysicalLine(nextLine, subregion
0800:                                + electricScroll - visibleLines
0801:                                + (lastLinePartial ? 2 : 1));
0802:                    } else {
0803:                        if (Debug.SCROLL_TO_DEBUG) {
0804:                            Log.log(Log.DEBUG, this , "neither");
0805:                            Log.log(Log.DEBUG, this , "Last physical line is "
0806:                                    + getLastPhysicalLine());
0807:                        }
0808:                        setFirstPhysicalLine(line, subregion
0809:                                - (visibleLines >> 1));
0810:                        if (Debug.SCROLL_TO_DEBUG) {
0811:                            Log.log(Log.DEBUG, this , "Last physical line is "
0812:                                    + getLastPhysicalLine());
0813:                        }
0814:                    }
0815:                } else if (screenLine < _electricScroll) {
0816:                    if (Debug.SCROLL_TO_DEBUG)
0817:                        Log.log(Log.DEBUG, this , "electric up");
0818:                    setFirstLine(getFirstLine() - _electricScroll + screenLine);
0819:                } else if (screenLine > visibleLines - _electricScroll
0820:                        - (lastLinePartial ? 2 : 1)) {
0821:                    if (Debug.SCROLL_TO_DEBUG)
0822:                        Log.log(Log.DEBUG, this , "electric down");
0823:                    setFirstLine(getFirstLine() + _electricScroll
0824:                            - visibleLines + screenLine
0825:                            + (lastLinePartial ? 2 : 1));
0826:                } //}}}
0827:
0828:                //{{{ Scroll horizontally
0829:                if (!displayManager.isLineVisible(line))
0830:                    return;
0831:
0832:                Point point = offsetToXY(line, offset, offsetXY);
0833:
0834:                point.x += extraEndVirt;
0835:
0836:                if (point.x < 0) {
0837:                    setHorizontalOffset(horizontalOffset - point.x + charWidth
0838:                            + 5);
0839:                } else if (point.x >= painter.getWidth() - charWidth - 5) {
0840:                    setHorizontalOffset(horizontalOffset
0841:                            + (painter.getWidth() - point.x) - charWidth - 5);
0842:                } //}}}
0843:            } //}}}
0844:
0845:            //{{{ addScrollListener() method
0846:            /**
0847:             * Adds a scroll listener to this text area.
0848:             * @param listener The listener
0849:             * @since jEdit 3.2pre2
0850:             */
0851:            public final void addScrollListener(ScrollListener listener) {
0852:                listenerList.add(ScrollListener.class, listener);
0853:            } //}}}
0854:
0855:            //{{{ removeScrollListener() method
0856:            /**
0857:             * Removes a scroll listener from this text area.
0858:             * @param listener The listener
0859:             * @since jEdit 3.2pre2
0860:             */
0861:            public final void removeScrollListener(ScrollListener listener) {
0862:                listenerList.remove(ScrollListener.class, listener);
0863:            } //}}}
0864:
0865:            //}}}
0866:
0867:            //{{{ Screen line stuff
0868:
0869:            //{{{ getPhysicalLineOfScreenLine() method
0870:            /**
0871:             * Returns the physical line number that contains the specified screen
0872:             * line.
0873:             * @param screenLine The screen line
0874:             * @since jEdit 4.0pre6
0875:             */
0876:            public int getPhysicalLineOfScreenLine(int screenLine) {
0877:                return chunkCache.getLineInfo(screenLine).physicalLine;
0878:            } //}}}
0879:
0880:            //{{{ getScreenLineOfOffset() method
0881:            /**
0882:             * Returns the screen (wrapped) line containing the specified offset.
0883:             * Returns -1 if the line is not currently visible on the screen.
0884:             * @param offset The offset
0885:             * @since jEdit 4.0pre4
0886:             */
0887:            public int getScreenLineOfOffset(int offset) {
0888:                int line = buffer.getLineOfOffset(offset);
0889:                offset -= buffer.getLineStartOffset(line);
0890:                return chunkCache.getScreenLineOfOffset(line, offset);
0891:            } //}}}
0892:
0893:            //{{{ getScreenLineStartOffset() method
0894:            /**
0895:             * Returns the start offset of the specified screen (wrapped) line.
0896:             * @param line The line
0897:             * @since jEdit 4.0pre4
0898:             */
0899:            public int getScreenLineStartOffset(int line) {
0900:                ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line);
0901:                if (lineInfo.physicalLine == -1)
0902:                    return -1;
0903:
0904:                return buffer.getLineStartOffset(lineInfo.physicalLine)
0905:                        + lineInfo.offset;
0906:            } //}}}
0907:
0908:            //{{{ getScreenLineEndOffset() method
0909:            /**
0910:             * Returns the end offset of the specified screen (wrapped) line.
0911:             * @param line The line
0912:             * @since jEdit 4.0pre4
0913:             */
0914:            public int getScreenLineEndOffset(int line) {
0915:                ChunkCache.LineInfo lineInfo = chunkCache.getLineInfo(line);
0916:                if (lineInfo.physicalLine == -1)
0917:                    return -1;
0918:
0919:                return buffer.getLineStartOffset(lineInfo.physicalLine)
0920:                        + lineInfo.offset + lineInfo.length;
0921:            } //}}}
0922:
0923:            //}}}
0924:
0925:            //{{{ Offset conversion
0926:
0927:            //{{{ xyToOffset() method
0928:            /**
0929:             * Converts a point to an offset.
0930:             * Note that unlike in previous jEdit versions, this method now returns
0931:             * -1 if the y co-ordinate is out of bounds.
0932:             *
0933:             * @param x The x co-ordinate of the point
0934:             * @param y The y co-ordinate of the point
0935:             */
0936:            public int xyToOffset(int x, int y) {
0937:                return xyToOffset(x, y, true);
0938:            } //}}}
0939:
0940:            //{{{ xyToOffset() method
0941:            /**
0942:             * Converts a point to an offset.
0943:             * Note that unlike in previous jEdit versions, this method now returns
0944:             * -1 if the y co-ordinate is out of bounds.
0945:             *
0946:             * @param x The x co-ordinate of the point
0947:             * @param y The y co-ordinate of the point
0948:             * @param round Round up to next letter if past the middle of a letter?
0949:             * @since jEdit 3.2pre6
0950:             */
0951:            public int xyToOffset(int x, int y, boolean round) {
0952:                FontMetrics fm = painter.getFontMetrics();
0953:                int height = fm.getHeight();
0954:                int line = y / height;
0955:
0956:                if (line < 0 || line >= visibleLines)
0957:                    return -1;
0958:
0959:                return xToScreenLineOffset(line, x, round);
0960:            } //}}}
0961:
0962:            //{{{ xToScreenLineOffset() method
0963:            /**
0964:             * Converts a point in a given screen line to an offset.
0965:             * Note that unlike in previous jEdit versions, this method now returns
0966:             * -1 if the y co-ordinate is out of bounds.
0967:             *
0968:             * @param x The x co-ordinate of the point
0969:             * @param screenLine The screen line
0970:             * @param round Round up to next letter if past the middle of a letter?
0971:             * @since jEdit 3.2pre6
0972:             */
0973:            public int xToScreenLineOffset(int screenLine, int x, boolean round) {
0974:                ChunkCache.LineInfo lineInfo = chunkCache
0975:                        .getLineInfo(screenLine);
0976:                if (lineInfo.physicalLine == -1) {
0977:                    return getLineEndOffset(displayManager.getLastVisibleLine()) - 1;
0978:                } else {
0979:                    int offset = Chunk.xToOffset(lineInfo.chunks, x
0980:                            - horizontalOffset, round);
0981:                    if (offset == -1
0982:                            || offset == lineInfo.offset + lineInfo.length)
0983:                        offset = lineInfo.offset + lineInfo.length - 1;
0984:
0985:                    return getLineStartOffset(lineInfo.physicalLine) + offset;
0986:                }
0987:            } //}}}
0988:
0989:            //{{{ offsetToXY() method
0990:            /**
0991:             * Converts an offset into a point in the text area painter's
0992:             * co-ordinate space.
0993:             * @param offset The offset
0994:             * @return The location of the offset on screen, or <code>null</code>
0995:             * if the specified offset is not visible
0996:             */
0997:            public Point offsetToXY(int offset) {
0998:                int line = buffer.getLineOfOffset(offset);
0999:                offset -= buffer.getLineStartOffset(line);
1000:                Point retVal = new Point();
1001:                return offsetToXY(line, offset, retVal);
1002:            } //}}}
1003:
1004:            //{{{ offsetToXY() method
1005:            /**
1006:             * Converts an offset into a point in the text area painter's
1007:             * co-ordinate space.
1008:             * @param line The line
1009:             * @param offset The offset
1010:             * @return The location of the offset on screen, or <code>null</code>
1011:             * if the specified offset is not visible
1012:             */
1013:            public Point offsetToXY(int line, int offset) {
1014:                return offsetToXY(line, offset, new Point());
1015:            } //}}}
1016:
1017:            //{{{ offsetToXY() method
1018:            /**
1019:             * Converts a line,offset pair into an x,y (pixel) point relative to the
1020:             * upper left corner (0,0) of the text area.
1021:             *
1022:             * @param line The physical line number (from top of document)
1023:             * @param offset The offset in characters, from the start of the line
1024:             * @param retVal The point to store the return value in
1025:             * @return <code>retVal</code> for convenience, or <code>null</code>
1026:             * if the specified offset is not visible
1027:             * @since jEdit 4.0pre4
1028:             */
1029:            public Point offsetToXY(int line, int offset, Point retVal) {
1030:                if (!displayManager.isLineVisible(line))
1031:                    return null;
1032:                int screenLine = chunkCache.getScreenLineOfOffset(line, offset);
1033:                if (screenLine == -1)
1034:                    return null;
1035:
1036:                FontMetrics fm = painter.getFontMetrics();
1037:
1038:                retVal.y = screenLine * fm.getHeight();
1039:
1040:                ChunkCache.LineInfo info = chunkCache.getLineInfo(screenLine);
1041:
1042:                retVal.x = (int) (horizontalOffset + Chunk.offsetToX(
1043:                        info.chunks, offset));
1044:
1045:                return retVal;
1046:            } //}}}
1047:
1048:            //}}}
1049:
1050:            //{{{ Painting
1051:
1052:            //{{{ invalidateScreenLineRange() method
1053:            /**
1054:             * Marks a range of screen lines as needing a repaint.
1055:             * @param start The first line
1056:             * @param end The last line
1057:             * @since jEdit 4.0pre4
1058:             */
1059:            public void invalidateScreenLineRange(int start, int end) {
1060:                if (buffer.isLoading())
1061:                    return;
1062:
1063:                if (start > end) {
1064:                    int tmp = end;
1065:                    end = start;
1066:                    start = tmp;
1067:                }
1068:
1069:                if (chunkCache.needFullRepaint())
1070:                    end = visibleLines;
1071:
1072:                FontMetrics fm = painter.getFontMetrics();
1073:                int y = start * fm.getHeight();
1074:                int height = (end - start + 1) * fm.getHeight();
1075:                painter.repaint(0, y, painter.getWidth(), height);
1076:                gutter.repaint(0, y, gutter.getWidth(), height);
1077:            } //}}}
1078:
1079:            //{{{ invalidateLine() method
1080:            /**
1081:             * Marks a line as needing a repaint.
1082:             * @param line The physical line to invalidate
1083:             */
1084:            public void invalidateLine(int line) {
1085:                if (!isShowing() || buffer.isLoading()
1086:                        || line < getFirstPhysicalLine() || line > physLastLine
1087:                        || !displayManager.isLineVisible(line))
1088:                    return;
1089:
1090:                int startLine = -1;
1091:                int endLine = -1;
1092:
1093:                for (int i = 0; i < visibleLines; i++) {
1094:                    ChunkCache.LineInfo info = chunkCache.getLineInfo(i);
1095:
1096:                    if ((info.physicalLine >= line || info.physicalLine == -1)
1097:                            && startLine == -1) {
1098:                        startLine = i;
1099:                    }
1100:
1101:                    if ((info.physicalLine >= line && info.lastSubregion)
1102:                            || info.physicalLine == -1) {
1103:                        endLine = i;
1104:                        break;
1105:                    }
1106:                }
1107:
1108:                if (chunkCache.needFullRepaint() || endLine == -1)
1109:                    endLine = visibleLines;
1110:
1111:                invalidateScreenLineRange(startLine, endLine);
1112:            } //}}}
1113:
1114:            //{{{ invalidateLineRange() method
1115:            /**
1116:             * Marks a range of physical lines as needing a repaint.
1117:             * @param start The first line to invalidate
1118:             * @param end The last line to invalidate
1119:             */
1120:            public void invalidateLineRange(int start, int end) {
1121:                if (!isShowing() || buffer.isLoading())
1122:                    return;
1123:
1124:                if (end < start) {
1125:                    int tmp = end;
1126:                    end = start;
1127:                    start = tmp;
1128:                }
1129:
1130:                if (end < getFirstPhysicalLine()
1131:                        || start > getLastPhysicalLine())
1132:                    return;
1133:
1134:                int startScreenLine = -1;
1135:                int endScreenLine = -1;
1136:
1137:                for (int i = 0; i < visibleLines; i++) {
1138:                    ChunkCache.LineInfo info = chunkCache.getLineInfo(i);
1139:
1140:                    if ((info.physicalLine >= start || info.physicalLine == -1)
1141:                            && startScreenLine == -1) {
1142:                        startScreenLine = i;
1143:                    }
1144:
1145:                    if ((info.physicalLine >= end && info.lastSubregion)
1146:                            || info.physicalLine == -1) {
1147:                        endScreenLine = i;
1148:                        break;
1149:                    }
1150:                }
1151:
1152:                if (startScreenLine == -1)
1153:                    startScreenLine = 0;
1154:
1155:                if (chunkCache.needFullRepaint() || endScreenLine == -1)
1156:                    endScreenLine = visibleLines;
1157:
1158:                invalidateScreenLineRange(startScreenLine, endScreenLine);
1159:            } //}}}
1160:
1161:            //}}}
1162:
1163:            //{{{ Convenience methods
1164:
1165:            //{{{ getBufferLength() method
1166:            /**
1167:             * Returns the length of the buffer.
1168:             */
1169:            public final int getBufferLength() {
1170:                return buffer.getLength();
1171:            } //}}}
1172:
1173:            //{{{ getLineCount() method
1174:            /**
1175:             * Returns the number of physical lines in the buffer.
1176:             */
1177:            public final int getLineCount() {
1178:                return buffer.getLineCount();
1179:            } //}}}
1180:
1181:            //{{{ getLineOfOffset() method
1182:            /**
1183:             * Returns the line containing the specified offset.
1184:             * @param offset The offset
1185:             */
1186:            public final int getLineOfOffset(int offset) {
1187:                return buffer.getLineOfOffset(offset);
1188:            } //}}}
1189:
1190:            //{{{ getLineStartOffset() method
1191:            /**
1192:             * Returns the start offset of the specified line.
1193:             * @param line The line (physical line)
1194:             * @return The start offset of the specified line, or -1 if the line is
1195:             * invalid
1196:             */
1197:            public int getLineStartOffset(int line) {
1198:                return buffer.getLineStartOffset(line);
1199:            } //}}}
1200:
1201:            //{{{ getLineEndOffset() method
1202:            /**
1203:             * Returns the end offset of the specified line.
1204:             * @param line The line (physical line)
1205:             * @return The end offset of the specified line, or -1 if the line is
1206:             * invalid.
1207:             */
1208:            public int getLineEndOffset(int line) {
1209:                return buffer.getLineEndOffset(line);
1210:            } //}}}
1211:
1212:            //{{{ getLineLength() method
1213:            /**
1214:             * Returns the length of the specified line.
1215:             * @param line The line
1216:             */
1217:            public int getLineLength(int line) {
1218:                return buffer.getLineLength(line);
1219:            } //}}}
1220:
1221:            //{{{ getText() method
1222:            /**
1223:             * Returns the specified substring of the buffer.
1224:             * @param start The start offset
1225:             * @param len The length of the substring
1226:             * @return The substring
1227:             */
1228:            public final String getText(int start, int len) {
1229:                return buffer.getText(start, len);
1230:            } //}}}
1231:
1232:            //{{{ getText() method
1233:            /**
1234:             * Copies the specified substring of the buffer into a segment.
1235:             * @param start The start offset
1236:             * @param len The length of the substring
1237:             * @param segment The segment
1238:             */
1239:            public final void getText(int start, int len, Segment segment) {
1240:                buffer.getText(start, len, segment);
1241:            } //}}}
1242:
1243:            //{{{ getLineText() method
1244:            /**
1245:             * Returns the text on the specified line.
1246:             * @param lineIndex the line number
1247:             * @return The text, or null if the lineIndex is invalid
1248:             */
1249:            public final String getLineText(int lineIndex) {
1250:                return buffer.getLineText(lineIndex);
1251:            } //}}}
1252:
1253:            //{{{ getLineText() method
1254:            /**
1255:             * Copies the text on the specified line into a Segment. If lineIndex
1256:             * is invalid, the segment will contain a null string.
1257:             * @param lineIndex The line number (physical line)
1258:             * @param segment the segment into which the data will be stored.
1259:             */
1260:            public final void getLineText(int lineIndex, Segment segment) {
1261:                buffer.getLineText(lineIndex, segment);
1262:            } //}}}
1263:
1264:            //{{{ getText() method
1265:            /**
1266:             * Returns the entire text of this text area.
1267:             */
1268:            public String getText() {
1269:                return buffer.getText(0, buffer.getLength());
1270:            } //}}}
1271:
1272:            //{{{ setText() method
1273:            /**
1274:             * Sets the entire text of this text area.
1275:             * @param text the new content of the buffer
1276:             */
1277:            public void setText(String text) {
1278:                try {
1279:                    buffer.beginCompoundEdit();
1280:                    buffer.remove(0, buffer.getLength());
1281:                    buffer.insert(0, text);
1282:                } finally {
1283:                    buffer.endCompoundEdit();
1284:                }
1285:            } //}}}
1286:
1287:            //}}}
1288:
1289:            //{{{ Selection
1290:
1291:            //{{{ selectAll() method
1292:            /**
1293:             * Selects all text in the buffer. Preserves the scroll position.
1294:             */
1295:            public final void selectAll() {
1296:                int firstLine = getFirstLine();
1297:                int horizOffset = getHorizontalOffset();
1298:
1299:                setSelection(new Selection.Range(0, buffer.getLength()));
1300:                moveCaretPosition(buffer.getLength(), true);
1301:
1302:                setFirstLine(firstLine);
1303:                setHorizontalOffset(horizOffset);
1304:            } //}}}
1305:
1306:            //{{{ selectLine() method
1307:            /**
1308:             * Selects the current line.
1309:             * @since jEdit 2.7pre2
1310:             */
1311:            public void selectLine() {
1312:                int caretLine = getCaretLine();
1313:                int start = getLineStartOffset(caretLine);
1314:                int end = getLineEndOffset(caretLine) - 1;
1315:                Selection s = new Selection.Range(start, end);
1316:                if (multi)
1317:                    addToSelection(s);
1318:                else
1319:                    setSelection(s);
1320:                moveCaretPosition(end);
1321:            } //}}}
1322:
1323:            //{{{ selectParagraph() method
1324:            /**
1325:             * Selects the paragraph at the caret position.
1326:             * @since jEdit 2.7pre2
1327:             */
1328:            public void selectParagraph() {
1329:                int caretLine = getCaretLine();
1330:
1331:                if (getLineLength(caretLine) == 0) {
1332:                    getToolkit().beep();
1333:                    return;
1334:                }
1335:
1336:                int start = caretLine;
1337:                int end = caretLine;
1338:
1339:                while (start >= 0) {
1340:                    if (getLineLength(start) == 0)
1341:                        break;
1342:                    else
1343:                        start--;
1344:                }
1345:
1346:                while (end < getLineCount()) {
1347:                    if (getLineLength(end) == 0)
1348:                        break;
1349:                    else
1350:                        end++;
1351:                }
1352:
1353:                int selectionStart = getLineStartOffset(start + 1);
1354:                int selectionEnd = getLineEndOffset(end - 1) - 1;
1355:                Selection s = new Selection.Range(selectionStart, selectionEnd);
1356:                if (multi)
1357:                    addToSelection(s);
1358:                else
1359:                    setSelection(s);
1360:                moveCaretPosition(selectionEnd);
1361:            } //}}}
1362:
1363:            //{{{ selectWord() method
1364:            /**
1365:             * Selects the word at the caret position.
1366:             * @since jEdit 2.7pre2
1367:             */
1368:            public void selectWord() {
1369:                int line = getCaretLine();
1370:                int lineStart = getLineStartOffset(line);
1371:                int offset = getCaretPosition() - lineStart;
1372:
1373:                if (getLineLength(line) == 0)
1374:                    return;
1375:
1376:                String lineText = getLineText(line);
1377:                String noWordSep = buffer.getStringProperty("noWordSep");
1378:
1379:                if (offset == getLineLength(line))
1380:                    offset--;
1381:
1382:                int wordStart = TextUtilities.findWordStart(lineText, offset,
1383:                        noWordSep, true, false, false);
1384:                int wordEnd = TextUtilities.findWordEnd(lineText, offset + 1,
1385:                        noWordSep, true, false, false);
1386:
1387:                Selection s = new Selection.Range(lineStart + wordStart,
1388:                        lineStart + wordEnd);
1389:                if (multi)
1390:                    addToSelection(s);
1391:                else
1392:                    setSelection(s);
1393:                moveCaretPosition(lineStart + wordEnd);
1394:            } //}}}
1395:
1396:            //{{{ selectToMatchingBracket() method
1397:            /**
1398:             * Selects from the bracket at the specified position to the
1399:             * corresponding bracket.
1400:             * @since jEdit 4.2pre1
1401:             */
1402:            public Selection selectToMatchingBracket(int position,
1403:                    boolean quickCopy) {
1404:                int positionLine = buffer.getLineOfOffset(position);
1405:                int lineOffset = position
1406:                        - buffer.getLineStartOffset(positionLine);
1407:                if (getLineLength(positionLine) != 0) {
1408:                    int bracket = TextUtilities.findMatchingBracket(buffer,
1409:                            positionLine, Math.max(0, lineOffset - 1));
1410:
1411:                    if (bracket != -1) {
1412:                        Selection s;
1413:
1414:                        if (bracket < position) {
1415:                            if (!quickCopy)
1416:                                moveCaretPosition(position, false);
1417:                            s = new Selection.Range(bracket, position);
1418:                        } else {
1419:                            if (!quickCopy)
1420:                                moveCaretPosition(bracket + 1, false);
1421:                            s = new Selection.Range(position - 1, bracket + 1);
1422:                        }
1423:
1424:                        if (!multi && !quickCopy)
1425:                            selectNone();
1426:
1427:                        addToSelection(s);
1428:                        return s;
1429:                    }
1430:                }
1431:
1432:                return null;
1433:            } //}}}
1434:
1435:            //{{{ selectToMatchingBracket() method
1436:            /**
1437:             * Selects from the bracket at the caret position to the corresponding
1438:             * bracket.
1439:             * @since jEdit 4.0pre2
1440:             */
1441:            public void selectToMatchingBracket() {
1442:                selectToMatchingBracket(caret, false);
1443:            } //}}}
1444:
1445:            //{{{ selectBlock() method
1446:            /**
1447:             * Selects the code block surrounding the caret.
1448:             * @since jEdit 2.7pre2
1449:             */
1450:            public void selectBlock() {
1451:
1452:                Selection s = getSelectionAtOffset(caret);
1453:                int start, end;
1454:                if (s == null)
1455:                    start = end = caret;
1456:                else {
1457:                    start = s.start;
1458:                    end = s.end;
1459:                }
1460:
1461:                String text = getText(0, buffer.getLength());
1462:
1463:                // We can't do the backward scan if start == 0
1464:                if (start == 0) {
1465:                    getToolkit().beep();
1466:                    return;
1467:                }
1468:
1469:                // Scan backwards, trying to find a bracket
1470:                String openBrackets = "([{";
1471:                String closeBrackets = ")]}";
1472:                int count = 1;
1473:                char openBracket = '\0';
1474:                char closeBracket = '\0';
1475:
1476:                backward_scan: while (--start > 0) {
1477:                    char c = text.charAt(start);
1478:                    int index = openBrackets.indexOf(c);
1479:                    if (index != -1) {
1480:                        if (--count == 0) {
1481:                            openBracket = c;
1482:                            closeBracket = closeBrackets.charAt(index);
1483:                            break backward_scan;
1484:                        }
1485:                    } else if (closeBrackets.indexOf(c) != -1)
1486:                        count++;
1487:                }
1488:
1489:                // Reset count
1490:                count = 1;
1491:
1492:                // Scan forward, matching that bracket
1493:                if (openBracket == '\0') {
1494:                    getToolkit().beep();
1495:                    return;
1496:                }
1497:                forward_scan: do {
1498:                    char c = text.charAt(end);
1499:                    if (c == closeBracket) {
1500:                        if (--count == 0) {
1501:                            end++;
1502:                            break forward_scan;
1503:                        }
1504:                    } else if (c == openBracket)
1505:                        count++;
1506:                } while (++end < buffer.getLength());
1507:
1508:                s = new Selection.Range(start, end);
1509:                if (multi)
1510:                    addToSelection(s);
1511:                else
1512:                    setSelection(s);
1513:                moveCaretPosition(end);
1514:            } //}}}
1515:
1516:            //{{{ lineInStructureScope() method
1517:            /**
1518:             * Returns if the specified line is contained in the currently
1519:             * matched structure's scope.
1520:             * @since jEdit 4.2pre3
1521:             */
1522:            public boolean lineInStructureScope(int line) {
1523:                if (match == null)
1524:                    return false;
1525:
1526:                if (match.startLine < caretLine)
1527:                    return line >= match.startLine && line <= caretLine;
1528:                else
1529:                    return line <= match.endLine && line >= caretLine;
1530:            } //}}}
1531:
1532:            //{{{ invertSelection() method
1533:            /**
1534:             * Inverts the selection.
1535:             * @since jEdit 4.0pre1
1536:             */
1537:            public final void invertSelection() {
1538:                selectionManager.invertSelection();
1539:            } //}}}
1540:
1541:            //{{{ getSelectionCount() method
1542:            /**
1543:             * Returns the number of selections. This can be used to test
1544:             * for the existence of selections.
1545:             * @since jEdit 3.2pre2
1546:             */
1547:            public int getSelectionCount() {
1548:                return selectionManager.getSelectionCount();
1549:            } //}}}
1550:
1551:            //{{{ getSelection() method
1552:            /**
1553:             * Returns the current selection.
1554:             * @since jEdit 3.2pre1
1555:             */
1556:            public Selection[] getSelection() {
1557:                return selectionManager.getSelection();
1558:            } //}}}
1559:
1560:            //{{{ getSelectionIterator() method
1561:            /**
1562:             * Returns the current selection.
1563:             * @since jEdit 4.3pre1
1564:             */
1565:            public Iterator<Selection> getSelectionIterator() {
1566:                return selectionManager.selection.iterator();
1567:            } //}}}
1568:
1569:            //{{{ getSelection() method
1570:            /**
1571:             * Returns the selection with the specified index. This must be
1572:             * between 0 and the return value of <code>getSelectionCount()</code>.
1573:             * @since jEdit 4.3pre1
1574:             * @param index the index of the selection you want
1575:             */
1576:            public Selection getSelection(int index) {
1577:                return selectionManager.selection.get(index);
1578:            } //}}}
1579:
1580:            //{{{ selectNone() method
1581:            /**
1582:             * Deselects everything.
1583:             */
1584:            public void selectNone() {
1585:                invalidateSelectedLines();
1586:                setSelection((Selection) null);
1587:            } //}}}
1588:
1589:            //{{{ setSelection() method
1590:            /**
1591:             * Sets the selection. Nested and overlapping selections are merged
1592:             * where possible. Null elements of the array are ignored.
1593:             * @param selection The new selection
1594:             * since jEdit 3.2pre1
1595:             */
1596:            public void setSelection(Selection[] selection) {
1597:                // invalidate the old selection
1598:                invalidateSelectedLines();
1599:                selectionManager.setSelection(selection);
1600:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1601:            } //}}}
1602:
1603:            //{{{ setSelection() method
1604:            /**
1605:             * Sets the selection. Nested and overlapping selections are merged
1606:             * where possible.
1607:             * @param selection The new selection
1608:             * since jEdit 3.2pre1
1609:             */
1610:            public void setSelection(Selection selection) {
1611:                invalidateSelectedLines();
1612:                selectionManager.setSelection(selection);
1613:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1614:            } //}}}
1615:
1616:            //{{{ addToSelection() method
1617:            /**
1618:             * Adds to the selection. Nested and overlapping selections are merged
1619:             * where possible.
1620:             * @param selection The new selection
1621:             * since jEdit 3.2pre1
1622:             */
1623:            public void addToSelection(Selection[] selection) {
1624:                invalidateSelectedLines();
1625:                selectionManager.addToSelection(selection);
1626:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1627:            } //}}}
1628:
1629:            //{{{ addToSelection() method
1630:            /**
1631:             * Adds to the selection. Nested and overlapping selections are merged
1632:             * where possible.
1633:             * @param selection The new selection
1634:             * since jEdit 3.2pre1
1635:             */
1636:            public void addToSelection(Selection selection) {
1637:                invalidateSelectedLines();
1638:                selectionManager.addToSelection(selection);
1639:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1640:            } //}}}
1641:
1642:            //{{{ getSelectionAtOffset() method
1643:            /**
1644:             * Returns the selection containing the specific offset, or <code>null</code>
1645:             * if there is no selection at that offset.
1646:             * @param offset The offset
1647:             * @since jEdit 3.2pre1
1648:             */
1649:            public Selection getSelectionAtOffset(int offset) {
1650:                return selectionManager.getSelectionAtOffset(offset);
1651:            } //}}}
1652:
1653:            //{{{ removeFromSelection() method
1654:            /**
1655:             * Deactivates the specified selection.
1656:             * @param sel The selection
1657:             * @since jEdit 3.2pre1
1658:             */
1659:            public void removeFromSelection(Selection sel) {
1660:                invalidateSelectedLines();
1661:                selectionManager.removeFromSelection(sel);
1662:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1663:            } //}}}
1664:
1665:            //{{{ removeFromSelection() method
1666:            /**
1667:             * Deactivates the selection at the specified offset. If there is
1668:             * no selection at that offset, does nothing.
1669:             * @param offset The offset
1670:             * @since jEdit 3.2pre1
1671:             */
1672:            public void removeFromSelection(int offset) {
1673:                Selection sel = getSelectionAtOffset(offset);
1674:                if (sel == null)
1675:                    return;
1676:
1677:                invalidateSelectedLines();
1678:                selectionManager.removeFromSelection(sel);
1679:                finishCaretUpdate(caretLine, NO_SCROLL, true);
1680:            } //}}}
1681:
1682:            //{{{ resizeSelection() method
1683:            /**
1684:             * Resizes the selection at the specified offset, or creates a new
1685:             * one if there is no selection at the specified offset. This is a
1686:             * utility method that is mainly useful in the mouse event handler
1687:             * because it handles the case of end being before offset gracefully
1688:             * (unlike the rest of the selection API).
1689:             * @param offset The offset
1690:             * @param end The new selection end
1691:             * @param extraEndVirt Only for rectangular selections - specifies how
1692:             * far it extends into virtual space.
1693:             * @param rect Make the selection rectangular?
1694:             * @since jEdit 3.2pre1
1695:             */
1696:            public void resizeSelection(int offset, int end, int extraEndVirt,
1697:                    boolean rect) {
1698:                Selection s = selectionManager.getSelectionAtOffset(offset);
1699:                if (s != null) {
1700:                    invalidateLineRange(s.startLine, s.endLine);
1701:                    selectionManager.removeFromSelection(s);
1702:                }
1703:
1704:                selectionManager.resizeSelection(offset, end, extraEndVirt,
1705:                        rect);
1706:                fireCaretEvent();
1707:            } //}}}
1708:
1709:            //{{{ extendSelection() method
1710:            /**
1711:             * Extends the selection at the specified offset, or creates a new
1712:             * one if there is no selection at the specified offset. This is
1713:             * different from resizing in that the new chunk is added to the
1714:             * selection in question, instead of replacing it.
1715:             * @param offset The offset
1716:             * @param end The new selection end
1717:             * @since jEdit 3.2pre1
1718:             */
1719:            public void extendSelection(int offset, int end) {
1720:                extendSelection(offset, end, 0, 0);
1721:            } //}}}
1722:
1723:            //{{{ extendSelection() method
1724:            /**
1725:             * Extends the selection at the specified offset, or creates a new
1726:             * one if there is no selection at the specified offset. This is
1727:             * different from resizing in that the new chunk is added to the
1728:             * selection in question, instead of replacing it.
1729:             * @param offset The offset
1730:             * @param end The new selection end
1731:             * @param extraStartVirt Extra virtual space at the start
1732:             * @param extraEndVirt Extra virtual space at the end
1733:             * @since jEdit 4.2pre1
1734:             */
1735:            public void extendSelection(int offset, int end,
1736:                    int extraStartVirt, int extraEndVirt) {
1737:                Selection s = getSelectionAtOffset(offset);
1738:                if (s != null) {
1739:                    invalidateLineRange(s.startLine, s.endLine);
1740:                    selectionManager.removeFromSelection(s);
1741:
1742:                    if (offset == s.start) {
1743:                        offset = end;
1744:                        end = s.end;
1745:                    } else if (offset == s.end) {
1746:                        offset = s.start;
1747:                    }
1748:                }
1749:
1750:                if (end < offset) {
1751:                    int tmp = end;
1752:                    end = offset;
1753:                    offset = tmp;
1754:                }
1755:
1756:                if (rectangularSelectionMode) {
1757:                    s = new Selection.Rect(offset, end);
1758:                    ((Selection.Rect) s).extraStartVirt = extraStartVirt;
1759:                    ((Selection.Rect) s).extraEndVirt = extraEndVirt;
1760:                } else
1761:                    s = new Selection.Range(offset, end);
1762:
1763:                selectionManager.addToSelection(s);
1764:                fireCaretEvent();
1765:
1766:                if (rectangularSelectionMode && extraEndVirt != 0) {
1767:                    int line = getLineOfOffset(end);
1768:                    scrollTo(line, getLineLength(line) + extraEndVirt, false);
1769:                }
1770:            } //}}}
1771:
1772:            //{{{ getSelectedText() method
1773:            /**
1774:             * Returns the text in the specified selection.
1775:             * @param s The selection
1776:             * @since jEdit 3.2pre1
1777:             */
1778:            public String getSelectedText(Selection s) {
1779:                StringBuffer buf = new StringBuffer(s.end - s.start);
1780:                s.getText(buffer, buf);
1781:                return buf.toString();
1782:            } //}}}
1783:
1784:            //{{{ getSelectedText() method
1785:            /**
1786:             * Returns the text in all active selections.
1787:             * @param separator The string to insert between each text chunk
1788:             * (for example, a newline)
1789:             * @since jEdit 3.2pre1
1790:             */
1791:            public String getSelectedText(String separator) {
1792:                Selection[] sel = selectionManager.getSelection();
1793:                if (sel.length == 0)
1794:                    return null;
1795:
1796:                StringBuffer buf = new StringBuffer();
1797:                for (int i = 0; i < sel.length; i++) {
1798:                    if (i != 0)
1799:                        buf.append(separator);
1800:
1801:                    sel[i].getText(buffer, buf);
1802:                }
1803:
1804:                return buf.toString();
1805:            } //}}}
1806:
1807:            //{{{ getSelectedText() method
1808:            /**
1809:             * Returns the text in all active selections, with a newline
1810:             * between each text chunk.
1811:             */
1812:            public String getSelectedText() {
1813:                return getSelectedText("\n");
1814:            } //}}}
1815:
1816:            //{{{ setSelectedText() method
1817:            /**
1818:             * Replaces the selection with the specified text.
1819:             * @param s The selection
1820:             * @param selectedText The new text
1821:             * @since jEdit 3.2pre1
1822:             */
1823:            public void setSelectedText(Selection s, String selectedText) {
1824:                if (!isEditable()) {
1825:                    throw new InternalError("Text component" + " read only");
1826:                }
1827:
1828:                try {
1829:                    buffer.beginCompoundEdit();
1830:
1831:                    moveCaretPosition(s.setText(buffer, selectedText));
1832:                }
1833:                // No matter what happends... stops us from leaving buffer
1834:                // in a bad state
1835:                finally {
1836:                    buffer.endCompoundEdit();
1837:                }
1838:
1839:                // no no no!!!!
1840:                //selectNone();
1841:            } //}}}
1842:
1843:            //{{{ setSelectedText() method
1844:            /**
1845:             * Replaces the selection at the caret with the specified text.
1846:             * If there is no selection at the caret, the text is inserted at
1847:             * the caret position.
1848:             */
1849:            public void setSelectedText(String selectedText) {
1850:                int newCaret = replaceSelection(selectedText);
1851:                if (newCaret != -1)
1852:                    moveCaretPosition(newCaret);
1853:                selectNone();
1854:            } //}}}
1855:
1856:            //{{{ setSelectedText() method
1857:            /**
1858:             * Replaces the selection at the caret with the specified text.
1859:             * If there is no selection at the caret, the text is inserted at
1860:             * the caret position.
1861:             * @param selectedText The new selection
1862:             * @param moveCaret Move caret to insertion location if necessary
1863:             * @since jEdit 4.2pre5
1864:             */
1865:            public void setSelectedText(String selectedText, boolean moveCaret) {
1866:                int newCaret = replaceSelection(selectedText);
1867:                if (moveCaret && newCaret != -1)
1868:                    moveCaretPosition(newCaret);
1869:                selectNone();
1870:            } //}}}
1871:
1872:            //{{{ replaceSelection() method
1873:            /**
1874:             * Set the selection, but does not deactivate it, and does not move the
1875:             * caret.
1876:             *
1877:             * Please use {@link #setSelectedText(String)} instead.
1878:             *
1879:             * @param selectedText The new selection
1880:             * @return The new caret position
1881:             * @since 4.3pre1
1882:             */
1883:            public int replaceSelection(String selectedText) {
1884:                if (!isEditable())
1885:                    throw new RuntimeException("Text component read only");
1886:
1887:                int newCaret = -1;
1888:
1889:                if (getSelectionCount() == 0) {
1890:                    // for compatibility with older jEdit versions
1891:                    buffer.insert(caret, selectedText);
1892:                } else {
1893:                    try {
1894:
1895:                        buffer.beginCompoundEdit();
1896:
1897:                        Selection[] selection = getSelection();
1898:                        for (int i = 0; i < selection.length; i++)
1899:                            newCaret = selection[i].setText(buffer,
1900:                                    selectedText);
1901:                    } finally {
1902:                        buffer.endCompoundEdit();
1903:                    }
1904:                }
1905:
1906:                return newCaret;
1907:            } //}}}
1908:
1909:            //{{{ getSelectedLines() method
1910:            /**
1911:             * Returns a sorted array of line numbers on which a selection or
1912:             * selections are present.<p>
1913:             *
1914:             * This method is the most convenient way to iterate through selected
1915:             * lines in a buffer. The line numbers in the array returned by this
1916:             * method can be passed as a parameter to such methods as
1917:             * {@link JEditBuffer#getLineText(int)}.
1918:             *
1919:             * @since jEdit 3.2pre1
1920:             */
1921:            public int[] getSelectedLines() {
1922:                if (selectionManager.getSelectionCount() == 0)
1923:                    return new int[] { caretLine };
1924:
1925:                return selectionManager.getSelectedLines();
1926:            } //}}}
1927:
1928:            //}}}
1929:
1930:            //{{{ Caret
1931:
1932:            //{{{ caretAutoScroll() method
1933:            /**
1934:             * Return if change in buffer should scroll this text area.
1935:             * @since jEdit 4.3pre2
1936:             */
1937:            public boolean caretAutoScroll() {
1938:                return focusedComponent == this ;
1939:            } //}}}
1940:
1941:            //{{{ addStructureMatcher() method
1942:            /**
1943:             * Adds a structure matcher.
1944:             * @since jEdit 4.2pre3
1945:             */
1946:            public void addStructureMatcher(StructureMatcher matcher) {
1947:                structureMatchers.add(matcher);
1948:            } //}}}
1949:
1950:            //{{{ removeStructureMatcher() method
1951:            /**
1952:             * Removes a structure matcher.
1953:             * @since jEdit 4.2pre3
1954:             */
1955:            public void removeStructureMatcher(StructureMatcher matcher) {
1956:                structureMatchers.remove(matcher);
1957:            } //}}}
1958:
1959:            //{{{ getStructureMatchStart() method
1960:            /**
1961:             * Returns the structure element (bracket, or XML tag, etc) matching the
1962:             * one before the caret.
1963:             * @since jEdit 4.2pre3
1964:             */
1965:            public StructureMatcher.Match getStructureMatch() {
1966:                return match;
1967:            } //}}}
1968:
1969:            //{{{ blinkCaret() method
1970:            /**
1971:             * Blinks the caret.
1972:             */
1973:            public final void blinkCaret() {
1974:                if (caretBlinks) {
1975:                    blink = !blink;
1976:                    invalidateLine(caretLine);
1977:                } else
1978:                    blink = true;
1979:            } //}}}
1980:
1981:            //{{{ centerCaret() method
1982:            /**
1983:             * Centers the caret on the screen.
1984:             * @since jEdit 2.7pre2
1985:             */
1986:            public void centerCaret() {
1987:                int offset = getScreenLineStartOffset(visibleLines >> 1);
1988:                if (offset == -1)
1989:                    getToolkit().beep();
1990:                else
1991:                    setCaretPosition(offset);
1992:            } //}}}
1993:
1994:            //{{{ setCaretPosition() method
1995:            /**
1996:             * Sets the caret position and deactivates the selection.
1997:             * @param newCaret The caret position
1998:             */
1999:            public void setCaretPosition(int newCaret) {
2000:                selectNone();
2001:                moveCaretPosition(newCaret, true);
2002:            } //}}}
2003:
2004:            //{{{ setCaretPosition() method
2005:            /**
2006:             * Sets the caret position and deactivates the selection.
2007:             * @param newCaret The caret position
2008:             * @param doElectricScroll Do electric scrolling?
2009:             */
2010:            public void setCaretPosition(int newCaret, boolean doElectricScroll) {
2011:                selectNone();
2012:                moveCaretPosition(newCaret, doElectricScroll);
2013:            } //}}}
2014:
2015:            //{{{ moveCaretPosition() method
2016:            /**
2017:             * Sets the caret position without deactivating the selection.
2018:             * @param newCaret The caret position
2019:             */
2020:            public void moveCaretPosition(int newCaret) {
2021:                moveCaretPosition(newCaret, true);
2022:            } //}}}
2023:
2024:            //{{{ moveCaretPosition() method
2025:            /**
2026:             * Sets the caret position without deactivating the selection.
2027:             * @param newCaret The caret position
2028:             * @param doElectricScroll Do electric scrolling?
2029:             */
2030:            public void moveCaretPosition(int newCaret, boolean doElectricScroll) {
2031:                moveCaretPosition(newCaret, doElectricScroll ? ELECTRIC_SCROLL
2032:                        : NORMAL_SCROLL);
2033:            } //}}}
2034:
2035:            //{{{ moveCaretPosition() method
2036:            public static final int NO_SCROLL = 0;
2037:            public static final int NORMAL_SCROLL = 1;
2038:            public static final int ELECTRIC_SCROLL = 2;
2039:
2040:            /**
2041:             * Sets the caret position without deactivating the selection.
2042:             * @param newCaret The caret position
2043:             * @param scrollMode The scroll mode (NO_SCROLL, NORMAL_SCROLL, or
2044:             * ELECTRIC_SCROLL).
2045:             * @since jEdit 4.2pre1
2046:             */
2047:            public void moveCaretPosition(int newCaret, int scrollMode) {
2048:                if (newCaret < 0 || newCaret > buffer.getLength()) {
2049:                    throw new IllegalArgumentException("caret out of bounds: "
2050:                            + newCaret);
2051:                }
2052:
2053:                int oldCaretLine = caretLine;
2054:
2055:                if (caret == newCaret)
2056:                    finishCaretUpdate(oldCaretLine, scrollMode, false);
2057:                else {
2058:                    caret = newCaret;
2059:                    caretLine = getLineOfOffset(newCaret);
2060:
2061:                    magicCaret = -1;
2062:
2063:                    finishCaretUpdate(oldCaretLine, scrollMode, true);
2064:                }
2065:            } //}}}
2066:
2067:            //{{{ getCaretPosition() method
2068:            /**
2069:             * Returns a zero-based index of the caret position.
2070:             */
2071:            public int getCaretPosition() {
2072:                return caret;
2073:            } //}}}
2074:
2075:            //{{{ getCaretLine() method
2076:            /**
2077:             * Returns the line number containing the caret.
2078:             */
2079:            public int getCaretLine() {
2080:                return caretLine;
2081:            } //}}}
2082:
2083:            //{{{ getMagicCaretPosition() method
2084:            /**
2085:             * Returns an internal position used to keep the caret in one
2086:             * column while moving around lines of varying lengths.
2087:             * @since jEdit 4.2pre1
2088:             */
2089:            public int getMagicCaretPosition() {
2090:                if (magicCaret == -1) {
2091:                    magicCaret = chunkCache.subregionOffsetToX(caretLine, caret
2092:                            - getLineStartOffset(caretLine));
2093:                }
2094:
2095:                return magicCaret;
2096:            } //}}}
2097:
2098:            //{{{ setMagicCaretPosition() method
2099:            /**
2100:             * Sets the `magic' caret position. This can be used to preserve
2101:             * the column position when moving up and down lines.
2102:             * @param magicCaret The magic caret position
2103:             * @since jEdit 4.2pre1
2104:             */
2105:            public void setMagicCaretPosition(int magicCaret) {
2106:                this .magicCaret = magicCaret;
2107:            } //}}}
2108:
2109:            //{{{ addCaretListener() method
2110:            /**
2111:             * Adds a caret change listener to this text area.
2112:             * @param listener The listener
2113:             */
2114:            public final void addCaretListener(CaretListener listener) {
2115:                listenerList.add(CaretListener.class, listener);
2116:            } //}}}
2117:
2118:            //{{{ removeCaretListener() method
2119:            /**
2120:             * Removes a caret change listener from this text area.
2121:             * @param listener The listener
2122:             */
2123:            public final void removeCaretListener(CaretListener listener) {
2124:                listenerList.remove(CaretListener.class, listener);
2125:            } //}}}
2126:
2127:            //{{{ goToNextBracket() method
2128:            /**
2129:             * Moves the caret to the next closing bracket.
2130:             * @param select true if you want to extend selection
2131:             * @since jEdit 2.7pre2.
2132:             */
2133:            public void goToNextBracket(boolean select) {
2134:                int newCaret = -1;
2135:
2136:                if (caret != buffer.getLength()) {
2137:                    String text = getText(caret, buffer.getLength() - caret - 1);
2138:
2139:                    loop: for (int i = 0; i < text.length(); i++) {
2140:                        switch (text.charAt(i)) {
2141:                        case ')':
2142:                        case ']':
2143:                        case '}':
2144:                            newCaret = caret + i + 1;
2145:                            break loop;
2146:                        }
2147:                    }
2148:                }
2149:
2150:                if (newCaret == -1)
2151:                    getToolkit().beep();
2152:                else {
2153:                    if (select)
2154:                        extendSelection(caret, newCaret);
2155:                    else if (!multi)
2156:                        selectNone();
2157:                    moveCaretPosition(newCaret);
2158:                }
2159:            } //}}}
2160:
2161:            //{{{ goToNextCharacter() method
2162:            /**
2163:             * Moves the caret to the next character.
2164:             * @param select true if you want to extend selection
2165:             * @since jEdit 2.7pre2.
2166:             */
2167:            public void goToNextCharacter(boolean select) {
2168:                Selection s = getSelectionAtOffset(caret);
2169:
2170:                if (!select && s instanceof  Selection.Range) {
2171:                    if (multi) {
2172:                        if (caret != s.end) {
2173:                            moveCaretPosition(s.end);
2174:                            return;
2175:                        }
2176:                    } else {
2177:                        setCaretPosition(s.end);
2178:                        return;
2179:                    }
2180:                }
2181:
2182:                int extraStartVirt, extraEndVirt;
2183:                if (s instanceof  Selection.Rect) {
2184:                    extraStartVirt = ((Selection.Rect) s).extraStartVirt;
2185:                    extraEndVirt = ((Selection.Rect) s).extraEndVirt;
2186:                } else {
2187:                    extraStartVirt = 0;
2188:                    extraEndVirt = 0;
2189:                }
2190:
2191:                int newCaret = caret;
2192:
2193:                if (caret == buffer.getLength()) {
2194:                    if (select
2195:                            && (rectangularSelectionMode || s instanceof  Selection.Rect)) {
2196:                        if (s != null && caret == s.start)
2197:                            extraStartVirt++;
2198:                        else
2199:                            extraEndVirt++;
2200:                    } else {
2201:                        getToolkit().beep();
2202:                        return;
2203:                    }
2204:                } else if (caret == getLineEndOffset(caretLine) - 1) {
2205:                    if (select
2206:                            && (rectangularSelectionMode || s instanceof  Selection.Rect)) {
2207:                        if (s != null && caret == s.start)
2208:                            extraStartVirt++;
2209:                        else
2210:                            extraEndVirt++;
2211:                    } else {
2212:                        int line = displayManager.getNextVisibleLine(caretLine);
2213:                        if (line == -1) {
2214:                            getToolkit().beep();
2215:                            return;
2216:                        } else
2217:                            newCaret = getLineStartOffset(line);
2218:                    }
2219:                } else
2220:                    newCaret = caret + 1;
2221:
2222:                if (select)
2223:                    extendSelection(caret, newCaret, extraStartVirt,
2224:                            extraEndVirt);
2225:                else if (!multi)
2226:                    selectNone();
2227:
2228:                moveCaretPosition(newCaret);
2229:            } //}}}
2230:
2231:            //{{{ goToNextLine() method
2232:            /**
2233:             * Move the caret to the next line.
2234:             * @param select true if you want to extend selection
2235:             * @since jEdit 2.7pre2
2236:             */
2237:            public void goToNextLine(boolean select) {
2238:                Selection s = getSelectionAtOffset(caret);
2239:                boolean rectSelect = s == null ? rectangularSelectionMode
2240:                        : s instanceof  Selection.Rect;
2241:                int magic = getMagicCaretPosition();
2242:                int newCaret = chunkCache.getBelowPosition(caretLine, caret
2243:                        - buffer.getLineStartOffset(caretLine), magic + 1,
2244:                        rectSelect && select);
2245:                if (newCaret == -1) {
2246:                    int end = getLineEndOffset(caretLine) - 1;
2247:                    if (caret == end) {
2248:                        getToolkit().beep();
2249:                        return;
2250:                    } else
2251:                        newCaret = end;
2252:                }
2253:
2254:                _changeLine(select, newCaret);
2255:
2256:                setMagicCaretPosition(magic);
2257:            }//}}}
2258:
2259:            //{{{ goToNextPage() method
2260:            /**
2261:             * Moves the caret to the next screenful.
2262:             * @param select true if you want to extend selection
2263:             * @since jEdit 2.7pre2.
2264:             */
2265:            public void goToNextPage(boolean select) {
2266:                scrollToCaret(false);
2267:                int magic = getMagicCaretPosition();
2268:                if (caretLine < displayManager.getFirstVisibleLine()) {
2269:                    caretLine = displayManager.getNextVisibleLine(caretLine);
2270:                }
2271:
2272:                int newCaret;
2273:
2274:                if (getFirstLine() + getVisibleLines() >= displayManager
2275:                        .getScrollLineCount()) {
2276:                    int lastVisibleLine = displayManager.getLastVisibleLine();
2277:                    newCaret = getLineEndOffset(lastVisibleLine) - 1;
2278:                } else {
2279:                    int caretScreenLine = getScreenLineOfOffset(caret);
2280:
2281:                    scrollDownPage();
2282:
2283:                    newCaret = xToScreenLineOffset(caretScreenLine, magic, true);
2284:                }
2285:
2286:                if (select)
2287:                    extendSelection(caret, newCaret);
2288:                else if (!multi)
2289:                    selectNone();
2290:
2291:                moveCaretPosition(newCaret, false);
2292:
2293:                setMagicCaretPosition(magic);
2294:            } //}}}
2295:
2296:            //{{{ goToNextParagraph() method
2297:            /**
2298:             * Moves the caret to the start of the next paragraph.
2299:             * @param select true if you want to extend selection
2300:             * @since jEdit 2.7pre2
2301:             */
2302:            public void goToNextParagraph(boolean select) {
2303:                int lineNo = getCaretLine();
2304:
2305:                int newCaret = getBufferLength();
2306:
2307:                boolean foundBlank = false;
2308:
2309:                loop: for (int i = lineNo + 1; i < getLineCount(); i++) {
2310:                    if (!displayManager.isLineVisible(i))
2311:                        continue;
2312:
2313:                    getLineText(i, lineSegment);
2314:
2315:                    for (int j = 0; j < lineSegment.count; j++) {
2316:                        switch (lineSegment.array[lineSegment.offset + j]) {
2317:                        case ' ':
2318:                        case '\t':
2319:                            break;
2320:                        default:
2321:                            if (foundBlank) {
2322:                                newCaret = getLineStartOffset(i);
2323:                                break loop;
2324:                            } else
2325:                                continue loop;
2326:                        }
2327:                    }
2328:
2329:                    foundBlank = true;
2330:                }
2331:
2332:                if (select)
2333:                    extendSelection(caret, newCaret);
2334:                else if (!multi)
2335:                    selectNone();
2336:                moveCaretPosition(newCaret);
2337:            } //}}}
2338:
2339:            //{{{ goToNextWord() method
2340:            /**
2341:             * Moves the caret to the start of the next word.
2342:             * Note that if the "view.eatWhitespace" boolean propery is false,
2343:             * this method moves the caret to the end of the current word instead.
2344:             * @param select true if you want to extend selection
2345:             * @since jEdit 2.7pre2
2346:             */
2347:            public void goToNextWord(boolean select) {
2348:                goToNextWord(select, false);
2349:            } //}}}
2350:
2351:            //{{{ goToNextWord() method
2352:            /**
2353:             * Moves the caret to the start of the next word.
2354:             * @since jEdit 4.1pre5
2355:             */
2356:            public void goToNextWord(boolean select, boolean eatWhitespace) {
2357:                int lineStart = getLineStartOffset(caretLine);
2358:                int newCaret = caret - lineStart;
2359:                String lineText = getLineText(caretLine);
2360:
2361:                if (newCaret == lineText.length()) {
2362:                    int nextLine = displayManager.getNextVisibleLine(caretLine);
2363:                    if (nextLine == -1) {
2364:                        getToolkit().beep();
2365:                        return;
2366:                    }
2367:
2368:                    newCaret = getLineStartOffset(nextLine);
2369:                } else {
2370:                    String noWordSep = buffer.getStringProperty("noWordSep");
2371:                    boolean camelCasedWords = buffer
2372:                            .getBooleanProperty("camelCasedWords");
2373:                    newCaret = TextUtilities.findWordEnd(lineText,
2374:                            newCaret + 1, noWordSep, true, camelCasedWords,
2375:                            eatWhitespace);
2376:
2377:                    newCaret += lineStart;
2378:                }
2379:
2380:                if (select)
2381:                    extendSelection(caret, newCaret);
2382:                else if (!multi)
2383:                    selectNone();
2384:                moveCaretPosition(newCaret);
2385:            } //}}}
2386:
2387:            //{{{ goToPrevBracket() method
2388:            /**
2389:             * Moves the caret to the previous bracket.
2390:             * @param select true if you want to extend selection
2391:             * @since jEdit 2.7pre2
2392:             */
2393:            public void goToPrevBracket(boolean select) {
2394:                String text = getText(0, caret);
2395:
2396:                int newCaret = -1;
2397:
2398:                loop: for (int i = getCaretPosition() - 1; i >= 0; i--) {
2399:                    switch (text.charAt(i)) {
2400:                    case '(':
2401:                    case '[':
2402:                    case '{':
2403:                        newCaret = i;
2404:                        break loop;
2405:                    }
2406:                }
2407:
2408:                if (newCaret == -1)
2409:                    getToolkit().beep();
2410:                else {
2411:                    if (select)
2412:                        extendSelection(caret, newCaret);
2413:                    else if (!multi)
2414:                        selectNone();
2415:                    moveCaretPosition(newCaret);
2416:                }
2417:            } //}}}
2418:
2419:            //{{{ goToPrevCharacter() method
2420:            /**
2421:             * Moves the caret to the previous character.
2422:             * @param select true if you want to extend selection
2423:             * @since jEdit 2.7pre2.
2424:             */
2425:            public void goToPrevCharacter(boolean select) {
2426:                Selection s = getSelectionAtOffset(caret);
2427:
2428:                if (caret == 0) {
2429:                    getToolkit().beep();
2430:                    return;
2431:                }
2432:
2433:                if (!select && s instanceof  Selection.Range) {
2434:                    if (multi) {
2435:                        if (caret != s.start) {
2436:                            moveCaretPosition(s.start);
2437:                            return;
2438:                        }
2439:                    } else {
2440:                        setCaretPosition(s.start);
2441:                        return;
2442:                    }
2443:                }
2444:
2445:                int extraStartVirt = 0;
2446:                int extraEndVirt = 0;
2447:                int newCaret = caret;
2448:
2449:                if (select && caret == getLineEndOffset(caretLine) - 1) {
2450:                    if (s instanceof  Selection.Rect) {
2451:                        extraStartVirt = ((Selection.Rect) s).extraStartVirt;
2452:                        extraEndVirt = ((Selection.Rect) s).extraEndVirt;
2453:                        if (caret == s.start) {
2454:                            if (extraStartVirt == 0)
2455:                                newCaret = caret - 1;
2456:                            else
2457:                                extraStartVirt--;
2458:                        } else {
2459:                            if (extraEndVirt == 0)
2460:                                newCaret = caret - 1;
2461:                            else
2462:                                extraEndVirt--;
2463:                        }
2464:                    } else
2465:                        newCaret = caret - 1;
2466:                } else if (caret == getLineStartOffset(caretLine)) {
2467:                    int line = displayManager.getPrevVisibleLine(caretLine);
2468:                    if (line == -1) {
2469:                        getToolkit().beep();
2470:                        return;
2471:                    }
2472:                    newCaret = getLineEndOffset(line) - 1;
2473:                } else
2474:                    newCaret = caret - 1;
2475:
2476:                if (select)
2477:                    extendSelection(caret, newCaret, extraStartVirt,
2478:                            extraEndVirt);
2479:                else if (!multi)
2480:                    selectNone();
2481:                moveCaretPosition(newCaret);
2482:            } //}}}
2483:
2484:            //{{{ goToPrevLine() method
2485:            /**
2486:             * Moves the caret to the previous line.
2487:             * @param select true if you want to extend selection
2488:             * @since jEdit 2.7pre2
2489:             */
2490:            public void goToPrevLine(boolean select) {
2491:                Selection s = getSelectionAtOffset(caret);
2492:                boolean rectSelect = s == null ? rectangularSelectionMode
2493:                        : s instanceof  Selection.Rect;
2494:                int magic = getMagicCaretPosition();
2495:
2496:                int newCaret = chunkCache.getAbovePosition(caretLine, caret
2497:                        - buffer.getLineStartOffset(caretLine), magic + 1,
2498:                        rectSelect && select);
2499:                if (newCaret == -1) {
2500:                    int start = getLineStartOffset(caretLine);
2501:                    if (caret == start) {
2502:                        getToolkit().beep();
2503:                        return;
2504:                    } else
2505:                        newCaret = start;
2506:                }
2507:
2508:                _changeLine(select, newCaret);
2509:
2510:                setMagicCaretPosition(magic);
2511:            } //}}}
2512:
2513:            //{{{ goToPrevPage() method
2514:            /**
2515:             * Moves the caret to the previous screenful.
2516:             * @param select true if you want to extend selection
2517:             * @since jEdit 2.7pre2
2518:             */
2519:            public void goToPrevPage(boolean select) {
2520:                scrollToCaret(false);
2521:                int magic = getMagicCaretPosition();
2522:
2523:                if (caretLine < displayManager.getFirstVisibleLine()) {
2524:                    caretLine = displayManager.getNextVisibleLine(caretLine);
2525:                }
2526:
2527:                int newCaret;
2528:
2529:                if (getFirstLine() == 0) {
2530:                    int firstVisibleLine = displayManager.getFirstVisibleLine();
2531:                    newCaret = getLineStartOffset(firstVisibleLine);
2532:                } else {
2533:                    int caretScreenLine = getScreenLineOfOffset(caret);
2534:
2535:                    scrollUpPage();
2536:
2537:                    newCaret = xToScreenLineOffset(caretScreenLine, magic, true);
2538:                }
2539:
2540:                if (select)
2541:                    extendSelection(caret, newCaret);
2542:                else if (!multi)
2543:                    selectNone();
2544:                moveCaretPosition(newCaret, false);
2545:
2546:                setMagicCaretPosition(magic);
2547:            } //}}}
2548:
2549:            //{{{ goToPrevParagraph() method
2550:            /**
2551:             * Moves the caret to the start of the previous paragraph.
2552:             * @param select true if you want to extend selection
2553:             * @since jEdit 2.7pre2
2554:             */
2555:            public void goToPrevParagraph(boolean select) {
2556:                int lineNo = caretLine;
2557:                int newCaret = 0;
2558:
2559:                boolean foundBlank = false;
2560:
2561:                loop: for (int i = lineNo - 1; i >= 0; i--) {
2562:                    if (!displayManager.isLineVisible(i))
2563:                        continue;
2564:
2565:                    getLineText(i, lineSegment);
2566:
2567:                    for (int j = 0; j < lineSegment.count; j++) {
2568:                        switch (lineSegment.array[lineSegment.offset + j]) {
2569:                        case ' ':
2570:                        case '\t':
2571:                            break;
2572:                        default:
2573:                            if (foundBlank) {
2574:                                newCaret = getLineEndOffset(i) - 1;
2575:                                break loop;
2576:                            } else
2577:                                continue loop;
2578:                        }
2579:                    }
2580:
2581:                    foundBlank = true;
2582:                }
2583:
2584:                if (select)
2585:                    extendSelection(caret, newCaret);
2586:                else if (!multi)
2587:                    selectNone();
2588:                moveCaretPosition(newCaret);
2589:            } //}}}
2590:
2591:            //{{{ goToPrevWord() method
2592:            /**
2593:             * Moves the caret to the start of the previous word.
2594:             * @param select true if you want to extend selection
2595:             * @since jEdit 2.7pre2
2596:             */
2597:            public void goToPrevWord(boolean select) {
2598:                goToPrevWord(select, false);
2599:            } //}}}
2600:
2601:            //{{{ goToPrevWord() method
2602:            /**
2603:             * Moves the caret to the start of the previous word.
2604:             * @since jEdit 4.1pre5
2605:             */
2606:            public void goToPrevWord(boolean select, boolean eatWhitespace) {
2607:                int lineStart = getLineStartOffset(caretLine);
2608:                int newCaret = caret - lineStart;
2609:                String lineText = getLineText(caretLine);
2610:
2611:                if (newCaret == 0) {
2612:                    if (lineStart == 0) {
2613:                        getToolkit().beep();
2614:                        return;
2615:                    } else {
2616:                        int prevLine = displayManager
2617:                                .getPrevVisibleLine(caretLine);
2618:                        if (prevLine == -1) {
2619:                            getToolkit().beep();
2620:                            return;
2621:                        }
2622:
2623:                        newCaret = getLineEndOffset(prevLine) - 1;
2624:                    }
2625:                } else {
2626:                    String noWordSep = buffer.getStringProperty("noWordSep");
2627:                    boolean camelCasedWords = buffer
2628:                            .getBooleanProperty("camelCasedWords");
2629:                    newCaret = TextUtilities.findWordStart(lineText,
2630:                            newCaret - 1, noWordSep, true, camelCasedWords,
2631:                            eatWhitespace);
2632:
2633:                    newCaret += lineStart;
2634:                }
2635:
2636:                if (select)
2637:                    extendSelection(caret, newCaret);
2638:                else if (!multi)
2639:                    selectNone();
2640:                moveCaretPosition(newCaret);
2641:            } //}}}
2642:
2643:            //{{{ smartHome() method
2644:            /**
2645:             * On subsequent invocations, first moves the caret to the first
2646:             * non-whitespace character of the line, then the beginning of the
2647:             * line, then to the first visible line.
2648:             * @param select true if you want to extend selection
2649:             * @since jEdit 4.3pre7
2650:             */
2651:            public void smartHome(boolean select) {
2652:                switch (getInputHandler().getLastActionCount()) {
2653:                case 1:
2654:                    goToStartOfWhiteSpace(select);
2655:                    break;
2656:                case 2:
2657:                    goToStartOfLine(select);
2658:                    break;
2659:                default: //case 3:
2660:                    goToFirstVisibleLine(select);
2661:                    break;
2662:                }
2663:            } //}}}
2664:
2665:            //{{{ smartEnd() method
2666:            /**
2667:             * On subsequent invocations, first moves the caret to the last
2668:             * non-whitespace character of the line, then the end of the
2669:             * line, then to the last visible line.
2670:             * @param select true if you want to extend selection
2671:             * @since jEdit 4.3pre7
2672:             */
2673:            public void smartEnd(boolean select) {
2674:                switch (getInputHandler().getLastActionCount()) {
2675:                case 1:
2676:                    goToEndOfWhiteSpace(select);
2677:                    break;
2678:                case 2:
2679:                    goToEndOfLine(select);
2680:                    break;
2681:                default: //case 3:
2682:                    goToLastVisibleLine(select);
2683:                    break;
2684:                }
2685:            } //}}}
2686:
2687:            //{{{ goToStartOfLine() method
2688:            /**
2689:             * Moves the caret to the beginning of the current line.
2690:             * @param select true if you want to extend selection
2691:             * @since jEdit 2.7pre2
2692:             */
2693:            public void goToStartOfLine(boolean select) {
2694:                Selection s = getSelectionAtOffset(caret);
2695:                int line = select || s == null ? caretLine : s.startLine;
2696:                int newCaret = getLineStartOffset(line);
2697:                if (select)
2698:                    extendSelection(caret, newCaret);
2699:                else if (!multi)
2700:                    selectNone();
2701:                moveCaretPosition(newCaret);
2702:            } //}}}
2703:
2704:            //{{{ goToEndOfLine() method
2705:            /**
2706:             * Moves the caret to the end of the current line.
2707:             * @param select true if you want to extend selection
2708:             * @since jEdit 2.7pre2
2709:             */
2710:            public void goToEndOfLine(boolean select) {
2711:                Selection s = getSelectionAtOffset(caret);
2712:                int line = select || s == null ? caretLine : s.endLine;
2713:                int newCaret = getLineEndOffset(line) - 1;
2714:                if (select)
2715:                    extendSelection(caret, newCaret);
2716:                else if (!multi)
2717:                    selectNone();
2718:                moveCaretPosition(newCaret);
2719:
2720:                // so that end followed by up arrow will always put caret at
2721:                // the end of the previous line, for example
2722:                //setMagicCaretPosition(Integer.MAX_VALUE);
2723:            } //}}}
2724:
2725:            //{{{ goToStartOfWhiteSpace() method
2726:            /**
2727:             * Moves the caret to the first non-whitespace character of the current
2728:             * line.
2729:             * @param select true if you want to extend selection
2730:             * @since jEdit 2.7pre2
2731:             */
2732:            public void goToStartOfWhiteSpace(boolean select) {
2733:                Selection s = getSelectionAtOffset(caret);
2734:                int line, offset;
2735:                if (select || s == null) {
2736:                    line = caretLine;
2737:                    offset = caret - buffer.getLineStartOffset(line);
2738:                } else {
2739:                    line = s.startLine;
2740:                    offset = s.start - buffer.getLineStartOffset(line);
2741:                }
2742:
2743:                int firstIndent = chunkCache.getSubregionStartOffset(line,
2744:                        offset);
2745:                if (firstIndent == getLineStartOffset(line)) {
2746:                    firstIndent = StandardUtilities
2747:                            .getLeadingWhiteSpace(getLineText(line));
2748:                    if (firstIndent == getLineLength(line))
2749:                        firstIndent = 0;
2750:                    firstIndent += getLineStartOffset(line);
2751:                }
2752:
2753:                if (select)
2754:                    extendSelection(caret, firstIndent);
2755:                else if (!multi)
2756:                    selectNone();
2757:                moveCaretPosition(firstIndent);
2758:            } //}}}
2759:
2760:            //{{{ goToEndOfWhiteSpace() method
2761:            /**
2762:             * Moves the caret to the last non-whitespace character of the current
2763:             * line.
2764:             * @param select true if you want to extend selection
2765:             * @since jEdit 2.7pre2
2766:             */
2767:            public void goToEndOfWhiteSpace(boolean select) {
2768:                Selection s = getSelectionAtOffset(caret);
2769:                int line, offset;
2770:                if (select || s == null) {
2771:                    line = caretLine;
2772:                    offset = caret - getLineStartOffset(line);
2773:                } else {
2774:                    line = s.endLine;
2775:                    offset = s.end - getLineStartOffset(line);
2776:                }
2777:
2778:                int lastIndent = chunkCache.getSubregionEndOffset(line, offset);
2779:
2780:                if (lastIndent == getLineEndOffset(line)) {
2781:                    lastIndent = getLineLength(line)
2782:                            - StandardUtilities
2783:                                    .getTrailingWhiteSpace(getLineText(line));
2784:                    if (lastIndent == 0)
2785:                        lastIndent = getLineLength(line);
2786:                    lastIndent += getLineStartOffset(line);
2787:                } else {
2788:                    lastIndent--;
2789:                }
2790:
2791:                if (select)
2792:                    extendSelection(caret, lastIndent);
2793:                else if (!multi)
2794:                    selectNone();
2795:                moveCaretPosition(lastIndent);
2796:            } //}}}
2797:
2798:            //{{{ goToFirstVisibleLine() method
2799:            /**
2800:             * Moves the caret to the first visible line.
2801:             * @param select true if you want to extend selection
2802:             * @since jEdit 2.7pre2
2803:             */
2804:            public void goToFirstVisibleLine(boolean select) {
2805:                int firstVisibleLine = getFirstLine() == 0 ? 0 : electricScroll;
2806:                int firstVisible = getScreenLineStartOffset(firstVisibleLine);
2807:                if (firstVisible == -1) {
2808:                    firstVisible = getLineStartOffset(displayManager
2809:                            .getFirstVisibleLine());
2810:                }
2811:
2812:                if (select)
2813:                    extendSelection(caret, firstVisible);
2814:                else if (!multi)
2815:                    selectNone();
2816:                moveCaretPosition(firstVisible);
2817:            } //}}}
2818:
2819:            //{{{ goToLastVisibleLine() method
2820:            /**
2821:             * Moves the caret to the last visible line.
2822:             * @param select true if you want to extend selection
2823:             * @since jEdit 2.7pre2
2824:             */
2825:            public void goToLastVisibleLine(boolean select) {
2826:                int lastVisible;
2827:
2828:                if (getFirstLine() + visibleLines >= displayManager
2829:                        .getScrollLineCount()) {
2830:                    lastVisible = getLineEndOffset(displayManager
2831:                            .getLastVisibleLine()) - 1;
2832:                } else {
2833:                    lastVisible = visibleLines - electricScroll - 1;
2834:                    if (lastLinePartial)
2835:                        lastVisible--;
2836:                    if (lastVisible < 0)
2837:                        lastVisible = 0;
2838:                    lastVisible = getScreenLineEndOffset(lastVisible) - 1;
2839:                    if (lastVisible == -1) {
2840:                        lastVisible = getLineEndOffset(displayManager
2841:                                .getLastVisibleLine()) - 1;
2842:                    }
2843:                }
2844:
2845:                if (select)
2846:                    extendSelection(caret, lastVisible);
2847:                else if (!multi)
2848:                    selectNone();
2849:                moveCaretPosition(lastVisible);
2850:            } //}}}
2851:
2852:            //{{{ goToBufferStart() method
2853:            /**
2854:             * Moves the caret to the beginning of the buffer.
2855:             * @param select true if you want to extend selection
2856:             * @since jEdit 4.0pre3
2857:             */
2858:            public void goToBufferStart(boolean select) {
2859:                int start = buffer.getLineStartOffset(displayManager
2860:                        .getFirstVisibleLine());
2861:                if (select)
2862:                    extendSelection(caret, start);
2863:                else if (!multi)
2864:                    selectNone();
2865:                moveCaretPosition(start);
2866:            } //}}}
2867:
2868:            //{{{ goToBufferEnd() method
2869:            /**
2870:             * Moves the caret to the end of the buffer.
2871:             * @param select true if you want to extend selection
2872:             * @since jEdit 4.0pre3
2873:             */
2874:            public void goToBufferEnd(boolean select) {
2875:                int end = buffer.getLineEndOffset(displayManager
2876:                        .getLastVisibleLine()) - 1;
2877:                if (select)
2878:                    extendSelection(caret, end);
2879:                else if (!multi)
2880:                    selectNone();
2881:                moveCaretPosition(end);
2882:            } //}}}
2883:
2884:            //{{{ goToMatchingBracket() method
2885:            /**
2886:             * Moves the caret to the bracket matching the one before the caret.
2887:             * @since jEdit 2.7pre3
2888:             */
2889:            public void goToMatchingBracket() {
2890:                if (getLineLength(caretLine) != 0) {
2891:                    int dot = caret - getLineStartOffset(caretLine);
2892:
2893:                    int bracket = TextUtilities.findMatchingBracket(buffer,
2894:                            caretLine, Math.max(0, dot - 1));
2895:                    if (bracket != -1) {
2896:                        selectNone();
2897:                        moveCaretPosition(bracket + 1, false);
2898:                        return;
2899:                    }
2900:                }
2901:
2902:                getToolkit().beep();
2903:            } //}}}
2904:
2905:            //}}}
2906:
2907:            //{{{ User input
2908:
2909:            //{{{ userInput() method
2910:            /**
2911:             * Handles the insertion of the specified character. It performs the
2912:             * following operations above and beyond simply inserting the text:
2913:             * <ul>
2914:             * <li>Inserting a TAB with a selection will shift to the right
2915:             * <li>Inserting a BACK_SPACE or a DELETE will remove a character
2916:             * <li>Inserting an indent open/close bracket will re-indent the current
2917:             * line as necessary
2918:             * </ul>
2919:             *
2920:             * @param ch The character
2921:             * @see #setSelectedText(String)
2922:             * @see #isOverwriteEnabled()
2923:             * @since jEdit 4.3pre7
2924:             */
2925:            public void userInput(char ch) {
2926:                if (!isEditable()) {
2927:                    getToolkit().beep();
2928:                    return;
2929:                }
2930:
2931:                /* Null before addNotify() */
2932:                if (hiddenCursor != null)
2933:                    getPainter().setCursor(hiddenCursor);
2934:
2935:                switch (ch) {
2936:                case '\t':
2937:                    userInputTab();
2938:                    break;
2939:                case '\b':
2940:                    backspace();
2941:                    break;
2942:                case '\u007F':
2943:                    delete();
2944:                    break;
2945:                default:
2946:                    boolean indent = buffer.isElectricKey(ch, caretLine);
2947:                    String str = String.valueOf(ch);
2948:                    if (getSelectionCount() == 0) {
2949:                        if (!doWordWrap(ch == ' '))
2950:                            insert(str, indent);
2951:                    } else
2952:                        replaceSelection(str);
2953:                    break;
2954:                }
2955:            } //}}}
2956:
2957:            //{{{ isOverwriteEnabled() method
2958:            /**
2959:             * Returns true if overwrite mode is enabled, false otherwise.
2960:             */
2961:            public final boolean isOverwriteEnabled() {
2962:                return overwrite;
2963:            } //}}}
2964:
2965:            //{{{ setOverwriteEnabled() method
2966:            /**
2967:             * Sets overwrite mode.
2968:             */
2969:            public final void setOverwriteEnabled(boolean overwrite) {
2970:                blink = true;
2971:                caretTimer.restart();
2972:
2973:                this .overwrite = overwrite;
2974:                invalidateLine(caretLine);
2975:                fireStatusChanged(StatusListener.OVERWRITE_CHANGED, overwrite);
2976:            } //}}}
2977:
2978:            //{{{ toggleOverwriteEnabled() method
2979:            /**
2980:             * Toggles overwrite mode.
2981:             * @since jEdit 2.7pre2
2982:             */
2983:            public final void toggleOverwriteEnabled() {
2984:                setOverwriteEnabled(!overwrite);
2985:            } //}}}
2986:
2987:            //{{{ backspace() method
2988:            /**
2989:             * Deletes the character before the caret, or the selection, if one is
2990:             * active.
2991:             * @since jEdit 2.7pre2
2992:             */
2993:            public void backspace() {
2994:                delete(false);
2995:            } //}}}
2996:
2997:            //{{{ backspaceWord() method
2998:            /**
2999:             * Deletes the word before the caret.
3000:             * @since jEdit 2.7pre2
3001:             */
3002:            public void backspaceWord() {
3003:                backspaceWord(false);
3004:            } //}}}
3005:
3006:            //{{{ backspaceWord() method
3007:            /**
3008:             * Deletes the word before the caret.
3009:             * @param eatWhitespace If true, will eat whitespace
3010:             * @since jEdit 4.2pre5
3011:             */
3012:            public void backspaceWord(boolean eatWhitespace) {
3013:                if (!buffer.isEditable()) {
3014:                    getToolkit().beep();
3015:                    return;
3016:                }
3017:
3018:                if (getSelectionCount() != 0) {
3019:                    setSelectedText("");
3020:                    return;
3021:                }
3022:
3023:                int lineStart = getLineStartOffset(caretLine);
3024:                int _caret = caret - lineStart;
3025:
3026:                String lineText = getLineText(caretLine);
3027:
3028:                if (_caret == 0) {
3029:                    if (lineStart == 0) {
3030:                        getToolkit().beep();
3031:                        return;
3032:                    }
3033:                    _caret--;
3034:                } else {
3035:                    String noWordSep = buffer.getStringProperty("noWordSep");
3036:                    boolean camelCasedWords = buffer
3037:                            .getBooleanProperty("camelCasedWords");
3038:                    _caret = TextUtilities.findWordStart(lineText, _caret - 1,
3039:                            noWordSep, true, camelCasedWords, eatWhitespace);
3040:                }
3041:
3042:                buffer.remove(_caret + lineStart, caret - (_caret + lineStart));
3043:            } //}}}
3044:
3045:            //{{{ delete() method
3046:            /**
3047:             * Deletes the character after the caret.
3048:             * @since jEdit 2.7pre2
3049:             */
3050:            public void delete() {
3051:                delete(true);
3052:            } //}}}
3053:
3054:            //{{{ deleteToEndOfLine() method
3055:            /**
3056:             * Deletes from the caret to the end of the current line.
3057:             * @since jEdit 2.7pre2
3058:             */
3059:            public void deleteToEndOfLine() {
3060:                if (!buffer.isEditable()) {
3061:                    getToolkit().beep();
3062:                    return;
3063:                }
3064:
3065:                buffer.remove(caret, getLineEndOffset(caretLine) - caret - 1);
3066:            } //}}}
3067:
3068:            //{{{ deleteLine() method
3069:            /**
3070:             * Deletes the line containing the caret.
3071:             * @since jEdit 2.7pre2
3072:             */
3073:            public void deleteLine() {
3074:                if (!buffer.isEditable()) {
3075:                    getToolkit().beep();
3076:                    return;
3077:                }
3078:
3079:                int x = chunkCache.subregionOffsetToX(caretLine, caret
3080:                        - getLineStartOffset(caretLine));
3081:                int[] lines = getSelectedLines();
3082:
3083:                try {
3084:                    buffer.beginCompoundEdit();
3085:
3086:                    for (int i = lines.length - 1; i >= 0; i--) {
3087:                        int start = getLineStartOffset(lines[i]);
3088:                        int end = getLineEndOffset(lines[i]);
3089:                        if (end > buffer.getLength()) {
3090:                            if (start != 0)
3091:                                start--;
3092:                            end--;
3093:                        }
3094:                        buffer.remove(start, end - start);
3095:                    }
3096:                } finally {
3097:                    buffer.endCompoundEdit();
3098:                }
3099:
3100:                int lastLine = displayManager.getLastVisibleLine();
3101:
3102:                if (caretLine == lastLine) {
3103:                    int offset = chunkCache.xToSubregionOffset(lastLine, 0, x,
3104:                            true);
3105:                    setCaretPosition(buffer.getLineStartOffset(lastLine)
3106:                            + offset);
3107:                } else {
3108:                    int offset = chunkCache.xToSubregionOffset(caretLine, 0, x,
3109:                            true);
3110:                    setCaretPosition(getLineStartOffset(caretLine) + offset);
3111:                }
3112:            } //}}}
3113:
3114:            //{{{ deleteParagraph() method
3115:            /**
3116:             * Deletes the paragraph containing the caret.
3117:             * @since jEdit 2.7pre2
3118:             */
3119:            public void deleteParagraph() {
3120:                if (!buffer.isEditable()) {
3121:                    getToolkit().beep();
3122:                    return;
3123:                }
3124:
3125:                // find the beginning of the paragraph.
3126:                int start = 0;
3127:                for (int i = caretLine - 1; i >= 0; i--) {
3128:                    if (lineContainsSpaceAndTabs(i)) {
3129:                        start = getLineStartOffset(i);
3130:                        break;
3131:                    }
3132:                }
3133:
3134:                // Find the end of the paragraph
3135:                int end = buffer.getLength();
3136:                for (int i = caretLine + 1; i < getLineCount(); i++) {
3137:                    //if(!displayManager.isLineVisible(i))
3138:                    //	continue loop;
3139:
3140:                    if (lineContainsSpaceAndTabs(i)) {
3141:                        end = getLineEndOffset(i) - 1;
3142:                        break;
3143:                    }
3144:                }
3145:
3146:                buffer.remove(start, end - start);
3147:            } //}}}
3148:
3149:            //{{{ deleteToStartOfLine() method
3150:            /**
3151:             * Deletes from the caret to the beginning of the current line.
3152:             * @since jEdit 2.7pre2
3153:             */
3154:            public void deleteToStartOfLine() {
3155:                if (!buffer.isEditable()) {
3156:                    getToolkit().beep();
3157:                    return;
3158:                }
3159:
3160:                buffer.remove(getLineStartOffset(caretLine), caret
3161:                        - getLineStartOffset(caretLine));
3162:            } //}}}
3163:
3164:            //{{{ deleteWord() method
3165:            /**
3166:             * Deletes the word in front of the caret.
3167:             * @since jEdit 2.7pre2
3168:             */
3169:            public void deleteWord() {
3170:                deleteWord(false);
3171:            } //}}}
3172:
3173:            //{{{ deleteWord() method
3174:            /**
3175:             * Deletes the word in front of the caret.
3176:             *
3177:            .	 * @param eatWhitespace If true, will eat whitespace
3178:             * @since jEdit 4.2pre5
3179:             */
3180:            public void deleteWord(boolean eatWhitespace) {
3181:                if (!buffer.isEditable()) {
3182:                    getToolkit().beep();
3183:                    return;
3184:                }
3185:
3186:                if (getSelectionCount() != 0) {
3187:                    setSelectedText("");
3188:                    return;
3189:                }
3190:
3191:                int lineStart = getLineStartOffset(caretLine);
3192:                int _caret = caret - lineStart;
3193:
3194:                String lineText = getLineText(caretLine);
3195:
3196:                if (_caret == lineText.length()) {
3197:                    if (lineStart + _caret == buffer.getLength()) {
3198:                        getToolkit().beep();
3199:                        return;
3200:                    }
3201:                    _caret++;
3202:                } else {
3203:                    String noWordSep = buffer.getStringProperty("noWordSep");
3204:                    boolean camelCasedWords = buffer
3205:                            .getBooleanProperty("camelCasedWords");
3206:                    _caret = TextUtilities.findWordEnd(lineText, _caret + 1,
3207:                            noWordSep, true, camelCasedWords, eatWhitespace);
3208:                }
3209:
3210:                buffer.remove(caret, (_caret + lineStart) - caret);
3211:            } //}}}
3212:
3213:            //{{{ isMultipleSelectionEnabled() method
3214:            /**
3215:             * Returns if multiple selection is enabled.
3216:             * @since jEdit 3.2pre1
3217:             */
3218:            public final boolean isMultipleSelectionEnabled() {
3219:                return multi;
3220:            } //}}}
3221:
3222:            //{{{ toggleMultipleSelectionEnabled() method
3223:            /**
3224:             * Toggles multiple selection.
3225:             * @since jEdit 3.2pre1
3226:             */
3227:            public final void toggleMultipleSelectionEnabled() {
3228:                setMultipleSelectionEnabled(!multi);
3229:            } //}}}
3230:
3231:            //{{{ setMultipleSelectionEnabled() method
3232:            /**
3233:             * Set multiple selection on or off according to the value of
3234:             * <code>multi</code>. This only affects the ability to
3235:             * make multiple selections in the user interface; macros and plugins
3236:             * can manipulate them regardless of the setting of this flag. In fact,
3237:             * in most cases, calling this method should not be necessary.
3238:             *
3239:             * @param multi Should multiple selection be enabled?
3240:             * @since jEdit 3.2pre1
3241:             */
3242:            public final void setMultipleSelectionEnabled(boolean multi) {
3243:                this .multi = multi;
3244:                fireStatusChanged(StatusListener.MULTI_SELECT_CHANGED, multi);
3245:                painter.repaint();
3246:            } //}}}
3247:
3248:            //{{{ isRectangularSelectionEnabled() method
3249:            /**
3250:             * Returns if rectangular selection is enabled.
3251:             * @since jEdit 4.2pre1
3252:             */
3253:            public final boolean isRectangularSelectionEnabled() {
3254:                return rectangularSelectionMode;
3255:            } //}}}
3256:
3257:            //{{{ toggleRectangularSelectionEnabled() method
3258:            /**
3259:             * Toggles rectangular selection.
3260:             * @since jEdit 4.2pre1
3261:             */
3262:            public final void toggleRectangularSelectionEnabled() {
3263:                setRectangularSelectionEnabled(!rectangularSelectionMode);
3264:
3265:                if (getSelectionCount() == 1) {
3266:                    Selection s = getSelection(0);
3267:                    removeFromSelection(s);
3268:                    if (rectangularSelectionMode) {
3269:                        addToSelection(new Selection.Rect(s.getStart(), s
3270:                                .getEnd()));
3271:                    } else {
3272:                        addToSelection(new Selection.Range(s.getStart(), s
3273:                                .getEnd()));
3274:                    }
3275:                }
3276:            } //}}}
3277:
3278:            //{{{ setRectangularSelectionEnabled() method
3279:            /**
3280:             * Set rectangular selection on or off according to the value of
3281:             * <code>rectangularSelectionMode</code>. This only affects the ability
3282:             * to make multiple selections from the keyboard. A rectangular
3283:             * selection can always be created by dragging with the mouse by holding
3284:             * down <b>Control</b>, regardless of the state of this flag.
3285:             *
3286:             * @param rectangularSelectionMode Should rectangular selection be
3287:             * enabled?
3288:             * @since jEdit 4.2pre1
3289:             */
3290:            public final void setRectangularSelectionEnabled(
3291:                    boolean rectangularSelectionMode) {
3292:                this .rectangularSelectionMode = rectangularSelectionMode;
3293:                fireStatusChanged(StatusListener.RECT_SELECT_CHANGED,
3294:                        rectangularSelectionMode);
3295:                painter.repaint();
3296:            } //}}}
3297:
3298:            //}}}
3299:
3300:            //{{{ Folding
3301:
3302:            //{{{ goToParentFold() method
3303:            /**
3304:             * Moves the caret to the fold containing the one at the caret
3305:             * position.
3306:             * @since jEdit 4.0pre3
3307:             */
3308:            public void goToParentFold() {
3309:                int line = -1;
3310:                int level = buffer.getFoldLevel(caretLine);
3311:                for (int i = caretLine - 1; i >= 0; i--) {
3312:                    if (buffer.getFoldLevel(i) < level) {
3313:                        line = i;
3314:                        break;
3315:                    }
3316:                }
3317:
3318:                if (line == -1) {
3319:                    getToolkit().beep();
3320:                    return;
3321:                }
3322:
3323:                int magic = getMagicCaretPosition();
3324:
3325:                int newCaret = buffer.getLineStartOffset(line)
3326:                        + chunkCache.xToSubregionOffset(line, 0, magic + 1,
3327:                                true);
3328:                if (!multi)
3329:                    selectNone();
3330:
3331:                moveCaretPosition(newCaret);
3332:                setMagicCaretPosition(magic);
3333:            } //}}}
3334:
3335:            //{{{ goToNextFold() method
3336:            /**
3337:             * Moves the caret to the next fold.
3338:             * @param select true if you want to extend selection
3339:             * @since jEdit 4.0pre3
3340:             */
3341:            public void goToNextFold(boolean select) {
3342:                int nextFold = -1;
3343:                for (int i = caretLine + 1; i < buffer.getLineCount(); i++) {
3344:                    if (buffer.isFoldStart(i)
3345:                            && displayManager.isLineVisible(i)) {
3346:                        nextFold = i;
3347:                        break;
3348:                    }
3349:                }
3350:
3351:                if (nextFold == -1) {
3352:                    getToolkit().beep();
3353:                    return;
3354:                }
3355:
3356:                int magic = getMagicCaretPosition();
3357:
3358:                int newCaret = buffer.getLineStartOffset(nextFold)
3359:                        + chunkCache.xToSubregionOffset(nextFold, 0, magic + 1,
3360:                                true);
3361:                if (select)
3362:                    extendSelection(caret, newCaret);
3363:                else if (!multi)
3364:                    selectNone();
3365:
3366:                moveCaretPosition(newCaret);
3367:                setMagicCaretPosition(magic);
3368:            } //}}}
3369:
3370:            //{{{ goToPrevFold() method
3371:            /**
3372:             * Moves the caret to the previous fold.
3373:             * @param select true if you want to extend selection
3374:             * @since jEdit 4.0pre3
3375:             */
3376:            public void goToPrevFold(boolean select) {
3377:                int prevFold = -1;
3378:                for (int i = caretLine - 1; i >= 0; i--) {
3379:                    if (buffer.isFoldStart(i)
3380:                            && displayManager.isLineVisible(i)) {
3381:                        prevFold = i;
3382:                        break;
3383:                    }
3384:                }
3385:
3386:                if (prevFold == -1) {
3387:                    getToolkit().beep();
3388:                    return;
3389:                }
3390:
3391:                int magic = getMagicCaretPosition();
3392:
3393:                int newCaret = buffer.getLineStartOffset(prevFold)
3394:                        + chunkCache.xToSubregionOffset(prevFold, 0, magic + 1,
3395:                                true);
3396:                if (select)
3397:                    extendSelection(caret, newCaret);
3398:                else if (!multi)
3399:                    selectNone();
3400:
3401:                moveCaretPosition(newCaret);
3402:                setMagicCaretPosition(magic);
3403:            } //}}}
3404:
3405:            //{{{ collapseFold() method
3406:            /**
3407:             * Like {@link DisplayManager#collapseFold(int)}, but
3408:             * also moves the caret to the first line of the fold.
3409:             * @since jEdit 4.0pre3
3410:             */
3411:            public void collapseFold() {
3412:                collapseFold(caretLine);
3413:            } //}}}
3414:
3415:            //{{{ collapseFold() method
3416:            /**
3417:             * Like {@link DisplayManager#collapseFold(int)}, but
3418:             * also moves the caret to the first line of the fold.
3419:             * @since jEdit 4.3pre7
3420:             */
3421:            public void collapseFold(int line) {
3422:                int x = chunkCache.subregionOffsetToX(caretLine, caret
3423:                        - getLineStartOffset(caretLine));
3424:
3425:                displayManager.collapseFold(line);
3426:
3427:                if (displayManager.isLineVisible(caretLine))
3428:                    return;
3429:
3430:                line = displayManager.getPrevVisibleLine(caretLine);
3431:
3432:                if (!multi) {
3433:                    // cannot use selectNone() beacause the finishCaretUpdate method will reopen the fold
3434:                    invalidateSelectedLines();
3435:                    selectionManager.setSelection((Selection) null);
3436:                }
3437:                moveCaretPosition(buffer.getLineStartOffset(line)
3438:                        + chunkCache.xToSubregionOffset(line, 0, x, true));
3439:            } //}}}
3440:
3441:            //{{{ expandFold() method
3442:            /**
3443:             * Like {@link DisplayManager#expandFold(int,boolean)}, but
3444:             * also moves the caret to the first sub-fold.
3445:             * @since jEdit 4.0pre3
3446:             */
3447:            public void expandFold(boolean fully) {
3448:                int x = chunkCache.subregionOffsetToX(caretLine, caret
3449:                        - getLineStartOffset(caretLine));
3450:
3451:                int line = displayManager.expandFold(caretLine, fully);
3452:
3453:                if (!fully && line != -1) {
3454:                    if (!multi)
3455:                        selectNone();
3456:                    moveCaretPosition(getLineStartOffset(line)
3457:                            + chunkCache.xToSubregionOffset(line, 0, x, true));
3458:                }
3459:            } //}}}
3460:
3461:            //{{{ selectFold() method
3462:            /**
3463:             * Selects the fold that contains the caret line number.
3464:             * @since jEdit 3.1pre3
3465:             */
3466:            public void selectFold() {
3467:                selectFold(caretLine);
3468:            } //}}}
3469:
3470:            //{{{ selectFold() method
3471:            /**
3472:             * Selects the fold that contains the specified line number.
3473:             * @param line The line number
3474:             * @since jEdit 4.0pre1
3475:             */
3476:            public void selectFold(int line) {
3477:                int[] lines = buffer.getFoldAtLine(line);
3478:
3479:                int newCaret = getLineEndOffset(lines[1]) - 1;
3480:                Selection s = new Selection.Range(getLineStartOffset(lines[0]),
3481:                        newCaret);
3482:                if (multi)
3483:                    addToSelection(s);
3484:                else
3485:                    setSelection(s);
3486:                moveCaretPosition(newCaret);
3487:            } //}}}
3488:
3489:            //{{{ narrowToFold() method
3490:            /**
3491:             * Hides all lines except those in the fold containing the caret.
3492:             * @since jEdit 4.0pre1
3493:             */
3494:            public void narrowToFold() {
3495:                int[] lines = buffer.getFoldAtLine(caretLine);
3496:                if (lines[0] == 0 && lines[1] == buffer.getLineCount() - 1)
3497:                    getToolkit().beep();
3498:                else
3499:                    displayManager.narrow(lines[0], lines[1]);
3500:            } //}}}
3501:
3502:            //{{{ narrowToSelection() method
3503:            /**
3504:             * Hides all lines except those in the selection.
3505:             * @since jEdit 4.0pre1
3506:             */
3507:            public void narrowToSelection() {
3508:                if (getSelectionCount() != 1) {
3509:                    getToolkit().beep();
3510:                    return;
3511:                }
3512:
3513:                Selection sel = getSelection(0);
3514:                displayManager.narrow(sel.getStartLine(), sel.getEndLine());
3515:
3516:                selectNone();
3517:            } //}}}
3518:
3519:            //{{{ addExplicitFold() method
3520:            /**
3521:             * Surrounds the selection with explicit fold markers.
3522:             * @since jEdit 4.0pre3
3523:             */
3524:            public void addExplicitFold() throws TextAreaException {
3525:                if (!buffer.isEditable()) {
3526:                    getToolkit().beep();
3527:                    return;
3528:                }
3529:                if (!buffer.getStringProperty("folding").equals("explicit")) {
3530:                    throw new TextAreaException("folding-not-explicit");
3531:                }
3532:
3533:                try {
3534:                    buffer.beginCompoundEdit();
3535:
3536:                    if (getSelectionCount() == 0) {
3537:                        addExplicitFold(caret, caret, caretLine, caretLine);
3538:                    } else {
3539:                        Selection[] selections = getSelection();
3540:                        Selection selection = null;
3541:                        int caretBack = 0;
3542:                        for (int i = 0; i < selections.length; i++) {
3543:                            selection = selections[i];
3544:                            caretBack = addExplicitFold(selection.start,
3545:                                    selection.end, selection.startLine,
3546:                                    selection.endLine);
3547:                        }
3548:                        // Selection cannot be null because there is at least 1 selection
3549:                        assert selection != null;
3550:                        setCaretPosition(selection.start - caretBack, false);
3551:                    }
3552:                } finally {
3553:                    buffer.endCompoundEdit();
3554:                }
3555:            } //}}}
3556:
3557:            //}}}
3558:
3559:            //{{{ Text editing
3560:
3561:            //{{{ lineComment() method
3562:            /**
3563:             * Prepends each line of the selection with the line comment string.
3564:             * @since jEdit 3.2pre1
3565:             */
3566:            public void lineComment() {
3567:                if (!buffer.isEditable()) {
3568:                    getToolkit().beep();
3569:                    return;
3570:                }
3571:                String comment = buffer.getContextSensitiveProperty(caret,
3572:                        "lineComment");
3573:                if (comment == null || comment.length() == 0) {
3574:                    rangeLineComment();
3575:                    return;
3576:                }
3577:
3578:                comment += ' ';
3579:
3580:                buffer.beginCompoundEdit();
3581:
3582:                int[] lines = getSelectedLines();
3583:
3584:                try {
3585:                    for (int i = 0; i < lines.length; i++) {
3586:                        String text = getLineText(lines[i]);
3587:                        buffer.insert(getLineStartOffset(lines[i])
3588:                                + StandardUtilities.getLeadingWhiteSpace(text),
3589:                                comment);
3590:                    }
3591:                } finally {
3592:                    buffer.endCompoundEdit();
3593:                }
3594:
3595:                selectNone();
3596:            } //}}}
3597:
3598:            //{{{ rangeLineComment() method
3599:            /**
3600:             * This method will surround each selected line with a range comment.
3601:             * This is used when calling line comment if the edit mode doesn't have
3602:             * a line comment property
3603:             * @since jEdit 4.3pre10
3604:             */
3605:            private void rangeLineComment() {
3606:                String commentStart = buffer.getContextSensitiveProperty(caret,
3607:                        "commentStart");
3608:                String commentEnd = buffer.getContextSensitiveProperty(caret,
3609:                        "commentEnd");
3610:                if (!buffer.isEditable() || commentStart == null
3611:                        || commentEnd == null || commentStart.length() == 0
3612:                        || commentEnd.length() == 0) {
3613:                    getToolkit().beep();
3614:                    return;
3615:                }
3616:
3617:                commentStart += ' ';
3618:                commentEnd = ' ' + commentEnd;
3619:
3620:                try {
3621:                    buffer.beginCompoundEdit();
3622:                    int[] lines = getSelectedLines();
3623:                    for (int i = 0; i < lines.length; i++) {
3624:                        String text = getLineText(lines[i]);
3625:                        if (text.trim().length() == 0)
3626:                            continue;
3627:                        buffer.insert(getLineEndOffset(lines[i]) - 1,
3628:                                commentEnd);
3629:                        buffer.insert(getLineStartOffset(lines[i])
3630:                                + StandardUtilities.getLeadingWhiteSpace(text),
3631:                                commentStart);
3632:                    }
3633:                } finally {
3634:                    buffer.endCompoundEdit();
3635:                }
3636:            } //}}}
3637:
3638:            //{{{ rangeComment() method
3639:            /**
3640:             * Adds comment start and end strings to the beginning and end of the
3641:             * selection.
3642:             * @since jEdit 3.2pre1
3643:             */
3644:            public void rangeComment() {
3645:                String commentStart = buffer.getContextSensitiveProperty(caret,
3646:                        "commentStart");
3647:                String commentEnd = buffer.getContextSensitiveProperty(caret,
3648:                        "commentEnd");
3649:                if (!buffer.isEditable() || commentStart == null
3650:                        || commentEnd == null || commentStart.length() == 0
3651:                        || commentEnd.length() == 0) {
3652:                    getToolkit().beep();
3653:                    return;
3654:                }
3655:
3656:                commentStart += ' ';
3657:                commentEnd = ' ' + commentEnd;
3658:
3659:                try {
3660:                    buffer.beginCompoundEdit();
3661:
3662:                    Selection[] selection = getSelection();
3663:
3664:                    if (selection.length == 0) {
3665:                        int oldCaret = caret;
3666:                        buffer.insert(caret, commentStart);
3667:                        buffer.insert(caret, commentEnd);
3668:                        setCaretPosition(oldCaret + commentStart.length());
3669:                    }
3670:
3671:                    for (int i = 0; i < selection.length; i++) {
3672:                        Selection s = selection[i];
3673:                        if (s instanceof  Selection.Range) {
3674:                            buffer.insert(s.start, commentStart);
3675:                            buffer.insert(s.end, commentEnd);
3676:                        } else if (s instanceof  Selection.Rect) {
3677:                            Selection.Rect rect = (Selection.Rect) s;
3678:                            int start = rect.getStartColumn(buffer);
3679:                            int end = rect.getEndColumn(buffer);
3680:
3681:                            for (int j = s.startLine; j <= s.endLine; j++) {
3682:                                buffer.insertAtColumn(j, end, commentEnd);
3683:                                buffer.insertAtColumn(j, start, commentStart);
3684:                            }
3685:                        }
3686:                    }
3687:
3688:                    selectNone();
3689:                } finally {
3690:                    buffer.endCompoundEdit();
3691:                }
3692:            } //}}}
3693:
3694:            //{{{ formatParagraph() method
3695:            /**
3696:             * Formats the paragraph containing the caret.
3697:             * @since jEdit 2.7pre2
3698:             */
3699:            public void formatParagraph() throws TextAreaException {
3700:                if (!buffer.isEditable()) {
3701:                    getToolkit().beep();
3702:                    return;
3703:                }
3704:
3705:                if (maxLineLen <= 0) {
3706:                    throw new TextAreaException("format-maxlinelen");
3707:                }
3708:
3709:                Selection[] selection = getSelection();
3710:                if (selection.length != 0) {
3711:                    buffer.beginCompoundEdit();
3712:
3713:                    for (int i = 0; i < selection.length; i++) {
3714:                        Selection s = selection[i];
3715:                        setSelectedText(s, TextUtilities.format(
3716:                                getSelectedText(s), maxLineLen, buffer
3717:                                        .getTabSize()));
3718:                    }
3719:
3720:                    buffer.endCompoundEdit();
3721:                } else {
3722:                    int lineNo = getCaretLine();
3723:
3724:                    int start = 0, end = buffer.getLength();
3725:
3726:                    for (int i = lineNo - 1; i >= 0; i--) {
3727:                        if (lineContainsSpaceAndTabs(i)) {
3728:                            start = getLineEndOffset(i);
3729:                            break;
3730:                        }
3731:                    }
3732:
3733:                    for (int i = lineNo + 1; i < getLineCount(); i++) {
3734:                        if (lineContainsSpaceAndTabs(i)) {
3735:                            end = getLineStartOffset(i) - 1;
3736:                            break;
3737:                        }
3738:                    }
3739:
3740:                    try {
3741:                        buffer.beginCompoundEdit();
3742:
3743:                        String text = buffer.getText(start, end - start);
3744:                        int offset = getCaretPosition() - start;
3745:                        int noSpaceOffset = TextUtilities
3746:                                .indexIgnoringWhitespace(text, offset);
3747:                        buffer.remove(start, end - start);
3748:                        text = TextUtilities.format(text, maxLineLen, buffer
3749:                                .getTabSize());
3750:                        buffer.insert(start, text);
3751:                        int caretPos = start;
3752:                        if (text.length() != 0) {
3753:                            caretPos += Math.min(text.length(), TextUtilities
3754:                                    .ignoringWhitespaceIndex(text,
3755:                                            noSpaceOffset));
3756:                        }
3757:                        moveCaretPosition(caretPos);
3758:                    } finally {
3759:                        buffer.endCompoundEdit();
3760:                    }
3761:                }
3762:            } //}}}
3763:
3764:            //{{{ spacesToTabs() method
3765:            /**
3766:             * Converts spaces to tabs in the selection.
3767:             * @since jEdit 2.7pre2
3768:             */
3769:            public void spacesToTabs() {
3770:                Selection[] selection = getSelection();
3771:
3772:                if (!buffer.isEditable()) {
3773:                    getToolkit().beep();
3774:                    return;
3775:                }
3776:
3777:                buffer.beginCompoundEdit();
3778:
3779:                if (selection.length == 0) {
3780:                    setText(TextUtilities.spacesToTabs(getText(), buffer
3781:                            .getTabSize()));
3782:                } else {
3783:                    for (int i = 0; i < selection.length; i++) {
3784:                        Selection s = selection[i];
3785:                        setSelectedText(s, TextUtilities.spacesToTabs(
3786:                                getSelectedText(s), buffer.getTabSize()));
3787:                    }
3788:                }
3789:
3790:                buffer.endCompoundEdit();
3791:            } //}}}
3792:
3793:            //{{{ tabsToSpaces() method
3794:            /**
3795:             * Converts tabs to spaces in the selection.
3796:             * @since jEdit 2.7pre2
3797:             */
3798:            public void tabsToSpaces() {
3799:                Selection[] selection = getSelection();
3800:
3801:                if (!buffer.isEditable()) {
3802:                    getToolkit().beep();
3803:                    return;
3804:                }
3805:
3806:                buffer.beginCompoundEdit();
3807:
3808:                if (selection.length == 0) {
3809:                    setText(TextUtilities.tabsToSpaces(getText(), buffer
3810:                            .getTabSize()));
3811:                } else {
3812:                    for (int i = 0; i < selection.length; i++) {
3813:                        Selection s = selection[i];
3814:                        setSelectedText(s, TextUtilities.tabsToSpaces(
3815:                                getSelectedText(s), buffer.getTabSize()));
3816:                    }
3817:                }
3818:
3819:                buffer.endCompoundEdit();
3820:            } //}}}
3821:
3822:            //{{{ toUpperCase() method
3823:            /**
3824:             * Converts the selected text to upper case.
3825:             * @since jEdit 2.7pre2
3826:             */
3827:            public void toUpperCase() {
3828:                if (!buffer.isEditable()) {
3829:                    getToolkit().beep();
3830:                    return;
3831:                }
3832:
3833:                Selection[] selection = getSelection();
3834:                int caret = -1;
3835:                if (selection.length == 0) {
3836:                    caret = getCaretPosition();
3837:                    selectWord();
3838:                    selection = getSelection();
3839:                }
3840:                if (selection.length == 0) {
3841:                    if (caret != -1)
3842:                        setCaretPosition(caret);
3843:                    getToolkit().beep();
3844:                    return;
3845:                }
3846:
3847:                buffer.beginCompoundEdit();
3848:
3849:                for (int i = 0; i < selection.length; i++) {
3850:                    Selection s = selection[i];
3851:                    setSelectedText(s, getSelectedText(s).toUpperCase());
3852:                }
3853:
3854:                buffer.endCompoundEdit();
3855:                if (caret != -1)
3856:                    setCaretPosition(caret);
3857:            } //}}}
3858:
3859:            //{{{ toLowerCase() method
3860:            /**
3861:             * Converts the selected text to lower case.
3862:             * @since jEdit 2.7pre2
3863:             */
3864:            public void toLowerCase() {
3865:                if (!buffer.isEditable()) {
3866:                    getToolkit().beep();
3867:                    return;
3868:                }
3869:
3870:                Selection[] selection = getSelection();
3871:                int caret = -1;
3872:                if (selection.length == 0) {
3873:                    caret = getCaretPosition();
3874:                    selectWord();
3875:                    selection = getSelection();
3876:                }
3877:                if (selection.length == 0) {
3878:                    if (caret != -1)
3879:                        setCaretPosition(caret);
3880:                    getToolkit().beep();
3881:                    return;
3882:                }
3883:
3884:                buffer.beginCompoundEdit();
3885:
3886:                for (int i = 0; i < selection.length; i++) {
3887:                    Selection s = selection[i];
3888:                    setSelectedText(s, getSelectedText(s).toLowerCase());
3889:                }
3890:
3891:                buffer.endCompoundEdit();
3892:                if (caret != -1)
3893:                    setCaretPosition(caret);
3894:            } //}}}
3895:
3896:            //{{{ removeTrailingWhiteSpace() method
3897:            /**
3898:             * Removes trailing whitespace from all lines in the selection.
3899:             * @since jEdit 2.7pre2
3900:             */
3901:            public void removeTrailingWhiteSpace() {
3902:                if (!buffer.isEditable())
3903:                    getToolkit().beep();
3904:                else {
3905:                    buffer.removeTrailingWhiteSpace(getSelectedLines());
3906:                }
3907:            } //}}}
3908:
3909:            //{{{ insertEnterAndIndent() method
3910:            public void insertEnterAndIndent() {
3911:                if (!isEditable())
3912:                    getToolkit().beep();
3913:                else {
3914:                    try {
3915:                        buffer.beginCompoundEdit();
3916:                        setSelectedText("\n");
3917:                        buffer.indentLine(caretLine, true);
3918:                    } finally {
3919:                        buffer.endCompoundEdit();
3920:                    }
3921:                }
3922:            } //}}}
3923:
3924:            //{{{ insertTabAndIndent() method
3925:            public void insertTabAndIndent() {
3926:                if (!isEditable()) {
3927:                    getToolkit().beep();
3928:                    return;
3929:                }
3930:
3931:                if (getSelectionCount() == 0) {
3932:                    // if caret is inside leading whitespace, indent.
3933:                    String text = buffer.getLineText(caretLine);
3934:                    int start = buffer.getLineStartOffset(caretLine);
3935:                    int whiteSpace = StandardUtilities
3936:                            .getLeadingWhiteSpace(text);
3937:
3938:                    if (caret - start <= whiteSpace
3939:                            && buffer.indentLine(caretLine, false))
3940:                        return;
3941:                }
3942:
3943:                userInput('\t');
3944:            } //}}}
3945:
3946:            //{{{ indentSelectedLines() method
3947:            /**
3948:             * Indents all selected lines.
3949:             * @since jEdit 3.1pre3
3950:             */
3951:            public void indentSelectedLines() {
3952:                if (!buffer.isEditable())
3953:                    getToolkit().beep();
3954:                else {
3955:                    buffer.indentLines(getSelectedLines());
3956:                    selectNone();
3957:                }
3958:            } //}}}
3959:
3960:            //{{{ shiftIndentLeft() method
3961:            /**
3962:             * Shifts the indent to the left.
3963:             * @since jEdit 2.7pre2
3964:             */
3965:            public void shiftIndentLeft() {
3966:                if (!buffer.isEditable())
3967:                    getToolkit().beep();
3968:                else {
3969:                    buffer.shiftIndentLeft(getSelectedLines());
3970:                }
3971:            } //}}}
3972:
3973:            //{{{ shiftIndentRight() method
3974:            /**
3975:             * Shifts the indent to the right.
3976:             * @since jEdit 2.7pre2
3977:             */
3978:            public void shiftIndentRight() {
3979:                if (!buffer.isEditable())
3980:                    getToolkit().beep();
3981:                else
3982:                    buffer.shiftIndentRight(getSelectedLines());
3983:            } //}}}
3984:
3985:            //{{{ joinLines() method
3986:            /**
3987:             * Joins the current and the next line.
3988:             * @since jEdit 2.7pre2
3989:             */
3990:            public void joinLines() {
3991:                if (getSelectionCount() == 0) {
3992:                    int end = getLineEndOffset(caretLine);
3993:                    if (!buffer.isEditable() || end > buffer.getLength()) {
3994:                        getToolkit().beep();
3995:                        return;
3996:                    }
3997:
3998:                    try {
3999:                        buffer.beginCompoundEdit();
4000:                        String nextLineText = buffer.getLineText(caretLine + 1);
4001:                        buffer.remove(end - 1, StandardUtilities
4002:                                .getLeadingWhiteSpace(nextLineText) + 1);
4003:                        if (nextLineText.length() != 0)
4004:                            buffer.insert(end - 1, " ");
4005:                    } finally {
4006:                        buffer.endCompoundEdit();
4007:                    }
4008:                    setCaretPosition(end - 1);
4009:                } else {
4010:                    try {
4011:                        buffer.beginCompoundEdit();
4012:                        Selection[] selections = selectionManager
4013:                                .getSelection();
4014:                        for (int i = 0; i < selections.length; i++) {
4015:                            Selection selection = selections[i];
4016:                            joinLines(selection);
4017:                        }
4018:                    } finally {
4019:                        buffer.endCompoundEdit();
4020:                    }
4021:                }
4022:            } //}}}
4023:
4024:            //{{{ joinLines() method
4025:            /**
4026:             * Join the lines in the selection.
4027:             * If you use this method you have to lock the buffer in compound edit mode
4028:             *
4029:             * @param selection the selection
4030:             * @since jEdit 4.3pre8
4031:             */
4032:            private void joinLines(Selection selection) {
4033:                do {
4034:                    if (selection.startLine == buffer.getLineCount() - 1)
4035:                        return;
4036:                    int end = getLineEndOffset(selection.startLine);
4037:                    String nextLineText = buffer
4038:                            .getLineText(selection.startLine + 1);
4039:                    buffer.remove(end - 1, StandardUtilities
4040:                            .getLeadingWhiteSpace(nextLineText) + 1);
4041:                    if (nextLineText.length() != 0)
4042:                        buffer.insert(end - 1, " ");
4043:                } while (selection.startLine < selection.endLine);
4044:            } //}}}
4045:
4046:            //}}}
4047:
4048:            //{{{ AWT stuff
4049:
4050:            //{{{ addLeftOfScrollBar() method
4051:            /**
4052:             * Adds a component to the box left of the vertical scroll bar. The
4053:             * ErrorList plugin uses this to show a global error overview, for
4054:             * example.
4055:             *
4056:             * @param comp The component
4057:             * @since jEdit 4.2pre1
4058:             */
4059:            public void addLeftOfScrollBar(Component comp) {
4060:                verticalBox.add(comp, verticalBox.getComponentCount() - 1);
4061:            } //}}}
4062:
4063:            //{{{ removeLeftOfScrollBar() method
4064:            /**
4065:             * Removes a component from the box left of the vertical scroll bar.
4066:             *
4067:             * @param comp The component
4068:             * @since jEdit 4.2pre1
4069:             */
4070:            public void removeLeftOfScrollBar(Component comp) {
4071:                verticalBox.remove(comp);
4072:            } //}}}
4073:
4074:            //{{{ addNotify() method
4075:            /**
4076:             * Called by the AWT when this component is added to a parent.
4077:             * Adds document listener.
4078:             */
4079:            public void addNotify() {
4080:                super .addNotify();
4081:
4082:                ToolTipManager.sharedInstance().registerComponent(painter);
4083:                ToolTipManager.sharedInstance().registerComponent(gutter);
4084:
4085:                recalculateVisibleLines();
4086:                if (!buffer.isLoading())
4087:                    recalculateLastPhysicalLine();
4088:                propertiesChanged();
4089:
4090:                hiddenCursor = getToolkit().createCustomCursor(
4091:                        getGraphicsConfiguration().createCompatibleImage(16,
4092:                                16, Transparency.BITMASK), new Point(0, 0),
4093:                        "Hidden");
4094:            } //}}}
4095:
4096:            //{{{ removeNotify() method
4097:            /**
4098:             * Called by the AWT when this component is removed from it's parent.
4099:             * This clears the pointer to the currently focused component.
4100:             * Also removes document listener.
4101:             */
4102:            public void removeNotify() {
4103:                super .removeNotify();
4104:
4105:                ToolTipManager.sharedInstance().unregisterComponent(painter);
4106:                ToolTipManager.sharedInstance().unregisterComponent(gutter);
4107:
4108:                if (focusedComponent == this )
4109:                    focusedComponent = null;
4110:            } //}}}
4111:
4112:            //{{{ getFocusTraversalKeysEnabled() method
4113:            /**
4114:             * Java 1.4 compatibility fix to make Tab key work.
4115:             * @since jEdit 3.2pre4
4116:             */
4117:            public boolean getFocusTraversalKeysEnabled() {
4118:                return false;
4119:            } //}}}
4120:
4121:            //{{{ getFocusCycleRoot() method
4122:            /**
4123:             * Java 1.4 compatibility fix to make Tab traversal work in a sane
4124:             * manner.
4125:             * @since jEdit 4.2pre3
4126:             */
4127:            public boolean getFocusCycleRoot() {
4128:                return true;
4129:            } //}}}
4130:
4131:            //{{{ processKeyEvent() method
4132:            public void processKeyEvent(KeyEvent evt) {
4133:                getInputHandler().processKeyEvent(evt,
4134:                        1 /* source=TEXTAREA (1) */, false);
4135:                if (!evt.isConsumed())
4136:                    super .processKeyEvent(evt);
4137:
4138:            } //}}}
4139:
4140:            //{{{ addTopComponent() method
4141:            /**
4142:             * Adds a component above the gutter, text area, and vertical scroll bar.
4143:             *
4144:             * @since jEdit 4.2pre3
4145:             */
4146:            public void addTopComponent(Component comp) {
4147:                add(ScrollLayout.TOP, comp);
4148:            } //}}}
4149:
4150:            //{{{ removeTopComponent() method
4151:            /**
4152:             * Removes a component from above the gutter, text area, and vertical scroll bar.
4153:             *
4154:             * @since jEdit 4.2pre3
4155:             */
4156:            public void removeTopComponent(Component comp) {
4157:                remove(comp);
4158:            } //}}}
4159:
4160:            //{{{ Input method support
4161:            private InputMethodSupport inputMethodSupport;
4162:
4163:            public InputMethodRequests getInputMethodRequests() {
4164:                if (inputMethodSupport == null) {
4165:                    inputMethodSupport = new InputMethodSupport(this );
4166:                    Log.log(Log.DEBUG, this , "InputMethodSupport is activated");
4167:                }
4168:                return inputMethodSupport;
4169:            } //}}}
4170:
4171:            //}}}
4172:
4173:            //{{{ addStatusListener() method
4174:            /**
4175:             * Adds a scroll listener to this text area.
4176:             * @param listener The listener
4177:             * @since jEdit 4.3pre2
4178:             */
4179:            public final void addStatusListener(StatusListener listener) {
4180:                listenerList.add(StatusListener.class, listener);
4181:            } //}}}
4182:
4183:            //{{{ removeStatusListener() method
4184:            /**
4185:             * Removes a scroll listener from this text area.
4186:             * @param listener The listener
4187:             * @since jEdit 4.3pre2
4188:             */
4189:            public final void removeStatusListener(StatusListener listener) {
4190:                listenerList.remove(StatusListener.class, listener);
4191:            } //}}}
4192:
4193:            //{{{ propertiesChanged() method
4194:            /**
4195:             * Called by jEdit when necessary. Plugins should not call this method.
4196:             */
4197:            public void propertiesChanged() {
4198:                if (buffer == null)
4199:                    return;
4200:
4201:                int _tabSize = buffer.getTabSize();
4202:                char[] foo = new char[_tabSize];
4203:                for (int i = 0; i < foo.length; i++)
4204:                    foo[i] = ' ';
4205:
4206:                tabSize = painter.getStringWidth(new String(foo));
4207:
4208:                charWidth = (int) Math.round(painter.getFont().getStringBounds(
4209:                        foo, 0, 1, painter.getFontRenderContext()).getWidth());
4210:
4211:                String oldWrap = wrap;
4212:                wrap = buffer.getStringProperty("wrap");
4213:                hardWrap = wrap.equals("hard");
4214:                softWrap = wrap.equals("soft");
4215:                boolean oldWrapToWidth = wrapToWidth;
4216:                int oldWrapMargin = wrapMargin;
4217:                setMaxLineLength(buffer.getIntegerProperty("maxLineLen", 0));
4218:
4219:                boolean wrapSettingsChanged = !(wrap.equals(oldWrap)
4220:                        && oldWrapToWidth == wrapToWidth && oldWrapMargin == wrapMargin);
4221:
4222:                if (displayManager != null && !bufferChanging
4223:                        && !buffer.isLoading() && wrapSettingsChanged) {
4224:                    displayManager.invalidateScreenLineCounts();
4225:                    displayManager.notifyScreenLineChanges();
4226:                }
4227:
4228:                repaintMgr.setFastScroll(false);
4229:                chunkCache.invalidateAll();
4230:                gutter.repaint();
4231:                painter.repaint();
4232:            } //}}}
4233:
4234:            //{{{ Deprecated methods
4235:
4236:            //{{{ getSelectionStart() method
4237:            /**
4238:             * @deprecated Instead, obtain a Selection instance using
4239:             * any means, and call its <code>getStart()</code> method
4240:             */
4241:            public final int getSelectionStart() {
4242:                if (getSelectionCount() != 1)
4243:                    return caret;
4244:
4245:                return getSelection(0).getStart();
4246:            } //}}}
4247:
4248:            //{{{ getSelectionStart() method
4249:            /**
4250:             * @deprecated Instead, obtain a Selection instance using
4251:             * any means, and call its <code>getStart(int)</code> method
4252:             */
4253:            public int getSelectionStart(int line) {
4254:                if (getSelectionCount() != 1)
4255:                    return caret;
4256:
4257:                return getSelection(0).getStart(buffer, line);
4258:            } //}}}
4259:
4260:            //{{{ getSelectionStartLine() method
4261:            /**
4262:             * @deprecated Instead, obtain a Selection instance using
4263:             * any means, and call its <code>getStartLine()</code> method
4264:             */
4265:            public final int getSelectionStartLine() {
4266:                if (getSelectionCount() != 1)
4267:                    return caret;
4268:
4269:                return getSelection(0).getStartLine();
4270:            } //}}}
4271:
4272:            //{{{ setSelectionStart() method
4273:            /**
4274:             * @deprecated Do not use.
4275:             */
4276:            public final void setSelectionStart(int selectionStart) {
4277:                int selectionEnd = getSelectionCount() == 1 ? getSelection(0)
4278:                        .getEnd() : caret;
4279:                select(selectionStart, selectionEnd, true);
4280:            } //}}}
4281:
4282:            //{{{ getSelectionEnd() method
4283:            /**
4284:             * @deprecated Instead, obtain a Selection instance using
4285:             * any means, and call its <code>getEnd()</code> method
4286:             */
4287:            public final int getSelectionEnd() {
4288:                return getSelectionCount() == 1 ? getSelection(0).getEnd()
4289:                        : caret;
4290:
4291:            } //}}}
4292:
4293:            //{{{ getSelectionEnd() method
4294:            /**
4295:             * @deprecated Instead, obtain a Selection instance using
4296:             * any means, and call its <code>getEnd(int)</code> method
4297:             */
4298:            public int getSelectionEnd(int line) {
4299:                if (getSelectionCount() != 1)
4300:                    return caret;
4301:
4302:                return getSelection(0).getEnd(buffer, line);
4303:            } //}}}
4304:
4305:            //{{{ getSelectionEndLine() method
4306:            /**
4307:             * @deprecated Instead, obtain a Selection instance using
4308:             * any means, and call its <code>getEndLine()</code> method
4309:             */
4310:            public final int getSelectionEndLine() {
4311:                if (getSelectionCount() != 1)
4312:                    return caret;
4313:
4314:                return getSelection(0).getEndLine();
4315:            } //}}}
4316:
4317:            //{{{ setSelectionEnd() method
4318:            /**
4319:             * @deprecated Do not use.
4320:             */
4321:            public final void setSelectionEnd(int selectionEnd) {
4322:                select(getSelectionStart(), selectionEnd, true);
4323:            } //}}}
4324:
4325:            //{{{ getMarkPosition() method
4326:            /**
4327:             * @deprecated Do not use.
4328:             */
4329:            public final int getMarkPosition() {
4330:                Selection s = getSelectionAtOffset(caret);
4331:                if (s == null)
4332:                    return caret;
4333:
4334:                if (s.start == caret)
4335:                    return s.end;
4336:                else if (s.end == caret)
4337:                    return s.start;
4338:                else
4339:                    return caret;
4340:            } //}}}
4341:
4342:            //{{{ getMarkLine() method
4343:            /**
4344:             * @deprecated Do not use.
4345:             */
4346:            public final int getMarkLine() {
4347:                if (getSelectionCount() != 1)
4348:                    return caretLine;
4349:
4350:                Selection s = getSelection(0);
4351:                if (s.start == caret)
4352:                    return s.endLine;
4353:                else if (s.end == caret)
4354:                    return s.startLine;
4355:                else
4356:                    return caretLine;
4357:            } //}}}
4358:
4359:            //{{{ select() method
4360:            /**
4361:             * @deprecated Instead, call either <code>addToSelection()</code>,
4362:             * or <code>setSelection()</code> with a new Selection instance.
4363:             */
4364:            public void select(int start, int end) {
4365:                select(start, end, true);
4366:            } //}}}
4367:
4368:            //{{{ select() method
4369:            /**
4370:             * @deprecated Instead, call either <code>addToSelection()</code>,
4371:             * or <code>setSelection()</code> with a new Selection instance.
4372:             */
4373:            public void select(int start, int end, boolean doElectricScroll) {
4374:                selectNone();
4375:
4376:                int newStart, newEnd;
4377:                if (start < end) {
4378:                    newStart = start;
4379:                    newEnd = end;
4380:                } else {
4381:                    newStart = end;
4382:                    newEnd = start;
4383:                }
4384:
4385:                setSelection(new Selection.Range(newStart, newEnd));
4386:                moveCaretPosition(end, doElectricScroll);
4387:            } //}}}
4388:
4389:            //{{{ isSelectionRectangular() method
4390:            /**
4391:             * @deprecated Instead, check if the appropriate Selection
4392:             * is an instance of the Selection.Rect class.
4393:             */
4394:            public boolean isSelectionRectangular() {
4395:                Selection s = getSelectionAtOffset(caret);
4396:                return s != null && s instanceof  Selection.Rect;
4397:            } //}}}
4398:
4399:            //}}}
4400:
4401:            //{{{ Package-private members
4402:
4403:            static TextArea focusedComponent;
4404:
4405:            //{{{ Instance variables
4406:            final Segment lineSegment = new Segment();
4407:            MouseInputAdapter mouseHandler;
4408:            final ChunkCache chunkCache;
4409:            final FastRepaintManager repaintMgr;
4410:            DisplayManager displayManager;
4411:            final SelectionManager selectionManager;
4412:            boolean bufferChanging;
4413:
4414:            int maxHorizontalScrollWidth;
4415:
4416:            String wrap;
4417:            boolean hardWrap;
4418:            boolean softWrap;
4419:            boolean wrapToWidth;
4420:            int maxLineLen;
4421:            int wrapMargin;
4422:            float tabSize;
4423:            int charWidth;
4424:
4425:            boolean scrollBarsInitialized;
4426:
4427:            /**
4428:             * Cursor location, measured as an offset (in pixels) from upper left corner
4429:             * of the TextArea.
4430:             */
4431:            final Point offsetXY;
4432:
4433:            boolean lastLinePartial;
4434:
4435:            boolean blink;
4436:
4437:            //}}}
4438:
4439:            //{{{ isCaretVisible() method
4440:            /**
4441:             * Returns true if the caret is visible, false otherwise.
4442:             */
4443:            final boolean isCaretVisible() {
4444:                return blink && hasFocus();
4445:            } //}}}
4446:
4447:            //{{{ isStructureHighlightVisible() method
4448:            /**
4449:             * Returns true if the structure highlight is visible, false otherwise.
4450:             * @since jEdit 4.2pre3
4451:             */
4452:            final boolean isStructureHighlightVisible() {
4453:                return match != null && hasFocus()
4454:                        && displayManager.isLineVisible(match.startLine)
4455:                        && displayManager.isLineVisible(match.endLine);
4456:            } //}}}
4457:
4458:            //{{{ updateMaxHorizontalScrollWidth() method
4459:            void updateMaxHorizontalScrollWidth() {
4460:                int max = chunkCache.getMaxHorizontalScrollWidth();
4461:
4462:                if (max != maxHorizontalScrollWidth) {
4463:                    maxHorizontalScrollWidth = max;
4464:                    horizontal.setValues(Math.max(0, Math.min(
4465:                            maxHorizontalScrollWidth + charWidth
4466:                                    - painter.getWidth(), -horizontalOffset)),
4467:                            painter.getWidth(), 0, maxHorizontalScrollWidth
4468:                                    + charWidth);
4469:                    horizontal.setUnitIncrement(10);
4470:                    horizontal.setBlockIncrement(painter.getWidth());
4471:                } else if (horizontal.getValue() != -horizontalOffset) {
4472:                    horizontal.setValue(-horizontalOffset);
4473:                }
4474:            } //}}}
4475:
4476:            //{{{ recalculateVisibleLines() method
4477:            void recalculateVisibleLines() {
4478:                if (painter == null)
4479:                    return;
4480:                int height = painter.getHeight();
4481:                int lineHeight = painter.getFontMetrics().getHeight();
4482:                if (lineHeight == 0)
4483:                    visibleLines = 0;
4484:                else if (height <= 0) {
4485:                    visibleLines = 0;
4486:                    lastLinePartial = false;
4487:                } else {
4488:                    visibleLines = height / lineHeight;
4489:                    lastLinePartial = (height % lineHeight != 0);
4490:                    if (lastLinePartial)
4491:                        visibleLines++;
4492:                }
4493:
4494:                chunkCache.recalculateVisibleLines();
4495:
4496:                // this does the "trick" to eliminate blank space at the end
4497:                if (displayManager != null && buffer != null
4498:                        && !buffer.isLoading())
4499:                    setFirstLine(getFirstLine());
4500:
4501:                updateScrollBar();
4502:            } //}}}
4503:
4504:            //{{{ foldStructureChanged() method
4505:            void foldStructureChanged() {
4506:                repaintMgr.setFastScroll(false);
4507:                chunkCache.invalidateAll();
4508:                recalculateLastPhysicalLine();
4509:                repaint();
4510:            } //}}}
4511:
4512:            //{{{ updateScrollBar() method
4513:            /**
4514:             * Updates the state of the scroll bars. This should be called
4515:             * if the number of lines in the buffer changes, or when the
4516:             * size of the text are changes.
4517:             */
4518:            void updateScrollBar() {
4519:                if (buffer == null)
4520:                    return;
4521:
4522:                if (Debug.SCROLL_DEBUG)
4523:                    Log.log(Log.DEBUG, this , "updateScrollBar(), slc="
4524:                            + displayManager.getScrollLineCount());
4525:
4526:                if (vertical != null && visibleLines != 0) {
4527:                    if (Debug.SCROLL_DEBUG)
4528:                        Log.log(Log.DEBUG, this , "Vertical ok");
4529:                    int lineCount = displayManager.getScrollLineCount();
4530:                    int firstLine = getFirstLine();
4531:                    int visible = visibleLines - (lastLinePartial ? 1 : 0);
4532:
4533:                    vertical.setValues(firstLine, visible, 0, lineCount);
4534:                    vertical.setUnitIncrement(2);
4535:                    vertical.setBlockIncrement(visible);
4536:                }
4537:            } //}}}
4538:
4539:            //{{{ _finishCaretUpdate() method
4540:            /* called by DisplayManager.BufferChangeHandler.transactionComplete() */
4541:            void _finishCaretUpdate() {
4542:                if (!queuedCaretUpdate)
4543:                    return;
4544:
4545:                try {
4546:                    if (match != null) {
4547:                        if (oldCaretLine < match.startLine)
4548:                            invalidateLineRange(oldCaretLine, match.endLine);
4549:                        else
4550:                            invalidateLineRange(match.startLine, oldCaretLine);
4551:                        match = null;
4552:                    }
4553:
4554:                    int newCaretScreenLine = chunkCache.getScreenLineOfOffset(
4555:                            caretLine, caret
4556:                                    - buffer.getLineStartOffset(caretLine));
4557:                    if (caretScreenLine == -1)
4558:                        invalidateScreenLineRange(newCaretScreenLine,
4559:                                newCaretScreenLine);
4560:                    else
4561:                        invalidateScreenLineRange(caretScreenLine,
4562:                                newCaretScreenLine);
4563:                    caretScreenLine = newCaretScreenLine;
4564:
4565:                    invalidateSelectedLines();
4566:
4567:                    // When the user is typing, etc, we don't want the caret
4568:                    // to blink
4569:                    blink = true;
4570:                    caretTimer.restart();
4571:
4572:                    if (!displayManager.isLineVisible(caretLine)) {
4573:                        if (caretLine < displayManager.getFirstVisibleLine()
4574:                                || caretLine > displayManager
4575:                                        .getLastVisibleLine()) {
4576:                            int collapseFolds = buffer.getIntegerProperty(
4577:                                    "collapseFolds", 0);
4578:                            if (collapseFolds != 0) {
4579:                                displayManager.expandFolds(collapseFolds);
4580:                                displayManager.expandFold(caretLine, false);
4581:                            } else
4582:                                displayManager.expandAllFolds();
4583:                        } else
4584:                            displayManager.expandFold(caretLine, false);
4585:                    }
4586:
4587:                    if (queuedScrollMode == ELECTRIC_SCROLL)
4588:                        scrollToCaret(true);
4589:                    else if (queuedScrollMode == NORMAL_SCROLL)
4590:                        scrollToCaret(false);
4591:
4592:                    updateBracketHighlightWithDelay();
4593:                    if (queuedFireCaretEvent)
4594:                        fireCaretEvent();
4595:                }
4596:                // in case one of the above fails, we still want to
4597:                // clear these flags.
4598:                finally {
4599:                    queuedCaretUpdate = queuedFireCaretEvent = false;
4600:                    queuedScrollMode = NO_SCROLL;
4601:                }
4602:            } //}}}
4603:
4604:            //{{{ invalidateStructureMatch() method
4605:            void invalidateStructureMatch() {
4606:                if (match != null)
4607:                    invalidateLineRange(match.startLine, match.endLine);
4608:            } //}}}
4609:
4610:            //{{{ startDragAndDrop() method
4611:            void startDragAndDrop(InputEvent evt, boolean copy) {
4612:                TransferHandler transferHandler = getTransferHandler();
4613:                if (transferHandler != null) {
4614:                    Log.log(Log.DEBUG, this , "Drag and drop callback");
4615:                    transferHandler.exportAsDrag(this , evt,
4616:                            copy ? TransferHandler.COPY : TransferHandler.MOVE);
4617:                }
4618:            } //}}}
4619:
4620:            //{{{ fireNarrowActive() method
4621:            void fireNarrowActive() {
4622:                Object[] listeners = listenerList.getListenerList();
4623:                for (int i = listeners.length - 2; i >= 0; i--) {
4624:                    if (listeners[i] == StatusListener.class) {
4625:                        try {
4626:                            ((StatusListener) listeners[i + 1])
4627:                                    .narrowActive(this );
4628:                        } catch (Throwable t) {
4629:                            Log.log(Log.ERROR, this , t);
4630:                        }
4631:                    }
4632:                }
4633:            } //}}}
4634:
4635:            //}}}
4636:
4637:            //{{{ Private members
4638:
4639:            //{{{ Static variables
4640:            private static final Timer caretTimer;
4641:            private static final Timer structureTimer;
4642:            //}}}
4643:
4644:            //{{{ Instance variables
4645:            protected Cursor hiddenCursor;
4646:
4647:            private final Gutter gutter;
4648:            protected final TextAreaPainter painter;
4649:
4650:            private final EventListenerList listenerList;
4651:            private final MutableCaretEvent caretEvent;
4652:
4653:            private boolean caretBlinks;
4654:            private InputHandlerProvider inputHandlerProvider;
4655:
4656:            /** The last visible physical line index. */
4657:            private int physLastLine;
4658:
4659:            /**
4660:             * The last screen line index.
4661:             */
4662:            private int screenLastLine;
4663:
4664:            /** The visible lines count. */
4665:            private int visibleLines;
4666:            private int electricScroll;
4667:
4668:            private int horizontalOffset;
4669:
4670:            private boolean quickCopy;
4671:
4672:            // JDiff, error list add stuff here
4673:            private final Box verticalBox;
4674:            private final JScrollBar vertical;
4675:            private final JScrollBar horizontal;
4676:
4677:            protected JEditBuffer buffer;
4678:
4679:            protected int caret;
4680:            protected int caretLine;
4681:            private int caretScreenLine;
4682:
4683:            private final java.util.List<StructureMatcher> structureMatchers;
4684:            private StructureMatcher.Match match;
4685:
4686:            private int magicCaret;
4687:            /** Flag that tells if multiple selection is on. */
4688:            protected boolean multi;
4689:            private boolean overwrite;
4690:            private boolean rectangularSelectionMode;
4691:
4692:            private boolean dndEnabled;
4693:            private boolean dndInProgress;
4694:
4695:            // see finishCaretUpdate() & _finishCaretUpdate()
4696:            private boolean queuedCaretUpdate;
4697:            private int queuedScrollMode;
4698:            private boolean queuedFireCaretEvent;
4699:            private int oldCaretLine;
4700:
4701:            private boolean joinNonWordChars;
4702:            private boolean ctrlForRectangularSelection;
4703:
4704:            //}}}
4705:
4706:            //{{{ invalidateSelectedLines() method
4707:            /**
4708:             * Repaints the lines containing the selection.
4709:             */
4710:            private void invalidateSelectedLines() {
4711:                // to hide line highlight if selections are being added later on
4712:                invalidateLine(caretLine);
4713:
4714:                for (Selection s : selectionManager.selection)
4715:                    invalidateLineRange(s.startLine, s.endLine);
4716:            } //}}}
4717:
4718:            //{{{ finishCaretUpdate() method
4719:            /**
4720:             * the collapsing of scrolling/event firing inside compound edits
4721:             * greatly speeds up replace-all.
4722:             */
4723:            private void finishCaretUpdate(int oldCaretLine, int scrollMode,
4724:                    boolean fireCaretEvent) {
4725:                queuedFireCaretEvent |= fireCaretEvent;
4726:                queuedScrollMode = Math.max(scrollMode, queuedScrollMode);
4727:
4728:                if (queuedCaretUpdate)
4729:                    return;
4730:
4731:                this .oldCaretLine = oldCaretLine;
4732:                queuedCaretUpdate = true;
4733:
4734:                if (!buffer.isTransactionInProgress())
4735:                    _finishCaretUpdate();
4736:                /* otherwise DisplayManager.BufferChangeHandler calls */
4737:
4738:                repaintMgr.setFastScroll(false);
4739:            } //}}}
4740:
4741:            //{{{ fireCaretEvent() method
4742:            private void fireCaretEvent() {
4743:                Object[] listeners = listenerList.getListenerList();
4744:                for (int i = listeners.length - 2; i >= 0; i--) {
4745:                    if (listeners[i] == CaretListener.class) {
4746:                        try {
4747:                            ((CaretListener) listeners[i + 1])
4748:                                    .caretUpdate(caretEvent);
4749:                        } catch (Throwable t) {
4750:                            Log.log(Log.ERROR, this , t);
4751:                        }
4752:                    }
4753:                }
4754:            } //}}}
4755:
4756:            //{{{ fireScrollEvent() method
4757:            private void fireScrollEvent(boolean vertical) {
4758:                Object[] listeners = listenerList.getListenerList();
4759:                for (int i = listeners.length - 2; i >= 0; i--) {
4760:                    if (listeners[i] == ScrollListener.class) {
4761:                        try {
4762:                            if (vertical)
4763:                                ((ScrollListener) listeners[i + 1])
4764:                                        .scrolledVertically(this );
4765:                            else
4766:                                ((ScrollListener) listeners[i + 1])
4767:                                        .scrolledHorizontally(this );
4768:                        } catch (Throwable t) {
4769:                            Log.log(Log.ERROR, this , t);
4770:                        }
4771:                    }
4772:                }
4773:            } //}}}
4774:
4775:            //{{{ fireStatusChanged() method
4776:            private void fireStatusChanged(int flag, boolean value) {
4777:                Object[] listeners = listenerList.getListenerList();
4778:                for (int i = listeners.length - 2; i >= 0; i--) {
4779:                    if (listeners[i] == StatusListener.class) {
4780:                        try {
4781:                            ((StatusListener) listeners[i + 1]).statusChanged(
4782:                                    this , flag, value);
4783:                        } catch (Throwable t) {
4784:                            Log.log(Log.ERROR, this , t);
4785:                        }
4786:                    }
4787:                }
4788:            } //}}}
4789:
4790:            //{{{ fireBracketSelected() method
4791:            private void fireBracketSelected(int line, String text) {
4792:                Object[] listeners = listenerList.getListenerList();
4793:                for (int i = listeners.length - 2; i >= 0; i--) {
4794:                    if (listeners[i] == StatusListener.class) {
4795:                        try {
4796:                            ((StatusListener) listeners[i + 1])
4797:                                    .bracketSelected(this , line, text);
4798:                        } catch (Throwable t) {
4799:                            Log.log(Log.ERROR, this , t);
4800:                        }
4801:                    }
4802:                }
4803:            } //}}}
4804:
4805:            //{{{ _changeLine() method
4806:            private void _changeLine(boolean select, int newCaret) {
4807:                if (select) {
4808:                    RectParams params = getRectParams(caret, newCaret);
4809:                    int extraStartVirt;
4810:                    int extraEndVirt;
4811:                    if (params == null) {
4812:                        extraStartVirt = 0;
4813:                        extraEndVirt = 0;
4814:                    } else {
4815:                        extraStartVirt = params.extraStartVirt;
4816:                        extraEndVirt = params.extraEndVirt;
4817:                        newCaret = params.newCaret;
4818:                    }
4819:                    extendSelection(caret, newCaret, extraStartVirt,
4820:                            extraEndVirt);
4821:                } else if (!multi)
4822:                    selectNone();
4823:
4824:                moveCaretPosition(newCaret);
4825:            }//}}}
4826:
4827:            /**
4828:             * Check if the line contains only spaces and tabs.
4829:             *
4830:             * @param lineIndex the line index
4831:             * @return <code>true</code> if the line contains only spaces and tabs
4832:             */
4833:            private boolean lineContainsSpaceAndTabs(int lineIndex) {
4834:                getLineText(lineIndex, lineSegment);
4835:
4836:                for (int j = 0; j < lineSegment.count; j++) {
4837:                    switch (lineSegment.array[lineSegment.offset + j]) {
4838:                    case ' ':
4839:                    case '\t':
4840:                        break;
4841:                    default:
4842:                        return false;
4843:                    }
4844:                }
4845:                return true;
4846:            }
4847:
4848:            //{{{ insert() method
4849:            protected void insert(String str, boolean indent) {
4850:                try {
4851:                    // Don't overstrike if we're on the end of
4852:                    // the line
4853:                    if (overwrite || indent)
4854:                        buffer.beginCompoundEdit();
4855:
4856:                    if (overwrite) {
4857:                        int caretLineEnd = getLineEndOffset(caretLine);
4858:                        if (caretLineEnd - caret > 1)
4859:                            buffer.remove(caret, 1);
4860:                    }
4861:
4862:                    buffer.insert(caret, str);
4863:
4864:                    if (indent)
4865:                        buffer.indentLine(caretLine, true);
4866:                } finally {
4867:                    if (overwrite || indent)
4868:                        buffer.endCompoundEdit();
4869:                }
4870:            } //}}}
4871:
4872:            //{{{ insertTab() method
4873:            private void insertTab() {
4874:                int tabSize = buffer.getTabSize();
4875:                if (buffer.getBooleanProperty("noTabs")) {
4876:                    int lineStart = getLineStartOffset(caretLine);
4877:
4878:                    String line = getText(lineStart, caret - lineStart);
4879:
4880:                    int pos = 0;
4881:
4882:                    for (int i = 0; i < line.length(); i++) {
4883:                        switch (line.charAt(pos)) {
4884:                        case '\t':
4885:                            pos = 0;
4886:                            break;
4887:                        default:
4888:                            if (++pos >= tabSize)
4889:                                pos = 0;
4890:                            break;
4891:                        }
4892:                    }
4893:
4894:                    replaceSelection(StandardUtilities.createWhiteSpace(tabSize
4895:                            - pos, 0));
4896:                } else
4897:                    replaceSelection("\t");
4898:            } //}}}
4899:
4900:            //{{{ userInputTab() method
4901:            protected void userInputTab() {
4902:                if (getSelectionCount() == 1) {
4903:                    Selection sel = getSelection(0);
4904:                    if (sel instanceof  Selection.Rect
4905:                            || (sel.startLine == sel.endLine && (sel.start != buffer
4906:                                    .getLineStartOffset(sel.startLine) || sel.end != buffer
4907:                                    .getLineEndOffset(sel.startLine) - 1))) {
4908:                        insertTab();
4909:                    } else
4910:                        shiftIndentRight();
4911:                } else if (getSelectionCount() != 0)
4912:                    shiftIndentRight();
4913:                else
4914:                    insertTab();
4915:            } //}}}
4916:
4917:            //{{{ doWordWrap() method
4918:            /**
4919:             * Does hard wrap.
4920:             */
4921:            protected boolean doWordWrap(boolean spaceInserted) {
4922:                if (!hardWrap || maxLineLen <= 0)
4923:                    return false;
4924:
4925:                buffer.getLineText(caretLine, lineSegment);
4926:
4927:                int start = getLineStartOffset(caretLine);
4928:                int end = getLineEndOffset(caretLine);
4929:                int len = end - start - 1;
4930:
4931:                int caretPos = caret - start;
4932:
4933:                // only wrap if we're at the end of a line, or the rest of the
4934:                // line text is whitespace
4935:                for (int i = caretPos; i < len; i++) {
4936:                    char ch = lineSegment.array[lineSegment.offset + i];
4937:                    if (ch != ' ' && ch != '\t')
4938:                        return false;
4939:                }
4940:
4941:                int tabSize = buffer.getTabSize();
4942:
4943:                String wordBreakChars = buffer
4944:                        .getStringProperty("wordBreakChars");
4945:
4946:                int lastInLine = 0; // last character before wrap
4947:                int logicalLength = 0; // length with tabs expanded
4948:                int lastWordOffset = -1;
4949:                boolean lastWasSpace = true;
4950:                for (int i = 0; i < caretPos; i++) {
4951:                    char ch = lineSegment.array[lineSegment.offset + i];
4952:                    if (ch == '\t') {
4953:                        logicalLength += tabSize - (logicalLength % tabSize);
4954:                        if (!lastWasSpace && logicalLength <= maxLineLen) {
4955:                            lastInLine = i;
4956:                            lastWordOffset = i;
4957:                            lastWasSpace = true;
4958:                        }
4959:                    } else if (ch == ' ') {
4960:                        logicalLength++;
4961:                        if (!lastWasSpace && logicalLength <= maxLineLen + 1) {
4962:                            lastInLine = i;
4963:                            lastWordOffset = i;
4964:                            lastWasSpace = true;
4965:                        }
4966:                    } else if (wordBreakChars != null
4967:                            && wordBreakChars.indexOf(ch) != -1) {
4968:                        logicalLength++;
4969:                        if (!lastWasSpace && logicalLength <= maxLineLen) {
4970:                            lastInLine = i;
4971:                            lastWordOffset = i;
4972:                            lastWasSpace = true;
4973:                        }
4974:                    } else {
4975:                        lastInLine = i;
4976:                        logicalLength++;
4977:                        lastWasSpace = false;
4978:                    }
4979:                }
4980:
4981:                boolean returnValue;
4982:
4983:                int insertNewLineAt;
4984:                if (spaceInserted && logicalLength == maxLineLen
4985:                        && lastInLine == caretPos - 1) {
4986:                    insertNewLineAt = caretPos;
4987:                    returnValue = true;
4988:                } else if (logicalLength >= maxLineLen && lastWordOffset != -1) {
4989:                    insertNewLineAt = lastWordOffset;
4990:                    returnValue = false;
4991:                } else
4992:                    return false;
4993:
4994:                try {
4995:                    buffer.beginCompoundEdit();
4996:                    buffer.insert(start + insertNewLineAt, "\n");
4997:                    // caretLine would have been incremented
4998:                    // since insertNewLineAt <= caretPos
4999:                    buffer.indentLine(caretLine, true);
5000:                } finally {
5001:                    buffer.endCompoundEdit();
5002:                }
5003:
5004:                /* only ever return true if space was pressed
5005:                 * with logicalLength == maxLineLen */
5006:                return returnValue;
5007:            } //}}}
5008:
5009:            //{{{ updateStructureHighlightWithDelay() method
5010:            private static void updateBracketHighlightWithDelay() {
5011:                structureTimer.stop();
5012:                structureTimer.start();
5013:            } //}}}
5014:
5015:            //{{{ updateStructureHighlight() method
5016:            private void updateStructureHighlight() {
5017:                if (!painter.isStructureHighlightEnabled()
5018:                        && !gutter.isStructureHighlightEnabled())
5019:                    return;
5020:
5021:                for (StructureMatcher matcher : structureMatchers) {
5022:                    match = matcher.getMatch(this );
5023:                    if (match != null)
5024:                        break;
5025:                }
5026:
5027:                if (match != null) {
5028:                    if (caretLine < match.startLine)
5029:                        invalidateLineRange(caretLine, match.endLine);
5030:                    else
5031:                        invalidateLineRange(match.startLine, caretLine);
5032:
5033:                    if (!displayManager.isLineVisible(match.startLine)
5034:                            || chunkCache
5035:                                    .getScreenLineOfOffset(
5036:                                            match.startLine,
5037:                                            match.start
5038:                                                    - getLineStartOffset(match.startLine)) == -1) {
5039:                        showStructureStatusMessage(match.startLine < caretLine);
5040:                    }
5041:                }
5042:            } //}}}
5043:
5044:            //{{{ showStructureStatusMessage() method
5045:            private void showStructureStatusMessage(boolean backward) {
5046:                String text = buffer.getLineText(match.startLine).trim();
5047:                if (backward && match.startLine != 0 && text.length() == 1) {
5048:                    switch (text.charAt(0)) {
5049:                    case '{':
5050:                    case '}':
5051:                    case '[':
5052:                    case ']':
5053:                    case '(':
5054:                    case ')':
5055:                        text = buffer.getLineText(match.startLine - 1).trim()
5056:                                + ' ' + text;
5057:                        break;
5058:                    }
5059:                }
5060:
5061:                // get rid of embedded tabs not removed by trim()
5062:                fireBracketSelected(match.startLine + 1, text
5063:                        .replace('\t', ' '));
5064:            } //}}}
5065:
5066:            //{{{ recalculateLastPhysicalLine() method
5067:            void recalculateLastPhysicalLine() {
5068:                int oldScreenLastLine = screenLastLine;
5069:                for (int i = visibleLines - 1; i >= 0; i--) {
5070:                    ChunkCache.LineInfo info = chunkCache.getLineInfo(i);
5071:                    if (info.physicalLine != -1) {
5072:                        physLastLine = info.physicalLine;
5073:                        screenLastLine = i;
5074:                        break;
5075:                    }
5076:                }
5077:                invalidateScreenLineRange(oldScreenLastLine, screenLastLine);
5078:            } //}}}
5079:
5080:            //{{{ getRectParams() method
5081:            static class RectParams {
5082:                final int extraStartVirt;
5083:                final int extraEndVirt;
5084:                final int newCaret;
5085:
5086:                RectParams(int extraStartVirt, int extraEndVirt, int newCaret) {
5087:                    this .extraStartVirt = extraStartVirt;
5088:                    this .extraEndVirt = extraEndVirt;
5089:                    this .newCaret = newCaret;
5090:                }
5091:            }
5092:
5093:            /**
5094:             * Used when doing S+UP/DOWN to simplify dealing with virtual space.
5095:             */
5096:            private RectParams getRectParams(int caret, int newCaret) {
5097:                Selection s = getSelectionAtOffset(caret);
5098:                int virtualWidth;
5099:                if (s instanceof  Selection.Rect) {
5100:                    if (caret == s.end) {
5101:                        virtualWidth = buffer.getVirtualWidth(s.endLine, s.end
5102:                                - getLineStartOffset(s.endLine))
5103:                                + ((Selection.Rect) s).extraEndVirt;
5104:                    } else {
5105:                        virtualWidth = buffer.getVirtualWidth(s.startLine,
5106:                                s.start - getLineStartOffset(s.startLine))
5107:                                + ((Selection.Rect) s).extraStartVirt;
5108:                    }
5109:                } else if (rectangularSelectionMode) {
5110:                    virtualWidth = buffer.getVirtualWidth(caretLine, caret
5111:                            - buffer.getLineStartOffset(caretLine));
5112:                } else
5113:                    return null;
5114:
5115:                int newLine = getLineOfOffset(newCaret);
5116:                int[] totalVirtualWidth = new int[1];
5117:                int newOffset = buffer.getOffsetOfVirtualColumn(newLine,
5118:                        virtualWidth, totalVirtualWidth);
5119:                if (newOffset == -1) {
5120:                    int extraVirt = virtualWidth - totalVirtualWidth[0];
5121:                    newCaret = getLineEndOffset(newLine) - 1;
5122:
5123:                    boolean bias;
5124:                    if (s == null)
5125:                        bias = newCaret < caret;
5126:                    else if (s.start == caret)
5127:                        bias = newCaret <= s.end;
5128:                    else if (s.end == caret)
5129:                        bias = newCaret <= s.start;
5130:                    else
5131:                        bias = false;
5132:
5133:                    RectParams returnValue;
5134:                    if (bias)
5135:                        returnValue = new RectParams(extraVirt, 0, newCaret);
5136:                    else
5137:                        returnValue = new RectParams(0, extraVirt, newCaret);
5138:                    return returnValue;
5139:                } else {
5140:                    return new RectParams(0, 0, getLineStartOffset(newLine)
5141:                            + newOffset);
5142:                }
5143:            } //}}}
5144:
5145:            //{{{ delete() method
5146:            private void delete(boolean forward) {
5147:                if (!buffer.isEditable()) {
5148:                    getToolkit().beep();
5149:                    return;
5150:                }
5151:
5152:                if (getSelectionCount() != 0) {
5153:                    Selection[] selections = getSelection();
5154:                    for (int i = 0; i < selections.length; i++) {
5155:                        Selection s = selections[i];
5156:                        if (s instanceof  Selection.Rect) {
5157:                            Selection.Rect r = (Selection.Rect) s;
5158:                            int startColumn = r.getStartColumn(buffer);
5159:                            if (startColumn == r.getEndColumn(buffer)) {
5160:                                if (!forward && startColumn == 0)
5161:                                    getToolkit().beep();
5162:                                else
5163:                                    tallCaretDelete(r, forward);
5164:                            } else
5165:                                setSelectedText(s, null);
5166:                        } else
5167:                            setSelectedText(s, null);
5168:                    }
5169:                } else if (forward) {
5170:                    if (caret == buffer.getLength()) {
5171:                        getToolkit().beep();
5172:                        return;
5173:                    }
5174:
5175:                    buffer.remove(caret, 1);
5176:                } else {
5177:                    if (caret == 0) {
5178:                        getToolkit().beep();
5179:                        return;
5180:                    }
5181:
5182:                    buffer.remove(caret - 1, 1);
5183:                }
5184:            } //}}}
5185:
5186:            //{{{ tallCaretDelete() method
5187:            private void tallCaretDelete(Selection.Rect s, boolean forward) {
5188:                try {
5189:                    buffer.beginCompoundEdit();
5190:
5191:                    int[] width = new int[1];
5192:
5193:                    int startCol = s.getStartColumn(buffer);
5194:                    int startLine = s.startLine;
5195:                    int endLine = s.endLine;
5196:                    for (int i = startLine; i <= endLine; i++) {
5197:                        int offset = buffer.getOffsetOfVirtualColumn(i,
5198:                                startCol, width);
5199:                        if (offset == -1) {
5200:                            if (width[0] == startCol)
5201:                                offset = getLineLength(i);
5202:                            else {
5203:                                if (i == startLine && !forward)
5204:                                    shiftTallCaretLeft(s);
5205:                                continue;
5206:                            }
5207:                        }
5208:                        offset += buffer.getLineStartOffset(i);
5209:                        if (forward) {
5210:                            if (offset != buffer.getLineEndOffset(i) - 1)
5211:                                buffer.remove(offset, 1);
5212:                        } else
5213:                            buffer.remove(offset - 1, 1);
5214:                    }
5215:                } finally {
5216:                    buffer.endCompoundEdit();
5217:                }
5218:            } //}}}
5219:
5220:            //{{{ shiftTallCaretLeft() method
5221:            private void shiftTallCaretLeft(Selection.Rect s) {
5222:                removeFromSelection(s);
5223:                addToSelection(new Selection.Rect(buffer, s.getStartLine(), s
5224:                        .getStartColumn(buffer) - 1, s.getEndLine(), s
5225:                        .getEndColumn(buffer) - 1));
5226:            } //}}}
5227:
5228:            //{{{ setMaxLineLength() method
5229:            private void setMaxLineLength(int maxLineLen) {
5230:                this .maxLineLen = maxLineLen;
5231:
5232:                if (maxLineLen <= 0) {
5233:                    if (softWrap) {
5234:                        wrapToWidth = true;
5235:                        wrapMargin = painter.getWidth() - charWidth * 3;
5236:                    } else {
5237:                        wrapToWidth = false;
5238:                        wrapMargin = 0;
5239:                    }
5240:                } else {
5241:                    // stupidity
5242:                    char[] foo = new char[maxLineLen];
5243:                    for (int i = 0; i < foo.length; i++) {
5244:                        foo[i] = ' ';
5245:                    }
5246:                    wrapToWidth = false;
5247:                    wrapMargin = (int) painter.getFont().getStringBounds(foo,
5248:                            0, foo.length, painter.getFontRenderContext())
5249:                            .getWidth();
5250:                }
5251:            } //}}}
5252:
5253:            //{{{ addExplicitFold() method
5254:            /**
5255:             * Add an explicit fold.
5256:             * You should call this method inside a compoundEdit in the buffer.
5257:             * You must also check if the buffer fold mode is explicit before
5258:             * calling this method.
5259:             *
5260:             * @param caretStart the starting offset
5261:             * @param caretEnd   the end offset
5262:             * @param lineStart  the start line
5263:             * @param lineEnd    the end line
5264:             * @since jEdit 4.3pre3
5265:             */
5266:            protected int addExplicitFold(int caretStart, int caretEnd,
5267:                    int lineStart, int lineEnd) {
5268:                // need to "fix" the caret position so that we get the right rule.
5269:                // taking the start offset one char ahead and the end offset one char
5270:                // behing makes sure we get the right rule for the text being
5271:                // wrapped (tricky around mode boundaries, e.g., php code embedded
5272:                // in HTML code)
5273:                int startCaret = caretStart < buffer.getLength() ? caretStart + 1
5274:                        : caretStart;
5275:                int endCaret = caretEnd > 0 ? caretEnd - 1 : caretEnd;
5276:
5277:                String startLineComment = buffer.getContextSensitiveProperty(
5278:                        startCaret, "lineComment");
5279:                String startCommentStart = buffer.getContextSensitiveProperty(
5280:                        startCaret, "commentStart");
5281:                String startCommentEnd = buffer.getContextSensitiveProperty(
5282:                        startCaret, "commentEnd");
5283:                String endLineComment = buffer.getContextSensitiveProperty(
5284:                        endCaret, "lineComment");
5285:                String endCommentStart = buffer.getContextSensitiveProperty(
5286:                        endCaret, "commentStart");
5287:                String endCommentEnd = buffer.getContextSensitiveProperty(
5288:                        endCaret, "commentEnd");
5289:
5290:                String start;
5291:                int caretBack = 1;
5292:                if (startLineComment != null)
5293:                    start = startLineComment + "{{{ ";
5294:                else if (startCommentStart != null && startCommentEnd != null) {
5295:                    start = startCommentStart + "{{{  " + startCommentEnd;
5296:                    caretBack = 1 + startCommentStart.length();
5297:                } else
5298:                    start = "{{{ ";
5299:
5300:                if (startLineComment != null) {
5301:                    // add a new line if there's text after the comment
5302:                    // we're inserting
5303:                    if (buffer.getLineLength(lineStart) != caretStart) {
5304:                        start += '\n';
5305:                    }
5306:                } else {
5307:                    // always insert a new line if there's no comment character.
5308:                    start += "\n";
5309:                }
5310:
5311:                String end;
5312:                if (endLineComment != null)
5313:                    end = endLineComment + "}}}";
5314:                else if (endCommentStart != null && endCommentEnd != null)
5315:                    end = endCommentStart + "}}}" + endCommentEnd;
5316:                else
5317:                    end = "}}}";
5318:
5319:                String line = buffer.getLineText(lineStart);
5320:                String whitespace = line.substring(0, StandardUtilities
5321:                        .getLeadingWhiteSpace(line));
5322:
5323:                if (endLineComment != null) {
5324:                    // if we're inserting a line comment into a non-empty
5325:                    // line, we'll need to add a line break so we don't
5326:                    // comment out existing code.
5327:                    if (buffer.getLineLength(lineEnd) != caretEnd) {
5328:                        end += '\n';
5329:                    }
5330:                } else {
5331:                    // always insert a new line if there's no comment character.
5332:                    end += "\n";
5333:                }
5334:
5335:                if (caretEnd == buffer.getLineStartOffset(lineEnd))
5336:                    buffer.insert(caretEnd, end);
5337:                else {
5338:                    String lineText = buffer.getText(caretEnd - 1, 1);
5339:                    if (Character.isWhitespace(lineText.charAt(0)))
5340:                        buffer.insert(caretEnd, end);
5341:                    else
5342:                        buffer.insert(caretEnd, ' ' + end);
5343:                }
5344:
5345:                buffer.insert(caretStart, start + whitespace);
5346:
5347:                return caretBack;
5348:            } //}}}
5349:
5350:            //}}}
5351:
5352:            //{{{ Inner classes
5353:
5354:            //{{{ CaretBlinker class
5355:            static class CaretBlinker implements  ActionListener {
5356:                //{{{ actionPerformed() method
5357:                public void actionPerformed(ActionEvent evt) {
5358:                    if (focusedComponent != null && focusedComponent.hasFocus())
5359:                        focusedComponent.blinkCaret();
5360:                } //}}}
5361:            } //}}}
5362:
5363:            //{{{ MutableCaretEvent class
5364:            class MutableCaretEvent extends CaretEvent {
5365:                //{{{ MutableCaretEvent constructor
5366:                MutableCaretEvent() {
5367:                    super (TextArea.this );
5368:                } //}}}
5369:
5370:                //{{{ getDot() method
5371:                public int getDot() {
5372:                    return getCaretPosition();
5373:                } //}}}
5374:
5375:                //{{{ getMark() method
5376:                public int getMark() {
5377:                    return getMarkPosition();
5378:                } //}}}
5379:            } //}}}
5380:
5381:            //{{{ AdjustHandler class
5382:            class AdjustHandler implements  AdjustmentListener {
5383:                //{{{ adjustmentValueChanged() method
5384:                public void adjustmentValueChanged(AdjustmentEvent evt) {
5385:                    if (!scrollBarsInitialized)
5386:                        return;
5387:
5388:                    if (evt.getAdjustable() == vertical)
5389:                        setFirstLine(vertical.getValue());
5390:                    else
5391:                        setHorizontalOffset(-horizontal.getValue());
5392:                } //}}}
5393:            } //}}}
5394:
5395:            //{{{ FocusHandler class
5396:            class FocusHandler implements  FocusListener {
5397:                //{{{ focusGained() method
5398:                public void focusGained(FocusEvent evt) {
5399:                    if (bufferChanging)
5400:                        return;
5401:
5402:                    if (match != null) {
5403:                        if (caretLine < match.startLine)
5404:                            invalidateLineRange(caretLine, match.endLine);
5405:                        else
5406:                            invalidateLineRange(match.startLine, caretLine);
5407:                    } else
5408:                        invalidateLine(caretLine);
5409:
5410:                    focusedComponent = TextArea.this ;
5411:                } //}}}
5412:
5413:                //{{{ focusLost() method
5414:                public void focusLost(FocusEvent evt) {
5415:                    if (!isShowing())
5416:                        return;
5417:
5418:                    if (match != null) {
5419:                        if (caretLine < match.startLine)
5420:                            invalidateLineRange(caretLine, match.endLine);
5421:                        else
5422:                            invalidateLineRange(match.startLine, caretLine);
5423:                    } else
5424:                        invalidateLine(caretLine);
5425:                } //}}}
5426:            } //}}}
5427:
5428:            //{{{ MouseWheelHandler class
5429:            class MouseWheelHandler implements  MouseWheelListener {
5430:                public void mouseWheelMoved(MouseWheelEvent e) {
5431:                    /****************************************************
5432:                     * move caret depending on pressed control-keys:
5433:                     * - Alt: move cursor, do not select
5434:                     * - Alt+(shift or control): move cursor, select
5435:                     * - shift: scroll page
5436:                     * - control: scroll single line
5437:                     * - <else>: scroll 3 lines
5438:                     ****************************************************/
5439:                    if (e.isAltDown()) {
5440:                        boolean select = e.isShiftDown() || e.isControlDown();
5441:                        if (e.getWheelRotation() < 0)
5442:                            goToPrevLine(select);
5443:                        else
5444:                            goToNextLine(select);
5445:                    } else if (e.isShiftDown()) {
5446:                        if (e.getWheelRotation() > 0)
5447:                            scrollDownPage();
5448:                        else
5449:                            scrollUpPage();
5450:                    } else if (e.isControlDown()) {
5451:                        setFirstLine(getFirstLine() + e.getWheelRotation());
5452:                    } else if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
5453:                        setFirstLine(getFirstLine() + e.getUnitsToScroll());
5454:                    } else {
5455:                        setFirstLine(getFirstLine() + 3 * e.getWheelRotation());
5456:                    }
5457:                }
5458:            } //}}}
5459:
5460:            //}}}
5461:
5462:            //{{{ Class initializer
5463:            static {
5464:                caretTimer = new Timer(500, new CaretBlinker());
5465:                caretTimer.setInitialDelay(500);
5466:                caretTimer.start();
5467:
5468:                structureTimer = new Timer(100, new ActionListener() {
5469:                    public void actionPerformed(ActionEvent evt) {
5470:                        if (focusedComponent != null)
5471:                            focusedComponent.updateStructureHighlight();
5472:                    }
5473:                });
5474:                structureTimer.setInitialDelay(100);
5475:                structureTimer.setRepeats(false);
5476:            } //}}}
5477:
5478:            //{{{ main() method
5479:            public static void main(String[] args) {
5480:                JFrame frame = new JFrame();
5481:                TextArea text = new TextArea();
5482:                frame.getContentPane().add(text);
5483:                frame.pack();
5484:                frame.setVisible(true);
5485:            } //}}}
5486:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.