blob: b9b9c6513b5e09fa1d0416815b03a2eca159c822 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2010, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin, Google
* Anton Leherbauer (Wind River Systems)
* Jeff Overbey (Actilon Consulting) - Trimmed to minimum for Photran
*******************************************************************************/
package org.eclipse.photran.internal.ui.editor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
/**
* Utility that indents a number of lines in a document.
*/
public final class IndentUtil {
private static final String SLASHES= "//"; //$NON-NLS-1$
/**
* Returns the visual length of a given <code>CharSequence</code> taking into
* account the visual tabulator length.
*
* @param seq the string to measure
* @return the visual length of <code>seq</code>
*/
public static int computeVisualLength(CharSequence seq, int tablen) {
int size= 0;
for (int i= 0; i < seq.length(); i++) {
char ch= seq.charAt(i);
if (ch == '\t') {
if (tablen != 0)
size += tablen - size % tablen;
// else: size stays the same
} else {
size++;
}
}
return size;
}
/**
* Returns the indentation of the line <code>line</code> in <code>document</code>.
* The returned string may contain pairs of leading slashes that are considered
* part of the indentation.
*
* @param document the document
* @param line the line
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @return the indentation of <code>line</code> in <code>document</code>
* @throws BadLocationException if the document is changed concurrently
*/
public static String getCurrentIndent(IDocument document, int line, boolean indentInsideLineComments) throws BadLocationException {
IRegion region= document.getLineInformation(line);
int from= region.getOffset();
int endOffset= region.getOffset() + region.getLength();
int to= from;
if (indentInsideLineComments) {
// go behind line comments
while (to < endOffset - 2 && document.get(to, 2).equals(SLASHES))
to += 2;
}
while (to < endOffset) {
char ch= document.getChar(to);
if (!Character.isWhitespace(ch))
break;
to++;
}
return document.get(from, to - from);
}
/**
* Extends the string with whitespace to match displayed width.
* @param prefix add to this string
* @param displayedWidth the desired display width
* @param tabWidth the configured tab width
* @param useSpaces whether to use spaces only
*/
public static String changePrefix(String prefix, int displayedWidth, int tabWidth, boolean useSpaces) {
int column = computeVisualLength(prefix, tabWidth);
if (column > displayedWidth) {
return prefix;
}
final StringBuilder buffer = new StringBuilder(prefix);
appendIndent(buffer, displayedWidth, tabWidth, useSpaces, column);
return buffer.toString();
}
/**
* Appends whitespace to given buffer such that its visual length equals the given width.
* @param buffer the buffer to add whitespace to
* @param width the desired visual indent width
* @param tabWidth the configured tab width
* @param useSpaces whether tabs should be substituted by spaces
* @param startColumn the column where to start measurement
* @return StringBuilder
*/
private static StringBuilder appendIndent(StringBuilder buffer, int width, int tabWidth, boolean useSpaces, int startColumn) {
assert tabWidth > 0;
int tabStop = startColumn - startColumn % tabWidth;
int tabs = useSpaces ? 0 : (width-tabStop) / tabWidth;
for (int i = 0; i < tabs; ++i) {
buffer.append('\t');
tabStop += tabWidth;
startColumn = tabStop;
}
int spaces = width - startColumn;
for (int i = 0; i < spaces; ++i) {
buffer.append(' ');
}
return buffer;
}
}