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 <cstddef>
9#include <cstdlib>
10#include <cstdint>
11#include <cassert>
12#include <cstring>
13
14#include <stdexcept>
15#include <string>
16#include <string_view>
17#include <vector>
18#include <map>
19#include <set>
20#include <optional>
21#include <algorithm>
22#include <memory>
23
24#include "ScintillaTypes.h"
25#include "ScintillaMessages.h"
26#include "ScintillaStructures.h"
27#include "ILoader.h"
28#include "ILexer.h"
29
30#include "Debugging.h"
31#include "Geometry.h"
32#include "Platform.h"
33
34#include "CharacterCategoryMap.h"
35
36#include "Position.h"
37#include "UniqueString.h"
38#include "SplitVector.h"
39#include "Partitioning.h"
40#include "RunStyles.h"
41#include "ContractionState.h"
42#include "CellBuffer.h"
43#include "CallTip.h"
44#include "KeyMap.h"
45#include "Indicator.h"
46#include "LineMarker.h"
47#include "Style.h"
48#include "ViewStyle.h"
49#include "CharClassify.h"
50#include "Decoration.h"
51#include "CaseFolder.h"
52#include "Document.h"
53#include "Selection.h"
54#include "PositionCache.h"
55#include "EditModel.h"
56#include "MarginView.h"
57#include "EditView.h"
58#include "Editor.h"
59#include "AutoComplete.h"
60#include "ScintillaBase.h"
61
62using namespace Scintilla;
63using namespace Scintilla::Internal;
64
65ScintillaBase::ScintillaBase() {
66 displayPopupMenu = PopUp::All;
67 listType = 0;
68 maxListWidth = 0;
69 multiAutoCMode = MultiAutoComplete::Once;
70}
71
72ScintillaBase::~ScintillaBase() {
73}
74
75void ScintillaBase::Finalise() {
76 Editor::Finalise();
77 popup.Destroy();
78}
79
80void ScintillaBase::InsertCharacter(std::string_view sv, CharacterSource charSource) {
81 const bool isFillUp = ac.Active() && ac.IsFillUpChar(sv[0]);
82 if (!isFillUp) {
83 Editor::InsertCharacter(sv, charSource);
84 }
85 if (ac.Active()) {
86 AutoCompleteCharacterAdded(sv[0]);
87 // For fill ups add the character after the autocompletion has
88 // triggered so containers see the key so can display a calltip.
89 if (isFillUp) {
90 Editor::InsertCharacter(sv, charSource);
91 }
92 }
93}
94
95void ScintillaBase::Command(int cmdId) {
96
97 switch (cmdId) {
98
99 case idAutoComplete: // Nothing to do
100
101 break;
102
103 case idCallTip: // Nothing to do
104
105 break;
106
107 case idcmdUndo:
108 WndProc(Message::Undo, 0, 0);
109 break;
110
111 case idcmdRedo:
112 WndProc(Message::Redo, 0, 0);
113 break;
114
115 case idcmdCut:
116 WndProc(Message::Cut, 0, 0);
117 break;
118
119 case idcmdCopy:
120 WndProc(Message::Copy, 0, 0);
121 break;
122
123 case idcmdPaste:
124 WndProc(Message::Paste, 0, 0);
125 break;
126
127 case idcmdDelete:
128 WndProc(Message::Clear, 0, 0);
129 break;
130
131 case idcmdSelectAll:
132 WndProc(Message::SelectAll, 0, 0);
133 break;
134 }
135}
136
137int ScintillaBase::KeyCommand(Message iMessage) {
138 // Most key commands cancel autocompletion mode
139 if (ac.Active()) {
140 switch (iMessage) {
141 // Except for these
142 case Message::LineDown:
143 AutoCompleteMove(1);
144 return 0;
145 case Message::LineUp:
146 AutoCompleteMove(-1);
147 return 0;
148 case Message::PageDown:
149 AutoCompleteMove(ac.lb->GetVisibleRows());
150 return 0;
151 case Message::PageUp:
152 AutoCompleteMove(-ac.lb->GetVisibleRows());
153 return 0;
154 case Message::VCHome:
155 AutoCompleteMove(-5000);
156 return 0;
157 case Message::LineEnd:
158 AutoCompleteMove(5000);
159 return 0;
160 case Message::DeleteBack:
161 DelCharBack(true);
162 AutoCompleteCharacterDeleted();
163 EnsureCaretVisible();
164 return 0;
165 case Message::DeleteBackNotLine:
166 DelCharBack(false);
167 AutoCompleteCharacterDeleted();
168 EnsureCaretVisible();
169 return 0;
170 case Message::Tab:
171 AutoCompleteCompleted(0, CompletionMethods::Tab);
172 return 0;
173 case Message::NewLine:
174 AutoCompleteCompleted(0, CompletionMethods::Newline);
175 return 0;
176
177 default:
178 AutoCompleteCancel();
179 }
180 }
181
182 if (ct.inCallTipMode) {
183 if (
184 (iMessage != Message::CharLeft) &&
185 (iMessage != Message::CharLeftExtend) &&
186 (iMessage != Message::CharRight) &&
187 (iMessage != Message::CharRightExtend) &&
188 (iMessage != Message::EditToggleOvertype) &&
189 (iMessage != Message::DeleteBack) &&
190 (iMessage != Message::DeleteBackNotLine)
191 ) {
192 ct.CallTipCancel();
193 }
194 if ((iMessage == Message::DeleteBack) || (iMessage == Message::DeleteBackNotLine)) {
195 if (sel.MainCaret() <= ct.posStartCallTip) {
196 ct.CallTipCancel();
197 }
198 }
199 }
200 return Editor::KeyCommand(iMessage);
201}
202
203void ScintillaBase::ListNotify(ListBoxEvent *plbe) {
204 switch (plbe->event) {
205 case ListBoxEvent::EventType::selectionChange:
206 AutoCompleteSelection();
207 break;
208 case ListBoxEvent::EventType::doubleClick:
209 AutoCompleteCompleted(0, CompletionMethods::DoubleClick);
210 break;
211 }
212}
213
214void ScintillaBase::AutoCompleteInsert(Sci::Position startPos, Sci::Position removeLen, const char *text, Sci::Position textLen) {
215 UndoGroup ug(pdoc);
216 if (multiAutoCMode == MultiAutoComplete::Once) {
217 pdoc->DeleteChars(startPos, removeLen);
218 const Sci::Position lengthInserted = pdoc->InsertString(startPos, text, textLen);
219 SetEmptySelection(startPos + lengthInserted);
220 } else {
221 // MultiAutoComplete::Each
222 for (size_t r=0; r<sel.Count(); r++) {
223 if (!RangeContainsProtected(sel.Range(r).Start().Position(),
224 sel.Range(r).End().Position())) {
225 Sci::Position positionInsert = sel.Range(r).Start().Position();
226 positionInsert = RealizeVirtualSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
227 if (positionInsert - removeLen >= 0) {
228 positionInsert -= removeLen;
229 pdoc->DeleteChars(positionInsert, removeLen);
230 }
231 const Sci::Position lengthInserted = pdoc->InsertString(positionInsert, text, textLen);
232 if (lengthInserted > 0) {
233 sel.Range(r).caret.SetPosition(positionInsert + lengthInserted);
234 sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted);
235 }
236 sel.Range(r).ClearVirtualSpace();
237 }
238 }
239 }
240}
241
242void ScintillaBase::AutoCompleteStart(Sci::Position lenEntered, const char *list) {
243 //Platform::DebugPrintf("AutoComplete %s\n", list);
244 ct.CallTipCancel();
245
246 if (ac.chooseSingle && (listType == 0)) {
247 if (list && !strchr(list, ac.GetSeparator())) {
248 const char *typeSep = strchr(list, ac.GetTypesep());
249 const Sci::Position lenInsert = typeSep ?
250 (typeSep-list) : strlen(list);
251 if (ac.ignoreCase) {
252 // May need to convert the case before invocation, so remove lenEntered characters
253 AutoCompleteInsert(sel.MainCaret() - lenEntered, lenEntered, list, lenInsert);
254 } else {
255 AutoCompleteInsert(sel.MainCaret(), 0, list + lenEntered, lenInsert - lenEntered);
256 }
257 ac.Cancel();
258 return;
259 }
260 }
261
262 ListOptions options{
263 vs.ElementColour(Element::List),
264 vs.ElementColour(Element::ListBack),
265 vs.ElementColour(Element::ListSelected),
266 vs.ElementColour(Element::ListSelectedBack),
267 ac.options,
268 };
269
270 ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(),
271 lenEntered, vs.lineHeight, IsUnicodeMode(), technology, options);
272
273 const PRectangle rcClient = GetClientRectangle();
274 Point pt = LocationFromPosition(sel.MainCaret() - lenEntered);
275 PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
276 if (rcPopupBounds.Height() == 0)
277 rcPopupBounds = rcClient;
278
279 int heightLB = ac.heightLBDefault;
280 int widthLB = ac.widthLBDefault;
281 if (pt.x >= rcClient.right - widthLB) {
282 HorizontalScrollTo(static_cast<int>(xOffset + pt.x - rcClient.right + widthLB));
283 Redraw();
284 pt = PointMainCaret();
285 }
286 if (wMargin.Created()) {
287 pt = pt + GetVisibleOriginInMain();
288 }
289 PRectangle rcac;
290 rcac.left = pt.x - ac.lb->CaretFromEdge();
291 if (pt.y >= rcPopupBounds.bottom - heightLB && // Won't fit below.
292 pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above.
293 rcac.top = pt.y - heightLB;
294 if (rcac.top < rcPopupBounds.top) {
295 heightLB -= static_cast<int>(rcPopupBounds.top - rcac.top);
296 rcac.top = rcPopupBounds.top;
297 }
298 } else {
299 rcac.top = pt.y + vs.lineHeight;
300 }
301 rcac.right = rcac.left + widthLB;
302 rcac.bottom = static_cast<XYPOSITION>(std::min(static_cast<int>(rcac.top) + heightLB, static_cast<int>(rcPopupBounds.bottom)));
303 ac.lb->SetPositionRelative(rcac, &wMain);
304 ac.lb->SetFont(vs.styles[StyleDefault].font.get());
305 const int aveCharWidth = static_cast<int>(vs.styles[StyleDefault].aveCharWidth);
306 ac.lb->SetAverageCharWidth(aveCharWidth);
307 ac.lb->SetDelegate(this);
308
309 ac.SetList(list ? list : "");
310
311 // Fiddle the position of the list so it is right next to the target and wide enough for all its strings
312 PRectangle rcList = ac.lb->GetDesiredRect();
313 const int heightAlloced = static_cast<int>(rcList.bottom - rcList.top);
314 widthLB = std::max(widthLB, static_cast<int>(rcList.right - rcList.left));
315 if (maxListWidth != 0)
316 widthLB = std::min(widthLB, aveCharWidth*maxListWidth);
317 // Make an allowance for large strings in list
318 rcList.left = pt.x - ac.lb->CaretFromEdge();
319 rcList.right = rcList.left + widthLB;
320 if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Won't fit below.
321 ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above.
322 rcList.top = pt.y - heightAlloced;
323 } else {
324 rcList.top = pt.y + vs.lineHeight;
325 }
326 rcList.bottom = rcList.top + heightAlloced;
327 ac.lb->SetPositionRelative(rcList, &wMain);
328 ac.Show(true);
329 if (lenEntered != 0) {
330 AutoCompleteMoveToCurrentWord();
331 }
332}
333
334void ScintillaBase::AutoCompleteCancel() {
335 if (ac.Active()) {
336 NotificationData scn = {};
337 scn.nmhdr.code = Notification::AutoCCancelled;
338 scn.wParam = 0;
339 scn.listType = 0;
340 NotifyParent(scn);
341 }
342 ac.Cancel();
343}
344
345void ScintillaBase::AutoCompleteMove(int delta) {
346 ac.Move(delta);
347}
348
349void ScintillaBase::AutoCompleteMoveToCurrentWord() {
350 std::string wordCurrent = RangeText(ac.posStart - ac.startLen, sel.MainCaret());
351 ac.Select(wordCurrent.c_str());
352}
353
354void ScintillaBase::AutoCompleteSelection() {
355 const int item = ac.GetSelection();
356 std::string selected;
357 if (item != -1) {
358 selected = ac.GetValue(item);
359 }
360
361 NotificationData scn = {};
362 scn.nmhdr.code = Notification::AutoCSelectionChange;
363 scn.message = static_cast<Message>(0);
364 scn.wParam = listType;
365 scn.listType = listType;
366 const Sci::Position firstPos = ac.posStart - ac.startLen;
367 scn.position = firstPos;
368 scn.lParam = firstPos;
369 scn.text = selected.c_str();
370 NotifyParent(scn);
371}
372
373void ScintillaBase::AutoCompleteCharacterAdded(char ch) {
374 if (ac.IsFillUpChar(ch)) {
375 AutoCompleteCompleted(ch, CompletionMethods::FillUp);
376 } else if (ac.IsStopChar(ch)) {
377 AutoCompleteCancel();
378 } else {
379 AutoCompleteMoveToCurrentWord();
380 }
381}
382
383void ScintillaBase::AutoCompleteCharacterDeleted() {
384 if (sel.MainCaret() < ac.posStart - ac.startLen) {
385 AutoCompleteCancel();
386 } else if (ac.cancelAtStartPos && (sel.MainCaret() <= ac.posStart)) {
387 AutoCompleteCancel();
388 } else {
389 AutoCompleteMoveToCurrentWord();
390 }
391 NotificationData scn = {};
392 scn.nmhdr.code = Notification::AutoCCharDeleted;
393 scn.wParam = 0;
394 scn.listType = 0;
395 NotifyParent(scn);
396}
397
398void ScintillaBase::AutoCompleteCompleted(char ch, CompletionMethods completionMethod) {
399 const int item = ac.GetSelection();
400 if (item == -1) {
401 AutoCompleteCancel();
402 return;
403 }
404 const std::string selected = ac.GetValue(item);
405
406 ac.Show(false);
407
408 NotificationData scn = {};
409 scn.nmhdr.code = listType > 0 ? Notification::UserListSelection : Notification::AutoCSelection;
410 scn.message = static_cast<Message>(0);
411 scn.ch = ch;
412 scn.listCompletionMethod = completionMethod;
413 scn.wParam = listType;
414 scn.listType = listType;
415 const Sci::Position firstPos = ac.posStart - ac.startLen;
416 scn.position = firstPos;
417 scn.lParam = firstPos;
418 scn.text = selected.c_str();
419 NotifyParent(scn);
420
421 if (!ac.Active())
422 return;
423 ac.Cancel();
424
425 if (listType > 0)
426 return;
427
428 Sci::Position endPos = sel.MainCaret();
429 if (ac.dropRestOfWord)
430 endPos = pdoc->ExtendWordSelect(endPos, 1, true);
431 if (endPos < firstPos)
432 return;
433 AutoCompleteInsert(firstPos, endPos - firstPos, selected.c_str(), selected.length());
434 SetLastXChosen();
435
436 scn.nmhdr.code = Notification::AutoCCompleted;
437 NotifyParent(scn);
438
439}
440
441int ScintillaBase::AutoCompleteGetCurrent() const {
442 if (!ac.Active())
443 return -1;
444 return ac.GetSelection();
445}
446
447int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) const {
448 if (ac.Active()) {
449 const int item = ac.GetSelection();
450 if (item != -1) {
451 const std::string selected = ac.GetValue(item);
452 if (buffer)
453 memcpy(buffer, selected.c_str(), selected.length()+1);
454 return static_cast<int>(selected.length());
455 }
456 }
457 if (buffer)
458 *buffer = '\0';
459 return 0;
460}
461
462void ScintillaBase::CallTipShow(Point pt, const char *defn) {
463 ac.Cancel();
464 // If container knows about StyleCallTip then use it in place of the
465 // StyleDefault for the face name, size and character set. Also use it
466 // for the foreground and background colour.
467 const int ctStyle = ct.UseStyleCallTip() ? StyleCallTip : StyleDefault;
468 if (ct.UseStyleCallTip()) {
469 ct.SetForeBack(vs.styles[StyleCallTip].fore, vs.styles[StyleCallTip].back);
470 }
471 if (wMargin.Created()) {
472 pt = pt + GetVisibleOriginInMain();
473 }
474 PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
475 vs.lineHeight,
476 defn,
477 vs.styles[ctStyle].fontName,
478 vs.styles[ctStyle].sizeZoomed,
479 CodePage(),
480 vs.styles[ctStyle].characterSet,
481 vs.technology,
482 vs.localeName.c_str(),
483 wMain);
484 // If the call-tip window would be out of the client
485 // space
486 const PRectangle rcClient = GetClientRectangle();
487 const int offset = vs.lineHeight + static_cast<int>(rc.Height());
488 // adjust so it displays above the text.
489 if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) {
490 rc.top -= offset;
491 rc.bottom -= offset;
492 }
493 // adjust so it displays below the text.
494 if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) {
495 rc.top += offset;
496 rc.bottom += offset;
497 }
498 // Now display the window.
499 CreateCallTipWindow(rc);
500 ct.wCallTip.SetPositionRelative(rc, &wMain);
501 ct.wCallTip.Show();
502}
503
504void ScintillaBase::CallTipClick() {
505 NotificationData scn = {};
506 scn.nmhdr.code = Notification::CallTipClick;
507 scn.position = ct.clickPlace;
508 NotifyParent(scn);
509}
510
511bool ScintillaBase::ShouldDisplayPopup(Point ptInWindowCoordinates) const {
512 return (displayPopupMenu == PopUp::All ||
513 (displayPopupMenu == PopUp::Text && !PointInSelMargin(ptInWindowCoordinates)));
514}
515
516void ScintillaBase::ContextMenu(Point pt) {
517 if (displayPopupMenu != PopUp::Never) {
518 const bool writable = !WndProc(Message::GetReadOnly, 0, 0);
519 popup.CreatePopUp();
520 AddToPopUp("Undo Ctrl+Z", idcmdUndo, writable && pdoc->CanUndo());
521 AddToPopUp("Redo Ctrl+Shift+Z", idcmdRedo, writable && pdoc->CanRedo());
522 AddToPopUp("");
523 AddToPopUp("Cut Ctrl+X", idcmdCut, writable && !sel.Empty());
524 AddToPopUp("Copy Ctrl+C", idcmdCopy, !sel.Empty());
525 AddToPopUp("Paste Ctrl+V", idcmdPaste, writable && WndProc(Message::CanPaste, 0, 0));
526 AddToPopUp("Delete Back Space", idcmdDelete, writable && !sel.Empty());
527 AddToPopUp("");
528 AddToPopUp("Select All Ctrl+A", idcmdSelectAll);
529 popup.Show(pt, wMain);
530 }
531}
532
533void ScintillaBase::CancelModes() {
534 AutoCompleteCancel();
535 ct.CallTipCancel();
536 Editor::CancelModes();
537}
538
539void ScintillaBase::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modifiers) {
540 CancelModes();
541 Editor::ButtonDownWithModifiers(pt, curTime, modifiers);
542}
543
544void ScintillaBase::RightButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modifiers) {
545 CancelModes();
546 Editor::RightButtonDownWithModifiers(pt, curTime, modifiers);
547}
548
549namespace Scintilla::Internal {
550
551class LexState : public LexInterface {
552public:
553 explicit LexState(Document *pdoc_) noexcept;
554
555 // LexInterface deleted the standard operators and defined the virtual destructor so don't need to here.
556
557 const char *DescribeWordListSets();
558 void SetWordList(int n, const char *wl);
559 int GetIdentifier() const;
560 const char *GetName() const;
561 void *PrivateCall(int operation, void *pointer);
562 const char *PropertyNames();
563 TypeProperty PropertyType(const char *name);
564 const char *DescribeProperty(const char *name);
565 void PropSet(const char *key, const char *val);
566 const char *PropGet(const char *key) const;
567 int PropGetInt(const char *key, int defaultValue=0) const;
568 size_t PropGetExpanded(const char *key, char *result) const;
569
570 LineEndType LineEndTypesSupported() override;
571 int AllocateSubStyles(int styleBase, int numberStyles);
572 int SubStylesStart(int styleBase);
573 int SubStylesLength(int styleBase);
574 int StyleFromSubStyle(int subStyle);
575 int PrimaryStyleFromStyle(int style);
576 void FreeSubStyles();
577 void SetIdentifiers(int style, const char *identifiers);
578 int DistanceToSecondaryStyles();
579 const char *GetSubStyleBases();
580 int NamedStyles();
581 const char *NameOfStyle(int style);
582 const char *TagsOfStyle(int style);
583 const char *DescriptionOfStyle(int style);
584};
585
586}
587
588LexState::LexState(Document *pdoc_) noexcept : LexInterface(pdoc_) {
589}
590
591LexState *ScintillaBase::DocumentLexState() {
592 if (!pdoc->GetLexInterface()) {
593 pdoc->SetLexInterface(std::make_unique<LexState>(pdoc));
594 }
595 return dynamic_cast<LexState *>(pdoc->GetLexInterface());
596}
597
598const char *LexState::DescribeWordListSets() {
599 if (instance) {
600 return instance->DescribeWordListSets();
601 } else {
602 return nullptr;
603 }
604}
605
606void LexState::SetWordList(int n, const char *wl) {
607 if (instance) {
608 const Sci_Position firstModification = instance->WordListSet(n, wl);
609 if (firstModification >= 0) {
610 pdoc->ModifiedAt(firstModification);
611 }
612 }
613}
614
615int LexState::GetIdentifier() const {
616 if (instance) {
617 return instance->GetIdentifier();
618 }
619 return 0;
620}
621
622const char *LexState::GetName() const {
623 if (instance) {
624 return instance->GetName();
625 }
626 return "";
627}
628
629void *LexState::PrivateCall(int operation, void *pointer) {
630 if (instance) {
631 return instance->PrivateCall(operation, pointer);
632 } else {
633 return nullptr;
634 }
635}
636
637const char *LexState::PropertyNames() {
638 if (instance) {
639 return instance->PropertyNames();
640 } else {
641 return nullptr;
642 }
643}
644
645TypeProperty LexState::PropertyType(const char *name) {
646 if (instance) {
647 return static_cast<TypeProperty>(instance->PropertyType(name));
648 } else {
649 return TypeProperty::Boolean;
650 }
651}
652
653const char *LexState::DescribeProperty(const char *name) {
654 if (instance) {
655 return instance->DescribeProperty(name);
656 } else {
657 return nullptr;
658 }
659}
660
661void LexState::PropSet(const char *key, const char *val) {
662 if (instance) {
663 const Sci_Position firstModification = instance->PropertySet(key, val);
664 if (firstModification >= 0) {
665 pdoc->ModifiedAt(firstModification);
666 }
667 }
668}
669
670const char *LexState::PropGet(const char *key) const {
671 if (instance) {
672 return instance->PropertyGet(key);
673 } else {
674 return nullptr;
675 }
676}
677
678int LexState::PropGetInt(const char *key, int defaultValue) const {
679 if (instance) {
680 const char *value = instance->PropertyGet(key);
681 if (value && *value) {
682 return atoi(value);
683 }
684 }
685 return defaultValue;
686}
687
688size_t LexState::PropGetExpanded(const char *key, char *result) const {
689 if (instance) {
690 const char *value = instance->PropertyGet(key);
691 if (value) {
692 if (result) {
693 strcpy(result, value);
694 }
695 return strlen(value);
696 }
697 }
698 return 0;
699}
700
701LineEndType LexState::LineEndTypesSupported() {
702 if (instance) {
703 return static_cast<LineEndType>(instance->LineEndTypesSupported());
704 }
705 return LineEndType::Default;
706}
707
708int LexState::AllocateSubStyles(int styleBase, int numberStyles) {
709 if (instance) {
710 return instance->AllocateSubStyles(styleBase, numberStyles);
711 }
712 return -1;
713}
714
715int LexState::SubStylesStart(int styleBase) {
716 if (instance) {
717 return instance->SubStylesStart(styleBase);
718 }
719 return -1;
720}
721
722int LexState::SubStylesLength(int styleBase) {
723 if (instance) {
724 return instance->SubStylesLength(styleBase);
725 }
726 return 0;
727}
728
729int LexState::StyleFromSubStyle(int subStyle) {
730 if (instance) {
731 return instance->StyleFromSubStyle(subStyle);
732 }
733 return 0;
734}
735
736int LexState::PrimaryStyleFromStyle(int style) {
737 if (instance) {
738 return instance->PrimaryStyleFromStyle(style);
739 }
740 return 0;
741}
742
743void LexState::FreeSubStyles() {
744 if (instance) {
745 instance->FreeSubStyles();
746 }
747}
748
749void LexState::SetIdentifiers(int style, const char *identifiers) {
750 if (instance) {
751 instance->SetIdentifiers(style, identifiers);
752 pdoc->ModifiedAt(0);
753 }
754}
755
756int LexState::DistanceToSecondaryStyles() {
757 if (instance) {
758 return instance->DistanceToSecondaryStyles();
759 }
760 return 0;
761}
762
763const char *LexState::GetSubStyleBases() {
764 if (instance) {
765 return instance->GetSubStyleBases();
766 }
767 return "";
768}
769
770int LexState::NamedStyles() {
771 if (instance) {
772 return instance->NamedStyles();
773 } else {
774 return -1;
775 }
776}
777
778const char *LexState::NameOfStyle(int style) {
779 if (instance) {
780 return instance->NameOfStyle(style);
781 } else {
782 return nullptr;
783 }
784}
785
786const char *LexState::TagsOfStyle(int style) {
787 if (instance) {
788 return instance->TagsOfStyle(style);
789 } else {
790 return nullptr;
791 }
792}
793
794const char *LexState::DescriptionOfStyle(int style) {
795 if (instance) {
796 return instance->DescriptionOfStyle(style);
797 } else {
798 return nullptr;
799 }
800}
801
802void ScintillaBase::NotifyStyleToNeeded(Sci::Position endStyleNeeded) {
803 if (!DocumentLexState()->UseContainerLexing()) {
804 const Sci::Line lineEndStyled =
805 pdoc->SciLineFromPosition(pdoc->GetEndStyled());
806 const Sci::Position endStyled =
807 pdoc->LineStart(lineEndStyled);
808 DocumentLexState()->Colourise(endStyled, endStyleNeeded);
809 return;
810 }
811 Editor::NotifyStyleToNeeded(endStyleNeeded);
812}
813
814void ScintillaBase::NotifyLexerChanged(Document *, void *) {
815 vs.EnsureStyle(0xff);
816}
817
818sptr_t ScintillaBase::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
819 switch (iMessage) {
820 case Message::AutoCShow:
821 listType = 0;
822 AutoCompleteStart(PositionFromUPtr(wParam), ConstCharPtrFromSPtr(lParam));
823 break;
824
825 case Message::AutoCCancel:
826 ac.Cancel();
827 break;
828
829 case Message::AutoCActive:
830 return ac.Active();
831
832 case Message::AutoCPosStart:
833 return ac.posStart;
834
835 case Message::AutoCComplete:
836 AutoCompleteCompleted(0, CompletionMethods::Command);
837 break;
838
839 case Message::AutoCSetSeparator:
840 ac.SetSeparator(static_cast<char>(wParam));
841 break;
842
843 case Message::AutoCGetSeparator:
844 return ac.GetSeparator();
845
846 case Message::AutoCStops:
847 ac.SetStopChars(ConstCharPtrFromSPtr(lParam));
848 break;
849
850 case Message::AutoCSelect:
851 ac.Select(ConstCharPtrFromSPtr(lParam));
852 break;
853
854 case Message::AutoCGetCurrent:
855 return AutoCompleteGetCurrent();
856
857 case Message::AutoCGetCurrentText:
858 return AutoCompleteGetCurrentText(CharPtrFromSPtr(lParam));
859
860 case Message::AutoCSetCancelAtStart:
861 ac.cancelAtStartPos = wParam != 0;
862 break;
863
864 case Message::AutoCGetCancelAtStart:
865 return ac.cancelAtStartPos;
866
867 case Message::AutoCSetFillUps:
868 ac.SetFillUpChars(ConstCharPtrFromSPtr(lParam));
869 break;
870
871 case Message::AutoCSetChooseSingle:
872 ac.chooseSingle = wParam != 0;
873 break;
874
875 case Message::AutoCGetChooseSingle:
876 return ac.chooseSingle;
877
878 case Message::AutoCSetIgnoreCase:
879 ac.ignoreCase = wParam != 0;
880 break;
881
882 case Message::AutoCGetIgnoreCase:
883 return ac.ignoreCase;
884
885 case Message::AutoCSetCaseInsensitiveBehaviour:
886 ac.ignoreCaseBehaviour = static_cast<CaseInsensitiveBehaviour>(wParam);
887 break;
888
889 case Message::AutoCGetCaseInsensitiveBehaviour:
890 return static_cast<sptr_t>(ac.ignoreCaseBehaviour);
891
892 case Message::AutoCSetMulti:
893 multiAutoCMode = static_cast<MultiAutoComplete>(wParam);
894 break;
895
896 case Message::AutoCGetMulti:
897 return static_cast<sptr_t>(multiAutoCMode);
898
899 case Message::AutoCSetOrder:
900 ac.autoSort = static_cast<Ordering>(wParam);
901 break;
902
903 case Message::AutoCGetOrder:
904 return static_cast<sptr_t>(ac.autoSort);
905
906 case Message::UserListShow:
907 listType = static_cast<int>(wParam);
908 AutoCompleteStart(0, ConstCharPtrFromSPtr(lParam));
909 break;
910
911 case Message::AutoCSetAutoHide:
912 ac.autoHide = wParam != 0;
913 break;
914
915 case Message::AutoCGetAutoHide:
916 return ac.autoHide;
917
918 case Message::AutoCSetOptions:
919 ac.options = static_cast<AutoCompleteOption>(wParam);
920 break;
921
922 case Message::AutoCGetOptions:
923 return static_cast<sptr_t>(ac.options);
924
925 case Message::AutoCSetDropRestOfWord:
926 ac.dropRestOfWord = wParam != 0;
927 break;
928
929 case Message::AutoCGetDropRestOfWord:
930 return ac.dropRestOfWord;
931
932 case Message::AutoCSetMaxHeight:
933 ac.lb->SetVisibleRows(static_cast<int>(wParam));
934 break;
935
936 case Message::AutoCGetMaxHeight:
937 return ac.lb->GetVisibleRows();
938
939 case Message::AutoCSetMaxWidth:
940 maxListWidth = static_cast<int>(wParam);
941 break;
942
943 case Message::AutoCGetMaxWidth:
944 return maxListWidth;
945
946 case Message::RegisterImage:
947 ac.lb->RegisterImage(static_cast<int>(wParam), ConstCharPtrFromSPtr(lParam));
948 break;
949
950 case Message::RegisterRGBAImage:
951 ac.lb->RegisterRGBAImage(static_cast<int>(wParam), static_cast<int>(sizeRGBAImage.x), static_cast<int>(sizeRGBAImage.y),
952 ConstUCharPtrFromSPtr(lParam));
953 break;
954
955 case Message::ClearRegisteredImages:
956 ac.lb->ClearRegisteredImages();
957 break;
958
959 case Message::AutoCSetTypeSeparator:
960 ac.SetTypesep(static_cast<char>(wParam));
961 break;
962
963 case Message::AutoCGetTypeSeparator:
964 return ac.GetTypesep();
965
966 case Message::CallTipShow:
967 CallTipShow(LocationFromPosition(wParam),
968 ConstCharPtrFromSPtr(lParam));
969 break;
970
971 case Message::CallTipCancel:
972 ct.CallTipCancel();
973 break;
974
975 case Message::CallTipActive:
976 return ct.inCallTipMode;
977
978 case Message::CallTipPosStart:
979 return ct.posStartCallTip;
980
981 case Message::CallTipSetPosStart:
982 ct.posStartCallTip = wParam;
983 break;
984
985 case Message::CallTipSetHlt:
986 ct.SetHighlight(wParam, lParam);
987 break;
988
989 case Message::CallTipSetBack:
990 ct.colourBG = ColourRGBA::FromIpRGB(SPtrFromUPtr(wParam));
991 vs.styles[StyleCallTip].back = ct.colourBG;
992 InvalidateStyleRedraw();
993 break;
994
995 case Message::CallTipSetFore:
996 ct.colourUnSel = ColourRGBA::FromIpRGB(SPtrFromUPtr(wParam));
997 vs.styles[StyleCallTip].fore = ct.colourUnSel;
998 InvalidateStyleRedraw();
999 break;
1000
1001 case Message::CallTipSetForeHlt:
1002 ct.colourSel = ColourRGBA::FromIpRGB(SPtrFromUPtr(wParam));
1003 InvalidateStyleRedraw();
1004 break;
1005
1006 case Message::CallTipUseStyle:
1007 ct.SetTabSize(static_cast<int>(wParam));
1008 InvalidateStyleRedraw();
1009 break;
1010
1011 case Message::CallTipSetPosition:
1012 ct.SetPosition(wParam != 0);
1013 InvalidateStyleRedraw();
1014 break;
1015
1016 case Message::UsePopUp:
1017 displayPopupMenu = static_cast<PopUp>(wParam);
1018 break;
1019
1020 case Message::GetLexer:
1021 return DocumentLexState()->GetIdentifier();
1022
1023 case Message::SetILexer:
1024 DocumentLexState()->SetInstance(static_cast<ILexer5 *>(PtrFromSPtr(lParam)));
1025 return 0;
1026
1027 case Message::Colourise:
1028 if (DocumentLexState()->UseContainerLexing()) {
1029 pdoc->ModifiedAt(PositionFromUPtr(wParam));
1030 NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
1031 } else {
1032 DocumentLexState()->Colourise(PositionFromUPtr(wParam), lParam);
1033 }
1034 Redraw();
1035 break;
1036
1037 case Message::SetProperty:
1038 DocumentLexState()->PropSet(ConstCharPtrFromUPtr(wParam),
1039 ConstCharPtrFromSPtr(lParam));
1040 break;
1041
1042 case Message::GetProperty:
1043 return StringResult(lParam, DocumentLexState()->PropGet(ConstCharPtrFromUPtr(wParam)));
1044
1045 case Message::GetPropertyExpanded:
1046 return DocumentLexState()->PropGetExpanded(ConstCharPtrFromUPtr(wParam),
1047 CharPtrFromSPtr(lParam));
1048
1049 case Message::GetPropertyInt:
1050 return DocumentLexState()->PropGetInt(ConstCharPtrFromUPtr(wParam), static_cast<int>(lParam));
1051
1052 case Message::SetKeyWords:
1053 DocumentLexState()->SetWordList(static_cast<int>(wParam), ConstCharPtrFromSPtr(lParam));
1054 break;
1055
1056 case Message::GetLexerLanguage:
1057 return StringResult(lParam, DocumentLexState()->GetName());
1058
1059 case Message::PrivateLexerCall:
1060 return reinterpret_cast<sptr_t>(
1061 DocumentLexState()->PrivateCall(static_cast<int>(wParam), PtrFromSPtr(lParam)));
1062
1063#ifdef INCLUDE_DEPRECATED_FEATURES
1064 case SCI_GETSTYLEBITSNEEDED:
1065 return 8;
1066#endif
1067
1068 case Message::PropertyNames:
1069 return StringResult(lParam, DocumentLexState()->PropertyNames());
1070
1071 case Message::PropertyType:
1072 return static_cast<sptr_t>(DocumentLexState()->PropertyType(ConstCharPtrFromUPtr(wParam)));
1073
1074 case Message::DescribeProperty:
1075 return StringResult(lParam,
1076 DocumentLexState()->DescribeProperty(ConstCharPtrFromUPtr(wParam)));
1077
1078 case Message::DescribeKeyWordSets:
1079 return StringResult(lParam, DocumentLexState()->DescribeWordListSets());
1080
1081 case Message::GetLineEndTypesSupported:
1082 return static_cast<sptr_t>(DocumentLexState()->LineEndTypesSupported());
1083
1084 case Message::AllocateSubStyles:
1085 return DocumentLexState()->AllocateSubStyles(static_cast<int>(wParam), static_cast<int>(lParam));
1086
1087 case Message::GetSubStylesStart:
1088 return DocumentLexState()->SubStylesStart(static_cast<int>(wParam));
1089
1090 case Message::GetSubStylesLength:
1091 return DocumentLexState()->SubStylesLength(static_cast<int>(wParam));
1092
1093 case Message::GetStyleFromSubStyle:
1094 return DocumentLexState()->StyleFromSubStyle(static_cast<int>(wParam));
1095
1096 case Message::GetPrimaryStyleFromStyle:
1097 return DocumentLexState()->PrimaryStyleFromStyle(static_cast<int>(wParam));
1098
1099 case Message::FreeSubStyles:
1100 DocumentLexState()->FreeSubStyles();
1101 break;
1102
1103 case Message::SetIdentifiers:
1104 DocumentLexState()->SetIdentifiers(static_cast<int>(wParam),
1105 ConstCharPtrFromSPtr(lParam));
1106 break;
1107
1108 case Message::DistanceToSecondaryStyles:
1109 return DocumentLexState()->DistanceToSecondaryStyles();
1110
1111 case Message::GetSubStyleBases:
1112 return StringResult(lParam, DocumentLexState()->GetSubStyleBases());
1113
1114 case Message::GetNamedStyles:
1115 return DocumentLexState()->NamedStyles();
1116
1117 case Message::NameOfStyle:
1118 return StringResult(lParam, DocumentLexState()->
1119 NameOfStyle(static_cast<int>(wParam)));
1120
1121 case Message::TagsOfStyle:
1122 return StringResult(lParam, DocumentLexState()->
1123 TagsOfStyle(static_cast<int>(wParam)));
1124
1125 case Message::DescriptionOfStyle:
1126 return StringResult(lParam, DocumentLexState()->
1127 DescriptionOfStyle(static_cast<int>(wParam)));
1128
1129 default:
1130 return Editor::WndProc(iMessage, wParam, lParam);
1131 }
1132 return 0;
1133}
1134