| 0: | // Indent.cs | |
| 1: | // Copyright (c) 2000 Mike Krueger | |
| 2: | // | |
| 3: | // This program is free software; you can redistribute it and/or modify | |
| 4: | // it under the terms of the GNU General Public License as published by | |
| 5: | // the Free Software Foundation; either version 2 of the License, or | |
| 6: | // (at your option) any later version. | |
| 7: | // | |
| 8: | // This program is distributed in the hope that it will be useful, | |
| 9: | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10: | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11: | // GNU General Public License for more details. | |
| 12: | // | |
| 13: | // You should have received a copy of the GNU General Public License | |
| 14: | // along with this program; if not, write to the Free Software | |
| 15: | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 16: | ||
| 17: | using System; | |
| 18: | using System.Collections; | |
| 19: | using System.Drawing; | |
| 20: | using System.Text; | |
| 21: | ||
| 22: | using SharpDevelop.Tool.Data; | |
| 23: | ||
| 24: | namespace SharpDevelop.Internal.Text { | |
| 25: | ||
| 26: | /// <summary> | |
| 27: | /// This class handles the auto and smart indenting in the textbuffer while | |
| 28: | /// you type. | |
| 29: | /// </summary> | |
| 30: | public class Indent | |
| 31: | { | |
| 32: | public static Point SearchBracketBackward(Point start, TextBuffer buffer, char openingBracket, char closingBracket) | |
| 33: | { | |
| 34: | int brackets = -1; | |
| 35: | for (int y = start.Y ; y >= 0; --y) | |
| 36: | for (int x = (y == start.Y) ? start.X - 1 : buffer[y].Text.Length - 1; x >= 0; --x) { | |
| 37: | char ch = buffer[y].Text[x]; | |
| 38: | if (ch == closingBracket) { | |
| 39: | --brackets; | |
| 40: | } else if (ch == openingBracket) { | |
| 41: | ++brackets; | |
| 42: | if (brackets == 0) | |
| 43: | return new Point(x, y); | |
| 44: | } | |
| 45: | } | |
| 46: | return new Point(-1, -1); | |
| 47: | } | |
| 48: | ||
| 49: | public static Point SearchBracketForward(Point start, TextBuffer buffer, char openingBracket, char closingBracket) | |
| 50: | { | |
| 51: | int brackets = 1; | |
| 52: | for (int y = start.Y ; y < buffer.Length; ++y) | |
| 53: | for (int x = (y == start.Y) ? start.X + 1 : 0; x < buffer[y].Text.Length; ++x) { | |
| 54: | char ch = buffer[y].Text[x]; | |
| 55: | if (ch == openingBracket) { | |
| 56: | ++brackets; | |
| 57: | } else if (ch == closingBracket) { | |
| 58: | --brackets; | |
| 59: | if (brackets == 0) { | |
| 60: | return new Point(x, y); | |
| 61: | } | |
| 62: | } | |
| 63: | } | |
| 64: | return new Point(-1, -1); | |
| 65: | } | |
| 66: | ||
| 67: | /// <summary> | |
| 68: | /// returns the whitespaces which are before a non white space character in the line line | |
| 69: | /// as a string. | |
| 70: | /// </summary> | |
| 71: | static string GetIndentation(TextBuffer buffer, int line) | |
| 72: | { | |
| 73: | StringBuilder whitespaces = new StringBuilder(); | |
| 74: | foreach (char ch in buffer[line].Text) { | |
| 75: | if (Char.IsWhiteSpace(ch)) { | |
| 76: | whitespaces.Append(ch); | |
| 77: | } else { | |
| 78: | break; | |
| 79: | } | |
| 80: | } | |
| 81: | return whitespaces.ToString(); | |
| 82: | } | |
| 83: | ||
| 84: | /// <summary> | |
| 85: | /// This function sets the indentlevel in buffer in the line line. It returns the | |
| 86: | /// cursor position of the indenting; | |
| 87: | /// </summary> | |
| 88: | public static int IndentLine(TextBuffer buffer, int line, IndentStyle indentstyle) | |
| 89: | { | |
| 90: | switch (indentstyle) { | |
| 91: | case IndentStyle.None: | |
| 92: | break; | |
| 93: | case IndentStyle.Auto: | |
| 94: | if (line > 0) { | |
| 95: | string indentation = GetIndentation(buffer, line - 1); | |
| 96: | buffer[line ].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 97: | return indentation.Length; | |
| 98: | } | |
| 99: | break; | |
| 100: | case IndentStyle.Smart: | |
| 101: | bool isCsharp = false; | |
| 102: | foreach (string ext in buffer.Syntax.Extensions) { | |
| 103: | isCsharp |= ext == ".cs"; | |
| 104: | } | |
| 105: | if (!isCsharp) { | |
| 106: | goto case IndentStyle.Auto; | |
| 107: | } | |
| 108: | if (line > 0) { | |
| 109: | string lineBefore = buffer[line - 1].Text.Trim(); | |
| 110: | ||
| 111: | if (lineBefore.EndsWith(")") && buffer[line].Text.Trim().StartsWith("{")) { | |
| 112: | string indentation = GetIndentation(buffer, line - 1); | |
| 113: | buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 114: | return indentation.Length; | |
| 115: | } else if (buffer[line].Text.Trim().StartsWith("}")) { // indent closing bracket. | |
| 116: | Point closingBracketPoint = SearchBracketBackward(new Point(0, line), buffer, '{', '}'); | |
| 117: | ||
| 118: | if (closingBracketPoint.Y == -1) { // no closing bracket found -> autoindent | |
| 119: | goto case IndentStyle.Auto; | |
| 120: | } | |
| 121: | ||
| 122: | string indentation = GetIndentation(buffer, closingBracketPoint.Y); | |
| 123: | ||
| 124: | ||
| 125: | buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 126: | ||
| 127: | return indentation.Length; | |
| 128: | // | |
| 129: | // Point closingBracketPoint = SearchBracketBackward(new Point(0, line), buffer, '{', '}'); | |
| 130: | // | |
| 131: | // if (closingBracketPoint.Y == -1) // no closing bracket found -> autoindent | |
| 132: | // goto case IndentStyle.Auto; | |
| 133: | // | |
| 134: | // string indentation = GetIndentation(buffer, closingBracketPoint.Y); | |
| 135: | // | |
| 136: | // buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 137: | // | |
| 138: | // return indentation.Length; | |
| 139: | } else if (lineBefore.EndsWith(";")) { // expression ended, reset to valid indent. | |
| 140: | Point closingBracketPoint = SearchBracketBackward(new Point(0, line), buffer, '{', '}'); | |
| 141: | ||
| 142: | if (closingBracketPoint.Y == -1) { // no closing bracket found -> autoindent | |
| 143: | goto case IndentStyle.Auto; | |
| 144: | } | |
| 145: | ||
| 146: | // special handling for switch statement formatting. | |
| 147: | if (buffer[closingBracketPoint.Y].Text.Trim().StartsWith("switch")) { | |
| 148: | string indentation2 = GetIndentation(buffer, closingBracketPoint.Y); | |
| 149: | ||
| 150: | ||
| 151: | if (lineBefore.StartsWith("break;") || | |
| 152: | lineBefore.StartsWith("goto") || | |
| 153: | lineBefore.StartsWith("return")) { | |
| 154: | ||
| 155: | indentation2 += "\t"; | |
| 156: | } else { | |
| 157: | indentation2 += "\t\t"; | |
| 158: | } | |
| 159: | ||
| 160: | buffer[line].SetText(line, indentation2 + buffer[line].Text.Trim()); | |
| 161: | return indentation2.Length; | |
| 162: | } | |
| 163: | ||
| 164: | string indentation = GetIndentation(buffer, closingBracketPoint.Y); | |
| 165: | ||
| 166: | indentation += "\t"; | |
| 167: | ||
| 168: | buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 169: | ||
| 170: | return indentation.Length; | |
| 171: | } else | |
| 172: | if (lineBefore.EndsWith("{") || // indent opening bracket. | |
| 173: | lineBefore.EndsWith(":") || // indent case xyz: | |
| 174: | ||
| 175: | (lineBefore.EndsWith(")") && // indent single line if, for ... etc | |
| 176: | (lineBefore.StartsWith("if") || | |
| 177: | lineBefore.StartsWith("while") || | |
| 178: | lineBefore.StartsWith("for"))) || | |
| 179: | lineBefore.EndsWith("else")) { | |
| 180: | ||
| 181: | string indentation = GetIndentation(buffer, line - 1); | |
| 182: | int length = lineBefore.Length; | |
| 183: | ||
| 184: | indentation += "\t"; | |
| 185: | ||
| 186: | buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 187: | ||
| 188: | return indentation.Length; | |
| 189: | } else { | |
| 190: | ||
| 191: | // try to indent linewrap | |
| 192: | ArrayList bracketPos = new ArrayList(); | |
| 193: | for (int i = 0; i < lineBefore.Length; ++i) { // search for a ( bracket that isn't closed | |
| 194: | switch (lineBefore[i]) { | |
| 195: | case '(': | |
| 196: | bracketPos.Add(i); | |
| 197: | break; | |
| 198: | case ')': | |
| 199: | if (bracketPos.Count > 0) { | |
| 200: | bracketPos.RemoveAt(bracketPos.Count - 1); | |
| 201: | } | |
| 202: | break; | |
| 203: | } | |
| 204: | } | |
| 205: | if (bracketPos.Count > 0) { | |
| 206: | int bracketIndex = (int)bracketPos[bracketPos.Count - 1]; | |
| 207: | string indentation = GetIndentation(buffer, line - 1); | |
| 208: | ||
| 209: | for (int i = 0; i <= bracketIndex; ++i) // insert enough spaces to match | |
| 210: | indentation += " "; // brace start in the next line | |
| 211: | ||
| 212: | buffer[line].SetText(line, indentation + buffer[line].Text.Trim()); | |
| 213: | ||
| 214: | return indentation.Length; | |
| 215: | } | |
| 216: | ||
| 217: | // no linewrap -> autoindent | |
| 218: | goto case IndentStyle.Auto; | |
| 219: | } | |
| 220: | } | |
| 221: | break; | |
| 222: | } | |
| 223: | return 0; // default -> no indenting | |
| 224: | } | |
| 225: | ||
| 226: | public static void IndentLines(TextBuffer buffer, int begin, int end, IndentStyle indentstyle) | |
| 227: | { | |
| 228: | buffer.BeginUpdate(); | |
| 229: | for (int i = begin; i <= end; ++i) | |
| 230: | IndentLine(buffer, i, indentstyle); | |
| 231: | buffer.UndoStack.UndoLast(end - begin + 1); | |
| 232: | buffer.EndUpdate(); | |
| 233: | } | |
| 234: | } | |
| 235: | } |
This page was automatically generated by SharpDevelop.