Java Code Examples for org.eclipse.jface.text.IDocument#getChar()

The following examples show how to use org.eclipse.jface.text.IDocument#getChar() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: WhitespaceHandler.java    From e4macs with Eclipse Public License 1.0 6 votes vote down vote up
/**
 * Count the whitespace to the left and right of offset, potentially counting over EOLs.
 * @param document
 * @param offset
 * @param dir
 * @param ignoreCR - count over EOLs if true
 * @return the whitespace count
 * @throws BadLocationException
 */
protected int countWS(IDocument document, int offset, int dir, boolean ignoreCR) throws BadLocationException {
	String eol = getLineDelimiter();
	int lineOff = offset;
	int off = offset;
	int lastOff = document.getLength(); // -1;	// n
	char c;
	while ((-1 < off && off < lastOff) && (c = document.getChar(off)) <= ' ') { 
		if (eol.indexOf(c) != -1) {
			if (!ignoreCR) {
				break;
			}
			// preserve the position past the last EOL
			lineOff = off + dir;
		}
		off = off + dir;
	}
	// if ignoreCR == true, then we're interested in complete blank lines only
	return Math.abs(offset - (ignoreCR ? lineOff : off));
}
 
Example 2
Source File: HackDefaultCharacterPairMatcher.java    From e4macs with Eclipse Public License 1.0 6 votes vote down vote up
protected IRegion performMatch(IDocument doc, int caretOffset) throws BadLocationException {
	final int charOffset= caretOffset - 1;
	final char prevChar= doc.getChar(Math.max(charOffset, 0));
	if (!fPairs.contains(prevChar)) return null;
	final boolean isForward= fPairs.isStartCharacter(prevChar);
	fAnchor= isForward ? ICharacterPairMatcher.LEFT : ICharacterPairMatcher.RIGHT;
	final int searchStartPosition= isForward ? caretOffset : caretOffset - 2;
	final int adjustedOffset= isForward ? charOffset : caretOffset;
	final String partition= TextUtilities.getContentType(doc, fPartitioning, charOffset, false);
	final DocumentPartitionAccessor partDoc= new DocumentPartitionAccessor(doc, fPartitioning, partition);
	int endOffset= findMatchingPeer(partDoc, prevChar, fPairs.getMatching(prevChar),
			isForward,  isForward ? doc.getLength() : -1,
			searchStartPosition);
	if (endOffset == -1) return null;
	final int adjustedEndOffset= isForward ? endOffset + 1: endOffset;
	if (adjustedEndOffset == adjustedOffset) return null;
	return new Region(Math.min(adjustedOffset, adjustedEndOffset),
			Math.abs(adjustedEndOffset - adjustedOffset));
}
 
Example 3
Source File: BracketInserter.java    From typescript.java with MIT License 6 votes vote down vote up
public ExitFlags doExit(LinkedModeModel model, VerifyEvent event, int offset, int length) {

			if (fSize == fStack.size() && !isMasked(offset)) {
				if (event.character == fExitCharacter) {
					BracketLevel level = (BracketLevel) fStack.peek();
					if (level.fFirstPosition.offset > offset || level.fSecondPosition.offset < offset)
						return null;
					if (level.fSecondPosition.offset == offset && length == 0)
						// don't enter the character if if its the closing peer
						return new ExitFlags(ILinkedModeListener.UPDATE_CARET, false);
				}
				// when entering an anonymous class between the parenthesis', we
				// don't want
				// to jump after the closing parenthesis when return is pressed
				if (event.character == SWT.CR && offset > 0) {
					IDocument document = getSourceViewer().getDocument();
					try {
						if (document.getChar(offset - 1) == '{')
							return new ExitFlags(ILinkedModeListener.EXIT_ALL, true);
					} catch (BadLocationException e) {
					}
				}
			}
			return null;
		}
 
Example 4
Source File: SexpHandler.java    From e4macs with Eclipse Public License 1.0 6 votes vote down vote up
/**
 * If a _ is not a word break character, see if the BreakIterator stopped on one
 * 
 * @param doc
 * @param pos
 * @return new offset if word moves past any _'s, else pos
 */
int checkUnder(IDocument doc, int pos) {
	int result = pos;
	try {
		if (!isUnder()) {
			char c = doc.getChar(pos);
			if (!isDot() || c != '.') {
				IRegion lineInfo = doc.getLineInformationOfOffset(pos);
				int p = pos;
				// if we're at or just moved over an _
				if (c == '_' || (--p >= lineInfo.getOffset() && doc.getChar(p) == '_')) {
					int end = (lineInfo.getOffset() + lineInfo.getLength()); 
					if (end > p) {
						Matcher matcher = getUnderMatcher();
						matcher.reset(doc.get(p, end - p));
						if (matcher.matches()) {
							result = p + matcher.end(1);
						}
					}
				}
			}
		}
	} catch (BadLocationException e) {
	}
	return result;
}
 
Example 5
Source File: ParameterContextInformation.java    From xtext-eclipse with Eclipse Public License 2.0 5 votes vote down vote up
protected int getCommentEnd(IDocument d, int pos, int end) throws BadLocationException {
	while (pos < end) {
		char curr= d.getChar(pos);
		pos++;
		if (curr == '*') {
			if (pos < end && d.getChar(pos) == '/') {
				return pos + 1;
			}
		}
	}
	return end;
}
 
Example 6
Source File: JavadocCompletionProposal.java    From eclipse.jdt.ls with Eclipse Public License 2.0 5 votes vote down vote up
private boolean hasEndJavadoc(IDocument document, int offset) throws BadLocationException {
	int pos = -1;
	while (offset < document.getLength()) {
		char c = document.getChar(offset);
		if (!Character.isWhitespace(c) && !(c == '*')) {
			pos = offset;
			break;
		}
		offset++;
	}
	if (document.getLength() >= pos + 2 && document.get(pos - 1, 2).equals("*/")) {
		return true;
	}
	return false;
}
 
Example 7
Source File: DocumentHelper.java    From tlaplus with MIT License 5 votes vote down vote up
/**
 * At a given position in text retrieves the region marking the word, starting at and ending after the current position 
 * @param document document
 * @param documentOffset offset (position of the cursor)
 * @param detector for identification of words 
 * @return a region expanded forward
 */
public static IRegion getRegionExpandedForwards(IDocument document, int documentOffset, IWordDetector detector)
{

    // Use string buffer to collect characters
    int charCounter = 0;
    while (true)
    {
        try
        {
            // Read character forward
            char c = document.getChar(++documentOffset);

            // This was the start of a word
            if (!detector.isWordPart(c))
                break;

            // Count character
            charCounter++;

        } catch (BadLocationException e)
        {

            // Document end reached, no word
            break;
        }
    }

    return new Region(documentOffset - charCounter, charCounter + 1);
}
 
Example 8
Source File: SmartSemicolonAutoEditStrategy.java    From Eclipse-Postfix-Code-Completion with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * From <code>position</code> to the left, eats any whitespace and then a pair of brackets
 * as used to declare an array return type like <pre>String [ ]</pre>.
 * The return value is either the position of the opening bracket or <code>position</code> if no
 * pair of brackets can be parsed.
 *
 * @param document the document being modified
 * @param position the first character position in <code>document</code> to be considered
 * @param partitioning the document partitioning
 * @return the smallest character position of bracket pair or <code>position</code>
 */
private static int eatBrackets(IDocument document, int position, String partitioning) {
	// accept array return type
	int pos= firstNonWhitespaceBackward(document, position, partitioning, -1);
	try {
		if (pos > 1 && document.getChar(pos) == ']') {
			pos= firstNonWhitespaceBackward(document, pos - 1, partitioning, -1);
			if (pos > 0 && document.getChar(pos) == '[')
				return pos;
		}
	} catch (BadLocationException e) {
		// won't happen
	}
	return position;
}
 
Example 9
Source File: TypeScriptAutoIndentStrategy.java    From typescript.java with MIT License 5 votes vote down vote up
private int getCommentEnd(IDocument d, int offset, int endOffset) throws BadLocationException {
	while (offset < endOffset) {
		char curr= d.getChar(offset);
		offset++;
		if (curr == '*') {
			if (offset < endOffset && d.getChar(offset) == '/') {
				return offset + 1;
			}
		}
	}
	return endOffset;
}
 
Example 10
Source File: DocumentSourceAppender.java    From xtext-eclipse with Eclipse Public License 2.0 5 votes vote down vote up
public int getIndentationLevelAtOffset(int offset, IDocument document, XtextResource resource) {
	try {
		if (offset <= 0)
			return 0;
		int currentOffset = offset - 1;
		char currentChr = document.getChar(currentOffset);
		int indentationOffset = 0;
		if(currentChr == '\n' || currentChr == '\r') {
			-- currentOffset;
			if(currentOffset < 0)
				return 0;
			currentChr = document.getChar(currentOffset);
		}
		while (currentChr != '\n' && currentChr != '\r' && currentOffset > 0) {
			if (Character.isWhitespace(currentChr))
				++indentationOffset;
			else
				indentationOffset = 0;
			--currentOffset;
			currentChr = document.getChar(currentOffset);
		}
		return indentationOffset / getIndentString(resource).length();
	} catch (BadLocationException e) {
		LOG.error("Error calculating indentation at offset", e);
	}
	return 0;
}
 
Example 11
Source File: SmartSemicolonAutoEditStrategy.java    From Eclipse-Postfix-Code-Completion with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Computes an insert position for an opening brace if <code>offset</code> maps to a position in
 * <code>document</code> that looks like being the RHS of an assignment or like an array definition.
 *
 * @param document the document being modified
 * @param line the current line under investigation
 * @param offset the offset of the caret position, relative to the line start.
 * @param partitioning the document partitioning
 * @return an insert position  relative to the line start if <code>line</code> looks like being an array initialization at <code>offset</code>, -1 otherwise
 */
private static int computeArrayInitializationPos(IDocument document, ITextSelection line, int offset, String partitioning) {
	// search backward while WS, find = (not != <= >= ==) in default partition
	int pos= offset + line.getOffset();

	if (pos == 0)
		return -1;

	int p= firstNonWhitespaceBackward(document, pos - 1, partitioning, -1);

	if (p == -1)
		return -1;

	try {

		char ch= document.getChar(p);
		if (ch != '=' && ch != ']')
			return -1;

		if (p == 0)
			return offset;

		p= firstNonWhitespaceBackward(document, p - 1, partitioning, -1);
		if (p == -1)
			return -1;

		ch= document.getChar(p);
		if (Character.isJavaIdentifierPart(ch) || ch == ']' || ch == '[')
			return offset;

	} catch (BadLocationException e) {
	}
	return -1;
}
 
Example 12
Source File: OrganizeImportsFixesUnused.java    From Pydev with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * 
 * This leaves a bit of a mess e.g. "import " or "from " for some later process to clean up.
 * 
 */
private void deleteImport(PySelection ps, MarkerAnnotationAndPosition markerInfo)
        throws BadLocationException, CoreException {
    IMarker marker = markerInfo.markerAnnotation.getMarker();

    Integer start = (Integer) marker.getAttribute(IMarker.CHAR_START);
    Integer end = (Integer) marker.getAttribute(IMarker.CHAR_END);
    IDocument doc = ps.getDoc();
    while (start > 0) {
        char c;
        try {
            c = doc.getChar(start - 1);
        } catch (Exception e) {
            break;
        }
        if (c == '\r' || c == '\n') {
            break;
        }
        if (Character.isWhitespace(c) || c == ',') {
            start--;
            continue;
        }
        break;
    }
    ps.setSelection(start, end);
    ps.deleteSelection();
}
 
Example 13
Source File: WhatCursorPosition.java    From e4macs with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * @see com.mulgasoft.emacsplus.commands.EmacsPlusNoEditHandler#transform(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.IDocument, org.eclipse.jface.text.ITextSelection, org.eclipse.core.commands.ExecutionEvent)
 */
@Override
protected int transform(ITextEditor editor, IDocument document, ITextSelection currentSelection,
		ExecutionEvent event) throws BadLocationException {
	
	String msg = null;
	
	int offset = getCursorOffset(editor,currentSelection);
	int docLen = document.getLength();
	IRegion line = document.getLineInformationOfOffset(offset); 

	if (offset >= docLen) {
		msg = String.format(EOB_POSITION, offset,docLen);
	} else {
		char curChar = document.getChar(offset);
		String sChar = "";	//$NON-NLS-1$
		int percent = new Float(((offset * 100) / docLen) + .5).intValue();

		if (offset == line.getOffset() + line.getLength()){
			String ld = document.getLineDelimiter(document.getLineOfOffset(offset));
			char[] points = ld.toCharArray();
			for (int i=0; i<points.length; i++) {
				sChar += normalizeChar(points[i]);
			}
			msg = String.format(EOL_POSITION, sChar,offset,docLen,percent);
		} else {

			int curCode = (int) curChar;
			sChar = (curChar <= ' ' ? normalizeChar(curChar) : String.valueOf(curChar));
			msg = String.format(CURSOR_POSITION, sChar, curCode, curCode, curCode, offset, docLen, percent);
		}
	}
	EmacsPlusUtils.showMessage(editor, msg, false);
	setCmdResult(new Integer(offset));
	return super.transform(editor, document, currentSelection, event);

}
 
Example 14
Source File: AnonymousTypeCompletionProposal.java    From eclipse.jdt.ls with Eclipse Public License 2.0 5 votes vote down vote up
public String updateReplacementString(IDocument document, int offset, ImportRewrite impRewrite) throws CoreException, BadLocationException {
	// Construct empty body for performance concern
	// See https://github.com/microsoft/language-server-protocol/issues/1032#issuecomment-648748013
	String newBody = fSnippetSupport ? "{\n\t${0}\n}" : "{\n\n}";

	StringBuilder buf = new StringBuilder("new A()"); //$NON-NLS-1$
	buf.append(newBody);
	// use the code formatter
	String lineDelim = TextUtilities.getDefaultLineDelimiter(document);
	final IJavaProject project = fCompilationUnit.getJavaProject();
	IRegion lineInfo = document.getLineInformationOfOffset(fReplacementOffset);
	Map<String, String> options = project != null ? project.getOptions(true) : JavaCore.getOptions();
	String replacementString = CodeFormatterUtil.format(CodeFormatter.K_EXPRESSION, buf.toString(), 0, lineDelim, options);
	int lineEndOffset = lineInfo.getOffset() + lineInfo.getLength();
	int p = offset;
	if (p < document.getLength()) {
		char ch = document.getChar(p);
		while (p < lineEndOffset) {
			if (ch == '(' || ch == ')' || ch == ';' || ch == ',') {
				break;
			}
			ch = document.getChar(++p);
		}
		if (ch != ';' && ch != ',' && ch != ')') {
			replacementString = replacementString + ';';
		}
	}
	int beginIndex = replacementString.indexOf('(');
	replacementString = replacementString.substring(beginIndex);
	return replacementString;
}
 
Example 15
Source File: SmartSemicolonAutoEditStrategy.java    From Eclipse-Postfix-Code-Completion with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Checks whether a character to be inserted is already present at the insert location (perhaps
 * separated by some whitespace from <code>position</code>.
 *
 * @param document the document we are working on
 * @param position the insert position of <code>ch</code>
 * @param ch the character to be inserted
 * @return <code>true</code> if <code>ch</code> is already present at <code>location</code>, <code>false</code> otherwise
 */
private boolean alreadyPresent(IDocument document, char ch, int position) {
	int pos= firstNonWhitespaceForward(document, position, fPartitioning, document.getLength());
	try {
		if (pos != -1 && document.getChar(pos) == ch)
			return true;
	} catch (BadLocationException e) {
	}

	return false;
}
 
Example 16
Source File: PyBackspace.java    From Pydev with Eclipse Public License 1.0 4 votes vote down vote up
/**
 *
 * @param ps
 * @throws BadLocationException
 */
private void eraseSingleChar(PySelection ps) throws BadLocationException {
    ICoreTextSelection textSelection = ps.getTextSelection();

    int replaceLength = 1;
    int replaceOffset = textSelection.getOffset() - replaceLength;
    IDocument doc = ps.getDoc();

    if (replaceOffset >= 0 && replaceOffset + replaceLength < doc.getLength()) {
        char c = doc.getChar(replaceOffset);
        if (c == '(' || c == '[' || c == '{') {
            //When removing a (, check if we have to delete the corresponding ) too.
            char peer = StringUtils.getPeer(c);
            if (replaceOffset + replaceLength < doc.getLength()) {
                char c2 = doc.getChar(replaceOffset + 1);
                if (c2 == peer) {
                    //Ok, there's a closing one right next to it, now, what we have to do is
                    //check if the user was actually removing that one because there's an opening
                    //one without a match.
                    //To do that, we go backwards in the document searching for an opening match and then
                    //search its match. If it's found, it means we can delete both, otherwise, this
                    //delete will make things correct.

                    //Create a matcher only matching this char
                    PythonPairMatcher pythonPairMatcher = new PythonPairMatcher(new char[] { c, peer });
                    int openingPeerOffset = pythonPairMatcher.searchForAnyOpeningPeer(replaceOffset, doc);
                    if (openingPeerOffset == -1) {
                        replaceLength += 1;
                    } else {
                        int closingPeerOffset = pythonPairMatcher.searchForClosingPeer(openingPeerOffset, c, peer,
                                doc);
                        if (closingPeerOffset != -1) {
                            //we have a match, so, things are balanced and we can delete the next
                            replaceLength += 1;
                        }
                    }
                }
            }

        } else if (c == '\'' || c == '"') {
            //when removing a ' or ", check if we have to delete another ' or " too.
            Tuple<String, String> beforeAndAfterMatchingChars = ps.getBeforeAndAfterMatchingChars(c);
            int matchesBefore = beforeAndAfterMatchingChars.o1.length();
            int matchesAfter = beforeAndAfterMatchingChars.o2.length();
            if (matchesBefore == 1 && matchesBefore == matchesAfter) {
                replaceLength += 1;
            }
        }
    }

    makeDelete(doc, replaceOffset, replaceLength);
}
 
Example 17
Source File: ImpexCommandContentAssistProcessor.java    From hybris-commerce-eclipse-plugin with Apache License 2.0 4 votes vote down vote up
private ICompletionProposal[] standardMethod(ITextViewer viewer, int offset, List<String> keywords, List<ICompletionProposal> autoCompProposals) {
	
	int index = offset - 1;
	StringBuffer prefix = new StringBuffer();
	IDocument document = viewer.getDocument();
			
	while (index > 0) {
		try {
			char prev = document.getChar(index);
			if (Character.isWhitespace(prev)) {
				break;
			}
			prefix.insert(0, prev);
			index--;
		}
		catch (BadLocationException ble) {
			Activator.getDefault().log("could not get char", ble);
		}
	}

	if (prefix.length() > 0) {
		String word = prefix.toString();
		// limit to attributes
		if (containsOpenBracket(word)) {
			autoCompProposals.addAll(addHeaderAttributes(word, offset));
		}
		for (String keyword : keywords) {
			if (keyword.toUpperCase(Locale.ENGLISH).startsWith(word.toUpperCase(Locale.ENGLISH)) && word.length() < keyword.length()) {
				autoCompProposals.add(new CompletionProposal(keyword + " ", index + 1, offset - (index + 1), keyword.length() + 1));
			}
		}
	}
	else {
		// propose header keywords
		proposeHeaderOperands(offset, document, autoCompProposals);
	}
	
	if (!autoCompProposals.isEmpty()) {
		return (ICompletionProposal[]) autoCompProposals.toArray(new ICompletionProposal[autoCompProposals.size()]);
	}
	return null;

}
 
Example 18
Source File: PydevConsoleQuickAssistProcessor.java    From Pydev with Eclipse Public License 1.0 4 votes vote down vote up
/**
 * Computes quick assists for the console.
 */
@Override
public ICompletionProposal[] computeQuickAssistProposals(IQuickAssistInvocationContext invocationContext) {
    ISourceViewer sourceViewer = invocationContext.getSourceViewer();
    List<ICompletionProposalHandle> props = new ArrayList<ICompletionProposalHandle>();
    if (sourceViewer instanceof ScriptConsoleViewer) {
        ScriptConsoleViewer viewer = (ScriptConsoleViewer) sourceViewer;

        //currently, only the assign quick assist is used
        AssistAssign assistAssign = new AssistAssign();

        ISelection selection = sourceViewer.getSelectionProvider().getSelection();
        if (selection instanceof ITextSelection) {
            PySelection ps = PySelectionFromEditor.createPySelectionFromEditor(sourceViewer,
                    (ITextSelection) selection);
            int offset = viewer.getCaretOffset();
            String commandLine = viewer.getCommandLine();

            //let's calculate the 1st line that is not a whitespace.
            if (assistAssign.isValid(ps.getSelLength(), commandLine, offset)) {
                int commandLineOffset = viewer.getCommandLineOffset();
                try {
                    IDocument doc = sourceViewer.getDocument();
                    while (true) {
                        if (commandLineOffset == doc.getLength() - 1) {
                            break;
                        }
                        char c = doc.getChar(commandLineOffset);
                        if (Character.isWhitespace(c)) {
                            commandLineOffset++;
                        } else {
                            break;
                        }
                    }
                    props.addAll(assistAssign.getProps(ps, SharedUiPlugin.getImageCache(), sourceViewer, offset,
                            commandLine, commandLineOffset));

                } catch (BadLocationException e) {
                    Log.log(e);
                }
            }
        }
    }
    return ConvertCompletionProposals
            .convertHandlesToProposals(props.toArray(new ICompletionProposalHandle[props.size()]));
}
 
Example 19
Source File: IndentUtil.java    From Eclipse-Postfix-Code-Completion with Eclipse Public License 1.0 4 votes vote down vote up
/**
 * Computes and returns the indentation for a javadoc line. The line
 * must be inside a javadoc comment.
 *
 * @param document the document
 * @param line the line in document
 * @param scanner the scanner
 * @param partition the comment partition
 * @return the indent, or <code>null</code> if not computable
 * @throws BadLocationException
 */
private static String computeJavadocIndent(IDocument document, int line, JavaHeuristicScanner scanner, ITypedRegion partition) throws BadLocationException {
	if (line == 0) // impossible - the first line is never inside a javadoc comment
		return null;

	// don't make any assumptions if the line does not start with \s*\* - it might be
	// commented out code, for which we don't want to change the indent
	final IRegion lineInfo= document.getLineInformation(line);
	final int lineStart= lineInfo.getOffset();
	final int lineLength= lineInfo.getLength();
	final int lineEnd= lineStart + lineLength;
	int nonWS= scanner.findNonWhitespaceForwardInAnyPartition(lineStart, lineEnd);
	if (nonWS == JavaHeuristicScanner.NOT_FOUND || document.getChar(nonWS) != '*') {
		if (nonWS == JavaHeuristicScanner.NOT_FOUND)
			return document.get(lineStart, lineLength);
		return document.get(lineStart, nonWS - lineStart);
	}

	// take the indent from the previous line and reuse
	IRegion previousLine= document.getLineInformation(line - 1);
	int previousLineStart= previousLine.getOffset();
	int previousLineLength= previousLine.getLength();
	int previousLineEnd= previousLineStart + previousLineLength;

	StringBuffer buf= new StringBuffer();
	int previousLineNonWS= scanner.findNonWhitespaceForwardInAnyPartition(previousLineStart, previousLineEnd);
	if (previousLineNonWS == JavaHeuristicScanner.NOT_FOUND || document.getChar(previousLineNonWS) != '*') {
		// align with the comment start if the previous line is not an asterix line
		previousLine= document.getLineInformationOfOffset(partition.getOffset());
		previousLineStart= previousLine.getOffset();
		previousLineLength= previousLine.getLength();
		previousLineEnd= previousLineStart + previousLineLength;
		previousLineNonWS= scanner.findNonWhitespaceForwardInAnyPartition(previousLineStart, previousLineEnd);
		if (previousLineNonWS == JavaHeuristicScanner.NOT_FOUND)
			previousLineNonWS= previousLineEnd;

		// add the initial space
		// TODO this may be controlled by a formatter preference in the future
		buf.append(' ');
	}

	String indentation= document.get(previousLineStart, previousLineNonWS - previousLineStart);
	buf.insert(0, indentation);
	return buf.toString();
}
 
Example 20
Source File: PyAutoIndentStrategy.java    From Pydev with Eclipse Public License 1.0 3 votes vote down vote up
/**
 * Returns the first offset greater than <code>offset</code> and smaller than
 * <code>end</code> whose character is not a space or tab character. If no such
 * offset is found, <code>end</code> is returned.
 *
 * @param document the document to search in
 * @param offset the offset at which searching start
 * @param end the offset at which searching stops
 * @return the offset in the specified range whose character is not a space or tab
 * @exception BadLocationException if position is an invalid range in the given document
 */
private int findEndOfWhiteSpace(IDocument document, int offset, int end) throws BadLocationException {
    while (offset < end) {
        char c = document.getChar(offset);
        if (c != ' ' && c != '\t') {
            return offset;
        }
        offset++;
    }
    return end;
}