/** * Returns the start of the word at the given offset. * * @param textArea The text area. * @param offs The offset into the text area's content. * @return The start offset of the word. * @throws BadLocationException If <code>offs</code> is invalid. * @see #getWordEnd(RSyntaxTextArea, int) */ public static int getWordStart(RSyntaxTextArea textArea, int offs) throws BadLocationException { Document doc = textArea.getDocument(); Element line = getLineElem(doc, offs); if (line == null) { throw new BadLocationException("No word at " + offs, offs); } int lineStart = line.getStartOffset(); if (offs == lineStart) { // Start of the line. return offs; } int endOffs = Math.min(offs + 1, doc.getLength()); String s = doc.getText(lineStart, endOffs - lineStart); if (s != null && s.length() > 0) { int i = s.length() - 1; char ch = s.charAt(i); if (Character.isWhitespace(ch)) { while (i > 0 && Character.isWhitespace(s.charAt(i - 1))) { i--; } offs = lineStart + i; } else if (Character.isLetterOrDigit(ch)) { while (i > 0 && Character.isLetterOrDigit(s.charAt(i - 1))) { i--; } offs = lineStart + i; } } return offs; }
/** * Returns the end of the word at the given offset. * * @param textArea The text area. * @param offs The offset into the text area's content. * @return The end offset of the word. * @throws BadLocationException If <code>offs</code> is invalid. * @see #getWordStart(RSyntaxTextArea, int) */ public static int getWordEnd(RSyntaxTextArea textArea, int offs) throws BadLocationException { Document doc = textArea.getDocument(); int endOffs = textArea.getLineEndOffsetOfCurrentLine(); int lineEnd = Math.min(endOffs, doc.getLength()); if (offs == lineEnd) { // End of the line. return offs; } String s = doc.getText(offs, lineEnd - offs - 1); if (s != null && s.length() > 0) { // Should always be true int i = 0; int count = s.length(); char ch = s.charAt(i); if (Character.isWhitespace(ch)) { while (i < count && Character.isWhitespace(s.charAt(i++))) ; } else if (Character.isLetterOrDigit(ch)) { while (i < count && Character.isLetterOrDigit(s.charAt(i++))) ; } else { i = 2; } offs += i - 1; } return offs; }
/** * Returns the bounding box (in the current view) of a specified position in the model. This * method is designed for line-wrapped views to use, as it allows you to specify a "starting * position" in the line, from which the x-value is assumed to be zero. The idea is that you * specify the first character in a physical line as <code>p0</code>, as this is the character * where the x-pixel value is 0. * * @param textArea The text area containing the text. * @param s A segment in which to load the line. This is passed in so we don't have to reallocate * a new <code>Segment</code> for each call. * @param p0 The starting position in the physical line in the document. * @param p1 The position for which to get the bounding box in the view. * @param e How to expand tabs. * @param rect The rectangle whose x- and width-values are changed to represent the bounding box * of <code>p1</code>. This is reused to keep from needlessly reallocating Rectangles. * @param x0 The x-coordinate (pixel) marking the left-hand border of the text. This is useful if * the text area has a border, for example. * @return The bounding box in the view of the character <code>p1</code>. * @throws BadLocationException If <code>p0</code> or <code>p1</code> is not a valid location in * the specified text area's document. * @throws IllegalArgumentException If <code>p0</code> and <code>p1</code> are not on the same * line. */ public static Rectangle getLineWidthUpTo( RSyntaxTextArea textArea, Segment s, int p0, int p1, TabExpander e, Rectangle rect, int x0) throws BadLocationException { RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); // Ensure p0 and p1 are valid document positions. if (p0 < 0) throw new BadLocationException("Invalid document position", p0); else if (p1 > doc.getLength()) throw new BadLocationException("Invalid document position", p1); // Ensure p0 and p1 are in the same line, and get the start/end // offsets for that line. Element map = doc.getDefaultRootElement(); int lineNum = map.getElementIndex(p0); // We do ">1" because p1 might be the first position on the next line // or the last position on the previous one. // if (lineNum!=map.getElementIndex(p1)) if (Math.abs(lineNum - map.getElementIndex(p1)) > 1) throw new IllegalArgumentException( "p0 and p1 are not on the " + "same line (" + p0 + ", " + p1 + ")."); // Get the token list. Token t = doc.getTokenListForLine(lineNum); // Modify the token list 't' to begin at p0 (but still have correct // token types, etc.), and get the x-location (in pixels) of the // beginning of this new token list. makeTokenListStartAt(t, p0, e, textArea, 0); rect = t.listOffsetToView(textArea, e, p1, x0, rect); return rect; }
/** * Returns the template that should be inserted at the current caret position, assuming the * trigger character was pressed. * * @param textArea The text area that's getting text inserted into it. * @return A template that should be inserted, if appropriate, or <code>null</code> if no template * should be inserted. */ public CodeTemplate getTemplate(RSyntaxTextArea textArea) { int caretPos = textArea.getCaretPosition(); int charsToGet = Math.min(caretPos, maxTemplateIDLength); try { Document doc = textArea.getDocument(); doc.getText(caretPos - charsToGet, charsToGet, s); int index = Collections.binarySearch(templates, s, comparator); return index >= 0 ? (CodeTemplate) templates.get(index) : null; } catch (BadLocationException ble) { ble.printStackTrace(); throw new InternalError("Error in CodeTemplateManager"); } }
@Override public void actionPerformedImpl(ActionEvent e, RTextArea textArea) { if (!textArea.isEditable() || !textArea.isEnabled()) { UIManager.getLookAndFeel().provideErrorFeedback(textArea); return; } RSyntaxTextArea rsta = (RSyntaxTextArea) getTextComponent(e); RSyntaxDocument doc = (RSyntaxDocument) rsta.getDocument(); int line = textArea.getCaretLineNumber(); int type = doc.getLastTokenTypeOnLine(line); if (type < 0) { type = doc.getClosestStandardTokenTypeForInternalType(type); } // Only in MLC's should we try this if (type == Token.COMMENT_DOCUMENTATION || type == Token.COMMENT_MULTILINE) { insertBreakInMLC(e, rsta, line); } else { handleInsertBreak(rsta, true); } }
public static int getMatchingBracketPosition(RSyntaxTextArea textArea) { try { // Actually position just BEFORE caret. int caretPosition = textArea.getCaretPosition() - 1; if (caretPosition > -1) { // Some variables that will be used later. Token token; Element map; int curLine; Element line; int start, end; RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument(); char bracket = doc.charAt(caretPosition); // First, see if the previous char was a bracket // ('{', '}', '(', ')', '[', ']'). // If it was, then make sure this bracket isn't sitting in // the middle of a comment or string. If it isn't, then // initialize some stuff so we can continue on. char bracketMatch; boolean goForward; switch (bracket) { case '{': case '(': case '[': // Ensure this bracket isn't in a comment. map = doc.getDefaultRootElement(); curLine = map.getElementIndex(caretPosition); line = map.getElement(curLine); start = line.getStartOffset(); end = line.getEndOffset(); token = doc.getTokenListForLine(curLine); token = RSyntaxUtilities.getTokenAtOffset(token, caretPosition); // All brackets are always returned as "separators." if (token.type != Token.SEPARATOR) { return -1; } bracketMatch = bracket == '{' ? '}' : (bracket == '(' ? ')' : ']'); goForward = true; break; case '}': case ')': case ']': // Ensure this bracket isn't in a comment. map = doc.getDefaultRootElement(); curLine = map.getElementIndex(caretPosition); line = map.getElement(curLine); start = line.getStartOffset(); end = line.getEndOffset(); token = doc.getTokenListForLine(curLine); token = RSyntaxUtilities.getTokenAtOffset(token, caretPosition); // All brackets are always returned as "separators." if (token.type != Token.SEPARATOR) { return -1; } bracketMatch = bracket == '}' ? '{' : (bracket == ')' ? '(' : '['); goForward = false; break; default: return -1; } if (goForward) { int lastLine = map.getElementCount(); // Start just after the found bracket since we're sure // we're not in a comment. start = caretPosition + 1; int numEmbedded = 0; boolean haveTokenList = false; while (true) { doc.getText(start, end - start, charSegment); int segOffset = charSegment.offset; for (int i = segOffset; i < segOffset + charSegment.count; i++) { char ch = charSegment.array[i]; if (ch == bracket) { if (haveTokenList == false) { token = doc.getTokenListForLine(curLine); haveTokenList = true; } int offset = start + (i - segOffset); token = RSyntaxUtilities.getTokenAtOffset(token, offset); if (token.type == Token.SEPARATOR) numEmbedded++; } else if (ch == bracketMatch) { if (haveTokenList == false) { token = doc.getTokenListForLine(curLine); haveTokenList = true; } int offset = start + (i - segOffset); token = RSyntaxUtilities.getTokenAtOffset(token, offset); if (token.type == Token.SEPARATOR) { if (numEmbedded == 0) return offset; numEmbedded--; } } } // End of for (int i=segOffset; i<segOffset+charSegment.count; i++). // Bail out if we've gone through all lines and // haven't found the match. if (++curLine == lastLine) return -1; // Otherwise, go through the next line. haveTokenList = false; line = map.getElement(curLine); start = line.getStartOffset(); end = line.getEndOffset(); } // End of while (true). } // End of if (goForward). // Otherwise, we're going backward through the file // (since we found '}', ')' or ']'). else { // goForward==false // End just before the found bracket since we're sure // we're not in a comment. end = caretPosition; // - 1; int numEmbedded = 0; boolean haveTokenList = false; Token t2; while (true) { doc.getText(start, end - start, charSegment); int segOffset = charSegment.offset; int iStart = segOffset + charSegment.count - 1; for (int i = iStart; i >= segOffset; i--) { char ch = charSegment.array[i]; if (ch == bracket) { if (haveTokenList == false) { token = doc.getTokenListForLine(curLine); haveTokenList = true; } int offset = start + (i - segOffset); t2 = RSyntaxUtilities.getTokenAtOffset(token, offset); if (t2.type == Token.SEPARATOR) numEmbedded++; } else if (ch == bracketMatch) { if (haveTokenList == false) { token = doc.getTokenListForLine(curLine); haveTokenList = true; } int offset = start + (i - segOffset); t2 = RSyntaxUtilities.getTokenAtOffset(token, offset); if (t2.type == Token.SEPARATOR) { if (numEmbedded == 0) return offset; numEmbedded--; } } } // End of for (int i=segOffset; i<segOffset+charSegment.count; i++). // Bail out if we've gone through all lines and // haven't found the match. if (--curLine == -1) return -1; // Otherwise, get ready for going through the // next line. haveTokenList = false; line = map.getElement(curLine); start = line.getStartOffset(); end = line.getEndOffset(); } // End of while (true). } // End of else. } // End of if (caretPosition>-1). } catch (BadLocationException ble) { // Shouldn't ever happen. ble.printStackTrace(); } // Something went wrong... return -1; }