textutilities.java
来自「java写的多功能文件编辑器」· Java 代码 · 共 395 行
JAVA
395 行
/* * 04/13/2001 - 18:46:16 * * TextUtilities.java - Utility functions used by the text area classes * Copyright (C) 1999, 2000 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package org.gjt.sp.jedit.textarea;import javax.swing.text.*;import java.util.ArrayList;import org.gjt.sp.jedit.syntax.*;/** * Class with several utility functions used by the text area component. * This is a special version based on v 1.8 adapted by Matt Benson for Jext. * @author Slava Pestov * @author Matt Benson * @version $Id: TextUtilities.java,v 1.1.1.1 2001/08/20 22:32:16 gfx Exp $ */public class TextUtilities{ public static final String BRACKETS = "([{}])"; public static final int FORWARD = 1; public static final int BACKWARD = -1; /** * Returns an <CODE>ArrayList</CODE> filled with <CODE>Token</CODE>s * linked to the argument token, in the order specified. * @param token The initial <CODE>Token</CODE> that links to the others. * @param dir The <CODE>int</CODE> representation of the ordering to be * used when filling the <CODE>ArrayList</CODE>. */ private static ArrayList getTokenList(Token token, int dir) { ArrayList tokenList = new ArrayList(); while (token != null) { if (token.id == Token.END) { token = null; }//end if token.id == Token.END else {// The following is just a trick--size * 1 >= 0 but size * -1 <= 0 tokenList.add(Math.max(0, (tokenList.size() * dir)), token); token = token.next; }//end else }//end while token != null return tokenList; }//end getTokenList /** * Returns the offset of the bracket matching the one at the * specified offset of the document, or -1 if the bracket is * unmatched (or if the character is not a bracket). * @param doc The document * @param offset The offset * @exception BadLocationException If an out-of-bounds access * was attempted on the document text * @since jEdit 3.0pre1 */ public static int findMatchingBracket(SyntaxDocument doc, int offset) throws BadLocationException { if (doc.getLength() == 0) return -1; Element map = doc.getDefaultRootElement(); Element lineElement = doc.getParagraphElement(offset); Segment lineText = new Segment(); int lineStart = lineElement.getStartOffset(); int lineLength = lineElement.getEndOffset() - lineStart - 1; int line = map.getElementIndex(lineStart); doc.getText(lineStart, lineLength, lineText); offset-= lineStart; char c; try { c = lineText.array[lineText.offset + offset];//the character }//end try catch(ArrayIndexOutOfBoundsException e)//for when cursor is positioned at offset 0. { c = (char)0; }//end catch ArrayIndexOutOfBoundsException int whichBracket = BRACKETS.indexOf(c); if (whichBracket == -1) { return whichBracket; }//end if whichBracket == -1 char cprime = //corresponding character BRACKETS.charAt(BRACKETS.length() - 1 - whichBracket); int direction = (whichBracket < BRACKETS.length() / 2) ? FORWARD : BACKWARD; /* I didn't like the old switch statement. * Also I changed direction to an int which should be pos/neg 1 for ease in counting * with merged search logic as compared to SP versions which search bkwd & fwd separately. * Actually the merged search is pretty sloppy but Slava included the comment in an earlier * version that he was leaving the merge as an exercise to the reader, so I took him up on it. */ TokenMarker tokenMarker = doc.getTokenMarker(); if (tokenMarker == null) { return -1; }//end if tokenMarker == null ArrayList tokenList = getTokenList(tokenMarker.markTokens(lineText, line), direction); // Get the syntax token at 'offset'// only tokens with the same type will be checked for// the corresponding bracket byte idOfBracket = Token.INVALID;//default to invalid int tokenListOffset = 0; int tok = ((direction == FORWARD) ? 0 : tokenList.size() - 1); boolean foundBracket = false; do { Token testToken = null; try { testToken = (Token)tokenList.get(tok); }//end try catch (IndexOutOfBoundsException oob) { return -1; }//end catch IndexOutOfBoundsException tokenListOffset+= testToken.length; if (tokenListOffset > offset) { idOfBracket = testToken.id; if (direction == FORWARD) { tokenListOffset-= testToken.length; }//end if FORWARD foundBracket = true; }//end if this Token else { tok+= direction; }//end else } while (!foundBracket);//end do while loop if (idOfBracket == Token.INVALID) { return -1; }//end if idOfBracket == Token.INVALID int count = 0; int repetitions = ((direction == FORWARD) ? map.getElementCount() - line : line + 1); for (int i = 0; i < repetitions; i++) {// get text int index = line + (i * direction); lineElement = map.getElement(index); lineStart = lineElement.getStartOffset(); lineLength = lineElement.getEndOffset() - lineStart - 1; doc.getText(lineStart, lineLength, lineText); int scanStartOffset; if (index != line) { tokenList = getTokenList(tokenMarker.markTokens(lineText, line), direction); tok = 0; if (direction == FORWARD) { scanStartOffset = tokenListOffset = 0; }//end if direction == FORWARD else { tokenListOffset = lineLength; scanStartOffset = tokenListOffset - 1; }//end else }//end if not original line else { scanStartOffset = offset; }//end else for (; tok < tokenList.size(); tok++) { Token currTok = (Token)(tokenList.get(tok)); byte id = currTok.id; int len = currTok.length; // only check tokens with id 'idOfBracket' if (id == idOfBracket) { char[] word = new char[len]; int wordOffset = tokenListOffset + ((direction == FORWARD) ? 0 : (direction * word.length)); for (int j = 0; j < word.length; j++) { word[j] = lineText.array[lineText.offset + wordOffset + j]; }//end for thru word int oppositeEnd = ((direction == FORWARD) ? 0 : word.length -1); int wordSearch = scanStartOffset - wordOffset - direction;//set it 1 different than what we really want b/c we increment in the beginning of the loop do { wordSearch+= direction; char ch = word[wordSearch]; if (ch == c) { count++; }//end if ch == c else if (ch == cprime) { if (--count == 0) { return lineStart + wordOffset + wordSearch; } }//end else } while ((wordSearch + oppositeEnd + 1) != word.length); }//end if id == idOfBracket//the following skips to the next token offset by adding len of curr. token tokenListOffset+= (len * direction); scanStartOffset = tokenListOffset; if (direction == BACKWARD) { scanStartOffset--; }//end if }//end for tok... }//end for i// Nothing found return -1; }//end getMatchingBracket /** * Locates the start of the word at the specified position. * @param line The text * @param pos The position * @param noWordSep Characters that are non-alphanumeric, but * should be treated as word characters anyway */ public static int findWordStart(String line, int pos, String noWordSep) { char ch = line.charAt(pos); if (noWordSep == null) noWordSep = ""; boolean selectNoLetter = (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1); int wordStart = 0; for(int i = pos; i >= 0; i--) { ch = line.charAt(i); if (selectNoLetter ^ (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1)) { wordStart = i + 1; break; }//end if }//end for i return wordStart; }//end findWordStart/*** Locates the end of the word at the specified position.* @param line The text* @param pos The position* @param noWordSep Characters that are non-alphanumeric, but* should be treated as word characters anyway*/ public static int findWordEnd(String line, int pos, String noWordSep) { if (pos != 0) { pos--; }//end if pos != 0 char ch = line.charAt(pos); if (noWordSep == null) { noWordSep = ""; }//end if noWordSep == null boolean selectNoLetter = (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1); int wordEnd = line.length(); for(int i = pos; i < line.length(); i++) { ch = line.charAt(i); if (selectNoLetter ^ (!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1)) { wordEnd = i; break; }//end if }//end for i return wordEnd; }//end findWordEnd /*** Locates the next character type change searching in the specified direction.* Included for use with Jext's CsWord Action.* @param line The text.* @param pos The position.* @param direction The direction in which the search should be made.*/ public static int findTypeChange(String line, int pos, int direction) { int type = Character.getType(line.charAt(pos)); for (int i = pos + direction; ; i+= direction) { try { if (Character.getType(line.charAt(i)) != type) { return i; }//end if }//end try catch(IndexOutOfBoundsException oobe) { return i - direction; }//end catch }//end for i }//end findWordEnd }//end class TextUtilities/* * ChangeLog: * $Log: TextUtilities.java,v $ * Revision 1.1.1.1 2001/08/20 22:32:16 gfx * Jext 3.0pre5 * * Revision 1.2 2001/04/13 16:55:20 gfx * * Bug fix by Matt. Benson * * Revision 1.8 2000/07/15 06:56:29 sp * bracket matching debugged * * Revision 1.7 2000/07/14 06:00:45 sp * bracket matching now takes syntax info into account * * Revision 1.6 2000/01/28 00:20:58 sp * Lots of stuff * * Revision 1.5 1999/12/19 11:14:29 sp * Static abbrev expansion started * * Revision 1.4 1999/12/13 03:40:30 sp * Bug fixes, syntax is now mostly GPL'd * * Revision 1.3 1999/11/21 03:40:18 sp * Parts of EditBus not used by core moved to EditBus.jar * * Revision 1.2 1999/07/16 23:45:49 sp * 1.7pre6 BugFree version * * Revision 1.1 1999/06/29 09:03:18 sp * oops, forgot to add TextUtilities.java * */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?