diff options
Diffstat (limited to 'src/Document.cxx')
-rw-r--r-- | src/Document.cxx | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 44e55671f..7e4b888fc 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -34,6 +34,8 @@ Document::Document() { enteredCount = 0; enteredReadOnlyCount = 0; tabInChars = 8; + indentInChars = 0; + useTabs = true; watchers = 0; lenWatchers = 0; } @@ -501,26 +503,76 @@ int Document::DelCharBack(int pos) { } } -void Document::Indent(bool forwards, int lineBottom, int lineTop) { - if (forwards) { - // Indent by a tab - for (int line = lineBottom; line >= lineTop; line--) { - InsertChar(LineStart(line), '\t'); +static bool isindentchar(char ch) { + return (ch == ' ') || (ch == '\t'); +} + +static int NextTab(int pos, int tabSize) { + return ((pos / tabSize) + 1) * tabSize; +} + +static void CreateIndentation(char *linebuf, int length, int indent, int tabSize, bool insertSpaces) { + length--; // ensure space for \0 + if (!insertSpaces) { + while ((indent >= tabSize) && (length > 0)) { + *linebuf++ = '\t'; + indent -= tabSize; + length--; } - } else { - // Dedent - suck white space off the front of the line to dedent by equivalent of a tab - for (int line = lineBottom; line >= lineTop; line--) { - int ispc = 0; - while (ispc < tabInChars && cb.CharAt(LineStart(line) + ispc) == ' ') - ispc++; - int posStartLine = LineStart(line); - if (ispc == tabInChars) { - DeleteChars(posStartLine, ispc); - } else if (cb.CharAt(posStartLine + ispc) == '\t') { - DeleteChars(posStartLine, ispc + 1); - } else { // Hit a non-white - DeleteChars(posStartLine, ispc); - } + } + while ((indent > 0) && (length > 0)) { + *linebuf++ = ' '; + indent--; + length--; + } + *linebuf = '\0'; +} + +int Document::GetLineIndentation(int line) { + int indent = 0; + if (line >= 0) { + int lineStart = LineStart(line); + int length = Length(); + for (int i=lineStart;i<length;i++) { + char ch = cb.CharAt(i); + if (ch == ' ') + indent++; + else if (ch == '\t') + indent = NextTab(indent, tabInChars); + else + return indent; + } + } + return indent; +} + +int Document::GetLineIndentPosition(int line) { + int pos = LineStart(line); + int length = Length(); + while ((pos < length) && isindentchar(cb.CharAt(pos))) { + pos++; + } + return pos; +} + +void Document::Indent(bool forwards, int lineBottom, int lineTop) { + char linebuf[1000]; + // Dedent - suck white space off the front of the line to dedent by equivalent of a tab + for (int line = lineBottom; line >= lineTop; line--) { + int indentOfLine = GetLineIndentation(line); + int indentNew = indentOfLine; + if (forwards) + indentNew += IndentSize(); + else + indentNew -= IndentSize(); + if (indentNew < 0) + indentNew = 0; + if (indentNew != indentOfLine) { + CreateIndentation(linebuf, sizeof(linebuf), indentNew, tabInChars, !useTabs); + int thisLineStart = LineStart(line); + int indentPos = GetLineIndentPosition(line); + DeleteChars(thisLineStart, indentPos - thisLineStart); + InsertString(thisLineStart, linebuf); } } } |