Updated Spanish translation
[anjuta-git-plugin.git] / plugins / editor / aneditor.cxx
bloba2c9282149eb72024d8a0be1b1c31fc1ef375076
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 aneditor.cxx
4 Copyright (C) 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Most of the code stolen from SciTE and heavily modified.
22 * If code sections are later imported from SciTE, utmost care
23 * should be taken to ensure that it does not conflict with the present code.
26 #include "aneditor-priv.h"
28 #include <libanjuta/anjuta-debug.h>
30 static void lowerCaseString(char *s);
31 static AnEditor * aneditor_get(AnEditorID id);
33 gint on_aneditor_focus_in(GtkWidget* widget, gpointer * unused, AnEditor* ed);
34 gint on_aneditor_focus_out(GtkWidget* widget, gpointer * unused, AnEditor* ed);
36 static const char *extList[] = {
37 "", "x", "x.cpp", "x.cpp", "x.html", "x.xml", "x.js", "x.vbs", "x.mak", "x.java",
38 "x.lua", "x.py", "x.pl", "x.sql", "x.spec", "x.php3", "x.tex", "x.diff", "x.pas",
39 "x.cs", "x.properties", "x.conf", "x.bc", "x.adb", "x.lisp", "x.rb", ".m"
42 const AnEditorID ANE_ID_INVALID = G_MAXUINT;
43 AnEditorID AnEditor::focusedID = ANE_ID_INVALID;
45 AnEditor::AnEditor(PropSetFile* p) {
47 characterSet = 0;
48 language = "java";
49 lexLanguage = SCLEX_CPP;
51 indentSize = 8;
52 indentOpening = true;
53 indentClosing = true;
54 statementLookback = 10;
56 indentMaintain = true;
58 wrapLine = true;
59 isReadOnly = false;
60 fnEditor = 0;
61 ptrEditor = 0;
62 fnOutput = 0;
63 ptrOutput = 0;
64 tbVisible = false;
65 sbVisible = false;
66 tabVisible = false;
67 tabMultiLine = false;
68 visHeightTools = 0;
69 visHeightStatus = 0;
70 visHeightEditor = 1;
71 heightBar = 7;
73 heightOutput = 0;
75 allowMenuActions = true;
76 isDirty = false;
78 ptStartDrag.x = 0;
79 ptStartDrag.y = 0;
80 capturedMouse = false;
81 firstPropertiesRead = true;
82 splitVertical = false;
83 bufferedDraw = true;
84 bracesCheck = true;
85 bracesSloppy = false;
86 bracesStyle = 0;
87 braceCount = 0;
89 indentationWSVisible = true;
91 autoCompleteIgnoreCase = false;
92 callTipIgnoreCase = false;
93 autoCCausedByOnlyOne = false;
94 // startCalltipWord = 0;
96 // init calltips
97 SetCallTipDefaults( );
98 call_tip_node_queue = g_queue_new();
99 lastPos = 0;
101 autocompletion = NULL;
103 margin = false;
104 marginWidth = marginWidthDefault;
105 foldMargin = true;
106 foldMarginWidth = foldMarginWidthDefault;
107 lineNumbers = false;
108 lineNumbersWidth = lineNumbersWidthDefault;
109 usePalette = false;
111 accelGroup = NULL;
112 calltipShown = false;
113 debugTipOn = false;
115 fileName[0] = '\0';
116 props = p;
118 wEditor = scintilla_new();
119 g_object_ref (G_OBJECT (wEditor.GetID()));
120 gtk_object_sink (GTK_OBJECT (wEditor.GetID()));
121 scintilla_set_id(SCINTILLA(wEditor.GetID()), 0);
123 fnEditor = reinterpret_cast<SciFnDirect>(Platform::SendScintilla(
124 wEditor.GetID(), SCI_GETDIRECTFUNCTION, 0, 0));
126 ptrEditor = Platform::SendScintilla(wEditor.GetID(),
127 SCI_GETDIRECTPOINTER, 0, 0);
129 g_signal_connect(wEditor.GetID(), "sci-notify", G_CALLBACK(NotifySignal), this);
131 /* We will handle all accels ourself */
132 /* SendEditor(SCI_CLEARALLCMDKEYS); */
134 /*We have got our own popup menu */
135 SendEditor(SCI_USEPOPUP, false);
136 /* Set default editor mode */
137 SendEditor(SCI_SETEOLMODE, SC_EOL_LF);
139 #if 0
140 // Trap 'TAB' key for automatic indentation.
141 // SendEditor (SCI_ASSIGNCMDKEY, SCK_TAB, SCI_NULL);
142 g_signal_connect (wEditor.GetID(), "key-press-event",
143 G_CALLBACK (KeyPressEvent), this);
145 /* Register images to be used for autocomplete */
146 typedef struct {
147 SVNodeType type;
148 char **xpm_data;
149 } PixAndType;
150 PixAndType pix_list[] = {
151 { sv_none_t , sv_unknown_xpm }
152 , { sv_class_t, sv_class_xpm }
153 , { sv_struct_t, sv_struct_xpm }
154 , { sv_union_t, sv_struct_xpm }
155 , { sv_function_t, sv_function_xpm }
156 , { sv_macro_t, sv_macro_xpm }
157 , { sv_variable_t, sv_variable_xpm }
158 , { sv_private_func_t, sv_private_fun_xpm }
159 , { sv_private_var_t, sv_private_var_xpm }
160 , { sv_protected_func_t, sv_protected_fun_xpm }
161 , { sv_protected_var_t, sv_protected_var_xpm }
162 , { sv_public_func_t, sv_public_fun_xpm }
163 , { sv_public_var_t, sv_public_var_xpm }
165 for (guint i = 0; i < (sizeof(pix_list)/sizeof(pix_list[0])); ++i)
167 SendEditor(SCI_REGISTERIMAGE, (long) pix_list[i].type
168 , reinterpret_cast<long>(pix_list[i].xpm_data));
170 #endif
173 void AnEditor::SetParent(AnEditor *parent)
175 long pdoc = parent->SendEditor(SCI_GETDOCPOINTER, 0, 0);
176 SendEditor(SCI_SETDOCPOINTER, 0, pdoc);
179 #if 0
180 static SVNodeType
181 sv_get_node_type (TMTag *tag)
183 char access;
185 if (!tag || (tm_tag_file_t == tag->type))
186 return sv_none_t;
188 access = tag->atts.entry.access;
189 switch (tag->type)
191 case tm_tag_class_t:
192 return sv_class_t;
193 case tm_tag_struct_t:
194 return sv_struct_t;
195 case tm_tag_union_t:
196 return sv_union_t;
197 case tm_tag_function_t:
198 case tm_tag_prototype_t:
199 switch (access)
201 case TAG_ACCESS_PRIVATE:
202 return sv_private_func_t;
204 case TAG_ACCESS_PROTECTED:
205 return sv_protected_func_t;
207 case TAG_ACCESS_PUBLIC:
208 return sv_public_func_t;
210 default:
211 return sv_function_t;
213 case tm_tag_member_t:
214 switch (access)
216 case TAG_ACCESS_PRIVATE:
217 return sv_private_var_t;
219 case TAG_ACCESS_PROTECTED:
220 return sv_protected_var_t;
222 case TAG_ACCESS_PUBLIC:
223 return sv_public_var_t;
225 default:
226 return sv_variable_t;
229 case tm_tag_externvar_t:
230 case tm_tag_variable_t:
231 return sv_variable_t;
233 case tm_tag_macro_t:
234 case tm_tag_macro_with_arg_t:
235 return sv_macro_t;
237 default:
238 return sv_none_t;
243 #endif
245 void
246 AnEditor::SetAccelGroup(GtkAccelGroup* acl) {
247 accelGroup = acl;
250 AnEditor::~AnEditor() {
251 g_object_unref (G_OBJECT (wEditor.GetID()));
254 long AnEditor::SendEditor(unsigned int msg, unsigned long wParam, long lParam) {
255 return fnEditor(ptrEditor, msg, wParam, lParam);
258 long AnEditor::SendEditorString(unsigned int msg, unsigned long wParam, const char *s) {
259 return SendEditor(msg, wParam, reinterpret_cast<long>(s));
262 void AnEditor::ViewWhitespace(bool view) {
263 if (view && indentationWSVisible)
264 SendEditor(SCI_SETVIEWWS, SCWS_VISIBLEALWAYS);
265 else if (view)
266 SendEditor(SCI_SETVIEWWS, SCWS_VISIBLEAFTERINDENT);
267 else
268 SendEditor(SCI_SETVIEWWS, SCWS_INVISIBLE);
271 StyleAndWords AnEditor::GetStyleAndWords(const char *base) {
272 StyleAndWords sw;
273 SString fileNameForExtension = ExtensionFileName();
274 SString sAndW = props->GetNewExpand(base, fileNameForExtension.c_str());
275 sw.styleNumber = sAndW.value();
276 const char *space = strchr(sAndW.c_str(), ' ');
277 if (space)
278 sw.words = space + 1;
279 return sw;
282 void AnEditor::AssignKey(int key, int mods, int cmd) {
283 SendEditor(SCI_ASSIGNCMDKEY,
284 Platform::LongFromTwoShorts(static_cast<short>(key),
285 static_cast<short>(mods)), cmd);
288 void AnEditor::SetOverrideLanguage(int ID) {
289 overrideExtension = extList[ID - TE_LEXER_BASE];
292 int AnEditor::LengthDocument() {
293 return SendEditor(SCI_GETLENGTH);
296 int AnEditor::GetCaretInLine() {
297 int caret = SendEditor(SCI_GETCURRENTPOS);
298 int line = SendEditor(SCI_LINEFROMPOSITION, caret);
299 int lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
300 return caret - lineStart;
303 void AnEditor::GetLine(SString & text, int line) {
304 if (line < 0)
305 line = GetCurrentLineNumber();
306 int lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
307 int lineEnd = SendEditor(SCI_GETLINEENDPOSITION, line);
308 int len = lineEnd - lineStart + 1;
309 char *text_buffer = SString::StringAllocate (len);
310 GetRange(wEditor, lineStart, lineEnd, text_buffer);
311 text_buffer[len] = '\0';
312 text.attach(text_buffer, len);
315 int AnEditor::GetFullLine(SString & text, int line) {
316 int caret, lineStart, lineEnd;
317 if (line < 0)
319 line = GetCurrentLineNumber();
320 caret = GetCaretInLine();
321 lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
322 lineEnd = SendEditor(SCI_GETLINEENDPOSITION, line);
324 else
326 lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
327 lineEnd = SendEditor(SCI_GETLINEENDPOSITION, line);
328 caret = lineEnd - lineStart - 1;
330 int count = 25, current;
331 int len = lineEnd - lineStart + 1;
332 text.clear();
333 while(count)
336 char *text_buffer = SString::StringAllocate (len + text.length());
337 GetRange(wEditor, lineStart, lineEnd, text_buffer);
338 memcpy(text_buffer + len - 1, text.c_str(), text.length());
339 text_buffer[len + text.length()] = '\0';
340 text.attach(text_buffer, len + text.length());
342 current = caret;
343 while(current > 0)
345 if(text[current - 1] == ';' ||
346 text[current - 1] == '{' || text[current - 1] == '}')
348 return caret;
350 current--;
352 line--;
353 if(line < 0) break;
354 lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
355 lineEnd = SendEditor(SCI_GETLINEENDPOSITION, line);
356 len = lineEnd - lineStart;
357 caret += len;
358 len++;
359 count--;
361 text.clear();
362 return -1;
366 void AnEditor::GetRange(Window &win, int start, int end, char *text) {
367 TextRange tr;
368 tr.chrg.cpMin = start;
369 tr.chrg.cpMax = end;
370 tr.lpstrText = text;
371 Platform::SendScintilla(win.GetID(), SCI_GETTEXTRANGE, 0, reinterpret_cast<long>(&tr));
374 void AnEditor::GetRange(guint start, guint end, gchar *text, gboolean styled) {
375 TextRange tr;
376 tr.chrg.cpMin = start;
377 tr.chrg.cpMax = end;
378 tr.lpstrText = text;
379 if (styled)
380 SendEditor (SCI_GETSTYLEDTEXT, 0, reinterpret_cast<long>(&tr));
381 else
382 SendEditor (SCI_GETTEXTRANGE, 0, reinterpret_cast<long>(&tr));
385 #if 0
388 * Check if the given line is a preprocessor condition line.
389 * @return The kind of preprocessor condition (enum values).
391 int AnEditor::IsLinePreprocessorCondition(const char *line) {
392 const char *currChar = line;
393 char word[32];
394 int i = 0;
396 if (!currChar) {
397 return false;
399 while (isspacechar(*currChar) && *currChar) {
400 currChar++;
402 if (preprocessorSymbol && (*currChar == preprocessorSymbol)) {
403 currChar++;
404 while (isspacechar(*currChar) && *currChar) {
405 currChar++;
407 while (!isspacechar(*currChar) && *currChar) {
408 word[i++] = *currChar++;
410 word[i] = '\0';
411 if (preprocCondStart.InList(word)) {
412 return ppcStart;
414 if (preprocCondMiddle.InList(word)) {
415 return ppcMiddle;
417 if (preprocCondEnd.InList(word)) {
418 return ppcEnd;
421 return noPPC;
425 * Search a matching preprocessor condition line.
426 * @return @c true if the end condition are meet.
427 * Also set curLine to the line where one of these conditions is mmet.
429 bool AnEditor::FindMatchingPreprocessorCondition(
430 int &curLine, ///< Number of the line where to start the search
431 int direction, ///< Direction of search: 1 = forward, -1 = backward
432 int condEnd1, ///< First status of line for which the search is OK
433 int condEnd2) { ///< Second one
435 bool isInside = false;
436 SString line;
437 int status, level = 0;
438 int maxLines = SendEditor(SCI_GETLINECOUNT);
440 while (curLine < maxLines && curLine > 0 && !isInside) {
441 curLine += direction; // Increment or decrement
442 GetLine(line, curLine);
443 status = IsLinePreprocessorCondition(line.c_str());
445 if ((direction == 1 && status == ppcStart) || (direction == -1 && status == ppcEnd)) {
446 level++;
447 } else if (level > 0 && ((direction == 1 && status == ppcEnd) || (direction == -1 && status == ppcStart))) {
448 level--;
449 } else if (level == 0 && (status == condEnd1 || status == condEnd2)) {
450 isInside = true;
454 return isInside;
458 * Find if there is a preprocessor condition after or before the caret position,
459 * @return @c true if inside a preprocessor condition.
461 #ifdef __BORLANDC__
462 // Borland warns that isInside is assigned a value that is never used in this method.
463 // This is OK so turn off the warning just for this method.
464 #pragma warn -aus
465 #endif
466 bool AnEditor::FindMatchingPreprocCondPosition(
467 bool isForward, ///< @c true if search forward
468 int &mppcAtCaret, ///< Matching preproc. cond.: current position of caret
469 int &mppcMatch) { ///< Matching preproc. cond.: matching position
471 bool isInside = false;
472 int curLine;
473 SString line;
474 int status;
476 // Get current line
477 curLine = SendEditor(SCI_LINEFROMPOSITION, mppcAtCaret);
478 GetLine(line, curLine);
479 status = IsLinePreprocessorCondition(line.c_str());
481 switch (status) {
482 case ppcStart:
483 if (isForward) {
484 isInside = FindMatchingPreprocessorCondition(curLine, 1, ppcMiddle, ppcEnd);
485 } else {
486 mppcMatch = mppcAtCaret;
487 return true;
489 break;
490 case ppcMiddle:
491 if (isForward) {
492 isInside = FindMatchingPreprocessorCondition(curLine, 1, ppcMiddle, ppcEnd);
493 } else {
494 isInside = FindMatchingPreprocessorCondition(curLine, -1, ppcStart, ppcMiddle);
496 break;
497 case ppcEnd:
498 if (isForward) {
499 mppcMatch = mppcAtCaret;
500 return true;
501 } else {
502 isInside = FindMatchingPreprocessorCondition(curLine, -1, ppcStart, ppcMiddle);
504 break;
505 default: // Should be noPPC
507 if (isForward) {
508 isInside = FindMatchingPreprocessorCondition(curLine, 1, ppcMiddle, ppcEnd);
509 } else {
510 isInside = FindMatchingPreprocessorCondition(curLine, -1, ppcStart, ppcMiddle);
512 break;
515 if (isInside) {
516 mppcMatch = SendEditor(SCI_POSITIONFROMLINE, curLine);
518 return isInside;
520 #endif
522 #ifdef __BORLANDC__
523 #pragma warn .aus
524 #endif
527 * Find if there is a brace next to the caret, checking before caret first, then
528 * after caret. If brace found also find its matching brace.
529 * @return @c true if inside a bracket pair.
531 bool AnEditor::FindMatchingBracePosition(bool editor, int &braceAtCaret, int &braceOpposite, bool sloppy) {
532 bool isInside = false;
533 // Window &win = editor ? wEditor : wOutput;
534 Window &win = wEditor;
535 int bracesStyleCheck = editor ? bracesStyle : 0;
536 int caretPos = Platform::SendScintilla(win.GetID(), SCI_GETCURRENTPOS, 0, 0);
537 braceAtCaret = -1;
538 braceOpposite = -1;
539 char charBefore = '\0';
540 char styleBefore = '\0';
541 WindowAccessor acc(win.GetID(), *props);
542 if (caretPos > 0) {
543 charBefore = acc[caretPos - 1];
544 styleBefore = static_cast<char>(acc.StyleAt(caretPos - 1) & 31);
546 // Priority goes to character before caret
547 if (charBefore && strchr("[](){}", charBefore) &&
548 ((styleBefore == bracesStyleCheck) || (!bracesStyle))) {
549 braceAtCaret = caretPos - 1;
551 bool colonMode = false;
552 if (lexLanguage == SCLEX_PYTHON && ':' == charBefore) {
553 braceAtCaret = caretPos - 1;
554 colonMode = true;
556 bool isAfter = true;
557 if (sloppy && (braceAtCaret < 0)) {
558 // No brace found so check other side
559 char charAfter = acc[caretPos];
560 char styleAfter = static_cast<char>(acc.StyleAt(caretPos) & 31);
561 if (charAfter && strchr("[](){}", charAfter) && (styleAfter == bracesStyleCheck)) {
562 braceAtCaret = caretPos;
563 isAfter = false;
565 if (lexLanguage == SCLEX_PYTHON && ':' == charAfter) {
566 braceAtCaret = caretPos;
567 colonMode = true;
570 if (braceAtCaret >= 0) {
571 if (colonMode) {
572 int lineStart = Platform::SendScintilla(win.GetID(), SCI_LINEFROMPOSITION, braceAtCaret);
573 int lineMaxSubord = Platform::SendScintilla(win.GetID(), SCI_GETLASTCHILD, lineStart, -1);
574 braceOpposite = Platform::SendScintilla(win.GetID(), SCI_GETLINEENDPOSITION, lineMaxSubord);
575 } else {
576 braceOpposite = Platform::SendScintilla(win.GetID(), SCI_BRACEMATCH, braceAtCaret, 0);
578 if (braceOpposite > braceAtCaret) {
579 isInside = isAfter;
580 } else {
581 isInside = !isAfter;
584 return isInside;
587 void AnEditor::BraceMatch(bool editor) {
588 if (!bracesCheck)
589 return;
590 int braceAtCaret = -1;
591 int braceOpposite = -1;
592 FindMatchingBracePosition(editor, braceAtCaret, braceOpposite, bracesSloppy);
593 // Window &win = editor ? wEditor : wOutput;
594 Window &win = wEditor;
595 if ((braceAtCaret != -1) && (braceOpposite == -1)) {
596 Platform::SendScintilla(win.GetID(), SCI_BRACEBADLIGHT, braceAtCaret, 0);
597 SendEditor(SCI_SETHIGHLIGHTGUIDE, 0);
598 } else {
599 char chBrace = static_cast<char>(Platform::SendScintilla(
600 win.GetID(), SCI_GETCHARAT, braceAtCaret, 0));
601 Platform::SendScintilla(win.GetID(), SCI_BRACEHIGHLIGHT, braceAtCaret, braceOpposite);
602 int columnAtCaret = Platform::SendScintilla(win.GetID(), SCI_GETCOLUMN, braceAtCaret, 0);
603 int columnOpposite = Platform::SendScintilla(win.GetID(), SCI_GETCOLUMN, braceOpposite, 0);
604 if (chBrace == ':') {
605 int lineStart = Platform::SendScintilla(win.GetID(), SCI_LINEFROMPOSITION, braceAtCaret);
606 int indentPos = Platform::SendScintilla(win.GetID(), SCI_GETLINEINDENTPOSITION, lineStart, 0);
607 int indentPosNext = Platform::SendScintilla(win.GetID(), SCI_GETLINEINDENTPOSITION, lineStart + 1, 0);
608 columnAtCaret = Platform::SendScintilla(win.GetID(), SCI_GETCOLUMN, indentPos, 0);
609 int columnAtCaretNext = Platform::SendScintilla(win.GetID(), SCI_GETCOLUMN, indentPosNext, 0);
610 int indentSize = Platform::SendScintilla(win.GetID(), SCI_GETINDENT);
611 if (columnAtCaretNext - indentSize > 1)
612 columnAtCaret = columnAtCaretNext - indentSize;
613 //Platform::DebugPrintf(": %d %d %d\n", lineStart, indentPos, columnAtCaret);
614 if (columnOpposite == 0) // If the final line of the structure is empty
615 columnOpposite = columnAtCaret;
618 if (props->GetInt("highlight.indentation.guides"))
619 Platform::SendScintilla(win.GetID(), SCI_SETHIGHLIGHTGUIDE, Platform::Minimum(columnAtCaret, columnOpposite), 0);
623 CharacterRange AnEditor::GetSelection() {
624 CharacterRange crange;
625 crange.cpMin = SendEditor(SCI_GETSELECTIONSTART);
626 crange.cpMax = SendEditor(SCI_GETSELECTIONEND);
627 return crange;
630 void AnEditor::SetSelection(int anchor, int currentPos) {
631 SendEditor(SCI_SETSEL, anchor, currentPos);
634 bool AnEditor::iswordcharforsel(char ch) {
635 return !strchr("\t\n\r !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", ch);
638 void AnEditor::SelectionWord(char *word, int len) {
639 int lengthDoc = LengthDocument();
640 CharacterRange cr = GetSelection();
641 int selStart = cr.cpMin;
642 int selEnd = cr.cpMax;
643 if (selStart == selEnd) {
644 WindowAccessor acc(wEditor.GetID(), *props);
645 // Try and find a word at the caret
646 if (iswordcharforsel(acc[selStart])) {
647 while ((selStart > 0) && (iswordcharforsel(acc[selStart - 1])))
648 selStart--;
649 while ((selEnd < lengthDoc - 1) && (iswordcharforsel(acc[selEnd + 1])))
650 selEnd++;
651 if (selStart < selEnd)
652 selEnd++; // Because normal selections end one past
655 word[0] = '\0';
656 if ((selStart < selEnd) && ((selEnd - selStart + 1) < len)) {
657 GetRange(wEditor, selStart, selEnd, word);
661 void AnEditor::WordSelect() {
662 int lengthDoc = LengthDocument();
663 int selStart;
664 int selEnd;
666 selStart = selEnd = SendEditor(SCI_GETCURRENTPOS);
667 WindowAccessor acc(wEditor.GetID(), *props);
668 if (iswordcharforsel(acc[selStart])) {
669 while ((selStart > 0) && (iswordcharforsel(acc[selStart - 1])))
670 selStart--;
671 while ((selEnd < lengthDoc - 1) && (iswordcharforsel(acc[selEnd + 1])))
672 selEnd++;
673 if (selStart < selEnd)
674 selEnd++; // Because normal selections end one past
676 SetSelection(selStart, selEnd);
679 void AnEditor::LineSelect() {
680 int pos = SendEditor(SCI_GETCURRENTPOS);
681 int line = SendEditor(SCI_LINEFROMPOSITION, pos);
682 int lineStart = SendEditor(SCI_POSITIONFROMLINE, line);
683 int lineEnd = SendEditor(SCI_GETLINEENDPOSITION, line);
685 SetSelection(lineStart, lineEnd);
688 void AnEditor::SelectionIntoProperties() {
689 CharacterRange cr = GetSelection();
690 char currentSelection[1000];
691 if ((cr.cpMin < cr.cpMax) && ((cr.cpMax - cr.cpMin + 1) < static_cast<int>(sizeof(currentSelection)))) {
692 GetRange(wEditor, cr.cpMin, cr.cpMax, currentSelection);
693 int len = strlen(currentSelection);
694 if (len > 2 && iscntrl(currentSelection[len - 1]))
695 currentSelection[len - 1] = '\0';
696 if (len > 2 && iscntrl(currentSelection[len - 2]))
697 currentSelection[len - 2] = '\0';
698 props->Set("CurrentSelection", currentSelection);
700 char word[200];
701 SelectionWord(word, sizeof(word));
702 props->Set("CurrentWord", word);
705 long AnEditor::Find (long flags, char* findWhat) {
706 if (!findWhat) return -1;
707 TextToFind ft = {{0, 0}, 0, {0, 0}};
708 CharacterRange crange = GetSelection();
709 if (flags & ANEFIND_REVERSE_FLAG) {
710 ft.chrg.cpMin = crange.cpMin - 1;
711 ft.chrg.cpMax = 1;
712 } else {
713 ft.chrg.cpMin = crange.cpMax;
714 ft.chrg.cpMax = LengthDocument();
716 ft.lpstrText = findWhat;
717 ft.chrgText.cpMin = 0;
718 ft.chrgText.cpMax = 0;
719 int posFind = SendEditor(SCI_FINDTEXT, flags, reinterpret_cast<long>(&ft));
720 if (posFind >= 0) {
721 EnsureRangeVisible(ft.chrgText.cpMin, ft.chrgText.cpMax);
722 SetSelection(ft.chrgText.cpMin, ft.chrgText.cpMax);
724 return posFind;
727 void AnEditor::BookmarkToggle( int lineno ) {
728 if (lineno == -1)
729 lineno = GetCurrentLineNumber();
730 int state = SendEditor(SCI_MARKERGET, lineno);
731 if ( state & (1 << ANE_MARKER_BOOKMARK))
732 SendEditor(SCI_MARKERDELETE, lineno, ANE_MARKER_BOOKMARK);
733 else {
734 SendEditor(SCI_MARKERADD, lineno, ANE_MARKER_BOOKMARK);
738 void AnEditor::BookmarkFirst() {
739 int lineno = GetCurrentLineNumber();
740 int nextLine = SendEditor(SCI_MARKERNEXT, 0, 1 << ANE_MARKER_BOOKMARK);
741 if (nextLine < 0 || nextLine == lineno)
742 gdk_beep(); // how do I beep? -- like this ;-)
743 else {
744 SendEditor(SCI_ENSUREVISIBLE, nextLine);
745 SendEditor(SCI_GOTOLINE, nextLine);
749 void AnEditor::BookmarkPrev() {
750 int lineno = GetCurrentLineNumber();
751 int nextLine = SendEditor(SCI_MARKERPREVIOUS, lineno - 1, 1 << ANE_MARKER_BOOKMARK);
752 if (nextLine < 0 || nextLine == lineno) {
753 if(props->GetInt("editor.wrapbookmarks")) {
754 int nrOfLines = SendEditor(SCI_GETLINECOUNT, 0, 1 << ANE_MARKER_BOOKMARK);
755 int nextLine = SendEditor(SCI_MARKERPREVIOUS, nrOfLines, 1 << ANE_MARKER_BOOKMARK);
756 if (nextLine < 0 || nextLine == lineno) {
757 gdk_beep(); // how do I beep? -- like this ;-)
758 } else {
759 SendEditor(SCI_ENSUREVISIBLE, nextLine);
760 SendEditor(SCI_GOTOLINE, nextLine);
763 } else {
764 SendEditor(SCI_ENSUREVISIBLE, nextLine);
765 SendEditor(SCI_GOTOLINE, nextLine);
769 void AnEditor::BookmarkNext() {
770 int lineno = GetCurrentLineNumber();
771 int nextLine = SendEditor(SCI_MARKERNEXT, lineno + 1, 1 << ANE_MARKER_BOOKMARK);
772 if (nextLine < 0 || nextLine == lineno) {
773 if(props->GetInt("editor.wrapbookmarks")) {
774 int nextLine = SendEditor(SCI_MARKERNEXT, 0, 1 << ANE_MARKER_BOOKMARK);
775 if (nextLine < 0 || nextLine == lineno) {
776 gdk_beep(); // how do I beep? -- like this ;-)
777 } else {
778 SendEditor(SCI_ENSUREVISIBLE, nextLine);
779 SendEditor(SCI_GOTOLINE, nextLine);
782 } else {
783 SendEditor(SCI_ENSUREVISIBLE, nextLine);
784 SendEditor(SCI_GOTOLINE, nextLine);
788 void AnEditor::BookmarkLast() {
789 int lineno = GetCurrentLineNumber();
790 int nextLine = SendEditor(SCI_MARKERPREVIOUS,
791 SendEditor(SCI_GETLINECOUNT), 1 << ANE_MARKER_BOOKMARK);
792 if (nextLine < 0 || nextLine == lineno)
793 gdk_beep(); // how do I beep? -- like this ;-)
794 else {
795 SendEditor(SCI_ENSUREVISIBLE, nextLine);
796 SendEditor(SCI_GOTOLINE, nextLine);
800 void AnEditor::BookmarkClear() {
801 SendEditor(SCI_MARKERDELETEALL, ANE_MARKER_BOOKMARK);
804 bool AnEditor::GetCurrentWord(char* buffer, int length) {
805 SString linebuf;
806 GetLine(linebuf);
807 int current = GetCaretInLine();
808 return FindWordInRegion(buffer, length, linebuf, current);
811 bool AnEditor::StartBlockComment() {
812 SString fileNameForExtension = ExtensionFileName();
813 SString language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
814 SString base("comment.block.");
815 SString comment_at_line_start("comment.block.at.line.start.");
816 base += language;
817 comment_at_line_start += language;
818 SString comment = props->Get(base.c_str());
819 if (comment == "") { // user friendly error message box
820 //SString error("Block comment variable \"");
821 //error += base;
822 //error += "\" is not defined in SciTE *.properties!";
823 //WindowMessageBox(wEditor, error, MB_OK | MB_ICONWARNING);
824 return true;
826 comment += " ";
827 SString long_comment = comment;
828 char linebuf[1000];
829 size_t comment_length = comment.length();
830 size_t selectionStart = SendEditor(SCI_GETSELECTIONSTART);
831 size_t selectionEnd = SendEditor(SCI_GETSELECTIONEND);
832 size_t caretPosition = SendEditor(SCI_GETCURRENTPOS);
833 // checking if caret is located in _beginning_ of selected block
834 bool move_caret = caretPosition < selectionEnd;
835 int selStartLine = SendEditor(SCI_LINEFROMPOSITION, selectionStart);
836 int selEndLine = SendEditor(SCI_LINEFROMPOSITION, selectionEnd);
837 int lines = selEndLine - selStartLine;
838 size_t firstSelLineStart = SendEditor(SCI_POSITIONFROMLINE, selStartLine);
839 // "caret return" is part of the last selected line
840 if ((lines > 0) &&
841 (selectionEnd == static_cast<size_t>(SendEditor(SCI_POSITIONFROMLINE, selEndLine))))
842 selEndLine--;
843 SendEditor(SCI_BEGINUNDOACTION);
844 for (int i = selStartLine; i <= selEndLine; i++) {
845 int lineStart = SendEditor(SCI_POSITIONFROMLINE, i);
846 int lineIndent = lineStart;
847 int lineEnd = SendEditor(SCI_GETLINEENDPOSITION, i);
848 if (props->GetInt(comment_at_line_start.c_str())) {
849 GetRange(wEditor, lineIndent, lineEnd, linebuf);
850 } else {
851 lineIndent = GetLineIndentPosition(i);
852 GetRange(wEditor, lineIndent, lineEnd, linebuf);
854 // empty lines are not commented
855 if (strlen(linebuf) < 1)
856 continue;
857 if (memcmp(linebuf, comment.c_str(), comment_length - 1) == 0) {
858 if (memcmp(linebuf, long_comment.c_str(), comment_length) == 0) {
859 // removing comment with space after it
860 SendEditor(SCI_SETSEL, lineIndent, lineIndent + comment_length);
861 SendEditorString(SCI_REPLACESEL, 0, "");
862 if (i == selStartLine) // is this the first selected line?
863 selectionStart -= comment_length;
864 selectionEnd -= comment_length; // every iteration
865 continue;
866 } else {
867 // removing comment _without_ space
868 SendEditor(SCI_SETSEL, lineIndent, lineIndent + comment_length - 1);
869 SendEditorString(SCI_REPLACESEL, 0, "");
870 if (i == selStartLine) // is this the first selected line?
871 selectionStart -= (comment_length - 1);
872 selectionEnd -= (comment_length - 1); // every iteration
873 continue;
876 if (i == selStartLine) // is this the first selected line?
877 selectionStart += comment_length;
878 selectionEnd += comment_length; // every iteration
879 SendEditorString(SCI_INSERTTEXT, lineIndent, long_comment.c_str());
881 // after uncommenting selection may promote itself to the lines
882 // before the first initially selected line;
883 // another problem - if only comment symbol was selected;
884 if (selectionStart < firstSelLineStart) {
885 if (selectionStart >= selectionEnd - (comment_length - 1))
886 selectionEnd = firstSelLineStart;
887 selectionStart = firstSelLineStart;
889 if (move_caret) {
890 // moving caret to the beginning of selected block
891 SendEditor(SCI_GOTOPOS, selectionEnd);
892 SendEditor(SCI_SETCURRENTPOS, selectionStart);
893 } else {
894 SendEditor(SCI_SETSEL, selectionStart, selectionEnd);
896 SendEditor(SCI_ENDUNDOACTION);
897 return true;
900 // Return true if the selected zone can be commented
901 // Return false if it cannot be commented or has been uncommented
902 // BOX_COMMENT : box_stream = true STREAM_COMMENT : box_stream = false
903 // Uncomment if the selected zone or the cursor is inside the comment
905 bool AnEditor::CanBeCommented(bool box_stream) {
906 SString fileNameForExtension = ExtensionFileName();
907 SString language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
908 SString start_base("comment.box.start.");
909 SString middle_base("comment.box.middle.");
910 SString end_base("comment.box.end.");
911 SString white_space(" ");
912 start_base += language;
913 middle_base += language;
914 end_base += language;
915 SString start_comment = props->Get(start_base.c_str());
916 SString middle_cmt = props->Get(middle_base.c_str());
917 SString end_comment = props->Get(end_base.c_str());
918 start_comment += white_space;
919 middle_cmt += white_space;
920 white_space += end_comment;
921 end_comment = white_space;
922 size_t start_comment_length = start_comment.length();
923 size_t end_comment_length = end_comment.length();
924 size_t middle_cmt_length = middle_cmt.length();
925 SString start_base_stream ("comment.stream.start.");
926 start_base_stream += language;
927 SString end_base_stream ("comment.stream.end.");
928 end_base_stream += language;
929 SString end_comment_stream = props->Get(end_base_stream.c_str());
930 SString white_space_stream(" ");
931 //SString end_white_space_stream(" ");
932 SString start_comment_stream = props->Get(start_base_stream.c_str());
933 start_comment_stream += white_space_stream;
934 size_t start_comment_stream_length = start_comment_stream.length();
935 white_space_stream +=end_comment_stream;
936 end_comment_stream = white_space_stream ;
937 size_t end_comment_stream_length = end_comment_stream.length();
939 char linebuf[1000];
940 size_t selectionStart = SendEditor(SCI_GETSELECTIONSTART);
941 size_t selectionEnd = SendEditor(SCI_GETSELECTIONEND);
942 if (selectionStart == selectionEnd)
943 return FALSE;
944 int line = SendEditor(SCI_LINEFROMPOSITION, selectionStart);
945 if (line < 0)
946 return FALSE;
947 bool start1 = false, start2 = false;
948 bool end1 = false, end2 = false;
949 int lineEnd1;
950 if (box_stream)
951 lineEnd1 = selectionStart + start_comment_length;
952 else
953 lineEnd1 = selectionStart + start_comment_stream_length +1;
954 if (lineEnd1 > LengthDocument())
955 lineEnd1 = LengthDocument();
957 int lineStart1 = 0;
958 size_t start_cmt = 0, end_cmt = 0;
959 int index = 0;
960 // Find Backward StartComment
961 while (line >= 0 && start1 == false && end1 == false)
963 lineStart1 = SendEditor(SCI_POSITIONFROMLINE, line);
964 GetRange(wEditor, lineStart1, lineEnd1, linebuf);
966 for (index = lineEnd1-lineStart1; index >= 0; index--)
968 if (end1= ((end_comment_length > 1 && !memcmp(linebuf+index,
969 end_comment.c_str(), end_comment_length ))
970 || (end_comment_stream_length > 0 && !memcmp(linebuf+index,
971 end_comment_stream.c_str(), end_comment_stream_length))))
972 break;
973 if (start1=((start_comment_length > 1 && !memcmp(linebuf+index,
974 start_comment.c_str(), start_comment_length))
975 || (start_comment_stream_length > 0 && !memcmp(linebuf+index,
976 start_comment_stream.c_str(), start_comment_stream_length))))
977 break;
979 line --;
980 lineEnd1= SendEditor(SCI_GETLINEENDPOSITION, line);
982 start_cmt = index + lineStart1;
983 line = SendEditor(SCI_LINEFROMPOSITION, selectionEnd);
984 if (box_stream)
985 lineStart1 = selectionEnd - start_comment_length;
986 else
987 lineStart1 = selectionEnd - start_comment_stream_length;
988 int last_line = SendEditor(SCI_GETLINECOUNT);
989 // Find Forward EndComment
990 while (line <= last_line && start2 == false && end2 == false)
992 lineEnd1= SendEditor(SCI_GETLINEENDPOSITION, line);
993 GetRange(wEditor, lineStart1, lineEnd1, linebuf);
994 for (index = 0; index <= (lineEnd1-lineStart1); index++)
996 if (start2= ((start_comment_length > 1 && !memcmp(linebuf+index,
997 start_comment.c_str(), start_comment_length))
998 || (start_comment_stream_length > 0 && !memcmp(linebuf+index,
999 start_comment_stream.c_str(), start_comment_stream_length))))
1000 break;
1001 if (end2= ((end_comment_length > 1 && !memcmp(linebuf+index,
1002 end_comment.c_str(), end_comment_length ))
1003 || (end_comment_stream_length > 0 && !memcmp(linebuf+index,
1004 end_comment_stream.c_str(), end_comment_stream_length))))
1005 break;
1007 line ++;
1008 end_cmt = lineStart1 + index;
1009 lineStart1 = SendEditor(SCI_POSITIONFROMLINE, line);
1011 // Uncomment
1012 if(start1 || end2)
1014 if (start1 && end2)
1016 SendEditor(SCI_BEGINUNDOACTION);
1017 if (box_stream) // Box
1019 SendEditor(SCI_SETSEL, start_cmt, start_cmt +
1020 start_comment_length);
1021 end_cmt -= start_comment_length;
1023 else // Stream
1025 SendEditor(SCI_SETSEL, start_cmt, start_cmt +
1026 start_comment_stream_length);
1027 end_cmt -= start_comment_stream_length;
1029 SendEditorString(SCI_REPLACESEL, 0, "");
1030 line = SendEditor(SCI_LINEFROMPOSITION, start_cmt) + 1;
1031 last_line = SendEditor(SCI_LINEFROMPOSITION, end_cmt) ;
1032 for (int i = line; i < last_line; i++)
1034 int s = SendEditor(SCI_POSITIONFROMLINE, i);
1035 int e = SendEditor(SCI_GETLINEENDPOSITION, i);
1036 GetRange(wEditor, s, e, linebuf);
1037 if (!memcmp(linebuf, middle_cmt.c_str(), middle_cmt_length))
1039 SendEditor(SCI_SETSEL, s, s + middle_cmt_length);
1040 SendEditorString(SCI_REPLACESEL, 0, "");
1041 end_cmt -= middle_cmt_length;
1044 if (box_stream) // Box
1045 SendEditor(SCI_SETSEL, end_cmt, end_cmt + end_comment_length);
1046 else // Stream
1047 SendEditor(SCI_SETSEL, end_cmt, end_cmt + end_comment_stream_length);
1048 SendEditorString(SCI_REPLACESEL, 0, "");
1049 SendEditor(SCI_ENDUNDOACTION);
1051 return false;
1053 return true;
1057 bool AnEditor::StartBoxComment() {
1058 SString fileNameForExtension = ExtensionFileName();
1059 SString language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
1060 SString start_base("comment.box.start.");
1061 SString middle_base("comment.box.middle.");
1062 SString end_base("comment.box.end.");
1063 SString white_space(" ");
1064 start_base += language;
1065 middle_base += language;
1066 end_base += language;
1067 SString start_comment = props->Get(start_base.c_str());
1068 SString middle_comment = props->Get(middle_base.c_str());
1069 SString end_comment = props->Get(end_base.c_str());
1070 if (start_comment == "" || middle_comment == "" || end_comment == "") {
1071 //SString error("Box comment variables \"");
1072 //error += start_base;
1073 //error += "\", \"";
1074 //error += middle_base;
1075 //error += "\"\nand \"";
1076 //error += end_base;
1077 //error += "\" are not ";
1078 //error += "defined in SciTE *.properties!";
1079 //WindowMessageBox(wSciTE, error, MB_OK | MB_ICONWARNING);
1080 return true;
1082 start_comment += white_space;
1083 middle_comment += white_space;
1084 white_space += end_comment;
1085 end_comment = white_space;
1086 size_t start_comment_length = start_comment.length();
1087 size_t middle_comment_length = middle_comment.length();
1088 size_t selectionStart = SendEditor(SCI_GETSELECTIONSTART);
1089 size_t selectionEnd = SendEditor(SCI_GETSELECTIONEND);
1090 size_t caretPosition = SendEditor(SCI_GETCURRENTPOS);
1091 // checking if caret is located in _beginning_ of selected block
1092 bool move_caret = caretPosition < selectionEnd;
1093 size_t selStartLine = SendEditor(SCI_LINEFROMPOSITION, selectionStart);
1094 size_t selEndLine = SendEditor(SCI_LINEFROMPOSITION, selectionEnd);
1095 size_t lines = selEndLine - selStartLine;
1096 // "caret return" is part of the last selected line
1097 if ((lines > 0) && (
1098 selectionEnd == static_cast<size_t>(SendEditor(SCI_POSITIONFROMLINE, selEndLine)))) {
1099 selEndLine--;
1100 lines--;
1101 // get rid of CRLF problems
1102 selectionEnd = SendEditor(SCI_GETLINEENDPOSITION, selEndLine);
1104 // Comment , Uncomment or Do Nothing
1105 if (CanBeCommented(true))
1107 SendEditor(SCI_BEGINUNDOACTION);
1108 // first commented line (start_comment)
1109 int lineStart = SendEditor(SCI_POSITIONFROMLINE, selStartLine);
1110 SendEditorString(SCI_INSERTTEXT, lineStart, start_comment.c_str());
1111 selectionStart += start_comment_length;
1112 // lines between first and last commented lines (middle_comment)
1113 for (size_t i = selStartLine + 1; i <= selEndLine; i++) {
1114 lineStart = SendEditor(SCI_POSITIONFROMLINE, i);
1115 SendEditorString(SCI_INSERTTEXT, lineStart, middle_comment.c_str());
1116 selectionEnd += middle_comment_length;
1118 // last commented line (end_comment)
1119 int lineEnd = SendEditor(SCI_GETLINEENDPOSITION, selEndLine);
1120 if (lines > 0) {
1121 SendEditorString(SCI_INSERTTEXT, lineEnd, "\n");
1122 SendEditorString(SCI_INSERTTEXT, lineEnd + 1, (end_comment.c_str() + 1));
1123 } else {
1124 SendEditorString(SCI_INSERTTEXT, lineEnd, end_comment.c_str());
1126 selectionEnd += (start_comment_length);
1127 if (move_caret) {
1128 // moving caret to the beginning of selected block
1129 SendEditor(SCI_GOTOPOS, selectionEnd);
1130 SendEditor(SCI_SETCURRENTPOS, selectionStart);
1131 } else {
1132 SendEditor(SCI_SETSEL, selectionStart, selectionEnd);
1134 SendEditor(SCI_ENDUNDOACTION);
1136 return true;
1139 bool AnEditor::StartStreamComment() {
1140 SString fileNameForExtension = ExtensionFileName();
1141 SString language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
1142 SString start_base("comment.stream.start.");
1143 SString end_base("comment.stream.end.");
1144 SString white_space(" ");
1145 //SString end_white_space(" ");
1146 start_base += language;
1147 end_base += language;
1148 SString start_comment = props->Get(start_base.c_str());
1149 SString end_comment = props->Get(end_base.c_str());
1150 if (start_comment == "" || end_comment == "") {
1151 //SString error("Stream comment variables \"");
1152 //error += start_base;
1153 //error += "\" and \n\"";
1154 //error += end_base;
1155 //error += "\" are not ";
1156 //error += "defined in SciTE *.properties!";
1157 //WindowMessageBox(wSciTE, error, MB_OK | MB_ICONWARNING);
1158 return true;
1160 start_comment += white_space;
1161 white_space += end_comment;
1162 end_comment = white_space;
1163 size_t start_comment_length = start_comment.length();
1164 size_t selectionStart = SendEditor(SCI_GETSELECTIONSTART);
1165 size_t selectionEnd = SendEditor(SCI_GETSELECTIONEND);
1166 size_t caretPosition = SendEditor(SCI_GETCURRENTPOS);
1167 // checking if caret is located in _beginning_ of selected block
1168 bool move_caret = caretPosition < selectionEnd;
1169 // if there is no selection?
1170 if (selectionEnd - selectionStart <= 0) {
1171 int selLine = SendEditor(SCI_LINEFROMPOSITION, selectionStart);
1172 int lineIndent = GetLineIndentPosition(selLine);
1173 int lineEnd = SendEditor(SCI_GETLINEENDPOSITION, selLine);
1174 if (RangeIsAllWhitespace(lineIndent, lineEnd))
1175 return true; // we are not dealing with empty lines
1176 SString linebuf;
1177 GetLine(linebuf);
1178 int current = GetCaretInLine();
1179 // checking if we are not inside a word
1180 if (!wordCharacters.contains(linebuf[current]))
1181 return true; // caret is located _between_ words
1182 int startword = current;
1183 int endword = current;
1184 int start_counter = 0;
1185 int end_counter = 0;
1186 while (startword > 0 && wordCharacters.contains(linebuf[startword - 1])) {
1187 start_counter++;
1188 startword--;
1190 // checking _beginning_ of the word
1191 if (startword == current)
1192 return true; // caret is located _before_ a word
1193 while (linebuf[endword + 1] != '\0' && wordCharacters.contains(linebuf[endword + 1])) {
1194 end_counter++;
1195 endword++;
1197 selectionStart -= start_counter;
1198 selectionEnd += (end_counter + 1);
1200 // Comment , Uncomment or Do Nothing
1201 if (CanBeCommented(false))
1203 SendEditor(SCI_BEGINUNDOACTION);
1204 SendEditorString(SCI_INSERTTEXT, selectionStart, start_comment.c_str());
1205 selectionEnd += start_comment_length;
1206 selectionStart += start_comment_length;
1207 SendEditorString(SCI_INSERTTEXT, selectionEnd, end_comment.c_str());
1208 if (move_caret) {
1209 // moving caret to the beginning of selected block
1210 SendEditor(SCI_GOTOPOS, selectionEnd);
1211 SendEditor(SCI_SETCURRENTPOS, selectionStart);
1212 } else {
1213 SendEditor(SCI_SETSEL, selectionStart, selectionEnd);
1215 SendEditor(SCI_ENDUNDOACTION);
1217 return true;
1220 #if 0
1221 SString AnEditor::GetMode(SString language) {
1222 SString mode;
1223 if (strcmp(language.c_str(), "cpp") == 0)
1225 mode += " Mode: C;";
1226 if (props->GetInt("use.tabs"))
1227 mode += " indent-tabs-mode: t;";
1228 mode += " c-basic-offset: ";
1229 mode += g_strdup_printf("%d", props->GetInt("indent.size"));
1230 mode += "; tab-width: ";
1231 mode += g_strdup_printf("%d ", props->GetInt("tabsize"));
1233 //~ Other languages
1234 //~ .....
1235 return mode;
1238 /* Insert or Modify a Comment line
1239 giving File indent */
1240 bool AnEditor::InsertCustomIndent() {
1241 #define MAXBUF 1000
1243 SString fileNameForExtension = ExtensionFileName();
1244 SString language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
1245 SString start_box_base("comment.box.start.");
1246 start_box_base += language;
1247 SString start_stream_base("comment.stream.start.");
1248 start_stream_base += language;
1249 SString end_box_base("comment.box.end.");
1250 end_box_base += language;
1251 SString end_stream_base("comment.stream.end.");
1252 end_stream_base += language;
1253 SString start_box = props->Get(start_box_base.c_str());
1254 SString start_stream = props->Get(start_stream_base.c_str());
1255 SString end_box = props->Get(end_box_base.c_str());
1256 SString end_stream = props->Get(end_stream_base.c_str());
1257 SString mark("-*-");
1258 int text_length = SendEditor(SCI_GETTEXTLENGTH);
1259 char buf[MAXBUF];
1260 int bufmax = text_length < MAXBUF ? text_length : MAXBUF;
1262 GetRange(wEditor, 0, bufmax - 1, buf);
1264 bool start_comment = false;
1265 bool indent_comment = false;
1266 int end_indent_comment = 0;
1268 for (int index = 0; index < bufmax; index++)
1270 if (!start_comment)
1272 if (memcmp(buf+index, start_box.c_str(), start_box.length()) == 0)
1274 index += (start_box.length() - 1);
1275 start_comment = true;
1276 continue;
1278 if (memcmp(buf+index, start_stream.c_str(), start_stream.length()) == 0)
1280 index += (start_stream.length() - 1);
1281 start_comment = true;
1282 continue;
1284 if (buf[index] != ' ' && buf[index] != '\t' && buf[index] != '\n')
1285 break;
1287 else
1289 if (!indent_comment)
1291 if (buf[index] == ' ' || buf[index] == '\t' || buf[index] == '\n')
1292 continue;
1293 if (memcmp(buf+index, mark.c_str(), 3) == 0)
1295 index += 3;
1296 indent_comment = true;
1298 else
1299 break;
1301 else
1303 if (memcmp(buf+index, end_box.c_str(), end_box.length()) == 0)
1305 end_indent_comment = index + end_box.length() - 1;
1306 break;
1308 if (memcmp(buf+index, end_stream.c_str(), end_stream.length()) == 0)
1310 end_indent_comment = index + end_stream.length() - 1;
1311 break;
1316 SString mode = GetMode(language);
1317 if (mode.c_str() != "")
1319 SString comment ;
1320 comment += start_stream.c_str() ;
1321 comment += " ";
1322 comment += mark.c_str();
1323 comment += mode.c_str();
1324 comment += mark.c_str();
1325 comment += " ";
1326 comment += end_stream.c_str() ;
1328 if (indent_comment)
1330 SendEditor(SCI_SETSEL, 0, end_indent_comment + 1);
1331 SendEditorString(SCI_REPLACESEL, 0, comment.c_str());
1333 else
1335 comment += "\n\n";
1336 SendEditorString(SCI_INSERTTEXT, 0, comment.c_str());
1339 return TRUE;
1342 #endif
1345 * Return the length of the given line, not counting the EOL.
1347 int AnEditor::GetLineLength(int line) {
1348 return SendEditor(SCI_GETLINEENDPOSITION, line) - SendEditor(SCI_POSITIONFROMLINE, line);
1351 int AnEditor::GetCurrentLineNumber() {
1352 CharacterRange crange = GetSelection();
1353 int selStart = crange.cpMin;
1354 return SendEditor(SCI_LINEFROMPOSITION, selStart);
1357 int AnEditor::GetCurrentScrollPosition() {
1358 int lineDisplayTop = SendEditor(SCI_GETFIRSTVISIBLELINE);
1359 return SendEditor(SCI_DOCLINEFROMVISIBLE, lineDisplayTop);
1362 // Upon a character being added, AnEditor may decide to perform some action
1363 // such as displaying a completion list.
1364 void AnEditor::CharAdded(char ch) {
1365 CharacterRange crange = GetSelection();
1366 int selStart = crange.cpMin;
1367 int selEnd = crange.cpMax;
1368 if ((selEnd == selStart) && (selStart > 0)) {
1369 int style = SendEditor(SCI_GETSTYLEAT, selStart - 1, 0);
1370 if (style != 1) {
1371 if (SendEditor(SCI_CALLTIPACTIVE)) { // calltip is active
1372 if (ch == ')') { // close our calltip
1374 braceCount--;
1376 if (braceCount < 1) { // shutdown at all
1377 ShutDownCallTip();
1378 SendEditor(SCI_CALLTIPCANCEL);
1379 return;
1382 ResumeCallTip();
1383 } else if (ch == '(') { // a new calltip is encountered?...
1384 SaveCallTip();
1385 braceCount++;
1386 StartCallTip_new();
1387 } else {
1388 // here it is, we continue the calltip
1389 //ContinueCallTip();
1390 ContinueCallTip_new();
1392 } else if (SendEditor(SCI_AUTOCACTIVE)) { // word autocompletion
1393 if (ch == '(') {
1394 braceCount++;
1395 //StartCallTip();
1396 StartCallTip_new();
1397 } else if (ch == ')') {
1398 braceCount--;
1399 } else if (!wordCharacters.contains(ch)) {
1400 SendEditor(SCI_AUTOCCANCEL);
1401 if (autocompletion) {
1402 g_completion_free (autocompletion);
1403 autocompletion = NULL;
1405 } else if (autoCCausedByOnlyOne) {
1406 StartAutoCompleteWord(props->GetInt("autocompleteword.automatic"));
1407 } else {
1408 StartAutoCompleteWord(0);
1410 } else if (HandleXml(ch)) {
1411 // Handled in the routine
1413 else { // we don't have autocompetion nor calltip active
1414 if (autocompletion) {
1415 g_completion_free (autocompletion);
1416 autocompletion = NULL;
1418 if (ch == '(') {
1419 braceCount = 1;
1420 //StartCallTip();
1423 // check whether we have some left nodes in call_tip_node_queue: this
1424 // can happen if we hit the "down key" when calltip is active
1427 if ( g_queue_is_empty( call_tip_node_queue ) != TRUE )
1428 ShutDownCallTip();
1430 // ok, let's start a new calltip
1431 StartCallTip_new();
1432 } else {
1433 autoCCausedByOnlyOne = false;
1434 if (indentMaintain)
1435 MaintainIndentation(ch);
1437 else if (props->GetInt("indent.automatic"))
1438 AutomaticIndentation(ch);
1440 if (autoCompleteStartCharacters.contains(ch)) {
1441 StartAutoComplete();
1442 } else if (props->GetInt("autocompleteword.automatic") &&
1443 !StartAutoCompleteRecordsFields(ch) &&
1444 wordCharacters.contains(ch)) {
1446 StartAutoCompleteWord(props->GetInt("autocompleteword.automatic"));
1447 autoCCausedByOnlyOne = SendEditor(SCI_AUTOCACTIVE);
1456 * This routine will auto complete XML or HTML tags that are still open by closing them
1457 * @parm ch The characer we are dealing with, currently only works with the '/' character
1458 * @return True if handled, false otherwise
1460 bool AnEditor::HandleXml(char ch) {
1461 // We're looking for this char
1462 // Quit quickly if not found
1463 if (ch != '>') {
1464 return false;
1467 // This may make sense only in certain languages
1468 if (lexLanguage != SCLEX_HTML && lexLanguage != SCLEX_XML &&
1469 lexLanguage != SCLEX_ASP && lexLanguage != SCLEX_PHP) {
1470 return false;
1473 // If the user has turned us off, quit now.
1474 // Default is off
1475 SString value = props->GetExpanded("xml.auto.close.tags");
1476 if ((value.length() == 0) || (value == "0")) {
1477 return false;
1480 // Grab the last 512 characters or so
1481 int nCaret = SendEditor(SCI_GETCURRENTPOS);
1482 char sel[512];
1483 int nMin = nCaret - (sizeof(sel) - 1);
1484 if (nMin < 0) {
1485 nMin = 0;
1488 if (nCaret - nMin < 3) {
1489 return false; // Smallest tag is 3 characters ex. <p>
1491 GetRange(wEditor, nMin, nCaret, sel);
1492 sel[sizeof(sel) - 1] = '\0';
1494 if (sel[nCaret - nMin - 2] == '/') {
1495 // User typed something like "<br/>"
1496 return false;
1499 SString strFound = FindOpenXmlTag(sel, nCaret - nMin);
1501 if (strFound.length() > 0) {
1502 SendEditor(SCI_BEGINUNDOACTION);
1503 SString toInsert = "</";
1504 toInsert += strFound;
1505 toInsert += ">";
1506 SendEditorString(SCI_REPLACESEL, 0, toInsert.c_str());
1507 SetSelection(nCaret, nCaret);
1508 SendEditor(SCI_ENDUNDOACTION);
1509 return true;
1512 return false;
1515 /** Search backward through nSize bytes looking for a '<', then return the tag if any
1516 * @return The tag name
1518 SString AnEditor::FindOpenXmlTag(const char sel[], int nSize) {
1519 SString strRet = "";
1521 if (nSize < 3) {
1522 // Smallest tag is "<p>" which is 3 characters
1523 return strRet;
1525 const char* pBegin = &sel[0];
1526 const char* pCur = &sel[nSize - 1];
1528 pCur--; // Skip past the >
1529 while (pCur > pBegin) {
1530 if (*pCur == '<') {
1531 break;
1532 } else if (*pCur == '>') {
1533 break;
1535 --pCur;
1538 if (*pCur == '<') {
1539 pCur++;
1540 while (strchr(":_-.", *pCur) || isalnum(*pCur)) {
1541 strRet += *pCur;
1542 pCur++;
1546 // Return the tag name or ""
1547 return strRet;
1550 void AnEditor::GoMatchingBrace(bool select) {
1551 int braceAtCaret = -1;
1552 int braceOpposite = -1;
1553 bool isInside = FindMatchingBracePosition(true, braceAtCaret, braceOpposite, true);
1554 // Convert the character positions into caret positions based on whether
1555 // the caret position was inside or outside the braces.
1556 if (isInside) {
1557 if (braceOpposite > braceAtCaret) {
1558 braceAtCaret++;
1559 } else {
1560 braceOpposite++;
1562 } else { // Outside
1563 if (braceOpposite > braceAtCaret) {
1564 braceOpposite++;
1565 } else {
1566 braceAtCaret++;
1569 if (braceOpposite >= 0) {
1570 EnsureRangeVisible(braceOpposite, braceOpposite);
1571 if (select) {
1572 SetSelection(braceAtCaret, braceOpposite);
1573 } else {
1574 SetSelection(braceOpposite, braceOpposite);
1579 int ControlIDOfCommand(unsigned long wParam) {
1580 return wParam & 0xffff;
1583 long AnEditor::Command(int cmdID, long wParam, long lParam) {
1584 switch (cmdID) {
1586 case ANE_INSERTTEXT:
1587 SendEditor(SCI_INSERTTEXT,wParam,lParam);
1588 break;
1590 case ANE_GETBOOKMARK_POS:
1591 return GetBookmarkLine( wParam );
1592 break; /* pleonastico */
1594 case ANE_BOOKMARK_TOGGLE_LINE:
1595 BookmarkToggle( wParam );
1596 break;
1598 case ANE_UNDO:
1599 SendEditor(SCI_UNDO);
1600 break;
1602 case ANE_REDO:
1603 SendEditor(SCI_REDO);
1604 break;
1606 case ANE_CUT:
1607 SendEditor(SCI_CUT);
1608 break;
1610 case ANE_COPY:
1611 SendEditor(SCI_COPY);
1612 break;
1614 case ANE_PASTE:
1615 SendEditor(SCI_PASTE);
1616 break;
1618 case ANE_CLEAR:
1619 SendEditor(SCI_CLEAR);
1620 break;
1622 case ANE_SELECTALL:
1623 SendEditor(SCI_SELECTALL);
1624 break;
1626 case ANE_FIND:
1627 return Find (wParam, (char*) lParam);
1629 case ANE_GOTOLINE:
1630 SendEditor(SCI_GOTOLINE, wParam);
1631 break;
1633 case ANE_SETZOOM:
1634 SendEditor(SCI_SETZOOM, wParam);
1635 break;
1637 case ANE_MATCHBRACE:
1638 GoMatchingBrace(false);
1639 break;
1641 case ANE_SELECTBLOCK:
1642 SelectBlock();
1643 break;
1645 case ANE_SELECTTOBRACE:
1646 GoMatchingBrace(true);
1647 break;
1649 case ANE_GETBLOCKSTARTLINE:
1650 return GetBlockStartLine();
1652 case ANE_GETBLOCKENDLINE:
1653 return GetBlockEndLine();
1655 case ANE_GETCURRENTWORD:
1656 return GetCurrentWord((char*)wParam, (int)lParam);
1658 case ANE_SHOWCALLTIP:
1659 StartCallTip_new();
1660 break;
1662 case ANE_COMPLETECALLTIP:
1663 CompleteCallTip();
1664 break;
1666 case ANE_COMPLETE:
1667 StartAutoComplete();
1668 break;
1670 case ANE_COMPLETEWORD:
1671 StartAutoCompleteWord(false);
1672 break;
1674 case ANE_TOGGLE_FOLD:
1675 FoldToggle();
1676 break;
1678 case ANE_OPEN_FOLDALL:
1679 FoldOpenAll();
1680 break;
1682 case ANE_CLOSE_FOLDALL:
1683 FoldCloseAll();
1684 break;
1686 case ANE_UPRCASE:
1687 SendEditor(SCI_UPPERCASE);
1688 break;
1690 case ANE_LWRCASE:
1691 SendEditor(SCI_LOWERCASE);
1692 break;
1694 case ANE_EXPAND:
1695 SendEditor(SCI_TOGGLEFOLD, GetCurrentLineNumber());
1696 break;
1698 case ANE_LINENUMBERMARGIN:
1699 lineNumbers = wParam;
1700 SendEditor(SCI_SETMARGINWIDTHN, 0, lineNumbers ? lineNumbersWidth : 0);
1701 break;
1703 case ANE_SELMARGIN:
1704 margin = wParam;
1705 SendEditor(SCI_SETMARGINWIDTHN, 1, margin ? marginWidth : 0);
1706 break;
1708 case ANE_FOLDMARGIN:
1709 foldMargin = wParam;
1710 SendEditor(SCI_SETMARGINWIDTHN, 2, foldMargin ? foldMarginWidth : 0);
1711 break;
1713 case ANE_VIEWEOL:
1714 SendEditor(SCI_SETVIEWEOL, wParam);
1715 break;
1717 case ANE_EOL_CRLF:
1718 SendEditor(SCI_SETEOLMODE, SC_EOL_CRLF);
1719 break;
1721 case ANE_EOL_CR:
1722 SendEditor(SCI_SETEOLMODE, SC_EOL_CR);
1723 break;
1725 case ANE_EOL_LF:
1726 SendEditor(SCI_SETEOLMODE, SC_EOL_LF);
1727 break;
1729 case ANE_EOL_CONVERT:
1730 switch (wParam) {
1731 case ANE_EOL_CRLF:
1732 SendEditor(SCI_SETEOLMODE, SC_EOL_CRLF);
1733 SendEditor(SCI_CONVERTEOLS, SC_EOL_CRLF);
1734 break;
1735 case ANE_EOL_LF:
1736 SendEditor(SCI_SETEOLMODE, SC_EOL_LF);
1737 SendEditor(SCI_CONVERTEOLS, SC_EOL_LF);
1738 break;
1739 case ANE_EOL_CR:
1740 SendEditor(SCI_SETEOLMODE, SC_EOL_CR);
1741 SendEditor(SCI_CONVERTEOLS, SC_EOL_CR);
1742 break;
1743 default:
1744 SendEditor(SCI_CONVERTEOLS, SendEditor(SCI_GETEOLMODE));
1745 break;
1747 break;
1749 case ANE_WORDPARTLEFT:
1750 SendEditor(SCI_WORDPARTLEFT);
1751 break;
1753 case ANE_WORDPARTLEFTEXTEND:
1754 SendEditor(SCI_WORDPARTLEFTEXTEND);
1755 break;
1757 case ANE_WORDPARTRIGHT:
1758 SendEditor(SCI_WORDPARTRIGHT);
1759 break;
1761 case ANE_WORDPARTRIGHTEXTEND:
1762 SendEditor(SCI_WORDPARTRIGHTEXTEND);
1763 break;
1765 case ANE_VIEWSPACE:
1766 ViewWhitespace(wParam);
1767 break;
1769 case ANE_VIEWGUIDES:
1770 SendEditor(SCI_SETINDENTATIONGUIDES, wParam);
1771 break;
1773 case ANE_BOOKMARK_TOGGLE:
1774 BookmarkToggle();
1775 break;
1776 case ANE_BOOKMARK_FIRST:
1777 BookmarkFirst();
1778 break;
1779 case ANE_BOOKMARK_PREV:
1780 BookmarkPrev();
1781 break;
1782 case ANE_BOOKMARK_NEXT:
1783 BookmarkNext();
1784 break;
1785 case ANE_BOOKMARK_LAST:
1786 BookmarkLast();
1787 break;
1788 case ANE_BOOKMARK_CLEAR:
1789 BookmarkClear();
1790 break;
1792 case ANE_SETTABSIZE:
1793 SendEditor(SCI_SETTABWIDTH, wParam);
1794 break;
1796 case ANE_SETLANGUAGE:
1797 SetOverrideLanguage(wParam);
1798 break;
1800 case ANE_SETHILITE:
1801 ReadProperties((char*)wParam);
1802 SendEditor(SCI_COLOURISE, 0, -1);
1803 break;
1805 case ANE_SETACCELGROUP:
1806 SetAccelGroup((GtkAccelGroup*)wParam);
1807 break;
1809 case ANE_GETTEXTRANGE: {
1810 guint start, end;
1811 if(wParam == lParam) return 0;
1812 start = (guint) MINIMUM(wParam, lParam);
1813 end = (guint) MAXIMUM(wParam, lParam);
1814 gchar *buff = (gchar*) g_malloc(end-start+10);
1815 if(!buff) return 0;
1816 GetRange(start, end, buff, false);
1817 return (long) buff;
1819 break;
1821 case ANE_INDENT_INCREASE:
1822 IndentationIncrease();
1823 break;
1825 case ANE_INDENT_DECREASE:
1826 IndentationDecrease();
1827 break;
1829 case ANE_GETLENGTH:
1830 return SendEditor(SCI_GETLENGTH);
1832 case ANE_GET_LINENO:
1833 return GetCurrentLineNumber();
1835 case ANE_LINEWRAP:
1836 SetLineWrap((bool)wParam);
1837 break;
1839 case ANE_READONLY:
1840 SetReadOnly((bool)wParam);
1841 break;
1843 case ANE_GETSTYLEDTEXT: {
1844 guint start, end;
1845 if(wParam == lParam) return 0;
1846 start = (guint) MINIMUM(wParam, lParam);
1847 end = (guint) MAXIMUM(wParam, lParam);
1848 gchar *buff = (gchar*) g_malloc((end-start+10)*2);
1849 if(!buff) return 0;
1850 GetRange(start, end, buff, true);
1851 return (long) buff;
1853 break;
1854 case ANE_TEXTWIDTH:
1855 return SendEditor(SCI_TEXTWIDTH, wParam, lParam);
1856 case ANE_GETLANGUAGE:
1857 return (long) language.c_str();
1859 case ANE_BLOCKCOMMENT:
1860 return StartBlockComment();
1862 case ANE_BOXCOMMENT:
1863 return StartBoxComment();
1865 case ANE_STREAMCOMMENT:
1866 return StartStreamComment();
1868 case ANE_CUSTOMINDENT:
1869 return InsertCustomIndent();
1871 case ANE_WORDSELECT:
1872 WordSelect();
1873 break;
1875 case ANE_LINESELECT:
1876 LineSelect();
1877 break;
1879 case ANE_GETCURRENTPOS:
1880 return SendEditor(SCI_GETCURRENTPOS);
1882 case ANE_GOTOPOS:
1883 return SendEditor(SCI_GOTOPOS, wParam);
1885 case ANE_SETWRAPBOOKMARKS:
1886 // Nothing to do.
1887 break;
1889 case ANE_SETAUTOINDENTATION:
1890 // Nothing to do.
1891 break;
1893 case ANE_SETUSETABFORINDENT:
1894 SendEditor(SCI_SETUSETABS, wParam);
1895 break;
1897 case ANE_SETINDENTSIZE:
1898 indentSize = wParam;
1899 SendEditor(SCI_SETINDENT, wParam);
1900 break;
1902 case ANE_SETINDENTBRACESCHECK:
1903 bracesCheck = wParam;
1904 break;
1906 case ANE_SETINDENTOPENING:
1907 indentOpening = wParam;
1908 break;
1910 case ANE_SETINDENTCLOSING:
1911 indentClosing = wParam;
1912 break;
1914 case ANE_SETINDENTMAINTAIN:
1915 if (wParam)
1916 props->Set ("indent.maintain.*", "1");
1917 else
1918 props->Set ("indent.opening.*", "0");
1919 indentMaintain = wParam;
1920 break;
1922 case ANE_SETTABINDENTS:
1923 SendEditor(SCI_SETTABINDENTS, wParam);
1924 break;
1926 case ANE_SETBACKSPACEUNINDENTS:
1927 SendEditor(SCI_SETBACKSPACEUNINDENTS, wParam);
1928 break;
1930 case ANE_SETFOLDSYMBOLS:
1931 SetFoldSymbols(reinterpret_cast<char *> (wParam));
1932 break;
1934 case ANE_SETFOLDUNDERLINE:
1935 if (wParam)
1936 SendEditor(SCI_SETFOLDFLAGS, props->GetInt("fold.flags"));
1937 else
1938 SendEditor(SCI_SETFOLDFLAGS, 0);
1939 break;
1940 case ANE_SETLINENUMWIDTH:
1941 lineNumbersWidth = wParam;
1942 SendEditor(SCI_SETMARGINWIDTHN, 0, lineNumbers ? lineNumbersWidth : 0);
1943 break;
1944 case ANE_SETEDGECOLUMN:
1945 SendEditor(SCI_SETEDGECOLUMN, wParam);
1946 break;
1947 default:
1948 break;
1950 return 0;
1953 void AnEditor::FoldChanged(int line, int levelNow, int levelPrev) {
1954 if (levelNow & SC_FOLDLEVELHEADERFLAG) {
1955 SendEditor(SCI_SETFOLDEXPANDED, line, 1);
1956 } else if (levelPrev & SC_FOLDLEVELHEADERFLAG) {
1957 if (!SendEditor(SCI_GETFOLDEXPANDED, line)) {
1958 // Removing the fold from one that has been contracted so should expand
1959 // otherwise lines are left invisible with no way to make them visible
1960 Expand(line, true, false, 0, levelPrev);
1965 void AnEditor::Expand(int &line, bool doExpand, bool force, int visLevels, int level) {
1966 int lineMaxSubord = SendEditor(SCI_GETLASTCHILD, line, level);
1967 line++;
1968 while (line <= lineMaxSubord) {
1969 if (force) {
1970 if (visLevels > 0)
1971 SendEditor(SCI_SHOWLINES, line, line);
1972 else
1973 SendEditor(SCI_HIDELINES, line, line);
1974 } else {
1975 if (doExpand)
1976 SendEditor(SCI_SHOWLINES, line, line);
1978 int levelLine = level;
1979 if (levelLine ==-1)
1980 levelLine = SendEditor(SCI_GETFOLDLEVEL, line);
1981 if (levelLine & SC_FOLDLEVELHEADERFLAG) {
1982 if (force) {
1983 if (visLevels > 1)
1984 SendEditor(SCI_SETFOLDEXPANDED, line, 1);
1985 else
1986 SendEditor(SCI_SETFOLDEXPANDED, line, 0);
1987 Expand(line, doExpand, force, visLevels - 1);
1988 } else {
1989 if (doExpand && SendEditor(SCI_GETFOLDEXPANDED, line)) {
1990 Expand(line, true, force, visLevels - 1);
1991 } else {
1992 Expand(line, false, force, visLevels - 1);
1995 } else {
1996 line++;
2001 void AnEditor::FoldCode(bool expanding) {
2002 int maxLine = SendEditor (SCI_GETTEXTLENGTH);
2003 SendEditor(SCI_COLOURISE, 0, -1);
2004 for (int line = 0; line < maxLine; line++) {
2005 int level = SendEditor(SCI_GETFOLDLEVEL, line);
2006 if ((level & SC_FOLDLEVELHEADERFLAG) &&
2007 (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) {
2008 if (expanding) {
2009 SendEditor(SCI_SETFOLDEXPANDED, line, 1);
2010 Expand(line, true);
2011 line--;
2012 } else {
2013 int lineMaxSubord = SendEditor(SCI_GETLASTCHILD, line, -1);
2014 SendEditor(SCI_SETFOLDEXPANDED, line, 0);
2015 if (lineMaxSubord > line)
2016 SendEditor(SCI_HIDELINES, line + 1, lineMaxSubord);
2022 void AnEditor::FoldOpenAll() {
2023 FoldCode (true);
2026 void AnEditor::FoldCloseAll() {
2027 FoldCode (false);
2030 void AnEditor::FoldToggle() {
2031 int curLine = SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
2032 int level = SendEditor(SCI_GETFOLDLEVEL, curLine);
2033 if (level & SC_FOLDLEVELHEADERFLAG) {
2034 SendEditor(SCI_TOGGLEFOLD, curLine);
2035 return;
2037 int parent = SendEditor (SCI_GETFOLDPARENT, curLine);
2038 int lastChild = SendEditor (SCI_GETLASTCHILD, parent, -1);
2039 if (curLine > parent && curLine <= lastChild)
2041 SendEditor(SCI_TOGGLEFOLD, parent);
2042 SendEditor(SCI_SETCURRENTPOS, SendEditor (SCI_POSITIONFROMLINE, parent));
2043 SendEditor(SCI_GOTOLINE, parent);
2045 else
2046 gdk_beep ();
2049 void AnEditor::SelectBlock () {
2050 int curLine = SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
2051 int parent = SendEditor (SCI_GETFOLDPARENT, curLine);
2052 int lastChild = SendEditor (SCI_GETLASTCHILD, parent, -1);
2053 if (curLine > parent && curLine <= lastChild)
2055 gint start, end;
2056 start = SendEditor(SCI_POSITIONFROMLINE, parent);
2057 end = SendEditor(SCI_POSITIONFROMLINE, lastChild+1);
2058 SetSelection(start, end);
2060 else
2061 gdk_beep ();
2064 int AnEditor::GetBlockStartLine (int curLine) {
2065 if(curLine < 0)
2067 curLine = SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
2069 int level = SendEditor(SCI_GETFOLDLEVEL, curLine);
2070 if (level & SC_FOLDLEVELHEADERFLAG) {
2071 return curLine;
2073 int parent = -1;
2074 int lastChild = curLine;
2075 while(parent == -1)
2077 parent = SendEditor (SCI_GETFOLDPARENT, lastChild);
2078 if (parent == -1)
2080 return -1;
2082 lastChild = SendEditor (SCI_GETLASTCHILD, parent, -1);
2083 if (curLine > parent && curLine <= lastChild)
2085 return parent;
2087 lastChild = parent - 1;
2088 parent = -1;
2090 return -1;
2093 int AnEditor::GetBlockEndLine (int curLine) {
2094 if(curLine < 0)
2096 curLine = SendEditor(SCI_LINEFROMPOSITION, SendEditor (SCI_GETCURRENTPOS));
2098 int level = SendEditor(SCI_GETFOLDLEVEL, curLine);
2099 if (level & SC_FOLDLEVELHEADERFLAG) {
2100 /* this may be a problem when we use this function on "start" block line */
2101 return curLine;
2103 int parent = -1;
2104 int lastChild = curLine;
2105 while(parent == -1)
2107 parent = SendEditor (SCI_GETFOLDPARENT, lastChild);
2108 if (parent == -1)
2110 return -1;
2112 lastChild = SendEditor (SCI_GETLASTCHILD, parent, -1);
2113 if (curLine > parent && curLine <= lastChild)
2115 return lastChild;
2117 lastChild = parent - 1;
2118 parent = -1;
2120 return -1;
2123 void AnEditor::EnsureRangeVisible(int posStart, int posEnd) {
2124 int lineStart = SendEditor(SCI_LINEFROMPOSITION, Platform::Minimum(posStart, posEnd));
2125 int lineEnd = SendEditor(SCI_LINEFROMPOSITION, Platform::Maximum(posStart, posEnd));
2126 for (int line = lineStart; line <= lineEnd; line++) {
2127 SendEditor(SCI_ENSUREVISIBLE, line);
2131 void AnEditor::SetLineWrap(bool wrap) {
2132 wrapLine = wrap;
2133 SendEditor(SCI_SETWRAPMODE, wrapLine ? SC_WRAP_WORD : SC_WRAP_NONE);
2134 SendEditor(SCI_SETHSCROLLBAR, !wrapLine);
2137 void AnEditor::SetReadOnly(bool readonly) {
2138 isReadOnly = readonly;
2139 SendEditor(SCI_SETREADONLY, isReadOnly);
2142 bool AnEditor::MarginClick(int position, int modifiers) {
2143 int lineClick = SendEditor(SCI_LINEFROMPOSITION, position);
2144 // SendEditor(SCI_GETFOLDLEVEL, lineClick) & SC_FOLDLEVELHEADERFLAG);
2145 if (modifiers & SCMOD_SHIFT) {
2146 FoldCloseAll();
2147 } else if (modifiers & SCMOD_CTRL) {
2148 FoldOpenAll();
2149 } else if (SendEditor(SCI_GETFOLDLEVEL, lineClick) & SC_FOLDLEVELHEADERFLAG) {
2150 if (modifiers & SCMOD_SHIFT) {
2151 // Ensure all children visible
2152 SendEditor(SCI_SETFOLDEXPANDED, lineClick, 1);
2153 Expand(lineClick, true, true, 100);
2154 } else if (modifiers & SCMOD_CTRL) {
2155 if (SendEditor(SCI_GETFOLDEXPANDED, lineClick)) {
2156 // Contract this line and all children
2157 SendEditor(SCI_SETFOLDEXPANDED, lineClick, 0);
2158 Expand(lineClick, false, true, 0);
2159 } else {
2160 // Expand this line and all children
2161 SendEditor(SCI_SETFOLDEXPANDED, lineClick, 1);
2162 Expand(lineClick, true, true, 100);
2164 } else {
2165 // Toggle this line
2166 SendEditor(SCI_TOGGLEFOLD, lineClick);
2169 return true;
2172 #if 0
2173 gint AnEditor::KeyPressEvent(GtkWidget *, GdkEventKey *event, AnEditor *anedit) {
2174 return anedit->KeyPress(event->state, event->keyval);
2176 #endif
2178 void AnEditor::NotifySignal(GtkWidget *, gint /*wParam*/, gpointer lParam, AnEditor *anedit) {
2179 anedit->Notify(reinterpret_cast<SCNotification *>(lParam));
2182 // FIXME:
2183 #if 0
2184 void
2185 eval_output_arrived_for_aneditor(GList* lines, gpointer data)
2187 // We expect lines->data to be a string of the form VARIABLE = VALUE,
2188 // and 'data' to be a pointer to an object of type
2189 // 'ExpressionEvaluationTipInfo'.
2191 if (data == NULL)
2192 return;
2194 auto_ptr<ExpressionEvaluationTipInfo> info(
2195 (ExpressionEvaluationTipInfo *) data);
2197 if (info->editor == NULL)
2198 return;
2200 if (info->editor != aneditor_get(AnEditor::focusedID))
2201 return;
2203 info->editor->EvalOutputArrived(lines, info->textPos, info->expression);
2205 #endif
2207 void AnEditor::EvalOutputArrived(GList* lines, int textPos,
2208 const string &expression) {
2210 if (textPos <= 0)
2211 return;
2213 // Return if debug Tip has been canceled
2214 if (!debugTipOn)
2215 return;
2217 if (g_list_length(lines) == 0 || lines->data == NULL)
2218 return;
2220 string result = (char *) lines->data;
2221 string::size_type posEquals = result.find(" = ");
2222 if (posEquals != string::npos)
2223 result.replace(0, posEquals, expression);
2225 SendEditorString(SCI_CALLTIPSHOW, textPos, result.c_str());
2226 SendEditor(SCI_CALLTIPSETHLT, 0, result.length());
2229 void AnEditor::EndDebugEval() {
2230 if (debugTipOn)
2232 SendEditor(SCI_CALLTIPCANCEL);
2233 debugTipOn = false;
2237 void AnEditor::HandleDwellStart(int mousePos) {
2238 if (mousePos == -1)
2239 return;
2241 char expr[256];
2242 //FIXME:
2243 #if 0
2244 if (!debugger_is_active() || !debugger_is_ready())
2246 // Do not show expression tip if it can't be shown.
2247 // string s = string(expr) + ": " + _("debugger not active");
2248 // SendEditorString(SCI_CALLTIPSHOW, mousePos, s.c_str());
2249 return;
2251 #endif
2252 // If debug tip is already running, return.
2253 if (debugTipOn)
2254 return;
2256 CharacterRange crange = GetSelection();
2257 if (crange.cpMin == crange.cpMax
2258 || mousePos < crange.cpMin
2259 || mousePos >= crange.cpMax)
2261 // There is no selection, or the mouse pointer is
2262 // out of the selection, so we search for a word
2263 // around the mouse pointer:
2264 if (!GetWordAtPosition(expr, sizeof(expr), mousePos))
2265 return;
2267 else
2269 long lensel = crange.cpMax - crange.cpMin;
2270 long max = sizeof(expr) - 1;
2271 guint end = (lensel < max ? crange.cpMax : crange.cpMin + max);
2272 GetRange(crange.cpMin, end, expr, false);
2274 // If there is any control character except TAB
2275 // in the expression, disregard it.
2276 size_t i;
2277 for (i = 0; i < end - crange.cpMin; i++)
2278 if ((unsigned char) expr[i] < ' ' && expr[i] != '\t')
2279 return;
2280 if (i < end - crange.cpMin)
2281 return;
2284 // Imitation of on_eval_ok_clicked():
2285 // The function eval_output_arrived_for_aneditor() will
2286 // be called eventually by the debugger with the result
2287 // of the print command for 'expr', and with the 'info'
2288 // pointer. That function must call delete on 'info'.
2290 // We don't turn GDB "pretty printing" on because we want
2291 // the entire value on a single line, in the case of a
2292 // struct or class.
2293 // We don't want static members of classes to clutter up
2294 // the displayed tip, however.
2296 //FIXME:
2297 #if 0
2298 ExpressionEvaluationTipInfo *info =
2299 new ExpressionEvaluationTipInfo(this, mousePos, expr);
2300 debugger_query_evaluate_expr_tip (expr, eval_output_arrived_for_aneditor, info);
2301 debugger_query_execute ();
2302 #endif
2303 debugTipOn = true;
2306 #if 0
2307 int AnEditor::KeyPress(unsigned int state, unsigned int keyval){
2309 unsigned int mask = GDK_SHIFT_MASK | GDK_LOCK_MASK |
2310 GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_MOD3_MASK |
2311 GDK_MOD4_MASK | GDK_MOD5_MASK;
2312 if (state & mask)
2313 return false;
2315 // Trap 'TAB' key for automatic indentation.
2316 // printf ("Key is '%c'\n", notification->ch);
2317 if ((keyval == GDK_Tab) &&
2318 (lexLanguage == SCLEX_CPP) &&
2319 (!indentMaintain) &&
2320 (props->GetInt("indent.automatic")) &&
2321 (!SendEditor(SCI_CALLTIPACTIVE)) &&
2322 (!SendEditor(SCI_AUTOCACTIVE))) {
2324 CharacterRange crange = GetSelection();
2325 int selStart = crange.cpMin;
2326 int selEnd = crange.cpMax;
2328 if (selStart == selEnd) {
2329 AutomaticIndentation('\t');
2330 return true;
2333 return false;
2335 #endif
2337 void AnEditor::Notify(SCNotification *notification) {
2338 switch (notification->nmhdr.code) {
2339 case SCN_CALLTIPCLICK:
2340 if (notification->position == 1) {
2341 call_tip_node.def_index--;
2342 if (call_tip_node.def_index < 0)
2343 call_tip_node.def_index = 0;
2345 if (notification->position == 2) {
2346 call_tip_node.def_index++;
2347 if (call_tip_node.def_index >= call_tip_node.max_def)
2348 call_tip_node.def_index = call_tip_node.max_def - 1;
2350 ResumeCallTip (false);
2351 break;
2352 case SCN_KEY: {
2353 if(!accelGroup) break;
2354 int mods = 0;
2355 if (notification->modifiers & SCMOD_SHIFT)
2356 mods |= GDK_SHIFT_MASK;
2357 if (notification->modifiers & SCMOD_CTRL)
2358 mods |= GDK_CONTROL_MASK;
2359 if (notification->modifiers & SCMOD_ALT)
2360 mods |= GDK_MOD1_MASK;
2361 gtk_accel_groups_activate(G_OBJECT (accelGroup), notification->ch,
2362 static_cast<GdkModifierType>(mods));
2365 case SCN_CHARADDED:
2366 CharAdded(static_cast<char>(notification->ch));
2367 break;
2369 case SCN_SAVEPOINTREACHED:
2370 isDirty = false;
2371 break;
2373 case SCN_SAVEPOINTLEFT:
2374 isDirty = true;
2375 break;
2377 case SCN_UPDATEUI:
2379 int pos = SendEditor(SCI_GETCURRENTPOS);
2380 BraceMatch(true);
2381 if (SendEditor(SCI_CALLTIPACTIVE) ) {
2382 // if we have a caret movement on left or right
2383 if (abs(pos - lastPos) == 1 ) {
2384 ContinueCallTip_new();
2387 lastPos = pos;
2389 break;
2391 case SCN_MODIFIED:
2392 if (notification->modificationType == SC_MOD_CHANGEFOLD) {
2393 FoldChanged(notification->line,
2394 notification->foldLevelNow, notification->foldLevelPrev);
2396 break;
2398 case SCN_MARGINCLICK:
2399 if (notification->margin == 2)
2400 MarginClick(notification->position, notification->modifiers);
2401 break;
2403 case SCN_NEEDSHOWN: {
2404 EnsureRangeVisible(notification->position, notification->position + notification->length);
2406 break;
2408 case SCN_DWELLSTART:
2409 HandleDwellStart(notification->position);
2410 break;
2412 case SCN_DWELLEND:
2413 EndDebugEval();
2414 // SendEditor(SCI_CALLTIPCANCEL);
2415 break;
2420 static int IntFromHexDigit(const char ch) {
2421 if (isdigit(ch))
2422 return ch - '0';
2423 else if (ch >= 'A' && ch <= 'F')
2424 return ch - 'A' + 10;
2425 else if (ch >= 'a' && ch <= 'f')
2426 return ch - 'a' + 10;
2427 else
2428 return 0;
2431 static Colour ColourFromString(const char *val) {
2432 int r = IntFromHexDigit(val[1]) * 16 + IntFromHexDigit(val[2]);
2433 int g = IntFromHexDigit(val[3]) * 16 + IntFromHexDigit(val[4]);
2434 int b = IntFromHexDigit(val[5]) * 16 + IntFromHexDigit(val[6]);
2435 return Colour(r, g, b);
2438 static long ColourOfProperty(PropSet *props, const char *key, ColourDesired colourDefault) {
2439 SString colour = props->Get(key);
2440 if (colour.length()) {
2441 return ColourFromString(colour.c_str()).AsLong();
2443 return colourDefault.AsLong();
2446 void AnEditor::SetOneStyle(Window &win, int style, const char *s) {
2447 char *val = StringDup(s);
2448 char *opt = val;
2449 while (opt) {
2450 char *cpComma = strchr(opt, ',');
2451 if (cpComma)
2452 *cpComma = '\0';
2453 char *colon = strchr(opt, ':');
2454 if (colon)
2455 *colon++ = '\0';
2456 if (0 == strcmp(opt, "italics"))
2457 Platform::SendScintilla(win.GetID(), SCI_STYLESETITALIC, style, 1);
2458 if (0 == strcmp(opt, "notitalics"))
2459 Platform::SendScintilla(win.GetID(), SCI_STYLESETITALIC, style, 0);
2460 if (0 == strcmp(opt, "bold"))
2461 Platform::SendScintilla(win.GetID(), SCI_STYLESETBOLD, style, 1);
2462 if (0 == strcmp(opt, "notbold"))
2463 Platform::SendScintilla(win.GetID(), SCI_STYLESETBOLD, style, 0);
2464 if (0 == strcmp(opt, "font"))
2465 Platform::SendScintilla(win.GetID(), SCI_STYLESETFONT, style, reinterpret_cast<long>(colon));
2466 if (0 == strcmp(opt, "fore"))
2467 Platform::SendScintilla(win.GetID(), SCI_STYLESETFORE, style, ColourFromString(colon).AsLong());
2468 if (0 == strcmp(opt, "back"))
2469 Platform::SendScintilla(win.GetID(), SCI_STYLESETBACK, style, ColourFromString(colon).AsLong());
2470 if (0 == strcmp(opt, "size"))
2471 Platform::SendScintilla(win.GetID(), SCI_STYLESETSIZE, style, atoi(colon));
2472 if (0 == strcmp(opt, "eolfilled"))
2473 Platform::SendScintilla(win.GetID(), SCI_STYLESETEOLFILLED, style, 1);
2474 if (0 == strcmp(opt, "noteolfilled"))
2475 Platform::SendScintilla(win.GetID(), SCI_STYLESETEOLFILLED, style, 0);
2476 if (0 == strcmp(opt, "underlined"))
2477 Platform::SendScintilla(win.GetID(), SCI_STYLESETUNDERLINE, style, 1);
2478 if (0 == strcmp(opt, "notunderlined"))
2479 Platform::SendScintilla(win.GetID(), SCI_STYLESETUNDERLINE, style, 0);
2480 if (0 == strcmp(opt, "case")) {
2481 if (*colon == 'u') {
2482 Platform::SendScintilla(win.GetID(), SCI_STYLESETCASE, style, SC_CASE_UPPER);
2483 } else if (*colon == 'l') {
2484 Platform::SendScintilla(win.GetID(), SCI_STYLESETCASE, style, SC_CASE_LOWER);
2485 } else {
2486 Platform::SendScintilla(win.GetID(), SCI_STYLESETCASE, style, SC_CASE_MIXED);
2489 if (0 == strcmp(opt, "visible"))
2490 Platform::SendScintilla(win.GetID(), SCI_STYLESETVISIBLE, style, 1);
2491 if (0 == strcmp(opt, "notvisible"))
2492 Platform::SendScintilla(win.GetID(), SCI_STYLESETVISIBLE, style, 0);
2493 if (0 == strcmp(opt, "changeable"))
2494 Platform::SendScintilla(win.GetID(), SCI_STYLESETCHANGEABLE, style, 1);
2495 if (0 == strcmp(opt, "notchangeable"))
2496 Platform::SendScintilla(win.GetID(), SCI_STYLESETCHANGEABLE, style, 0);
2497 if (cpComma)
2498 opt = cpComma + 1;
2499 else
2500 opt = 0;
2502 if (val)
2503 delete []val;
2504 Platform::SendScintilla(win.GetID(), SCI_STYLESETCHARACTERSET, style, characterSet);
2507 void AnEditor::SetStyleFor(Window &win, const char *lang) {
2508 for (int style = 0; style <= STYLE_MAX; style++) {
2509 if (style != STYLE_DEFAULT) {
2510 char key[200];
2511 sprintf(key, "style.%s.%0d", lang, style);
2512 SString sval = props->GetExpanded(key);
2513 // g_print ("Style for %s:%0d == %s\n", lang, style, sval.c_str());
2514 SetOneStyle(win, style, sval.c_str());
2519 void lowerCaseString(char *s) {
2520 while (*s) {
2521 *s = static_cast<char>(tolower(*s));
2522 s++;
2526 SString AnEditor::ExtensionFileName() {
2527 if (overrideExtension.length())
2528 return overrideExtension;
2529 else if (fileName[0]) {
2530 // Force extension to lower case
2531 char fileNameWithLowerCaseExtension[MAX_PATH];
2532 strcpy(fileNameWithLowerCaseExtension, fileName);
2533 char *extension = strrchr(fileNameWithLowerCaseExtension, '.');
2534 if (extension) {
2535 lowerCaseString(extension);
2537 return SString(fileNameWithLowerCaseExtension);
2538 } else
2539 return props->Get("default.file.ext");
2542 void AnEditor::ForwardPropertyToEditor(const char *key) {
2543 SString value = props->Get(key);
2544 SendEditorString(SCI_SETPROPERTY,
2545 reinterpret_cast<uptr_t>(key), value.c_str());
2548 SString AnEditor::FindLanguageProperty(const char *pattern, const char *defaultValue) {
2549 SString key = pattern;
2550 key.substitute("*", language.c_str());
2551 SString ret = props->GetExpanded(key.c_str());
2552 if (ret == "")
2553 ret = props->GetExpanded(pattern);
2554 if (ret == "")
2555 ret = defaultValue;
2556 return ret;
2559 void AnEditor::ReadProperties(const char *fileForExt) {
2560 //DWORD dwStart = timeGetTime();
2561 if (fileForExt)
2562 strcpy (fileName, fileForExt);
2563 else
2564 fileName[0] = '\0';
2566 SString fileNameForExtension;
2567 if(overrideExtension.length())
2568 fileNameForExtension = overrideExtension;
2569 else {
2570 fileNameForExtension = fileForExt;
2573 language = props->GetNewExpand("lexer.", fileNameForExtension.c_str());
2574 SendEditorString(SCI_SETLEXERLANGUAGE, 0, language.c_str());
2575 lexLanguage = SendEditor(SCI_GETLEXER);
2577 if ((lexLanguage == SCLEX_HTML) || (lexLanguage == SCLEX_XML))
2578 SendEditor(SCI_SETSTYLEBITS, 7);
2579 else
2580 SendEditor(SCI_SETSTYLEBITS, 5);
2582 SendEditor(SCI_SETLEXER, lexLanguage);
2584 SString kw0 = props->GetNewExpand("keywords.", fileNameForExtension.c_str());
2585 SendEditorString(SCI_SETKEYWORDS, 0, kw0.c_str());
2586 SString kw2 = props->GetNewExpand("keywords3.", fileNameForExtension.c_str());
2587 SendEditorString(SCI_SETKEYWORDS, 2, kw2.c_str());
2588 /* For C/C++ projects, get list of typedefs for colorizing */
2589 if (SCLEX_CPP == lexLanguage)
2591 const TMWorkspace *workspace = tm_get_workspace();
2593 /* Assign global keywords */
2594 if ((workspace) && (workspace->global_tags))
2596 GPtrArray *g_typedefs = tm_tags_extract(workspace->global_tags
2597 , tm_tag_typedef_t | tm_tag_struct_t | tm_tag_class_t);
2598 if ((g_typedefs) && (g_typedefs->len > 0))
2600 GString *s = g_string_sized_new(g_typedefs->len * 10);
2601 for (guint i = 0; i < g_typedefs->len; ++i)
2603 if (!(TM_TAG(g_typedefs->pdata[i])->atts.entry.scope))
2605 g_string_append(s, TM_TAG(g_typedefs->pdata[i])->name);
2606 g_string_append_c(s, ' ');
2609 SendEditorString(SCI_SETKEYWORDS, 3, s->str);
2610 g_string_free(s, TRUE);
2612 g_ptr_array_free(g_typedefs, TRUE);
2615 /* Assign project keywords */
2616 if ((workspace) && (workspace->work_object.tags_array))
2618 GPtrArray *typedefs = tm_tags_extract(workspace->work_object.tags_array
2619 , tm_tag_typedef_t | tm_tag_struct_t | tm_tag_class_t);
2620 if ((typedefs) && (typedefs->len > 0))
2622 GString *s = g_string_sized_new(typedefs->len * 10);
2623 for (guint i = 0; i < typedefs->len; ++i)
2625 if (!(TM_TAG(typedefs->pdata[i])->atts.entry.scope))
2627 if (TM_TAG(typedefs->pdata[i])->name)
2629 g_string_append(s, TM_TAG(typedefs->pdata[i])->name);
2630 g_string_append_c(s, ' ');
2634 SendEditorString(SCI_SETKEYWORDS, 1, s->str);
2635 g_string_free(s, TRUE);
2637 g_ptr_array_free(typedefs, TRUE);
2640 else
2642 SString kw1 = props->GetNewExpand("keywords2.", fileNameForExtension.c_str());
2643 SendEditorString(SCI_SETKEYWORDS, 1, kw1.c_str());
2644 SString kw3 = props->GetNewExpand("keywords4.", fileNameForExtension.c_str());
2645 SendEditorString(SCI_SETKEYWORDS, 3, kw3.c_str());
2646 SString kw4 = props->GetNewExpand("keywords5.", fileNameForExtension.c_str());
2647 SendEditorString(SCI_SETKEYWORDS, 4, kw4.c_str());
2648 SString kw5 = props->GetNewExpand("keywords6.", fileNameForExtension.c_str());
2649 SendEditorString(SCI_SETKEYWORDS, 5, kw5.c_str());
2652 ForwardPropertyToEditor("fold");
2653 ForwardPropertyToEditor("fold.use.plus");
2654 ForwardPropertyToEditor("fold.comment");
2655 ForwardPropertyToEditor("fold.comment.python");
2656 ForwardPropertyToEditor("fold.compact");
2657 ForwardPropertyToEditor("fold.html");
2658 ForwardPropertyToEditor("fold.preprocessor");
2659 ForwardPropertyToEditor("fold.quotes.python");
2660 ForwardPropertyToEditor("styling.within.preprocessor");
2661 ForwardPropertyToEditor("tab.timmy.whinge.level");
2662 ForwardPropertyToEditor("asp.default.language");
2664 // codePage = props->GetInt("code.page");
2665 //if (unicodeMode != uni8Bit) {
2666 // Override properties file to ensure Unicode displayed.
2667 // codePage = SC_CP_UTF8;
2668 // }
2669 // SendEditor(SCI_SETCODEPAGE, codePage);
2671 // Use unicode everytime.
2672 SendEditor(SCI_SETCODEPAGE, SC_CP_UTF8);
2674 characterSet = props->GetInt("character.set");
2675 setlocale(LC_CTYPE, props->Get("LC_CTYPE").c_str());
2677 SendEditor(SCI_SETCARETFORE,
2678 ColourOfProperty(props, "caret.fore", ColourDesired(0, 0, 0)));
2679 SendEditor(SCI_SETCARETWIDTH, props->GetInt("caret.width", 1));
2680 SendEditor(SCI_SETMOUSEDWELLTIME, props->GetInt("dwell.period", 750), 0);
2682 SString caretLineBack = props->Get("caret.line.back");
2683 if (caretLineBack.length()) {
2684 SendEditor(SCI_SETCARETLINEVISIBLE, 1);
2685 SendEditor(SCI_SETCARETLINEBACK,
2686 ColourFromString(caretLineBack.c_str()).AsLong());
2687 } else {
2688 SendEditor(SCI_SETCARETLINEVISIBLE, 0);
2691 SString controlCharSymbol = props->Get("control.char.symbol");
2692 if (controlCharSymbol.length()) {
2693 SendEditor(SCI_SETCONTROLCHARSYMBOL, static_cast<unsigned char>(controlCharSymbol[0]));
2694 } else {
2695 SendEditor(SCI_SETCONTROLCHARSYMBOL, 0);
2698 SendEditor(SCI_CALLTIPSETBACK,
2699 ColourOfProperty(props, "calltip.back", ColourDesired(0xff, 0xff, 0xff)));
2701 SString caretPeriod = props->Get("caret.period");
2702 if (caretPeriod.length()) {
2703 SendEditor(SCI_SETCARETPERIOD, caretPeriod.value());
2706 int caretSlop = props->GetInt("caret.policy.xslop", 1) ? CARET_SLOP : 0;
2707 int caretZone = props->GetInt("caret.policy.width", 50);
2708 int caretStrict = props->GetInt("caret.policy.xstrict") ? CARET_STRICT : 0;
2709 int caretEven = props->GetInt("caret.policy.xeven", 1) ? CARET_EVEN : 0;
2710 int caretJumps = props->GetInt("caret.policy.xjumps") ? CARET_JUMPS : 0;
2711 SendEditor(SCI_SETXCARETPOLICY, caretStrict | caretSlop | caretEven | caretJumps, caretZone);
2713 caretSlop = props->GetInt("caret.policy.yslop", 1) ? CARET_SLOP : 0;
2714 caretZone = props->GetInt("caret.policy.lines");
2715 caretStrict = props->GetInt("caret.policy.ystrict") ? CARET_STRICT : 0;
2716 caretEven = props->GetInt("caret.policy.yeven", 1) ? CARET_EVEN : 0;
2717 caretJumps = props->GetInt("caret.policy.yjumps") ? CARET_JUMPS : 0;
2718 SendEditor(SCI_SETYCARETPOLICY, caretStrict | caretSlop | caretEven | caretJumps, caretZone);
2720 int visibleStrict = props->GetInt("visible.policy.strict") ? VISIBLE_STRICT : 0;
2721 int visibleSlop = props->GetInt("visible.policy.slop", 1) ? VISIBLE_SLOP : 0;
2722 int visibleLines = props->GetInt("visible.policy.lines");
2723 SendEditor(SCI_SETVISIBLEPOLICY, visibleStrict | visibleSlop, visibleLines);
2725 SendEditor(SCI_SETEDGECOLUMN, props->GetInt("edge.column", 0));
2726 SendEditor(SCI_SETEDGEMODE, props->GetInt("edge.mode", EDGE_NONE));
2727 SendEditor(SCI_SETEDGECOLOUR,
2728 ColourOfProperty(props, "edge.colour", ColourDesired(0xff, 0xda, 0xda)));
2730 SString selfore = props->Get("selection.fore");
2731 if (selfore.length()) {
2732 SendEditor(SCI_SETSELFORE, 1, ColourFromString(selfore.c_str()).AsLong());
2733 } else {
2734 SendEditor(SCI_SETSELFORE, 0, 0);
2736 SString selBack = props->Get("selection.back");
2737 if (selBack.length()) {
2738 SendEditor(SCI_SETSELBACK, 1, ColourFromString(selBack.c_str()).AsLong());
2739 } else {
2740 if (selfore.length())
2741 SendEditor(SCI_SETSELBACK, 0, 0);
2742 else // Have to show selection somehow
2743 SendEditor(SCI_SETSELBACK, 1, ColourDesired(0xC0, 0xC0, 0xC0).AsLong());
2746 SString whitespaceFore = props->Get("whitespace.fore");
2747 if (whitespaceFore.length()) {
2748 SendEditor(SCI_SETWHITESPACEFORE, 1, ColourFromString(whitespaceFore.c_str()).AsLong());
2749 } else {
2750 SendEditor(SCI_SETWHITESPACEFORE, 0, 0);
2752 SString whitespaceBack = props->Get("whitespace.back");
2753 if (whitespaceBack.length()) {
2754 SendEditor(SCI_SETWHITESPACEBACK, 1, ColourFromString(whitespaceBack.c_str()).AsLong());
2755 } else {
2756 SendEditor(SCI_SETWHITESPACEBACK, 0, 0);
2759 for (int i = 0; i < 3; i++) {
2761 SString value_str;
2762 long default_indic_type[] = {INDIC_TT, INDIC_DIAGONAL, INDIC_SQUIGGLE};
2763 char *default_indic_color[] = {"0000FF", "#00FF00", "#FF0000"};
2764 char *style_name[] = {"normal", "warning", "error"};
2765 char key[200];
2766 sprintf(key, "indicators.style.%s", style_name[i]);
2768 value_str = props->Get(key);
2769 if (value_str.length() > 0) {
2770 if (strcasecmp (value_str.c_str(), "underline-plain") == 0) {
2771 SendEditor(SCI_INDICSETSTYLE, i, INDIC_PLAIN);
2772 } else if (strcasecmp (value_str.c_str(), "underline-tt") == 0) {
2773 SendEditor(SCI_INDICSETSTYLE, i, INDIC_TT);
2774 } else if (strcasecmp (value_str.c_str(), "underline-squiggle") == 0) {
2775 SendEditor(SCI_INDICSETSTYLE, i, INDIC_SQUIGGLE);
2776 } else if (strcasecmp (value_str.c_str(), "strike-out") == 0) {
2777 SendEditor(SCI_INDICSETSTYLE, i, INDIC_STRIKE);
2778 } else if (strcasecmp (value_str.c_str(), "diagonal") == 0) {
2779 SendEditor(SCI_INDICSETSTYLE, i, INDIC_DIAGONAL);
2780 } else {
2781 SendEditor(SCI_INDICSETSTYLE, i, default_indic_type[i]);
2783 } else {
2784 SendEditor(SCI_INDICSETSTYLE, i, default_indic_type[i]);
2786 sprintf(key, "indicator.%d.color", i);
2787 value_str = props->GetExpanded(key);
2788 if (value_str.length()) {
2789 SendEditor(SCI_INDICSETFORE, i, ColourFromString(value_str.c_str()).AsLong());
2790 } else {
2791 SendEditor(SCI_INDICSETFORE, i, ColourFromString(default_indic_color[i]).AsLong());
2795 char bracesStyleKey[200];
2796 sprintf(bracesStyleKey, "braces.%s.style", language.c_str());
2797 bracesStyle = props->GetInt(bracesStyleKey, 0);
2799 char key[200];
2800 SString sval;
2802 sval = FindLanguageProperty("calltip.*.ignorecase");
2803 callTipIgnoreCase = sval == "1";
2805 calltipWordCharacters = FindLanguageProperty("calltip.*.word.characters",
2806 "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
2808 calltipEndDefinition = FindLanguageProperty("calltip.*.end.definition");
2810 sprintf(key, "autocomplete.%s.start.characters", language.c_str());
2811 autoCompleteStartCharacters = props->GetExpanded(key);
2812 if (autoCompleteStartCharacters == "")
2813 autoCompleteStartCharacters = props->GetExpanded("autocomplete.*.start.characters");
2814 // "" is a quite reasonable value for this setting
2816 sprintf(key, "autocomplete.%s.fillups", language.c_str());
2817 autoCompleteFillUpCharacters = props->GetExpanded(key);
2818 if (autoCompleteFillUpCharacters == "")
2819 autoCompleteFillUpCharacters =
2820 props->GetExpanded("autocomplete.*.fillups");
2821 SendEditorString(SCI_AUTOCSETFILLUPS, 0,
2822 autoCompleteFillUpCharacters.c_str());
2824 sprintf(key, "autocomplete.%s.ignorecase", "*");
2825 sval = props->GetNewExpand(key, "");
2826 autoCompleteIgnoreCase = sval == "1";
2827 sprintf(key, "autocomplete.%s.ignorecase", language.c_str());
2828 sval = props->GetNewExpand(key, "");
2829 if (sval != "")
2830 autoCompleteIgnoreCase = sval == "1";
2831 SendEditor(SCI_AUTOCSETIGNORECASE, autoCompleteIgnoreCase ? 1 : 0);
2833 int autoCChooseSingle = props->GetInt("autocomplete.choose.single");
2834 SendEditor(SCI_AUTOCSETCHOOSESINGLE, autoCChooseSingle),
2836 SendEditor(SCI_AUTOCSETCANCELATSTART, 0),
2837 SendEditor(SCI_AUTOCSETDROPRESTOFWORD, 0),
2839 // Set styles
2840 // For each window set the global default style,
2841 // then the language default style,
2842 // then the other global styles,
2843 // then the other language styles
2845 SendEditor(SCI_STYLERESETDEFAULT, 0, 0);
2847 sprintf(key, "style.%s.%0d", "*", STYLE_DEFAULT);
2848 sval = props->GetNewExpand(key, "");
2849 SetOneStyle(wEditor, STYLE_DEFAULT, sval.c_str());
2851 sprintf(key, "style.%s.%0d", language.c_str(), STYLE_DEFAULT);
2852 sval = props->GetNewExpand(key, "");
2853 SetOneStyle(wEditor, STYLE_DEFAULT, sval.c_str());
2855 SendEditor(SCI_STYLECLEARALL, 0, 0);
2857 SetStyleFor(wEditor, "*");
2858 SetStyleFor(wEditor, language.c_str());
2860 if (firstPropertiesRead) {
2861 ReadPropertiesInitial();
2864 /* Gtk handles it correctly */
2865 SendEditor(SCI_SETUSEPALETTE, 0);
2867 SendEditor(SCI_SETPRINTMAGNIFICATION, props->GetInt("print.magnification"));
2868 SendEditor(SCI_SETPRINTCOLOURMODE, props->GetInt("print.colour.mode"));
2870 int blankMarginLeft = props->GetInt("blank.margin.left", 1);
2871 int blankMarginRight = props->GetInt("blank.margin.right", 1);
2872 SendEditor(SCI_SETMARGINLEFT, 0, blankMarginLeft);
2873 SendEditor(SCI_SETMARGINRIGHT, 0, blankMarginRight);
2875 SendEditor(SCI_SETMARGINWIDTHN, 1, margin ? marginWidth : 0);
2876 SendEditor(SCI_SETMARGINWIDTHN, 0, lineNumbers ?lineNumbersWidth : 0);
2878 bufferedDraw = props->GetInt("buffered.draw", 1);
2879 SendEditor(SCI_SETBUFFEREDDRAW, bufferedDraw);
2881 SendEditor(SCI_SETLAYOUTCACHE, props->GetInt("cache.layout"));
2883 bracesCheck = props->GetInt("braces.check");
2884 bracesSloppy = props->GetInt("braces.sloppy");
2886 wordCharacters = props->GetNewExpand("word.characters.", fileNameForExtension.c_str());
2887 if (wordCharacters.length()) {
2888 SendEditorString(SCI_SETWORDCHARS, 0, wordCharacters.c_str());
2889 } else {
2890 SendEditor(SCI_SETWORDCHARS, 0, 0);
2891 wordCharacters = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2893 // Why call this??
2894 // SendEditor(SCI_MARKERDELETEALL, static_cast<unsigned long>( -1));
2896 SendEditor(SCI_SETTABINDENTS, props->GetInt("tab.indents", 1));
2897 SendEditor(SCI_SETBACKSPACEUNINDENTS, props->GetInt("backspace.unindents", 1));
2899 SendEditor(SCI_SETUSETABS, props->GetInt("use.tabs", 1));
2900 int tabSize = props->GetInt("tabsize");
2901 if (tabSize) {
2902 SendEditor(SCI_SETTABWIDTH, tabSize);
2904 indentSize = props->GetInt("indent.size");
2905 SendEditor(SCI_SETINDENT, indentSize);
2907 indentOpening = props->GetInt("indent.opening");
2908 indentClosing = props->GetInt("indent.closing");
2910 indentMaintain = props->GetNewExpand("indent.maintain.", fileNameForExtension.c_str()).value();
2912 SString lookback = props->GetNewExpand("statement.lookback.", fileNameForExtension.c_str());
2913 statementLookback = lookback.value();
2914 statementIndent = GetStyleAndWords("statement.indent.");
2915 statementEnd =GetStyleAndWords("statement.end.");
2916 blockStart = GetStyleAndWords("block.start.");
2917 blockEnd = GetStyleAndWords("block.end.");
2921 SString list;
2922 list = props->GetNewExpand("preprocessor.symbol.", fileNameForExtension.c_str());
2923 preprocessorSymbol = list[0];
2924 list = props->GetNewExpand("preprocessor.start.", fileNameForExtension.c_str());
2925 preprocCondStart.Clear();
2926 preprocCondStart.Set(list.c_str());
2927 list = props->GetNewExpand("preprocessor.middle.", fileNameForExtension.c_str());
2928 preprocCondMiddle.Clear();
2929 preprocCondMiddle.Set(list.c_str());
2930 list = props->GetNewExpand("preprocessor.end.", fileNameForExtension.c_str());
2931 preprocCondEnd.Clear();
2932 preprocCondEnd.Set(list.c_str());
2935 if (props->GetInt("vc.home.key", 1)) {
2936 AssignKey(SCK_HOME, 0, SCI_VCHOME);
2937 AssignKey(SCK_HOME, SCMOD_SHIFT, SCI_VCHOMEEXTEND);
2938 } else {
2939 AssignKey(SCK_HOME, 0, SCI_HOME);
2940 AssignKey(SCK_HOME, SCMOD_SHIFT, SCI_HOMEEXTEND);
2942 if (props->GetInt("fold.underline"))
2943 SendEditor(SCI_SETFOLDFLAGS, props->GetInt("fold.flags"));
2944 else
2945 SendEditor(SCI_SETFOLDFLAGS, 0);
2947 // To put the folder markers in the line number region
2948 //SendEditor(SCI_SETMARGINMASKN, 0, SC_MASK_FOLDERS);
2950 SendEditor(SCI_SETMODEVENTMASK, SC_MOD_CHANGEFOLD);
2952 if (0==props->GetInt("undo.redo.lazy")) {
2953 // Trap for insert/delete notifications (also fired by undo
2954 // and redo) so that the buttons can be enabled if needed.
2955 SendEditor(SCI_SETMODEVENTMASK, SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT
2956 | SC_LASTSTEPINUNDOREDO | SendEditor(SCI_GETMODEVENTMASK, 0));
2958 //SC_LASTSTEPINUNDOREDO is probably not needed in the mask; it
2959 //doesn't seem to fire as an event of its own; just modifies the
2960 //insert and delete events.
2963 // Create a margin column for the folding symbols
2964 SendEditor(SCI_SETMARGINTYPEN, 2, SC_MARGIN_SYMBOL);
2966 SendEditor(SCI_SETMARGINWIDTHN, 2, foldMargin ? foldMarginWidth : 0);
2968 SendEditor(SCI_SETMARGINMASKN, 2, SC_MASK_FOLDERS);
2969 SendEditor(SCI_SETMARGINSENSITIVEN, 1, 1); // Breakpoints-Bookmarks
2970 SendEditor(SCI_SETMARGINSENSITIVEN, 2, 1);
2972 SString fold_symbols = props->Get("fold.symbols");
2973 SetFoldSymbols (fold_symbols);
2975 // Well, unlike scite, we want it everytime.
2976 firstPropertiesRead = true;
2979 void AnEditor::SetFoldSymbols(SString fold_symbols)
2981 if (fold_symbols.length() <= 0)
2982 fold_symbols = "plus/minus";
2983 if (strcasecmp(fold_symbols.c_str(), "arrows") == 0)
2985 // Arrow pointing right for contracted folders, arrow pointing down for expanded
2986 DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_ARROWDOWN, Colour(0, 0, 0), Colour(0, 0, 0));
2987 DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_ARROW, Colour(0, 0, 0), Colour(0, 0, 0));
2988 DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, Colour(0, 0, 0), Colour(0, 0, 0));
2989 DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, Colour(0, 0, 0), Colour(0, 0, 0));
2990 DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
2991 DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
2992 DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
2993 } else if (strcasecmp(fold_symbols.c_str(), "circular") == 0) {
2994 // Like a flattened tree control using circular headers and curved joins
2995 DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
2996 DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
2997 DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
2998 DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
2999 DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
3000 DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
3001 DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE, Colour(0xff, 0xff, 0xff), Colour(0x40, 0x40, 0x40));
3002 } else if (strcasecmp(fold_symbols.c_str(), "squares") == 0) {
3003 // Like a flattened tree control using square headers
3004 DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3005 DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3006 DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3007 DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3008 DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3009 DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3010 DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER, Colour(0xff, 0xff, 0xff), Colour(0x80, 0x80, 0x80));
3011 } else { // Default
3012 // Plus for contracted folders, minus for expanded
3013 DefineMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3014 DefineMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3015 DefineMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3016 DefineMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3017 DefineMarker(SC_MARKNUM_FOLDEREND, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3018 DefineMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3019 DefineMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_EMPTY, Colour(0xff, 0xff, 0xff), Colour(0, 0, 0));
3023 // Anjuta: In our case, we read it everytime
3024 void AnEditor::ReadPropertiesInitial() {
3025 indentationWSVisible = props->GetInt("view.indentation.whitespace", 1);
3026 ViewWhitespace(props->GetInt("view.whitespace"));
3027 SendEditor(SCI_SETINDENTATIONGUIDES, props->GetInt("view.indentation.guides"));
3028 SendEditor(SCI_SETVIEWEOL, props->GetInt("view.eol"));
3030 SetReadOnly(props->GetInt("file.readonly", 0));
3031 SetLineWrap(props->GetInt("view.line.wrap", 1));
3033 //lineNumbersWidth = 0;
3034 /* FIXME: This is nowhere configureable
3035 SString linenums = props->Get("margin.linenumber.width");
3036 if (linenums.length())
3037 lineNumbersWidth = linenums.value(); */
3038 //lineNumbers = lineNumbersWidth;
3039 /* We do this dynamicly in text_editor_load_file now */
3040 /* if (lineNumbersWidth == 0)
3041 lineNumbersWidth = lineNumbersWidthDefault;*/
3043 marginWidth = 0;
3044 SString margwidth = props->Get("margin.marker.width");
3045 if (margwidth.length())
3046 marginWidth = margwidth.value();
3047 margin = marginWidth;
3048 if (marginWidth == 0)
3049 marginWidth = marginWidthDefault;
3051 foldMarginWidth = props->GetInt("margin.fold.width", foldMarginWidthDefault);
3052 foldMargin = foldMarginWidth;
3053 if (foldMarginWidth == 0)
3054 foldMarginWidth = foldMarginWidthDefault;
3056 lineNumbers = props->GetInt("margin.linenumber.visible", 0);
3057 SendEditor(SCI_SETMARGINWIDTHN, 0, lineNumbers ? lineNumbersWidth : 0);
3058 margin = props->GetInt("margin.marker.visible", 0);
3059 SendEditor(SCI_SETMARGINWIDTHN, 1, margin ? marginWidth : 0);
3061 foldMargin = props->GetInt("margin.fold.visible", 1);
3062 SendEditor(SCI_SETMARGINWIDTHN, 2, foldMargin ? foldMarginWidth : 0);
3065 void AnEditor::DefineMarker(int marker, int markerType, Colour fore, Colour back)
3067 SendEditor(SCI_MARKERDEFINE, marker, markerType);
3068 SendEditor(SCI_MARKERSETFORE, marker, fore.AsLong());
3069 SendEditor(SCI_MARKERSETBACK, marker, back.AsLong());
3072 int AnEditor::GetBookmarkLine( const int nLineStart )
3074 int nNextLine = SendEditor(SCI_MARKERNEXT, nLineStart+1, 1 << ANE_MARKER_BOOKMARK);
3075 //printf( "...look %d --> %d\n", nLineStart, nNextLine );
3076 if ( (nNextLine < 0) || (nNextLine == nLineStart) )
3077 return -1 ;
3078 else
3079 return nNextLine;
3082 void AnEditor::FocusInEvent(GtkWidget* widget)
3084 if (calltipShown)
3086 StartCallTip_new();
3090 void AnEditor::FocusOutEvent(GtkWidget* widget)
3092 if (SendEditor(SCI_CALLTIPACTIVE))
3094 SendEditor(SCI_CALLTIPCANCEL);
3095 calltipShown = true;
3097 else
3099 calltipShown = false;
3103 static GList* editors;
3105 static AnEditor*
3106 aneditor_get(AnEditorID id)
3108 AnEditor* ed;
3109 if(id >= g_list_length(editors))
3111 DEBUG_PRINT("Invalid AnEditorID supplied");
3112 return NULL;
3114 ed = (AnEditor*)g_list_nth_data(editors, (guint)id);
3115 if(!ed)
3117 DEBUG_PRINT("Trying to use already destroyed AnEditor Object");
3118 return NULL;
3120 return ed;
3123 AnEditorID
3124 aneditor_new(gpointer propset)
3126 AnEditor* ed = new AnEditor((PropSetFile*)propset);
3127 if (!ed)
3129 DEBUG_PRINT("Memory allocation error.");
3130 return ANE_ID_INVALID;
3132 g_signal_connect(ed->GetID(), "focus_in_event",
3133 G_CALLBACK(on_aneditor_focus_in), ed);
3134 g_signal_connect(ed->GetID(), "focus_out_event",
3135 G_CALLBACK(on_aneditor_focus_out), ed);
3136 editors = g_list_append(editors, ed);
3137 return (AnEditorID)(g_list_length(editors) - 1);
3140 void
3141 aneditor_destroy(AnEditorID id)
3143 AnEditor* ed;
3145 ed = aneditor_get(id);
3146 if(!ed) return;
3148 /* We will not remove the editor from the list */
3149 /* so that already assigned handles work properly */
3150 /* We'll simply make it NULL to indicate that the */
3151 /* editor is destroyed */
3152 g_list_nth(editors, id)->data = NULL;
3154 /* Disconnect the focus in/out signals */
3155 g_signal_handlers_disconnect_by_func (ed->GetID(),
3156 (void*)G_CALLBACK(on_aneditor_focus_in), ed);
3157 g_signal_handlers_disconnect_by_func (ed->GetID(),
3158 (void*)G_CALLBACK(on_aneditor_focus_out), ed);
3160 delete ed;
3163 GtkWidget*
3164 aneditor_get_widget(AnEditorID handle)
3166 AnEditor *ed;
3167 ed = aneditor_get(handle);
3168 if(!ed) return NULL;
3170 // Forced conversion is safe here, so do it.
3171 return (GtkWidget*)ed->GetID();
3174 glong
3175 aneditor_command(AnEditorID handle, gint command, glong wparam, glong lparam)
3177 AnEditor *ed;
3178 ed = aneditor_get(handle);
3179 if(!ed) return 0;
3180 return ed->Command(command, wparam, lparam);
3183 void
3184 aneditor_set_focused_ed_ID(AnEditorID id)
3186 AnEditor::focusedID = id;
3189 void
3190 aneditor_set_parent(AnEditorID id, AnEditorID parent_id)
3192 AnEditor *editor;
3193 AnEditor *parent;
3195 editor = aneditor_get (id);
3196 parent = aneditor_get (parent_id);
3197 editor->SetParent(parent);
3200 gint
3201 on_aneditor_focus_in (GtkWidget* widget, gpointer* unused, AnEditor* ed)
3203 ed->FocusInEvent(widget);
3204 return FALSE;
3207 gint
3208 on_aneditor_focus_out (GtkWidget* widget, gpointer * unused, AnEditor* ed)
3210 ed->EndDebugEval();
3211 ed->FocusOutEvent(widget);
3212 return FALSE;