]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/ScintillaBase.cxx
6be8b74b533134932031686896dfc313572d4710
[wxWidgets.git] / contrib / src / stc / scintilla / src / ScintillaBase.cxx
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.
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <ctype.h>
12
13 #include "Platform.h"
14
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 "ContractionState.h"
24 #include "SVector.h"
25 #include "CellBuffer.h"
26 #include "CallTip.h"
27 #include "KeyMap.h"
28 #include "Indicator.h"
29 #include "XPM.h"
30 #include "LineMarker.h"
31 #include "Style.h"
32 #include "ViewStyle.h"
33 #include "AutoComplete.h"
34 #include "Document.h"
35 #include "Editor.h"
36 #include "ScintillaBase.h"
37
38 ScintillaBase::ScintillaBase() {
39 displayPopupMenu = true;
40 listType = 0;
41 maxListWidth = 0;
42 #ifdef SCI_LEXER
43 lexLanguage = SCLEX_CONTAINER;
44 performingStyle = false;
45 lexCurrent = 0;
46 for (int wl = 0;wl < numWordLists;wl++)
47 keyWordLists[wl] = new WordList;
48 keyWordLists[numWordLists] = 0;
49 #endif
50 }
51
52 ScintillaBase::~ScintillaBase() {
53 #ifdef SCI_LEXER
54 for (int wl = 0;wl < numWordLists;wl++)
55 delete keyWordLists[wl];
56 #endif
57 }
58
59 void ScintillaBase::Finalise() {
60 Editor::Finalise();
61 popup.Destroy();
62 }
63
64 void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) {
65 Editor::RefreshColourPalette(pal, want);
66 ct.RefreshColourPalette(pal, want);
67 }
68
69 void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
70 bool isFillUp = ac.Active() && ac.IsFillUpChar(*s);
71 if (!isFillUp) {
72 Editor::AddCharUTF(s, len, treatAsDBCS);
73 }
74 if (ac.Active()) {
75 AutoCompleteCharacterAdded(s[0]);
76 // For fill ups add the character after the autocompletion has
77 // triggered so containers see the key so can display a calltip.
78 if (isFillUp) {
79 Editor::AddCharUTF(s, len, treatAsDBCS);
80 }
81 }
82 }
83
84 void ScintillaBase::Command(int cmdId) {
85
86 switch (cmdId) {
87
88 case idAutoComplete: // Nothing to do
89
90 break;
91
92 case idCallTip: // Nothing to do
93
94 break;
95
96 case idcmdUndo:
97 WndProc(SCI_UNDO, 0, 0);
98 break;
99
100 case idcmdRedo:
101 WndProc(SCI_REDO, 0, 0);
102 break;
103
104 case idcmdCut:
105 WndProc(SCI_CUT, 0, 0);
106 break;
107
108 case idcmdCopy:
109 WndProc(SCI_COPY, 0, 0);
110 break;
111
112 case idcmdPaste:
113 WndProc(SCI_PASTE, 0, 0);
114 break;
115
116 case idcmdDelete:
117 WndProc(SCI_CLEAR, 0, 0);
118 break;
119
120 case idcmdSelectAll:
121 WndProc(SCI_SELECTALL, 0, 0);
122 break;
123 }
124 }
125
126 int ScintillaBase::KeyCommand(unsigned int iMessage) {
127 // Most key commands cancel autocompletion mode
128 if (ac.Active()) {
129 switch (iMessage) {
130 // Except for these
131 case SCI_LINEDOWN:
132 AutoCompleteMove(1);
133 return 0;
134 case SCI_LINEUP:
135 AutoCompleteMove( -1);
136 return 0;
137 case SCI_PAGEDOWN:
138 AutoCompleteMove(5);
139 return 0;
140 case SCI_PAGEUP:
141 AutoCompleteMove( -5);
142 return 0;
143 case SCI_VCHOME:
144 AutoCompleteMove( -5000);
145 return 0;
146 case SCI_LINEEND:
147 AutoCompleteMove(5000);
148 return 0;
149 case SCI_DELETEBACK:
150 DelCharBack(true);
151 AutoCompleteCharacterDeleted();
152 EnsureCaretVisible();
153 return 0;
154 case SCI_DELETEBACKNOTLINE:
155 DelCharBack(false);
156 AutoCompleteCharacterDeleted();
157 EnsureCaretVisible();
158 return 0;
159 case SCI_TAB:
160 AutoCompleteCompleted();
161 return 0;
162 case SCI_NEWLINE:
163 AutoCompleteCompleted();
164 return 0;
165
166 default:
167 ac.Cancel();
168 }
169 }
170
171 if (ct.inCallTipMode) {
172 if (
173 (iMessage != SCI_CHARLEFT) &&
174 (iMessage != SCI_CHARLEFTEXTEND) &&
175 (iMessage != SCI_CHARRIGHT) &&
176 (iMessage != SCI_CHARLEFTEXTEND) &&
177 (iMessage != SCI_EDITTOGGLEOVERTYPE) &&
178 (iMessage != SCI_DELETEBACK) &&
179 (iMessage != SCI_DELETEBACKNOTLINE)
180 ) {
181 ct.CallTipCancel();
182 }
183 if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) {
184 if (currentPos <= ct.posStartCallTip) {
185 ct.CallTipCancel();
186 }
187 }
188 }
189 return Editor::KeyCommand(iMessage);
190 }
191
192 void ScintillaBase::AutoCompleteDoubleClick(void* p) {
193 ScintillaBase* sci = reinterpret_cast<ScintillaBase*>(p);
194 sci->AutoCompleteCompleted();
195 }
196
197 void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
198 //Platform::DebugPrintf("AutoComplete %s\n", list);
199 ct.CallTipCancel();
200
201 if (ac.chooseSingle && (listType == 0)) {
202 if (list && !strchr(list, ac.GetSeparator())) {
203 const char *typeSep = strchr(list, ac.GetTypesep());
204 size_t lenInsert = (typeSep) ? (typeSep-list) : strlen(list);
205 if (ac.ignoreCase) {
206 SetEmptySelection(currentPos - lenEntered);
207 pdoc->DeleteChars(currentPos, lenEntered);
208 SetEmptySelection(currentPos);
209 pdoc->InsertString(currentPos, list, lenInsert);
210 SetEmptySelection(currentPos + lenInsert);
211 } else {
212 SetEmptySelection(currentPos);
213 pdoc->InsertString(currentPos, list + lenEntered, lenInsert - lenEntered);
214 SetEmptySelection(currentPos + lenInsert - lenEntered);
215 }
216 return;
217 }
218 }
219 ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos),
220 lenEntered, vs.lineHeight, IsUnicodeMode());
221
222 PRectangle rcClient = GetClientRectangle();
223 Point pt = LocationFromPosition(currentPos - lenEntered);
224
225 int heightLB = 100;
226 int widthLB = 100;
227 if (pt.x >= rcClient.right - widthLB) {
228 HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB);
229 Redraw();
230 pt = LocationFromPosition(currentPos);
231 }
232 PRectangle rcac;
233 rcac.left = pt.x - ac.lb->CaretFromEdge();
234 if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
235 pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
236 rcac.top = pt.y - heightLB;
237 if (rcac.top < 0) {
238 heightLB += rcac.top;
239 rcac.top = 0;
240 }
241 } else {
242 rcac.top = pt.y + vs.lineHeight;
243 }
244 rcac.right = rcac.left + widthLB;
245 rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
246 ac.lb->SetPositionRelative(rcac, wMain);
247 ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
248 unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
249 ac.lb->SetAverageCharWidth(aveCharWidth);
250 ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);
251
252 ac.SetList(list);
253
254 // Fiddle the position of the list so it is right next to the target and wide enough for all its strings
255 PRectangle rcList = ac.lb->GetDesiredRect();
256 int heightAlloced = rcList.bottom - rcList.top;
257 widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left);
258 if (maxListWidth != 0)
259 widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth);
260 // Make an allowance for large strings in list
261 rcList.left = pt.x - ac.lb->CaretFromEdge();
262 rcList.right = rcList.left + widthLB;
263 if (((pt.y + vs.lineHeight) >= (rcClient.bottom - heightAlloced)) && // Wont fit below.
264 ((pt.y + vs.lineHeight / 2) >= (rcClient.bottom + rcClient.top) / 2)) { // and there is more room above.
265 rcList.top = pt.y - heightAlloced;
266 } else {
267 rcList.top = pt.y + vs.lineHeight;
268 }
269 rcList.bottom = rcList.top + heightAlloced;
270 ac.lb->SetPositionRelative(rcList, wMain);
271 ac.Show(true);
272 if (lenEntered != 0) {
273 AutoCompleteMoveToCurrentWord();
274 }
275 }
276
277 void ScintillaBase::AutoCompleteCancel() {
278 ac.Cancel();
279 }
280
281 void ScintillaBase::AutoCompleteMove(int delta) {
282 ac.Move(delta);
283 }
284
285 void ScintillaBase::AutoCompleteMoveToCurrentWord() {
286 char wordCurrent[1000];
287 int i;
288 int startWord = ac.posStart - ac.startLen;
289 for (i = startWord; i < currentPos && i - startWord < 1000; i++)
290 wordCurrent[i - startWord] = pdoc->CharAt(i);
291 wordCurrent[Platform::Minimum(i - startWord, 999)] = '\0';
292 ac.Select(wordCurrent);
293 }
294
295 void ScintillaBase::AutoCompleteCharacterAdded(char ch) {
296 if (ac.IsFillUpChar(ch)) {
297 AutoCompleteCompleted();
298 } else if (ac.IsStopChar(ch)) {
299 ac.Cancel();
300 } else {
301 AutoCompleteMoveToCurrentWord();
302 }
303 }
304
305 void ScintillaBase::AutoCompleteCharacterDeleted() {
306 if (currentPos < ac.posStart - ac.startLen) {
307 ac.Cancel();
308 } else if (ac.cancelAtStartPos && (currentPos <= ac.posStart)) {
309 ac.Cancel();
310 } else {
311 AutoCompleteMoveToCurrentWord();
312 }
313 }
314
315 void ScintillaBase::AutoCompleteCompleted() {
316 int item = ac.lb->GetSelection();
317 char selected[1000];
318 selected[0] = '\0';
319 if (item != -1) {
320 ac.lb->GetValue(item, selected, sizeof(selected));
321 } else {
322 ac.Cancel();
323 return;
324 }
325
326 ac.Show(false);
327
328 listSelected = selected;
329 SCNotification scn = {0};
330 scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
331 scn.message = 0;
332 scn.wParam = listType;
333 scn.listType = listType;
334 Position firstPos = ac.posStart - ac.startLen;
335 scn.lParam = firstPos;
336 scn.text = listSelected.c_str();
337 NotifyParent(scn);
338
339 if (!ac.Active())
340 return;
341 ac.Cancel();
342
343 if (listType > 0)
344 return;
345
346 Position endPos = currentPos;
347 if (ac.dropRestOfWord)
348 endPos = pdoc->ExtendWordSelect(endPos, 1, true);
349 if (endPos < firstPos)
350 return;
351 pdoc->BeginUndoAction();
352 if (endPos != firstPos) {
353 pdoc->DeleteChars(firstPos, endPos - firstPos);
354 }
355 SetEmptySelection(ac.posStart);
356 if (item != -1) {
357 SString piece = selected;
358 pdoc->InsertString(firstPos, piece.c_str());
359 SetEmptySelection(firstPos + static_cast<int>(piece.length()));
360 }
361 pdoc->EndUndoAction();
362 }
363
364 int ScintillaBase::AutoCompleteGetCurrent() {
365 return ac.lb->GetSelection();
366 }
367
368 void ScintillaBase::CallTipShow(Point pt, const char *defn) {
369 AutoCompleteCancel();
370 pt.y += vs.lineHeight;
371 PRectangle rc = ct.CallTipStart(currentPos, pt,
372 defn,
373 vs.styles[STYLE_DEFAULT].fontName,
374 vs.styles[STYLE_DEFAULT].sizeZoomed,
375 CodePage(),
376 vs.styles[STYLE_DEFAULT].characterSet,
377 wMain);
378 // If the call-tip window would be out of the client
379 // space, adjust so it displays above the text.
380 PRectangle rcClient = GetClientRectangle();
381 if (rc.bottom > rcClient.bottom) {
382 int offset = vs.lineHeight + rc.Height();
383 rc.top -= offset;
384 rc.bottom -= offset;
385 }
386 // Now display the window.
387 CreateCallTipWindow(rc);
388 ct.wCallTip.SetPositionRelative(rc, wMain);
389 ct.wCallTip.Show();
390 }
391
392 void ScintillaBase::CallTipClick() {
393 SCNotification scn = {0};
394 scn.nmhdr.code = SCN_CALLTIPCLICK;
395 scn.position = ct.clickPlace;
396 NotifyParent(scn);
397 }
398
399 void ScintillaBase::ContextMenu(Point pt) {
400 if (displayPopupMenu) {
401 bool writable = !WndProc(SCI_GETREADONLY, 0, 0);
402 popup.CreatePopUp();
403 AddToPopUp("Undo", idcmdUndo, writable && pdoc->CanUndo());
404 AddToPopUp("Redo", idcmdRedo, writable && pdoc->CanRedo());
405 AddToPopUp("");
406 AddToPopUp("Cut", idcmdCut, writable && currentPos != anchor);
407 AddToPopUp("Copy", idcmdCopy, currentPos != anchor);
408 AddToPopUp("Paste", idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0));
409 AddToPopUp("Delete", idcmdDelete, writable && currentPos != anchor);
410 AddToPopUp("");
411 AddToPopUp("Select All", idcmdSelectAll);
412 popup.Show(pt, wMain);
413 }
414 }
415
416 void ScintillaBase::CancelModes() {
417 AutoCompleteCancel();
418 ct.CallTipCancel();
419 Editor::CancelModes();
420 }
421
422 void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
423 CancelModes();
424 Editor::ButtonDown(pt, curTime, shift, ctrl, alt);
425 }
426
427 #ifdef SCI_LEXER
428 void ScintillaBase::SetLexer(uptr_t wParam) {
429 lexLanguage = wParam;
430 lexCurrent = LexerModule::Find(lexLanguage);
431 if (!lexCurrent)
432 lexCurrent = LexerModule::Find(SCLEX_NULL);
433 }
434
435 void ScintillaBase::SetLexerLanguage(const char *languageName) {
436 lexLanguage = SCLEX_CONTAINER;
437 lexCurrent = LexerModule::Find(languageName);
438 if (!lexCurrent)
439 lexCurrent = LexerModule::Find(SCLEX_NULL);
440 if (lexCurrent)
441 lexLanguage = lexCurrent->GetLanguage();
442 }
443
444 void ScintillaBase::Colourise(int start, int end) {
445 if (!performingStyle) {
446 // Protect against reentrance, which may occur, for example, when
447 // fold points are discovered while performing styling and the folding
448 // code looks for child lines which may trigger styling.
449 performingStyle = true;
450
451 int lengthDoc = pdoc->Length();
452 if (end == -1)
453 end = lengthDoc;
454 int len = end - start;
455
456 PLATFORM_ASSERT(len >= 0);
457 PLATFORM_ASSERT(start + len <= lengthDoc);
458
459 //WindowAccessor styler(wMain.GetID(), props);
460 DocumentAccessor styler(pdoc, props, wMain.GetID());
461
462 int styleStart = 0;
463 if (start > 0)
464 styleStart = styler.StyleAt(start - 1);
465 styler.SetCodePage(pdoc->dbcsCodePage);
466
467 if (lexCurrent && (len > 0)) { // Should always succeed as null lexer should always be available
468 lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
469 styler.Flush();
470 if (styler.GetPropertyInt("fold")) {
471 lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
472 styler.Flush();
473 }
474 }
475
476 performingStyle = false;
477 }
478 }
479 #endif
480
481 void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
482 #ifdef SCI_LEXER
483 if (lexLanguage != SCLEX_CONTAINER) {
484 int endStyled = WndProc(SCI_GETENDSTYLED, 0, 0);
485 int lineEndStyled = WndProc(SCI_LINEFROMPOSITION, endStyled, 0);
486 endStyled = WndProc(SCI_POSITIONFROMLINE, lineEndStyled, 0);
487 Colourise(endStyled, endStyleNeeded);
488 return;
489 }
490 #endif
491 Editor::NotifyStyleToNeeded(endStyleNeeded);
492 }
493
494 sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
495 switch (iMessage) {
496 case SCI_AUTOCSHOW:
497 listType = 0;
498 AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
499 break;
500
501 case SCI_AUTOCCANCEL:
502 AutoCompleteCancel();
503 break;
504
505 case SCI_AUTOCACTIVE:
506 return ac.Active();
507
508 case SCI_AUTOCPOSSTART:
509 return ac.posStart;
510
511 case SCI_AUTOCCOMPLETE:
512 AutoCompleteCompleted();
513 break;
514
515 case SCI_AUTOCSETSEPARATOR:
516 ac.SetSeparator(static_cast<char>(wParam));
517 break;
518
519 case SCI_AUTOCGETSEPARATOR:
520 return ac.GetSeparator();
521
522 case SCI_AUTOCSTOPS:
523 ac.SetStopChars(reinterpret_cast<char *>(lParam));
524 break;
525
526 case SCI_AUTOCSELECT:
527 ac.Select(reinterpret_cast<char *>(lParam));
528 break;
529
530 case SCI_AUTOCGETCURRENT:
531 return AutoCompleteGetCurrent();
532
533 case SCI_AUTOCSETCANCELATSTART:
534 ac.cancelAtStartPos = wParam != 0;
535 break;
536
537 case SCI_AUTOCGETCANCELATSTART:
538 return ac.cancelAtStartPos;
539
540 case SCI_AUTOCSETFILLUPS:
541 ac.SetFillUpChars(reinterpret_cast<char *>(lParam));
542 break;
543
544 case SCI_AUTOCSETCHOOSESINGLE:
545 ac.chooseSingle = wParam != 0;
546 break;
547
548 case SCI_AUTOCGETCHOOSESINGLE:
549 return ac.chooseSingle;
550
551 case SCI_AUTOCSETIGNORECASE:
552 ac.ignoreCase = wParam != 0;
553 break;
554
555 case SCI_AUTOCGETIGNORECASE:
556 return ac.ignoreCase;
557
558 case SCI_USERLISTSHOW:
559 listType = wParam;
560 AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
561 break;
562
563 case SCI_AUTOCSETAUTOHIDE:
564 ac.autoHide = wParam != 0;
565 break;
566
567 case SCI_AUTOCGETAUTOHIDE:
568 return ac.autoHide;
569
570 case SCI_AUTOCSETDROPRESTOFWORD:
571 ac.dropRestOfWord = wParam != 0;
572 break;
573
574 case SCI_AUTOCGETDROPRESTOFWORD:
575 return ac.dropRestOfWord;
576
577 case SCI_AUTOCSETMAXHEIGHT:
578 ac.lb->SetVisibleRows(wParam);
579 break;
580
581 case SCI_AUTOCGETMAXHEIGHT:
582 return ac.lb->GetVisibleRows();
583
584 case SCI_AUTOCSETMAXWIDTH:
585 maxListWidth = wParam;
586 break;
587
588 case SCI_AUTOCGETMAXWIDTH:
589 return maxListWidth;
590
591 case SCI_REGISTERIMAGE:
592 ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
593 break;
594
595 case SCI_CLEARREGISTEREDIMAGES:
596 ac.lb->ClearRegisteredImages();
597 break;
598
599 case SCI_AUTOCSETTYPESEPARATOR:
600 ac.SetTypesep(static_cast<char>(wParam));
601 break;
602
603 case SCI_AUTOCGETTYPESEPARATOR:
604 return ac.GetTypesep();
605
606 case SCI_CALLTIPSHOW:
607 CallTipShow(LocationFromPosition(wParam),
608 reinterpret_cast<const char *>(lParam));
609 break;
610
611 case SCI_CALLTIPCANCEL:
612 ct.CallTipCancel();
613 break;
614
615 case SCI_CALLTIPACTIVE:
616 return ct.inCallTipMode;
617
618 case SCI_CALLTIPPOSSTART:
619 return ct.posStartCallTip;
620
621 case SCI_CALLTIPSETHLT:
622 ct.SetHighlight(wParam, lParam);
623 break;
624
625 case SCI_CALLTIPSETBACK:
626 ct.colourBG = ColourDesired(wParam);
627 InvalidateStyleRedraw();
628 break;
629
630 case SCI_CALLTIPSETFORE:
631 ct.colourUnSel = ColourDesired(wParam);
632 InvalidateStyleRedraw();
633 break;
634
635 case SCI_CALLTIPSETFOREHLT:
636 ct.colourSel = ColourDesired(wParam);
637 InvalidateStyleRedraw();
638 break;
639
640 case SCI_USEPOPUP:
641 displayPopupMenu = wParam != 0;
642 break;
643
644 #ifdef SCI_LEXER
645 case SCI_SETLEXER:
646 SetLexer(wParam);
647 lexLanguage = wParam;
648 break;
649
650 case SCI_GETLEXER:
651 return lexLanguage;
652
653 case SCI_COLOURISE:
654 if (lexLanguage == SCLEX_CONTAINER) {
655 pdoc->ModifiedAt(wParam);
656 NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
657 } else {
658 Colourise(wParam, lParam);
659 }
660 Redraw();
661 break;
662
663 case SCI_SETPROPERTY:
664 props.Set(reinterpret_cast<const char *>(wParam),
665 reinterpret_cast<const char *>(lParam));
666 break;
667
668 case SCI_GETPROPERTY: {
669 SString val = props.Get(reinterpret_cast<const char *>(wParam));
670 const int n = val.length();
671 if (lParam != 0) {
672 char *ptr = reinterpret_cast<char *>(lParam);
673 memcpy(ptr, val.c_str(), n);
674 ptr[n] = '\0'; // terminate
675 }
676 return n; // Not including NUL
677 }
678
679 case SCI_GETPROPERTYEXPANDED: {
680 SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
681 const int n = val.length();
682 if (lParam != 0) {
683 char *ptr = reinterpret_cast<char *>(lParam);
684 memcpy(ptr, val.c_str(), n);
685 ptr[n] = '\0'; // terminate
686 }
687 return n; // Not including NUL
688 }
689
690 case SCI_GETPROPERTYINT:
691 return props.GetInt(reinterpret_cast<const char *>(wParam), lParam);
692
693 case SCI_SETKEYWORDS:
694 if (wParam < numWordLists) {
695 keyWordLists[wParam]->Clear();
696 keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam));
697 }
698 break;
699
700 case SCI_SETLEXERLANGUAGE:
701 SetLexerLanguage(reinterpret_cast<const char *>(lParam));
702 break;
703
704 case SCI_GETSTYLEBITSNEEDED:
705 return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
706 #endif
707
708 default:
709 return Editor::WndProc(iMessage, wParam, lParam);
710 }
711 return 0l;
712 }