Add and use utils_get_help_url().
[geany-mirror.git] / scintilla / ScintillaBase.cxx
blobb463b88da2628c0d37b06471cf88955571e6dd1d
1 // Scintilla source code edit control
2 /** @file ScintillaBase.cxx
3 ** An enhanced subclass of Editor with calltips, autocomplete and context menu.
4 **/
5 // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <ctype.h>
13 #include "Platform.h"
15 #include "Scintilla.h"
16 #include "PropSet.h"
17 #ifdef SCI_LEXER
18 #include "SciLexer.h"
19 #include "Accessor.h"
20 #include "DocumentAccessor.h"
21 #include "KeyWords.h"
22 #endif
23 #include "SplitVector.h"
24 #include "Partitioning.h"
25 #include "RunStyles.h"
26 #include "ContractionState.h"
27 #include "CellBuffer.h"
28 #include "CallTip.h"
29 #include "KeyMap.h"
30 #include "Indicator.h"
31 #include "XPM.h"
32 #include "LineMarker.h"
33 #include "Style.h"
34 #include "ViewStyle.h"
35 #include "AutoComplete.h"
36 #include "CharClassify.h"
37 #include "Decoration.h"
38 #include "Document.h"
39 #include "PositionCache.h"
40 #include "Editor.h"
41 #include "ScintillaBase.h"
43 #ifdef SCI_NAMESPACE
44 using namespace Scintilla;
45 #endif
47 ScintillaBase::ScintillaBase() {
48 displayPopupMenu = true;
49 listType = 0;
50 maxListWidth = 0;
51 #ifdef SCI_LEXER
52 lexLanguage = SCLEX_CONTAINER;
53 performingStyle = false;
54 lexCurrent = 0;
55 for (int wl = 0;wl < numWordLists;wl++)
56 keyWordLists[wl] = new WordList;
57 keyWordLists[numWordLists] = 0;
58 #endif
61 ScintillaBase::~ScintillaBase() {
62 #ifdef SCI_LEXER
63 for (int wl = 0;wl < numWordLists;wl++)
64 delete keyWordLists[wl];
65 #endif
68 void ScintillaBase::Finalise() {
69 Editor::Finalise();
70 popup.Destroy();
73 void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
74 Editor::RefreshColourPalette(pal, want);
75 ct.RefreshColourPalette(pal, want);
78 void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
79 bool isFillUp = ac.Active() && ac.IsFillUpChar(*s);
80 if (!isFillUp) {
81 Editor::AddCharUTF(s, len, treatAsDBCS);
83 if (ac.Active()) {
84 AutoCompleteCharacterAdded(s[0]);
85 // For fill ups add the character after the autocompletion has
86 // triggered so containers see the key so can display a calltip.
87 if (isFillUp) {
88 Editor::AddCharUTF(s, len, treatAsDBCS);
93 void ScintillaBase::Command(int cmdId) {
95 switch (cmdId) {
97 case idAutoComplete: // Nothing to do
99 break;
101 case idCallTip: // Nothing to do
103 break;
105 case idcmdUndo:
106 WndProc(SCI_UNDO, 0, 0);
107 break;
109 case idcmdRedo:
110 WndProc(SCI_REDO, 0, 0);
111 break;
113 case idcmdCut:
114 WndProc(SCI_CUT, 0, 0);
115 break;
117 case idcmdCopy:
118 WndProc(SCI_COPY, 0, 0);
119 break;
121 case idcmdPaste:
122 WndProc(SCI_PASTE, 0, 0);
123 break;
125 case idcmdDelete:
126 WndProc(SCI_CLEAR, 0, 0);
127 break;
129 case idcmdSelectAll:
130 WndProc(SCI_SELECTALL, 0, 0);
131 break;
135 int ScintillaBase::KeyCommand(unsigned int iMessage) {
136 // Most key commands cancel autocompletion mode
137 if (ac.Active()) {
138 switch (iMessage) {
139 // Except for these
140 case SCI_LINEDOWN:
141 AutoCompleteMove(1);
142 return 0;
143 case SCI_LINEUP:
144 AutoCompleteMove( -1);
145 return 0;
146 case SCI_PAGEDOWN:
147 AutoCompleteMove(5);
148 return 0;
149 case SCI_PAGEUP:
150 AutoCompleteMove( -5);
151 return 0;
152 case SCI_VCHOME:
153 AutoCompleteMove( -5000);
154 return 0;
155 case SCI_LINEEND:
156 AutoCompleteMove(5000);
157 return 0;
158 case SCI_DELETEBACK:
159 DelCharBack(true);
160 AutoCompleteCharacterDeleted();
161 EnsureCaretVisible();
162 return 0;
163 case SCI_DELETEBACKNOTLINE:
164 DelCharBack(false);
165 AutoCompleteCharacterDeleted();
166 EnsureCaretVisible();
167 return 0;
168 case SCI_TAB:
169 AutoCompleteCompleted();
170 return 0;
171 case SCI_NEWLINE:
172 AutoCompleteCompleted();
173 return 0;
175 default:
176 AutoCompleteCancel();
180 if (ct.inCallTipMode) {
181 if (
182 (iMessage != SCI_CHARLEFT) &&
183 (iMessage != SCI_CHARLEFTEXTEND) &&
184 (iMessage != SCI_CHARRIGHT) &&
185 (iMessage != SCI_CHARRIGHTEXTEND) &&
186 (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
187 (iMessage != SCI_DELETEBACK) &&
188 (iMessage != SCI_DELETEBACKNOTLINE)
190 ct.CallTipCancel();
192 if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) {
193 if (currentPos <= ct.posStartCallTip) {
194 ct.CallTipCancel();
198 return Editor::KeyCommand(iMessage);
201 void ScintillaBase::AutoCompleteDoubleClick(void* p) {
202 ScintillaBase* sci = reinterpret_cast<ScintillaBase*>(p);
203 sci->AutoCompleteCompleted();
206 void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
207 //Platform::DebugPrintf("AutoComplete %s\n", list);
208 ct.CallTipCancel();
210 if (ac.chooseSingle && (listType == 0)) {
211 if (list && !strchr(list, ac.GetSeparator())) {
212 const char *typeSep = strchr(list, ac.GetTypesep());
213 size_t lenInsert = (typeSep) ? (typeSep-list) : strlen(list);
214 if (ac.ignoreCase) {
215 SetEmptySelection(currentPos - lenEntered);
216 pdoc->DeleteChars(currentPos, lenEntered);
217 SetEmptySelection(currentPos);
218 pdoc->InsertString(currentPos, list, lenInsert);
219 SetEmptySelection(currentPos + lenInsert);
220 } else {
221 SetEmptySelection(currentPos);
222 pdoc->InsertString(currentPos, list + lenEntered, lenInsert - lenEntered);
223 SetEmptySelection(currentPos + lenInsert - lenEntered);
225 return;
228 ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos),
229 lenEntered, vs.lineHeight, IsUnicodeMode());
231 PRectangle rcClient = GetClientRectangle();
232 Point pt = LocationFromPosition(currentPos - lenEntered);
233 PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
234 if (rcPopupBounds.Height() == 0)
235 rcPopupBounds = rcClient;
237 int heightLB = 100;
238 int widthLB = 100;
239 if (pt.x >= rcClient.right - widthLB) {
240 HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB);
241 Redraw();
242 pt = LocationFromPosition(currentPos);
244 PRectangle rcac;
245 rcac.left = pt.x - ac.lb->CaretFromEdge();
246 if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below.
247 pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above.
248 rcac.top = pt.y - heightLB;
249 if (rcac.top < rcPopupBounds.top) {
250 heightLB -= (rcPopupBounds.top - rcac.top);
251 rcac.top = rcPopupBounds.top;
253 } else {
254 rcac.top = pt.y + vs.lineHeight;
256 rcac.right = rcac.left + widthLB;
257 rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcPopupBounds.bottom);
258 ac.lb->SetPositionRelative(rcac, wMain);
259 ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
260 unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
261 ac.lb->SetAverageCharWidth(aveCharWidth);
262 ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);
264 ac.SetList(list);
266 // Fiddle the position of the list so it is right next to the target and wide enough for all its strings
267 PRectangle rcList = ac.lb->GetDesiredRect();
268 int heightAlloced = rcList.bottom - rcList.top;
269 widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left);
270 if (maxListWidth != 0)
271 widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth);
272 // Make an allowance for large strings in list
273 rcList.left = pt.x - ac.lb->CaretFromEdge();
274 rcList.right = rcList.left + widthLB;
275 if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Wont fit below.
276 ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above.
277 rcList.top = pt.y - heightAlloced;
278 } else {
279 rcList.top = pt.y + vs.lineHeight;
281 rcList.bottom = rcList.top + heightAlloced;
282 ac.lb->SetPositionRelative(rcList, wMain);
283 ac.Show(true);
284 if (lenEntered != 0) {
285 AutoCompleteMoveToCurrentWord();
289 void ScintillaBase::AutoCompleteCancel() {
290 if (ac.Active()) {
291 SCNotification scn = {0};
292 scn.nmhdr.code = SCN_AUTOCCANCELLED;
293 scn.wParam = 0;
294 scn.listType = 0;
295 NotifyParent(scn);
297 ac.Cancel();
300 void ScintillaBase::AutoCompleteMove(int delta) {
301 ac.Move(delta);
304 void ScintillaBase::AutoCompleteMoveToCurrentWord() {
305 char wordCurrent[1000];
306 int i;
307 int startWord = ac.posStart - ac.startLen;
308 for (i = startWord; i < currentPos && i - startWord < 1000; i++)
309 wordCurrent[i - startWord] = pdoc->CharAt(i);
310 wordCurrent[Platform::Minimum(i - startWord, 999)] = '\0';
311 ac.Select(wordCurrent);
314 void ScintillaBase::AutoCompleteCharacterAdded(char ch) {
315 if (ac.IsFillUpChar(ch)) {
316 AutoCompleteCompleted();
317 } else if (ac.IsStopChar(ch)) {
318 AutoCompleteCancel();
319 } else {
320 AutoCompleteMoveToCurrentWord();
324 void ScintillaBase::AutoCompleteCharacterDeleted() {
325 if (currentPos < ac.posStart - ac.startLen) {
326 AutoCompleteCancel();
327 } else if (ac.cancelAtStartPos && (currentPos <= ac.posStart)) {
328 AutoCompleteCancel();
329 } else {
330 AutoCompleteMoveToCurrentWord();
332 SCNotification scn = {0};
333 scn.nmhdr.code = SCN_AUTOCCHARDELETED;
334 scn.wParam = 0;
335 scn.listType = 0;
336 NotifyParent(scn);
339 void ScintillaBase::AutoCompleteCompleted() {
340 int item = ac.lb->GetSelection();
341 char selected[1000];
342 selected[0] = '\0';
343 if (item != -1) {
344 ac.lb->GetValue(item, selected, sizeof(selected));
345 } else {
346 AutoCompleteCancel();
347 return;
350 ac.Show(false);
352 listSelected = selected;
353 SCNotification scn = {0};
354 scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
355 scn.message = 0;
356 scn.wParam = listType;
357 scn.listType = listType;
358 Position firstPos = ac.posStart - ac.startLen;
359 scn.lParam = firstPos;
360 scn.text = listSelected.c_str();
361 NotifyParent(scn);
363 if (!ac.Active())
364 return;
365 ac.Cancel();
367 if (listType > 0)
368 return;
370 Position endPos = currentPos;
371 if (ac.dropRestOfWord)
372 endPos = pdoc->ExtendWordSelect(endPos, 1, true);
373 if (endPos < firstPos)
374 return;
375 pdoc->BeginUndoAction();
376 if (endPos != firstPos) {
377 pdoc->DeleteChars(firstPos, endPos - firstPos);
379 SetEmptySelection(ac.posStart);
380 if (item != -1) {
381 SString piece = selected;
382 pdoc->InsertCString(firstPos, piece.c_str());
383 SetEmptySelection(firstPos + static_cast<int>(piece.length()));
385 pdoc->EndUndoAction();
388 int ScintillaBase::AutoCompleteGetCurrent() {
389 if (!ac.Active())
390 return -1;
391 return ac.lb->GetSelection();
394 int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) {
395 if (ac.Active()) {
396 int item = ac.lb->GetSelection();
397 char selected[1000];
398 selected[0] = '\0';
399 if (item != -1) {
400 ac.lb->GetValue(item, selected, sizeof(selected));
401 if (buffer != NULL)
402 strcpy(buffer, selected);
403 return strlen(selected);
406 if (buffer != NULL)
407 *buffer = '\0';
408 return 0;
411 void ScintillaBase::CallTipShow(Point pt, const char *defn) {
412 ac.Cancel();
413 pt.y += vs.lineHeight;
414 // If container knows about STYLE_CALLTIP then use it in place of the
415 // STYLE_DEFAULT for the face name, size and character set. Also use it
416 // for the foreground and background colour.
417 int ctStyle = ct.UseStyleCallTip() ? STYLE_CALLTIP : STYLE_DEFAULT;
418 if (ct.UseStyleCallTip()) {
419 ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back);
421 PRectangle rc = ct.CallTipStart(currentPos, pt,
422 defn,
423 vs.styles[ctStyle].fontName,
424 vs.styles[ctStyle].sizeZoomed,
425 CodePage(),
426 vs.styles[ctStyle].characterSet,
427 wMain);
428 // If the call-tip window would be out of the client
429 // space, adjust so it displays above the text.
430 PRectangle rcClient = GetClientRectangle();
431 if (rc.bottom > rcClient.bottom) {
432 int offset = vs.lineHeight + rc.Height();
433 rc.top -= offset;
434 rc.bottom -= offset;
436 // Now display the window.
437 CreateCallTipWindow(rc);
438 ct.wCallTip.SetPositionRelative(rc, wMain);
439 ct.wCallTip.Show();
442 void ScintillaBase::CallTipClick() {
443 SCNotification scn = {0};
444 scn.nmhdr.code = SCN_CALLTIPCLICK;
445 scn.position = ct.clickPlace;
446 NotifyParent(scn);
449 void ScintillaBase::ContextMenu(Point pt) {
450 if (displayPopupMenu) {
451 bool writable = !WndProc(SCI_GETREADONLY, 0, 0);
452 popup.CreatePopUp();
453 AddToPopUp("Undo", idcmdUndo, writable && pdoc->CanUndo());
454 AddToPopUp("Redo", idcmdRedo, writable && pdoc->CanRedo());
455 AddToPopUp("");
456 AddToPopUp("Cut", idcmdCut, writable && currentPos != anchor);
457 AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
458 AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0));
459 AddToPopUp("Delete", idcmdDelete, writable && currentPos != anchor);
460 AddToPopUp("");
461 AddToPopUp("Select All", idcmdSelectAll);
462 popup.Show(pt, wMain);
466 void ScintillaBase::CancelModes() {
467 AutoCompleteCancel();
468 ct.CallTipCancel();
469 Editor::CancelModes();
472 void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
473 CancelModes();
474 Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
477 #ifdef SCI_LEXER
478 void ScintillaBase::SetLexer(uptr_t wParam) {
479 lexLanguage = wParam;
480 lexCurrent = LexerModule::Find(lexLanguage);
481 if (!lexCurrent)
482 lexCurrent = LexerModule::Find(SCLEX_NULL);
485 void ScintillaBase::SetLexerLanguage(const char *languageName) {
486 lexLanguage = SCLEX_CONTAINER;
487 lexCurrent = LexerModule::Find(languageName);
488 if (!lexCurrent)
489 lexCurrent = LexerModule::Find(SCLEX_NULL);
490 if (lexCurrent)
491 lexLanguage = lexCurrent->GetLanguage();
494 void ScintillaBase::Colourise(int start, int end) {
495 if (!performingStyle) {
496 // Protect against reentrance, which may occur, for example, when
497 // fold points are discovered while performing styling and the folding
498 // code looks for child lines which may trigger styling.
499 performingStyle = true;
501 int lengthDoc = pdoc->Length();
502 if (end == -1)
503 end = lengthDoc;
504 int len = end - start;
506 PLATFORM_ASSERT(len >= 0);
507 PLATFORM_ASSERT(start + len <= lengthDoc);
509 //WindowAccessor styler(wMain.GetID(), props);
510 DocumentAccessor styler(pdoc, props, wMain.GetID());
512 int styleStart = 0;
513 if (start > 0)
514 styleStart = styler.StyleAt(start - 1) & pdoc->stylingBitsMask;
515 styler.SetCodePage(pdoc->dbcsCodePage);
517 if (lexCurrent && (len > 0)) { // Should always succeed as null lexer should always be available
518 lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
519 styler.Flush();
520 if (styler.GetPropertyInt("fold")) {
521 lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
522 styler.Flush();
526 performingStyle = false;
529 #endif
531 void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
532 #ifdef SCI_LEXER
533 if (lexLanguage != SCLEX_CONTAINER) {
534 int endStyled = WndProc(SCI_GETENDSTYLED, 0, 0);
535 int lineEndStyled = WndProc(SCI_LINEFROMPOSITION, endStyled, 0);
536 endStyled = WndProc(SCI_POSITIONFROMLINE, lineEndStyled, 0);
537 Colourise(endStyled, endStyleNeeded);
538 return;
540 #endif
541 Editor::NotifyStyleToNeeded(endStyleNeeded);
544 sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
545 switch (iMessage) {
546 case SCI_AUTOCSHOW:
547 listType = 0;
548 AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
549 break;
551 case SCI_AUTOCCANCEL:
552 ac.Cancel();
553 break;
555 case SCI_AUTOCACTIVE:
556 return ac.Active();
558 case SCI_AUTOCPOSSTART:
559 return ac.posStart;
561 case SCI_AUTOCCOMPLETE:
562 AutoCompleteCompleted();
563 break;
565 case SCI_AUTOCSETSEPARATOR:
566 ac.SetSeparator(static_cast<char>(wParam));
567 break;
569 case SCI_AUTOCGETSEPARATOR:
570 return ac.GetSeparator();
572 case SCI_AUTOCSTOPS:
573 ac.SetStopChars(reinterpret_cast<char *>(lParam));
574 break;
576 case SCI_AUTOCSELECT:
577 ac.Select(reinterpret_cast<char *>(lParam));
578 break;
580 case SCI_AUTOCGETCURRENT:
581 return AutoCompleteGetCurrent();
583 case SCI_AUTOCGETCURRENTTEXT:
584 return AutoCompleteGetCurrentText(reinterpret_cast<char *>(lParam));
586 case SCI_AUTOCSETCANCELATSTART:
587 ac.cancelAtStartPos = wParam != 0;
588 break;
590 case SCI_AUTOCGETCANCELATSTART:
591 return ac.cancelAtStartPos;
593 case SCI_AUTOCSETFILLUPS:
594 ac.SetFillUpChars(reinterpret_cast<char *>(lParam));
595 break;
597 case SCI_AUTOCSETCHOOSESINGLE:
598 ac.chooseSingle = wParam != 0;
599 break;
601 case SCI_AUTOCGETCHOOSESINGLE:
602 return ac.chooseSingle;
604 case SCI_AUTOCSETIGNORECASE:
605 ac.ignoreCase = wParam != 0;
606 break;
608 case SCI_AUTOCGETIGNORECASE:
609 return ac.ignoreCase;
611 case SCI_USERLISTSHOW:
612 listType = wParam;
613 AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
614 break;
616 case SCI_AUTOCSETAUTOHIDE:
617 ac.autoHide = wParam != 0;
618 break;
620 case SCI_AUTOCGETAUTOHIDE:
621 return ac.autoHide;
623 case SCI_AUTOCSETDROPRESTOFWORD:
624 ac.dropRestOfWord = wParam != 0;
625 break;
627 case SCI_AUTOCGETDROPRESTOFWORD:
628 return ac.dropRestOfWord;
630 case SCI_AUTOCSETMAXHEIGHT:
631 ac.lb->SetVisibleRows(wParam);
632 break;
634 case SCI_AUTOCGETMAXHEIGHT:
635 return ac.lb->GetVisibleRows();
637 case SCI_AUTOCSETMAXWIDTH:
638 maxListWidth = wParam;
639 break;
641 case SCI_AUTOCGETMAXWIDTH:
642 return maxListWidth;
644 case SCI_REGISTERIMAGE:
645 ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
646 break;
648 case SCI_CLEARREGISTEREDIMAGES:
649 ac.lb->ClearRegisteredImages();
650 break;
652 case SCI_AUTOCSETTYPESEPARATOR:
653 ac.SetTypesep(static_cast<char>(wParam));
654 break;
656 case SCI_AUTOCGETTYPESEPARATOR:
657 return ac.GetTypesep();
659 case SCI_CALLTIPSHOW:
660 CallTipShow(LocationFromPosition(wParam),
661 reinterpret_cast<const char *>(lParam));
662 break;
664 case SCI_CALLTIPCANCEL:
665 ct.CallTipCancel();
666 break;
668 case SCI_CALLTIPACTIVE:
669 return ct.inCallTipMode;
671 case SCI_CALLTIPPOSSTART:
672 return ct.posStartCallTip;
674 case SCI_CALLTIPSETHLT:
675 ct.SetHighlight(wParam, lParam);
676 break;
678 case SCI_CALLTIPSETBACK:
679 ct.colourBG = ColourDesired(wParam);
680 vs.styles[STYLE_CALLTIP].back = ct.colourBG;
681 InvalidateStyleRedraw();
682 break;
684 case SCI_CALLTIPSETFORE:
685 ct.colourUnSel = ColourDesired(wParam);
686 vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel;
687 InvalidateStyleRedraw();
688 break;
690 case SCI_CALLTIPSETFOREHLT:
691 ct.colourSel = ColourDesired(wParam);
692 InvalidateStyleRedraw();
693 break;
695 case SCI_CALLTIPUSESTYLE:
696 ct.SetTabSize((int)wParam);
697 InvalidateStyleRedraw();
698 break;
700 case SCI_USEPOPUP:
701 displayPopupMenu = wParam != 0;
702 break;
704 #ifdef SCI_LEXER
705 case SCI_SETLEXER:
706 SetLexer(wParam);
707 lexLanguage = wParam;
708 break;
710 case SCI_GETLEXER:
711 return lexLanguage;
713 case SCI_COLOURISE:
714 if (lexLanguage == SCLEX_CONTAINER) {
715 pdoc->ModifiedAt(wParam);
716 NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
717 } else {
718 Colourise(wParam, lParam);
720 Redraw();
721 break;
723 case SCI_SETPROPERTY:
724 props.Set(reinterpret_cast<const char *>(wParam),
725 reinterpret_cast<const char *>(lParam));
726 break;
728 case SCI_GETPROPERTY: {
729 SString val = props.Get(reinterpret_cast<const char *>(wParam));
730 const int n = val.length();
731 if (lParam != 0) {
732 char *ptr = reinterpret_cast<char *>(lParam);
733 memcpy(ptr, val.c_str(), n);
734 ptr[n] = '\0'; // terminate
736 return n; // Not including NUL
739 case SCI_GETPROPERTYEXPANDED: {
740 SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
741 const int n = val.length();
742 if (lParam != 0) {
743 char *ptr = reinterpret_cast<char *>(lParam);
744 memcpy(ptr, val.c_str(), n);
745 ptr[n] = '\0'; // terminate
747 return n; // Not including NUL
750 case SCI_GETPROPERTYINT:
751 return props.GetInt(reinterpret_cast<const char *>(wParam), lParam);
753 case SCI_SETKEYWORDS:
754 if (wParam < numWordLists) {
755 keyWordLists[wParam]->Clear();
756 keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
758 break;
760 case SCI_SETLEXERLANGUAGE:
761 SetLexerLanguage(reinterpret_cast<const char *>(lParam));
762 break;
764 case SCI_GETSTYLEBITSNEEDED:
765 return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
766 #endif
768 default:
769 return Editor::WndProc(iMessage, wParam, lParam);
771 return 0l;