diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java
index 73c68fc3296..b18cc4b595b 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/template/c/CFormatter.java
@@ -31,6 +31,7 @@ import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.jface.text.source.LineRange;
import org.eclipse.jface.text.templates.DocumentTemplateContext;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.TemplateBuffer;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateVariable;
@@ -95,7 +96,7 @@ public class CFormatter {
VariableTracker tracker= new VariableTracker(buffer);
IDocument document= tracker.getDocument();
- internalFormat(document, context);
+ internalFormat(document, context, buffer);
convertLineDelimiters(document);
convertTabs(document);
if (isReplacedAreaEmpty(context))
@@ -110,21 +111,21 @@ public class CFormatter {
/**
* @param document
* @param context
+ * @param buffer
* @throws BadLocationException
*/
- private void internalFormat(IDocument document, TemplateContext context) throws BadLocationException {
+ private void internalFormat(IDocument document, TemplateContext context, TemplateBuffer buffer) throws BadLocationException {
if (fUseCodeFormatter) {
// try to format and fall back to indenting
try {
format(document, (TranslationUnitContext) context);
+ return;
} catch (BadLocationException e) {
- indent(document);
} catch (MalformedTreeException e) {
- indent(document);
}
- } else {
- indent(document);
}
+ // fallback: indent
+ indent(document, buffer);
}
private void convertLineDelimiters(IDocument document) throws BadLocationException {
@@ -182,11 +183,17 @@ public class CFormatter {
}
private void trimStart(IDocument document) throws BadLocationException {
- int i= 0;
- while ((i != document.getLength()) && Character.isWhitespace(document.getChar(i)))
+ trimAtOffset(0, document);
+ }
+
+ private String trimAtOffset(int offset, IDocument document) throws BadLocationException {
+ int i= offset;
+ while ((i < document.getLength()) && Character.isWhitespace(document.getChar(i)))
i++;
- document.replace(0, i, ""); //$NON-NLS-1$
+ String trim= document.get(offset, i - offset);
+ document.replace(offset, i - offset, ""); //$NON-NLS-1$
+ return trim;
}
private boolean isReplacedAreaEmpty(TemplateContext context) {
@@ -221,12 +228,56 @@ public class CFormatter {
edit.apply(doc, TextEdit.UPDATE_REGIONS);
}
- private void indent(IDocument document) throws BadLocationException, MalformedTreeException {
+ private void indent(IDocument document, TemplateBuffer buffer) throws BadLocationException, MalformedTreeException {
String indent = CodeFormatterUtil.createIndentString(fInitialIndentLevel, fProject);
+ prefixSelectionLines(document, buffer);
int lineCount= document.getNumberOfLines();
IndentUtil.indentLines(document, new LineRange(0, lineCount), indent);
}
+ /**
+ * Prefix each line of line_selection
substitutions with
+ * the prefix of the first line.
+ *
+ * @param document
+ * @param buffer
+ */
+ private void prefixSelectionLines(IDocument document, TemplateBuffer buffer) {
+ TemplateVariable[] variables= buffer.getVariables();
+ for (int i = 0; i < variables.length; i++) {
+ if (variables[i].getName().equals(GlobalTemplateVariables.LineSelection.NAME)) {
+ if (variables[i].getLength() > 0) {
+ final int tabWidth= CodeFormatterUtil.getTabWidth(fProject);
+ int delta= 0;
+ int[] offsets= variables[i].getOffsets();
+ for (int j= 0; j < offsets.length; j++) {
+ final int offset = offsets[j] + delta;
+ try {
+ int startLine= document.getLineOfOffset(offset);
+ int startOffset= document.getLineOffset(startLine);
+ int endLine= document.getLineOfOffset(offset+variables[i].getLength() - 1);
+ String prefix= document.get(startOffset, offset - startOffset);
+ String shift= trimAtOffset(offset, document);
+ delta -= shift.length();
+ if (shift.length() > 0 && startLine < endLine) {
+ int shiftWidth= IndentUtil.computeVisualLength(shift, tabWidth);
+ for (int line= startLine + 1; line <= endLine; ++line) {
+ delta -= IndentUtil.cutIndent(document, line, shiftWidth, tabWidth);
+ int lineOffset= document.getLineOffset(line);
+ document.replace(lineOffset, 0, prefix);
+ delta += prefix.length();
+ }
+ }
+ } catch (BadLocationException exc) {
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
/**
* Wraps a {@link TemplateBuffer} and tracks the variable offsets while changes to the buffer
* occur. Whitespace variables are also tracked.
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java
index d57404f180a..98c199d4fb0 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IndentUtil.java
@@ -219,6 +219,7 @@ public final class IndentUtil {
* @param line the line
* @param indent the indentation to insert
* @param commentlines
+ * @param relative
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0
* @throws BadLocationException on concurrent document modification
*/
@@ -239,18 +240,36 @@ public final class IndentUtil {
document.replace(insert, 0, indent.toString());
}
+ /**
+ * Cuts the visual equivalent of toDelete
characters out of the
+ * indentation of line line
in document
.
+ *
+ * @param document
+ * @param line
+ * @param shiftWidth
+ * @param tabWidth
+ * @return number of characters deleted
+ * @throws BadLocationException
+ */
+ public static int cutIndent(IDocument document, int line, int shiftWidth, int tabWidth) throws BadLocationException {
+ return cutIndent(document, line, shiftWidth, tabWidth, new boolean[1], 0, false);
+ }
+
/**
* Cuts the visual equivalent of toDelete
characters out of the
* indentation of line line
in document
. Leaves
- * leading comment signs alone.
+ * leading comment signs alone if desired.
*
* @param document the document
* @param line the line
* @param toDelete the number of space equivalents to delete.
+ * @param commentLines
+ * @param relative
* @param indentInsideLineComments option whether to indent inside line comments starting at column 0
+ * @return number of characters deleted
* @throws BadLocationException on concurrent document modification
*/
- private static void cutIndent(IDocument document, int line, int toDelete, int tabSize, boolean[] commentLines, int relative, boolean indentInsideLineComments) throws BadLocationException {
+ private static int cutIndent(IDocument document, int line, int toDelete, int tabSize, boolean[] commentLines, int relative, boolean indentInsideLineComments) throws BadLocationException {
IRegion region= document.getLineInformation(line);
int from= region.getOffset();
int endOffset= region.getOffset() + region.getLength();
@@ -276,7 +295,8 @@ public final class IndentUtil {
if (endOffset > to + 1 && document.get(to, 2).equals(SLASHES))
commentLines[relative]= true;
- document.replace(from, to - from, null);
+ document.replace(from, to - from, ""); //$NON-NLS-1$
+ return to - from;
}
/**
@@ -322,7 +342,7 @@ public final class IndentUtil {
* @param seq the string to measure
* @return the visual length of seq
*/
- private static int computeVisualLength(CharSequence seq, int tablen) {
+ public static int computeVisualLength(CharSequence seq, int tablen) {
int size= 0;
for (int i= 0; i < seq.length(); i++) {
@@ -597,4 +617,5 @@ public final class IndentUtil {
computed= new StringBuffer(previousIndent);
return computed.toString();
}
+
}