Updated Spanish translation
[anjuta-git-plugin.git] / plugins / editor / aneditor-indent.cxx
blob5fbddb9f06f472ee85548bef763090d8c9b47a76
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 aneditor-indent.cxx
4 Copyright (C) 2004 Naba Kumar
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "aneditor-priv.h"
23 void AnEditor::IndentationIncrease(){
24 CharacterRange crange = GetSelection();
25 if (crange.cpMin != crange.cpMax)
27 SendEditor (SCI_TAB);
28 return;
30 int line =SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
31 int indent =GetLineIndentation(line);
32 indent +=SendEditor(SCI_GETINDENT);
33 SetLineIndentation(line, indent);
36 void AnEditor::IndentationDecrease(){
37 CharacterRange crange = GetSelection();
38 if (crange.cpMin != crange.cpMax)
40 SendEditor (SCI_BACKTAB);
41 return;
43 int line =SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
44 int indent = GetLineIndentation(line);
45 indent -=SendEditor(SCI_GETINDENT);
46 if (indent < 0) indent = 0;
47 SetLineIndentation(line, indent);
50 void AnEditor::SetLineIndentation(int line, int indent) {
51 if (indent < 0)
52 return;
53 CharacterRange crange = GetSelection();
54 int posBefore = GetLineIndentPosition(line);
55 SendEditor(SCI_SETLINEINDENTATION, line, indent);
56 int posAfter = GetLineIndentPosition(line);
57 int posDifference = posAfter - posBefore;
58 if (posAfter > posBefore) {
59 // Move selection on
60 if (crange.cpMin >= posBefore) {
61 crange.cpMin += posDifference;
63 if (crange.cpMax >= posBefore) {
64 crange.cpMax += posDifference;
66 } else if (posAfter < posBefore) {
67 // Move selection back
68 if (crange.cpMin >= posAfter) {
69 if (crange.cpMin >= posBefore)
70 crange.cpMin += posDifference;
71 else
72 crange.cpMin = posAfter;
74 if (crange.cpMax >= posAfter) {
75 if (crange.cpMax >= posBefore)
76 crange.cpMax += posDifference;
77 else
78 crange.cpMax = posAfter;
81 SetSelection(crange.cpMin, crange.cpMax);
84 int AnEditor::GetLineIndentation(int line) {
85 return SendEditor(SCI_GETLINEINDENTATION, line);
88 int AnEditor::GetLineIndentPosition(int line) {
89 return SendEditor(SCI_GETLINEINDENTPOSITION, line);
92 bool AnEditor::RangeIsAllWhitespace(int start, int end) {
93 WindowAccessor acc(wEditor.GetID(), *props);
94 for (int i = start;i < end;i++) {
95 if ((acc[i] != ' ') && (acc[i] != '\t'))
96 return false;
98 return true;
101 #if 0
103 unsigned int AnEditor::GetLinePartsInStyle(int line, int style1, int style2,
104 SString sv[], int len) {
105 for (int i = 0; i < len; i++)
106 sv[i] = "";
107 WindowAccessor acc(wEditor.GetID(), *props);
108 SString s;
109 int part = 0;
110 int thisLineStart = SendEditor(SCI_POSITIONFROMLINE, line);
111 int nextLineStart = SendEditor(SCI_POSITIONFROMLINE, line + 1);
112 for (int pos = thisLineStart; pos < nextLineStart; pos++) {
113 if ((acc.StyleAt(pos) == style1) || (acc.StyleAt(pos) == style2)) {
114 char c[2];
115 c[0] = acc[pos];
116 c[1] = '\0';
117 s += c;
118 } else if (s.length() > 0) {
119 if (part < len) {
120 sv[part++] = s;
122 s = "";
125 if ((s.length() > 0) && (part < len)) {
126 sv[part++] = s;
128 return part;
131 static bool includes(const StyleAndWords &symbols, const SString value) {
132 if (symbols.words.length() == 0) {
133 return false;
134 } else if (IsAlphabetic(symbols.words[0])) {
135 // Set of symbols separated by spaces
136 size_t lenVal = value.length();
137 const char *symbol = symbols.words.c_str();
138 while (symbol) {
139 const char *symbolEnd = strchr(symbol, ' ');
140 size_t lenSymbol = strlen(symbol);
141 if (symbolEnd)
142 lenSymbol = symbolEnd - symbol;
143 if (lenSymbol == lenVal) {
144 if (strncmp(symbol, value.c_str(), lenSymbol) == 0) {
145 return true;
148 symbol = symbolEnd;
149 if (symbol)
150 symbol++;
152 } else {
153 // Set of individual characters. Only one character allowed for now
154 char ch = symbols.words[0];
155 return strchr(value.c_str(), ch) != 0;
157 return false;
160 #define ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
162 IndentationStatus AnEditor::GetIndentState(int line) {
163 // C like language indentation defined by braces and keywords
164 IndentationStatus indentState = isNone;
165 SString controlWords[20];
166 unsigned int parts = GetLinePartsInStyle(line, statementIndent.styleNumber,
167 -1, controlWords, ELEMENTS(controlWords));
168 for (unsigned int i = 0; i < parts; i++) {
169 if (includes(statementIndent, controlWords[i]))
170 indentState = isKeyWordStart;
172 // Braces override keywords
173 SString controlStrings[20];
174 parts = GetLinePartsInStyle(line, blockEnd.styleNumber,
175 -1, controlStrings, ELEMENTS(controlStrings));
176 for (unsigned int j = 0; j < parts; j++) {
177 if (includes(blockEnd, controlStrings[j]))
178 indentState = isBlockEnd;
179 if (includes(blockStart, controlStrings[j]))
180 indentState = isBlockStart;
182 return indentState;
185 int AnEditor::IndentOfBlockProper(int line) {
187 if (line < 0)
188 return 0;
190 int indentSize = SendEditor(SCI_GETINDENT);
191 int indentBlock = GetLineIndentation(line);
192 int minIndent = indentBlock;
193 int backLine = line;
195 IndentationStatus indentState = isNone;
196 if (statementIndent.IsEmpty() && blockStart.IsEmpty() && blockEnd.IsEmpty())
197 indentState = isBlockStart; // Don't bother searching backwards
199 int lineLimit = line - statementLookback;
200 if (lineLimit < 0)
201 lineLimit = 0;
202 bool noIndentFound = true;
203 while ((backLine >= lineLimit) && (indentState == 0)) {
204 indentState = GetIndentState(backLine);
205 if (indentState != 0) {
206 noIndentFound = false;
207 indentBlock = GetLineIndentation(backLine);
208 if (indentState == isBlockStart) {
209 if (!indentOpening)
210 indentBlock += indentSize;
212 if (indentState == isBlockEnd) {
213 if (indentClosing)
214 indentBlock -= indentSize;
215 if (indentBlock < 0)
216 indentBlock = 0;
218 if ((indentState == isKeyWordStart) && (backLine == line))
219 indentBlock += indentSize;
220 } else if (noIndentFound) {
221 int currentIndent = GetLineIndentation(backLine);
222 minIndent = MIN(minIndent, currentIndent);
224 backLine--;
226 if (noIndentFound && minIndent > 0)
227 indentBlock = minIndent;
228 return indentBlock;
231 int AnEditor::IndentOfBlock(int line) {
233 int backLine = line;
235 /* Find mismatched parenthesis */
236 if (lexLanguage == SCLEX_CPP) {
237 WindowAccessor acc(wEditor.GetID(), *props);
238 int currentPos = SendEditor(SCI_POSITIONFROMLINE, backLine + 1);
240 while (backLine >= 0) {
241 int thisLineStart = SendEditor(SCI_POSITIONFROMLINE, backLine);
242 int nextLineStart = currentPos;
243 // printf("Scanning at line: %d (%d)\n", backLine, currentPos);
245 int foundTerminator = false;
246 int pos;
247 for (pos = nextLineStart - 1; pos >= thisLineStart; pos--) {
249 // printf ("Style at %d = %d\n", pos, acc.StyleAt(pos));
251 if ((acc.StyleAt(pos) == 10)) {
252 char c[2];
253 c[0] = acc[pos];
254 c[1] = '\0';
255 // printf ("Looking at: \"%s\"\n", c);
256 if (includes(blockEnd, c) ||
257 includes(blockStart, c) ||
258 includes(statementEnd, c))
260 // printf ("Found block start/block end/statement end. Breaking\n");
261 foundTerminator = true;
262 break;
264 if (c[0] == '(' || c[0] == '[') {
265 int indentBlock = SendEditor(SCI_GETCOLUMN, pos) + 1;// - thisLineStart;
266 // printf ("Found Unmatched '(' at col: %d. Returning\n", indentBlock);
267 return indentBlock;
269 if (c[0] == ')' || c[0] == ']') {
270 int braceOpp;
271 int lineOpp;
272 braceOpp = SendEditor(SCI_BRACEMATCH, pos, 0);
273 // printf ("Brace opp. at %d\n", braceOpp);
274 if (braceOpp >= 0) {
275 currentPos = braceOpp - 1;
276 lineOpp = SendEditor (SCI_LINEFROMPOSITION,
277 braceOpp);
278 if (backLine != lineOpp) {
279 backLine = lineOpp;
280 // printf ("Jumping to line %d (%d)\n", backLine, currentPos);
281 break;
282 } else {
283 pos = currentPos;
285 } else {
286 foundTerminator = true;
287 break;
290 } else if ((acc.StyleAt(pos) == statementIndent.styleNumber) &&
291 (acc.StyleAt(pos+1) != statementIndent.styleNumber)) {
292 char buffer[128];
293 if (GetWordAtPosition (buffer, 128, pos)) {
294 if (includes (statementIndent, buffer)) {
295 printf ("Found keyword terminator before unmatched (\n");
296 foundTerminator = true;
297 break;
302 if (foundTerminator)
303 break;
304 if (pos < thisLineStart) {
305 backLine--;
306 currentPos = pos;
310 return IndentOfBlockProper(backLine);
312 #endif
314 void AnEditor::MaintainIndentation(char ch) {
315 int eolMode = SendEditor(SCI_GETEOLMODE);
316 int curLine = GetCurrentLineNumber();
317 int lastLine = curLine - 1;
318 int indentAmount = 0;
320 if (((eolMode == SC_EOL_CRLF || eolMode == SC_EOL_LF) && ch == '\n') ||
321 (eolMode == SC_EOL_CR && ch == '\r')) {
322 if (props->GetInt("indent.automatic")) {
323 while (lastLine >= 0 && GetLineLength(lastLine) == 0)
324 lastLine--;
326 if (lastLine >= 0) {
327 indentAmount = GetLineIndentation(lastLine);
329 if (indentAmount > 0) {
330 SetLineIndentation(curLine, indentAmount);
335 #if 0
336 void AnEditor::AutomaticIndentation(char ch) {
337 CharacterRange crange = GetSelection();
338 int selStart = crange.cpMin;
339 int curLine = GetCurrentLineNumber();
340 int thisLineStart = SendEditor(SCI_POSITIONFROMLINE, curLine);
341 int indentSize = SendEditor(SCI_GETINDENT);
343 if (blockEnd.IsSingleChar() && ch == blockEnd.words[0]) {
344 // Dedent maybe
345 if (!indentClosing) {
346 if (RangeIsAllWhitespace(thisLineStart, selStart - 1)) {
347 int indentBlock = IndentOfBlockProper(curLine - 1);
348 SetLineIndentation(curLine, indentBlock - indentSize);
351 } else if (!blockEnd.IsSingleChar() && (ch == ' ')) {
352 // Dedent maybe
353 if (!indentClosing && (GetIndentState(curLine) == isBlockEnd)) {}
354 } else if (ch == blockStart.words[0]) {
355 // Dedent maybe if first on line and previous line was starting keyword
356 if (!indentOpening &&
357 (GetIndentState(curLine - 1) == isKeyWordStart)) {
358 if (RangeIsAllWhitespace(thisLineStart, selStart - 1)) {
359 int indentBlock = IndentOfBlockProper(curLine - 1);
360 SetLineIndentation(curLine, indentBlock - indentSize);
363 } else if ((ch == '\r' || ch == '\n') && (selStart == thisLineStart)) {
364 // printf("New line block\n");
365 int indentBlock = IndentOfBlock(curLine - 1);
366 if (!indentClosing && !blockEnd.IsSingleChar()) {
367 // Dedent previous line maybe
369 SString controlWords[1];
370 // printf ("First if\n");
372 if (GetLinePartsInStyle(curLine-1, blockEnd.styleNumber,
373 -1, controlWords, ELEMENTS(controlWords))) {
374 // printf ("Second if\n");
375 if (includes(blockEnd, controlWords[0])) {
376 // printf ("Third if\n");
377 // Check if first keyword on line is an ender
378 SetLineIndentation(curLine-1,
379 IndentOfBlockProper(curLine-2)
380 - indentSize);
381 // Recalculate as may have changed previous line
382 indentBlock = IndentOfBlock(curLine - 1);
386 SetLineIndentation(curLine, indentBlock);
388 // Home cursor.
389 if (SendEditor (SCI_GETCOLUMN,
390 SendEditor(SCI_GETCURRENTPOS)) < indentBlock)
391 SendEditor (SCI_VCHOME);
393 } else if (lexLanguage == SCLEX_CPP) {
394 if ((ch == '\t')) {
396 int indentBlock = IndentOfBlock(curLine - 1);
397 int indentState = GetIndentState (curLine);
399 if (blockStart.IsSingleChar() && indentState == isBlockStart) {
400 if (!indentOpening) {
401 if (RangeIsAllWhitespace(thisLineStart, selStart - 1)) {
402 // int indentBlock = IndentOfBlockProper(curLine - 1);
403 SetLineIndentation(curLine, indentBlock - indentSize);
406 } else if (blockEnd.IsSingleChar() && indentState == isBlockEnd) {
407 if (!indentClosing) {
408 if (RangeIsAllWhitespace(thisLineStart, selStart - 1)) {
409 // int indentBlock = IndentOfBlockProper(curLine - 1);
410 SetLineIndentation(curLine, indentBlock - indentSize);
413 } else {
414 SetLineIndentation(curLine, indentBlock);
417 // Home cursor.
418 if (SendEditor (SCI_GETCOLUMN,
419 SendEditor(SCI_GETCURRENTPOS)) < indentBlock)
420 SendEditor (SCI_VCHOME);
424 #endif