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 <[email protected]> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #include <cstddef> 9 #include <cstdlib> 10 #include <cassert> 11 #include <cstring> 12 13 #include <stdexcept> 14 #include <string> 15 #include <string_view> 16 #include <vector> 17 #include <map> 18 #include <algorithm> 19 #include <memory> 20 21 #include "Platform.h" 22 23 #include "ILoader.h" 24 #include "ILexer.h" 25 #include "Scintilla.h" 26 27 #include "SciLexer.h" 28 29 #include "PropSetSimple.h" 30 #include "CharacterCategory.h" 31 32 #include "LexerModule.h" 33 #include "Catalogue.h" 34 35 #include "Position.h" 36 #include "UniqueString.h" 37 #include "SplitVector.h" 38 #include "Partitioning.h" 39 #include "RunStyles.h" 40 #include "ContractionState.h" 41 #include "CellBuffer.h" 42 #include "CallTip.h" 43 #include "KeyMap.h" 44 #include "Indicator.h" 45 #include "LineMarker.h" 46 #include "Style.h" 47 #include "ViewStyle.h" 48 #include "CharClassify.h" 49 #include "Decoration.h" 50 #include "CaseFolder.h" 51 #include "Document.h" 52 #include "Selection.h" 53 #include "PositionCache.h" 54 #include "EditModel.h" 55 #include "MarginView.h" 56 #include "EditView.h" 57 #include "Editor.h" 58 #include "AutoComplete.h" 59 #include "ScintillaBase.h" 60 61 #include "ExternalLexer.h" 62 63 #undef max 64 #undef min 65 66 using namespace Scintilla; 67 68 ScintillaBase::ScintillaBase() { 69 displayPopupMenu = SC_POPUP_ALL; 70 listType = 0; 71 maxListWidth = 0; 72 multiAutoCMode = SC_MULTIAUTOC_ONCE; 73 #ifdef SCI_LEXER 74 Scintilla_LinkLexers(); 75 #endif 76 } 77 78 ScintillaBase::~ScintillaBase() { 79 } 80 81 void ScintillaBase::Finalise() { 82 Editor::Finalise(); 83 popup.Destroy(); 84 } 85 86 void ScintillaBase::AddCharUTF(const char *s, unsigned int len, bool /*treatAsDBCS*/) { 87 InsertCharacter(std::string_view(s, len), CharacterSource::directInput); 88 } 89 90 void ScintillaBase::InsertCharacter(std::string_view sv, CharacterSource charSource) { 91 const bool isFillUp = ac.Active() && ac.IsFillUpChar(sv[0]); 92 if (!isFillUp) { 93 Editor::InsertCharacter(sv, charSource); 94 } 95 if (ac.Active()) { 96 AutoCompleteCharacterAdded(sv[0]); 97 // For fill ups add the character after the autocompletion has 98 // triggered so containers see the key so can display a calltip. 99 if (isFillUp) { 100 Editor::InsertCharacter(sv, charSource); 101 } 102 } 103 } 104 105 void ScintillaBase::Command(int cmdId) { 106 107 switch (cmdId) { 108 109 case idAutoComplete: // Nothing to do 110 111 break; 112 113 case idCallTip: // Nothing to do 114 115 break; 116 117 case idcmdUndo: 118 WndProc(SCI_UNDO, 0, 0); 119 break; 120 121 case idcmdRedo: 122 WndProc(SCI_REDO, 0, 0); 123 break; 124 125 case idcmdCut: 126 WndProc(SCI_CUT, 0, 0); 127 break; 128 129 case idcmdCopy: 130 WndProc(SCI_COPY, 0, 0); 131 break; 132 133 case idcmdPaste: 134 WndProc(SCI_PASTE, 0, 0); 135 break; 136 137 case idcmdDelete: 138 WndProc(SCI_CLEAR, 0, 0); 139 break; 140 141 case idcmdSelectAll: 142 WndProc(SCI_SELECTALL, 0, 0); 143 break; 144 } 145 } 146 147 int ScintillaBase::KeyCommand(unsigned int iMessage) { 148 // Most key commands cancel autocompletion mode 149 if (ac.Active()) { 150 switch (iMessage) { 151 // Except for these 152 case SCI_LINEDOWN: 153 AutoCompleteMove(1); 154 return 0; 155 case SCI_LINEUP: 156 AutoCompleteMove(-1); 157 return 0; 158 case SCI_PAGEDOWN: 159 AutoCompleteMove(ac.lb->GetVisibleRows()); 160 return 0; 161 case SCI_PAGEUP: 162 AutoCompleteMove(-ac.lb->GetVisibleRows()); 163 return 0; 164 case SCI_VCHOME: 165 AutoCompleteMove(-5000); 166 return 0; 167 case SCI_LINEEND: 168 AutoCompleteMove(5000); 169 return 0; 170 case SCI_DELETEBACK: 171 DelCharBack(true); 172 AutoCompleteCharacterDeleted(); 173 EnsureCaretVisible(); 174 return 0; 175 case SCI_DELETEBACKNOTLINE: 176 DelCharBack(false); 177 AutoCompleteCharacterDeleted(); 178 EnsureCaretVisible(); 179 return 0; 180 case SCI_TAB: 181 AutoCompleteCompleted(0, SC_AC_TAB); 182 return 0; 183 case SCI_NEWLINE: 184 AutoCompleteCompleted(0, SC_AC_NEWLINE); 185 return 0; 186 187 default: 188 AutoCompleteCancel(); 189 } 190 } 191 192 if (ct.inCallTipMode) { 193 if ( 194 (iMessage != SCI_CHARLEFT) && 195 (iMessage != SCI_CHARLEFTEXTEND) && 196 (iMessage != SCI_CHARRIGHT) && 197 (iMessage != SCI_CHARRIGHTEXTEND) && 198 (iMessage != SCI_EDITTOGGLEOVERTYPE) && 199 (iMessage != SCI_DELETEBACK) && 200 (iMessage != SCI_DELETEBACKNOTLINE) 201 ) { 202 ct.CallTipCancel(); 203 } 204 if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) { 205 if (sel.MainCaret() <= ct.posStartCallTip) { 206 ct.CallTipCancel(); 207 } 208 } 209 } 210 return Editor::KeyCommand(iMessage); 211 } 212 213 void ScintillaBase::ListNotify(ListBoxEvent *plbe) { 214 switch (plbe->event) { 215 case ListBoxEvent::EventType::selectionChange: 216 AutoCompleteSelection(); 217 break; 218 case ListBoxEvent::EventType::doubleClick: 219 AutoCompleteCompleted(0, SC_AC_DOUBLECLICK); 220 break; 221 } 222 } 223 224 void ScintillaBase::AutoCompleteInsert(Sci::Position startPos, Sci::Position removeLen, const char *text, Sci::Position textLen) { 225 UndoGroup ug(pdoc); 226 if (multiAutoCMode == SC_MULTIAUTOC_ONCE) { 227 pdoc->DeleteChars(startPos, removeLen); 228 const Sci::Position lengthInserted = pdoc->InsertString(startPos, text, textLen); 229 SetEmptySelection(startPos + lengthInserted); 230 } else { 231 // SC_MULTIAUTOC_EACH 232 for (size_t r=0; r<sel.Count(); r++) { 233 if (!RangeContainsProtected(sel.Range(r).Start().Position(), 234 sel.Range(r).End().Position())) { 235 Sci::Position positionInsert = sel.Range(r).Start().Position(); 236 positionInsert = RealizeVirtualSpace(positionInsert, sel.Range(r).caret.VirtualSpace()); 237 if (positionInsert - removeLen >= 0) { 238 positionInsert -= removeLen; 239 pdoc->DeleteChars(positionInsert, removeLen); 240 } 241 const Sci::Position lengthInserted = pdoc->InsertString(positionInsert, text, textLen); 242 if (lengthInserted > 0) { 243 sel.Range(r).caret.SetPosition(positionInsert + lengthInserted); 244 sel.Range(r).anchor.SetPosition(positionInsert + lengthInserted); 245 } 246 sel.Range(r).ClearVirtualSpace(); 247 } 248 } 249 } 250 } 251 252 void ScintillaBase::AutoCompleteStart(Sci::Position lenEntered, const char *list) { 253 //Platform::DebugPrintf("AutoComplete %s\n", list); 254 ct.CallTipCancel(); 255 256 if (ac.chooseSingle && (listType == 0)) { 257 if (list && !strchr(list, ac.GetSeparator())) { 258 const char *typeSep = strchr(list, ac.GetTypesep()); 259 const Sci::Position lenInsert = typeSep ? 260 (typeSep-list) : strlen(list); 261 if (ac.ignoreCase) { 262 // May need to convert the case before invocation, so remove lenEntered characters 263 AutoCompleteInsert(sel.MainCaret() - lenEntered, lenEntered, list, lenInsert); 264 } else { 265 AutoCompleteInsert(sel.MainCaret(), 0, list + lenEntered, lenInsert - lenEntered); 266 } 267 ac.Cancel(); 268 return; 269 } 270 } 271 ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(), 272 lenEntered, vs.lineHeight, IsUnicodeMode(), technology); 273 274 const PRectangle rcClient = GetClientRectangle(); 275 Point pt = LocationFromPosition(sel.MainCaret() - lenEntered); 276 PRectangle rcPopupBounds = wMain.GetMonitorRect(pt); 277 if (rcPopupBounds.Height() == 0) 278 rcPopupBounds = rcClient; 279 280 int heightLB = ac.heightLBDefault; 281 int widthLB = ac.widthLBDefault; 282 if (pt.x >= rcClient.right - widthLB) { 283 HorizontalScrollTo(static_cast<int>(xOffset + pt.x - rcClient.right + widthLB)); 284 Redraw(); 285 pt = PointMainCaret(); 286 } 287 if (wMargin.Created()) { 288 pt = pt + GetVisibleOriginInMain(); 289 } 290 PRectangle rcac; 291 rcac.left = pt.x - ac.lb->CaretFromEdge(); 292 if (pt.y >= rcPopupBounds.bottom - heightLB && // Won't fit below. 293 pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above. 294 rcac.top = pt.y - heightLB; 295 if (rcac.top < rcPopupBounds.top) { 296 heightLB -= static_cast<int>(rcPopupBounds.top - rcac.top); 297 rcac.top = rcPopupBounds.top; 298 } 299 } else { 300 rcac.top = pt.y + vs.lineHeight; 301 } 302 rcac.right = rcac.left + widthLB; 303 rcac.bottom = static_cast<XYPOSITION>(std::min(static_cast<int>(rcac.top) + heightLB, static_cast<int>(rcPopupBounds.bottom))); 304 ac.lb->SetPositionRelative(rcac, &wMain); 305 ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font); 306 const unsigned int aveCharWidth = static_cast<unsigned int>(vs.styles[STYLE_DEFAULT].aveCharWidth); 307 ac.lb->SetAverageCharWidth(aveCharWidth); 308 ac.lb->SetDelegate(this); 309 310 ac.SetList(list ? list : ""); 311 312 // Fiddle the position of the list so it is right next to the target and wide enough for all its strings 313 PRectangle rcList = ac.lb->GetDesiredRect(); 314 const int heightAlloced = static_cast<int>(rcList.bottom - rcList.top); 315 widthLB = std::max(widthLB, static_cast<int>(rcList.right - rcList.left)); 316 if (maxListWidth != 0) 317 widthLB = std::min(widthLB, static_cast<int>(aveCharWidth)*maxListWidth); 318 // Make an allowance for large strings in list 319 rcList.left = pt.x - ac.lb->CaretFromEdge(); 320 rcList.right = rcList.left + widthLB; 321 if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Won't fit below. 322 ((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above. 323 rcList.top = pt.y - heightAlloced; 324 } else { 325 rcList.top = pt.y + vs.lineHeight; 326 } 327 rcList.bottom = rcList.top + heightAlloced; 328 ac.lb->SetPositionRelative(rcList, &wMain); 329 ac.Show(true); 330 if (lenEntered != 0) { 331 AutoCompleteMoveToCurrentWord(); 332 } 333 } 334 335 void ScintillaBase::AutoCompleteCancel() { 336 if (ac.Active()) { 337 SCNotification scn = {}; 338 scn.nmhdr.code = SCN_AUTOCCANCELLED; 339 scn.wParam = 0; 340 scn.listType = 0; 341 NotifyParent(scn); 342 } 343 ac.Cancel(); 344 } 345 346 void ScintillaBase::AutoCompleteMove(int delta) { 347 ac.Move(delta); 348 } 349 350 void ScintillaBase::AutoCompleteMoveToCurrentWord() { 351 std::string wordCurrent = RangeText(ac.posStart - ac.startLen, sel.MainCaret()); 352 ac.Select(wordCurrent.c_str()); 353 } 354 355 void ScintillaBase::AutoCompleteSelection() { 356 const int item = ac.GetSelection(); 357 std::string selected; 358 if (item != -1) { 359 selected = ac.GetValue(item); 360 } 361 362 SCNotification scn = {}; 363 scn.nmhdr.code = SCN_AUTOCSELECTIONCHANGE; 364 scn.message = 0; 365 scn.wParam = listType; 366 scn.listType = listType; 367 const Sci::Position firstPos = ac.posStart - ac.startLen; 368 scn.position = firstPos; 369 scn.lParam = firstPos; 370 scn.text = selected.c_str(); 371 NotifyParent(scn); 372 } 373 374 void ScintillaBase::AutoCompleteCharacterAdded(char ch) { 375 if (ac.IsFillUpChar(ch)) { 376 AutoCompleteCompleted(ch, SC_AC_FILLUP); 377 } else if (ac.IsStopChar(ch)) { 378 AutoCompleteCancel(); 379 } else { 380 AutoCompleteMoveToCurrentWord(); 381 } 382 } 383 384 void ScintillaBase::AutoCompleteCharacterDeleted() { 385 if (sel.MainCaret() < ac.posStart - ac.startLen) { 386 AutoCompleteCancel(); 387 } else if (ac.cancelAtStartPos && (sel.MainCaret() <= ac.posStart)) { 388 AutoCompleteCancel(); 389 } else { 390 AutoCompleteMoveToCurrentWord(); 391 } 392 SCNotification scn = {}; 393 scn.nmhdr.code = SCN_AUTOCCHARDELETED; 394 scn.wParam = 0; 395 scn.listType = 0; 396 NotifyParent(scn); 397 } 398 399 void ScintillaBase::AutoCompleteCompleted(char ch, unsigned int completionMethod) { 400 const int item = ac.GetSelection(); 401 if (item == -1) { 402 AutoCompleteCancel(); 403 return; 404 } 405 const std::string selected = ac.GetValue(item); 406 407 ac.Show(false); 408 409 SCNotification scn = {}; 410 scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION; 411 scn.message = 0; 412 scn.ch = ch; 413 scn.listCompletionMethod = completionMethod; 414 scn.wParam = listType; 415 scn.listType = listType; 416 const Sci::Position firstPos = ac.posStart - ac.startLen; 417 scn.position = firstPos; 418 scn.lParam = firstPos; 419 scn.text = selected.c_str(); 420 NotifyParent(scn); 421 422 if (!ac.Active()) 423 return; 424 ac.Cancel(); 425 426 if (listType > 0) 427 return; 428 429 Sci::Position endPos = sel.MainCaret(); 430 if (ac.dropRestOfWord) 431 endPos = pdoc->ExtendWordSelect(endPos, 1, true); 432 if (endPos < firstPos) 433 return; 434 AutoCompleteInsert(firstPos, endPos - firstPos, selected.c_str(), selected.length()); 435 SetLastXChosen(); 436 437 scn.nmhdr.code = SCN_AUTOCCOMPLETED; 438 NotifyParent(scn); 439 440 } 441 442 int ScintillaBase::AutoCompleteGetCurrent() const { 443 if (!ac.Active()) 444 return -1; 445 return ac.GetSelection(); 446 } 447 448 int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) const { 449 if (ac.Active()) { 450 const int item = ac.GetSelection(); 451 if (item != -1) { 452 const std::string selected = ac.GetValue(item); 453 if (buffer) 454 memcpy(buffer, selected.c_str(), selected.length()+1); 455 return static_cast<int>(selected.length()); 456 } 457 } 458 if (buffer) 459 *buffer = '\0'; 460 return 0; 461 } 462 463 void ScintillaBase::CallTipShow(Point pt, const char *defn) { 464 ac.Cancel(); 465 // If container knows about STYLE_CALLTIP then use it in place of the 466 // STYLE_DEFAULT for the face name, size and character set. Also use it 467 // for the foreground and background colour. 468 const int ctStyle = ct.UseStyleCallTip() ? STYLE_CALLTIP : STYLE_DEFAULT; 469 if (ct.UseStyleCallTip()) { 470 ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back); 471 } 472 if (wMargin.Created()) { 473 pt = pt + GetVisibleOriginInMain(); 474 } 475 PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt, 476 vs.lineHeight, 477 defn, 478 vs.styles[ctStyle].fontName, 479 vs.styles[ctStyle].sizeZoomed, 480 CodePage(), 481 vs.styles[ctStyle].characterSet, 482 vs.technology, 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 504 void ScintillaBase::CallTipClick() { 505 SCNotification scn = {}; 506 scn.nmhdr.code = SCN_CALLTIPCLICK; 507 scn.position = ct.clickPlace; 508 NotifyParent(scn); 509 } 510 511 bool ScintillaBase::ShouldDisplayPopup(Point ptInWindowCoordinates) const { 512 return (displayPopupMenu == SC_POPUP_ALL || 513 (displayPopupMenu == SC_POPUP_TEXT && !PointInSelMargin(ptInWindowCoordinates))); 514 } 515 516 void ScintillaBase::ContextMenu(Point pt) { 517 if (displayPopupMenu) { 518 const bool writable = !WndProc(SCI_GETREADONLY, 0, 0); 519 popup.CreatePopUp(); 520 AddToPopUp(_T("撤销\tCtrl+Z"), idcmdUndo, writable && pdoc->CanUndo()); 521 AddToPopUp(_T("重做\tCtrl+Y"), idcmdRedo, writable && pdoc->CanRedo()); 522 AddToPopUp(_T("")); 523 AddToPopUp(_T("剪切\tCtrl+X"), idcmdCut, writable && !sel.Empty()); 524 AddToPopUp(_T("复制\tCtrl+C"), idcmdCopy, !sel.Empty()); 525 AddToPopUp(_T("粘贴\tCtrl+V"), idcmdPaste, writable && WndProc(SCI_CANPASTE, 0, 0)); 526 AddToPopUp(_T("删除"), idcmdDelete, writable && !sel.Empty()); 527 AddToPopUp(_T("")); 528 AddToPopUp(_T("全选\tCtrl+A"), idcmdSelectAll); 529 popup.Show(pt, wMain); 530 } 531 } 532 533 void ScintillaBase::CancelModes() { 534 AutoCompleteCancel(); 535 ct.CallTipCancel(); 536 Editor::CancelModes(); 537 } 538 539 void ScintillaBase::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { 540 CancelModes(); 541 Editor::ButtonDownWithModifiers(pt, curTime, modifiers); 542 } 543 544 void ScintillaBase::RightButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { 545 CancelModes(); 546 Editor::RightButtonDownWithModifiers(pt, curTime, modifiers); 547 } 548 549 namespace Scintilla { 550 551 class LexState : public LexInterface { 552 const LexerModule *lexCurrent; 553 void SetLexerModule(const LexerModule *lex); 554 PropSetSimple props; 555 int interfaceVersion; 556 public: 557 int lexLanguage; 558 559 explicit LexState(Document *pdoc_); 560 void SetInstance(ILexer5 *instance_); 561 // Deleted so LexState objects can not be copied. 562 LexState(const LexState &) = delete; 563 LexState(LexState &&) = delete; 564 LexState &operator=(const LexState &) = delete; 565 LexState &operator=(LexState &&) = delete; 566 ~LexState() override; 567 void SetLexer(uptr_t wParam); 568 void SetLexerLanguage(const char *languageName); 569 570 const char *DescribeWordListSets(); 571 void SetWordList(int n, const char *wl); 572 int GetIdentifier() const; 573 const char *GetName() const; 574 void *PrivateCall(int operation, void *pointer); 575 const char *PropertyNames(); 576 int PropertyType(const char *name); 577 const char *DescribeProperty(const char *name); 578 void PropSet(const char *key, const char *val); 579 const char *PropGet(const char *key) const; 580 int PropGetInt(const char *key, int defaultValue=0) const; 581 size_t PropGetExpanded(const char *key, char *result) const; 582 583 int LineEndTypesSupported() override; 584 int AllocateSubStyles(int styleBase, int numberStyles); 585 int SubStylesStart(int styleBase); 586 int SubStylesLength(int styleBase); 587 int StyleFromSubStyle(int subStyle); 588 int PrimaryStyleFromStyle(int style); 589 void FreeSubStyles(); 590 void SetIdentifiers(int style, const char *identifiers); 591 int DistanceToSecondaryStyles(); 592 const char *GetSubStyleBases(); 593 int NamedStyles(); 594 const char *NameOfStyle(int style); 595 const char *TagsOfStyle(int style); 596 const char *DescriptionOfStyle(int style); 597 }; 598 599 } 600 601 LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) { 602 lexCurrent = nullptr; 603 performingStyle = false; 604 interfaceVersion = lvRelease4; 605 lexLanguage = SCLEX_CONTAINER; 606 } 607 608 LexState::~LexState() { 609 if (instance) { 610 instance->Release(); 611 instance = nullptr; 612 } 613 } 614 615 void LexState::SetInstance(ILexer5 *instance_) { 616 if (instance) { 617 instance->Release(); 618 instance = nullptr; 619 } 620 instance = instance_; 621 pdoc->LexerChanged(); 622 } 623 624 LexState *ScintillaBase::DocumentLexState() { 625 if (!pdoc->GetLexInterface()) { 626 pdoc->SetLexInterface(std::make_unique<LexState>(pdoc)); 627 } 628 return dynamic_cast<LexState *>(pdoc->GetLexInterface()); 629 } 630 631 void LexState::SetLexerModule(const LexerModule *lex) { 632 if (lex != lexCurrent) { 633 if (instance) { 634 instance->Release(); 635 instance = nullptr; 636 } 637 interfaceVersion = lvRelease4; 638 lexCurrent = lex; 639 if (lexCurrent) { 640 instance = lexCurrent->Create(); 641 interfaceVersion = instance->Version(); 642 } 643 pdoc->LexerChanged(); 644 } 645 } 646 647 void LexState::SetLexer(uptr_t wParam) { 648 lexLanguage = static_cast<int>(wParam); 649 if (lexLanguage == SCLEX_CONTAINER) { 650 SetLexerModule(nullptr); 651 } else { 652 const LexerModule *lex = Catalogue::Find(lexLanguage); 653 if (!lex) 654 lex = Catalogue::Find(SCLEX_NULL); 655 SetLexerModule(lex); 656 } 657 } 658 659 void LexState::SetLexerLanguage(const char *languageName) { 660 const LexerModule *lex = Catalogue::Find(languageName); 661 if (!lex) 662 lex = Catalogue::Find(SCLEX_NULL); 663 if (lex) 664 lexLanguage = lex->GetLanguage(); 665 SetLexerModule(lex); 666 } 667 668 const char *LexState::DescribeWordListSets() { 669 if (instance) { 670 return instance->DescribeWordListSets(); 671 } else { 672 return nullptr; 673 } 674 } 675 676 void LexState::SetWordList(int n, const char *wl) { 677 if (instance) { 678 const Sci_Position firstModification = instance->WordListSet(n, wl); 679 if (firstModification >= 0) { 680 pdoc->ModifiedAt(firstModification); 681 } 682 } 683 } 684 685 int LexState::GetIdentifier() const { 686 if (lexCurrent) { 687 return lexCurrent->GetLanguage(); 688 } 689 if (instance) { 690 if (instance->Version() >= lvRelease5) { 691 return instance->GetIdentifier(); 692 } 693 } 694 return SCLEX_CONTAINER; 695 } 696 697 const char *LexState::GetName() const { 698 if (lexCurrent) { 699 return lexCurrent->languageName; 700 } 701 if (instance) { 702 if (instance->Version() >= lvRelease5) { 703 return instance->GetName(); 704 } 705 } 706 return ""; 707 } 708 709 void *LexState::PrivateCall(int operation, void *pointer) { 710 if (pdoc && instance) { 711 return instance->PrivateCall(operation, pointer); 712 } else { 713 return nullptr; 714 } 715 } 716 717 const char *LexState::PropertyNames() { 718 if (instance) { 719 return instance->PropertyNames(); 720 } else { 721 return nullptr; 722 } 723 } 724 725 int LexState::PropertyType(const char *name) { 726 if (instance) { 727 return instance->PropertyType(name); 728 } else { 729 return SC_TYPE_BOOLEAN; 730 } 731 } 732 733 const char *LexState::DescribeProperty(const char *name) { 734 if (instance) { 735 return instance->DescribeProperty(name); 736 } else { 737 return nullptr; 738 } 739 } 740 741 void LexState::PropSet(const char *key, const char *val) { 742 props.Set(key, val, strlen(key), strlen(val)); 743 if (instance) { 744 const Sci_Position firstModification = instance->PropertySet(key, val); 745 if (firstModification >= 0) { 746 pdoc->ModifiedAt(firstModification); 747 } 748 } 749 } 750 751 const char *LexState::PropGet(const char *key) const { 752 return props.Get(key); 753 } 754 755 int LexState::PropGetInt(const char *key, int defaultValue) const { 756 return props.GetInt(key, defaultValue); 757 } 758 759 size_t LexState::PropGetExpanded(const char *key, char *result) const { 760 return props.GetExpanded(key, result); 761 } 762 763 int LexState::LineEndTypesSupported() { 764 if (instance) { 765 return instance->LineEndTypesSupported(); 766 } 767 return 0; 768 } 769 770 int LexState::AllocateSubStyles(int styleBase, int numberStyles) { 771 if (instance) { 772 return instance->AllocateSubStyles(styleBase, numberStyles); 773 } 774 return -1; 775 } 776 777 int LexState::SubStylesStart(int styleBase) { 778 if (instance) { 779 return instance->SubStylesStart(styleBase); 780 } 781 return -1; 782 } 783 784 int LexState::SubStylesLength(int styleBase) { 785 if (instance) { 786 return instance->SubStylesLength(styleBase); 787 } 788 return 0; 789 } 790 791 int LexState::StyleFromSubStyle(int subStyle) { 792 if (instance) { 793 return instance->StyleFromSubStyle(subStyle); 794 } 795 return 0; 796 } 797 798 int LexState::PrimaryStyleFromStyle(int style) { 799 if (instance) { 800 return instance->PrimaryStyleFromStyle(style); 801 } 802 return 0; 803 } 804 805 void LexState::FreeSubStyles() { 806 if (instance) { 807 instance->FreeSubStyles(); 808 } 809 } 810 811 void LexState::SetIdentifiers(int style, const char *identifiers) { 812 if (instance) { 813 instance->SetIdentifiers(style, identifiers); 814 pdoc->ModifiedAt(0); 815 } 816 } 817 818 int LexState::DistanceToSecondaryStyles() { 819 if (instance) { 820 return instance->DistanceToSecondaryStyles(); 821 } 822 return 0; 823 } 824 825 const char *LexState::GetSubStyleBases() { 826 if (instance) { 827 return instance->GetSubStyleBases(); 828 } 829 return ""; 830 } 831 832 int LexState::NamedStyles() { 833 if (instance) { 834 return instance->NamedStyles(); 835 } else { 836 return -1; 837 } 838 } 839 840 const char *LexState::NameOfStyle(int style) { 841 if (instance) { 842 return instance->NameOfStyle(style); 843 } else { 844 return nullptr; 845 } 846 } 847 848 const char *LexState::TagsOfStyle(int style) { 849 if (instance) { 850 return instance->TagsOfStyle(style); 851 } else { 852 return nullptr; 853 } 854 } 855 856 const char *LexState::DescriptionOfStyle(int style) { 857 if (instance) { 858 return instance->DescriptionOfStyle(style); 859 } else { 860 return nullptr; 861 } 862 } 863 864 void ScintillaBase::NotifyStyleToNeeded(Sci::Position endStyleNeeded) { 865 if (DocumentLexState()->GetIdentifier() != SCLEX_CONTAINER) { 866 const Sci::Line lineEndStyled = 867 pdoc->SciLineFromPosition(pdoc->GetEndStyled()); 868 const Sci::Position endStyled = 869 pdoc->LineStart(lineEndStyled); 870 DocumentLexState()->Colourise(endStyled, endStyleNeeded); 871 return; 872 } 873 Editor::NotifyStyleToNeeded(endStyleNeeded); 874 } 875 876 void ScintillaBase::NotifyLexerChanged(Document *, void *) { 877 vs.EnsureStyle(0xff); 878 } 879 880 sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { 881 switch (iMessage) { 882 case SCI_AUTOCSHOW: 883 listType = 0; 884 AutoCompleteStart(static_cast<Sci::Position>(wParam), ConstCharPtrFromSPtr(lParam)); 885 break; 886 887 case SCI_AUTOCCANCEL: 888 ac.Cancel(); 889 break; 890 891 case SCI_AUTOCACTIVE: 892 return ac.Active(); 893 894 case SCI_AUTOCPOSSTART: 895 return ac.posStart; 896 897 case SCI_AUTOCCOMPLETE: 898 AutoCompleteCompleted(0, SC_AC_COMMAND); 899 break; 900 901 case SCI_AUTOCSETSEPARATOR: 902 ac.SetSeparator(static_cast<char>(wParam)); 903 break; 904 905 case SCI_AUTOCGETSEPARATOR: 906 return ac.GetSeparator(); 907 908 case SCI_AUTOCSTOPS: 909 ac.SetStopChars(ConstCharPtrFromSPtr(lParam)); 910 break; 911 912 case SCI_AUTOCSELECT: 913 ac.Select(ConstCharPtrFromSPtr(lParam)); 914 break; 915 916 case SCI_AUTOCGETCURRENT: 917 return AutoCompleteGetCurrent(); 918 919 case SCI_AUTOCGETCURRENTTEXT: 920 return AutoCompleteGetCurrentText(CharPtrFromSPtr(lParam)); 921 922 case SCI_AUTOCSETCANCELATSTART: 923 ac.cancelAtStartPos = wParam != 0; 924 break; 925 926 case SCI_AUTOCGETCANCELATSTART: 927 return ac.cancelAtStartPos; 928 929 case SCI_AUTOCSETFILLUPS: 930 ac.SetFillUpChars(ConstCharPtrFromSPtr(lParam)); 931 break; 932 933 case SCI_AUTOCSETCHOOSESINGLE: 934 ac.chooseSingle = wParam != 0; 935 break; 936 937 case SCI_AUTOCGETCHOOSESINGLE: 938 return ac.chooseSingle; 939 940 case SCI_AUTOCSETIGNORECASE: 941 ac.ignoreCase = wParam != 0; 942 break; 943 944 case SCI_AUTOCGETIGNORECASE: 945 return ac.ignoreCase; 946 947 case SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR: 948 ac.ignoreCaseBehaviour = static_cast<unsigned int>(wParam); 949 break; 950 951 case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR: 952 return ac.ignoreCaseBehaviour; 953 954 case SCI_AUTOCSETMULTI: 955 multiAutoCMode = static_cast<int>(wParam); 956 break; 957 958 case SCI_AUTOCGETMULTI: 959 return multiAutoCMode; 960 961 case SCI_AUTOCSETORDER: 962 ac.autoSort = static_cast<int>(wParam); 963 break; 964 965 case SCI_AUTOCGETORDER: 966 return ac.autoSort; 967 968 case SCI_USERLISTSHOW: 969 listType = static_cast<int>(wParam); 970 AutoCompleteStart(0, ConstCharPtrFromSPtr(lParam)); 971 break; 972 973 case SCI_AUTOCSETAUTOHIDE: 974 ac.autoHide = wParam != 0; 975 break; 976 977 case SCI_AUTOCGETAUTOHIDE: 978 return ac.autoHide; 979 980 case SCI_AUTOCSETDROPRESTOFWORD: 981 ac.dropRestOfWord = wParam != 0; 982 break; 983 984 case SCI_AUTOCGETDROPRESTOFWORD: 985 return ac.dropRestOfWord; 986 987 case SCI_AUTOCSETMAXHEIGHT: 988 ac.lb->SetVisibleRows(static_cast<int>(wParam)); 989 break; 990 991 case SCI_AUTOCGETMAXHEIGHT: 992 return ac.lb->GetVisibleRows(); 993 994 case SCI_AUTOCSETMAXWIDTH: 995 maxListWidth = static_cast<int>(wParam); 996 break; 997 998 case SCI_AUTOCGETMAXWIDTH: 999 return maxListWidth; 1000 1001 case SCI_REGISTERIMAGE: 1002 ac.lb->RegisterImage(static_cast<int>(wParam), ConstCharPtrFromSPtr(lParam)); 1003 break; 1004 1005 case SCI_REGISTERRGBAIMAGE: 1006 ac.lb->RegisterRGBAImage(static_cast<int>(wParam), static_cast<int>(sizeRGBAImage.x), static_cast<int>(sizeRGBAImage.y), 1007 ConstUCharPtrFromSPtr(lParam)); 1008 break; 1009 1010 case SCI_CLEARREGISTEREDIMAGES: 1011 ac.lb->ClearRegisteredImages(); 1012 break; 1013 1014 case SCI_AUTOCSETTYPESEPARATOR: 1015 ac.SetTypesep(static_cast<char>(wParam)); 1016 break; 1017 1018 case SCI_AUTOCGETTYPESEPARATOR: 1019 return ac.GetTypesep(); 1020 1021 case SCI_CALLTIPSHOW: 1022 CallTipShow(LocationFromPosition(wParam), 1023 ConstCharPtrFromSPtr(lParam)); 1024 break; 1025 1026 case SCI_CALLTIPCANCEL: 1027 ct.CallTipCancel(); 1028 break; 1029 1030 case SCI_CALLTIPACTIVE: 1031 return ct.inCallTipMode; 1032 1033 case SCI_CALLTIPPOSSTART: 1034 return ct.posStartCallTip; 1035 1036 case SCI_CALLTIPSETPOSSTART: 1037 ct.posStartCallTip = wParam; 1038 break; 1039 1040 case SCI_CALLTIPSETHLT: 1041 ct.SetHighlight(wParam, lParam); 1042 break; 1043 1044 case SCI_CALLTIPSETBACK: 1045 ct.colourBG = ColourDesired(static_cast<int>(wParam)); 1046 vs.styles[STYLE_CALLTIP].back = ct.colourBG; 1047 InvalidateStyleRedraw(); 1048 break; 1049 1050 case SCI_CALLTIPSETFORE: 1051 ct.colourUnSel = ColourDesired(static_cast<int>(wParam)); 1052 vs.styles[STYLE_CALLTIP].fore = ct.colourUnSel; 1053 InvalidateStyleRedraw(); 1054 break; 1055 1056 case SCI_CALLTIPSETFOREHLT: 1057 ct.colourSel = ColourDesired(static_cast<int>(wParam)); 1058 InvalidateStyleRedraw(); 1059 break; 1060 1061 case SCI_CALLTIPUSESTYLE: 1062 ct.SetTabSize(static_cast<int>(wParam)); 1063 InvalidateStyleRedraw(); 1064 break; 1065 1066 case SCI_CALLTIPSETPOSITION: 1067 ct.SetPosition(wParam != 0); 1068 InvalidateStyleRedraw(); 1069 break; 1070 1071 case SCI_USEPOPUP: 1072 displayPopupMenu = static_cast<int>(wParam); 1073 break; 1074 1075 case SCI_SETLEXER: 1076 DocumentLexState()->SetLexer(static_cast<int>(wParam)); 1077 break; 1078 1079 case SCI_GETLEXER: 1080 return DocumentLexState()->GetIdentifier(); 1081 1082 case SCI_SETILEXER: 1083 DocumentLexState()->SetInstance(reinterpret_cast<ILexer5 *>(lParam)); 1084 return 0; 1085 1086 case SCI_COLOURISE: 1087 if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) { 1088 pdoc->ModifiedAt(static_cast<Sci::Position>(wParam)); 1089 NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam); 1090 } else { 1091 DocumentLexState()->Colourise(static_cast<Sci::Position>(wParam), lParam); 1092 } 1093 Redraw(); 1094 break; 1095 1096 case SCI_SETPROPERTY: 1097 DocumentLexState()->PropSet(ConstCharPtrFromUPtr(wParam), 1098 ConstCharPtrFromSPtr(lParam)); 1099 break; 1100 1101 case SCI_GETPROPERTY: 1102 return StringResult(lParam, DocumentLexState()->PropGet(ConstCharPtrFromUPtr(wParam))); 1103 1104 case SCI_GETPROPERTYEXPANDED: 1105 return DocumentLexState()->PropGetExpanded(ConstCharPtrFromUPtr(wParam), 1106 CharPtrFromSPtr(lParam)); 1107 1108 case SCI_GETPROPERTYINT: 1109 return DocumentLexState()->PropGetInt(ConstCharPtrFromUPtr(wParam), static_cast<int>(lParam)); 1110 1111 case SCI_SETKEYWORDS: 1112 DocumentLexState()->SetWordList(static_cast<int>(wParam), ConstCharPtrFromSPtr(lParam)); 1113 break; 1114 1115 case SCI_SETLEXERLANGUAGE: 1116 DocumentLexState()->SetLexerLanguage(ConstCharPtrFromSPtr(lParam)); 1117 break; 1118 1119 case SCI_GETLEXERLANGUAGE: 1120 return StringResult(lParam, DocumentLexState()->GetName()); 1121 1122 #ifdef SCI_LEXER 1123 case SCI_LOADLEXERLIBRARY: 1124 ExternalLexerLoad(ConstCharPtrFromSPtr(lParam)); 1125 break; 1126 #endif 1127 1128 case SCI_PRIVATELEXERCALL: 1129 return reinterpret_cast<sptr_t>( 1130 DocumentLexState()->PrivateCall(static_cast<int>(wParam), reinterpret_cast<void *>(lParam))); 1131 1132 #ifdef INCLUDE_DEPRECATED_FEATURES 1133 case SCI_GETSTYLEBITSNEEDED: 1134 return 8; 1135 #endif 1136 1137 case SCI_PROPERTYNAMES: 1138 return StringResult(lParam, DocumentLexState()->PropertyNames()); 1139 1140 case SCI_PROPERTYTYPE: 1141 return DocumentLexState()->PropertyType(ConstCharPtrFromUPtr(wParam)); 1142 1143 case SCI_DESCRIBEPROPERTY: 1144 return StringResult(lParam, 1145 DocumentLexState()->DescribeProperty(ConstCharPtrFromUPtr(wParam))); 1146 1147 case SCI_DESCRIBEKEYWORDSETS: 1148 return StringResult(lParam, DocumentLexState()->DescribeWordListSets()); 1149 1150 case SCI_GETLINEENDTYPESSUPPORTED: 1151 return DocumentLexState()->LineEndTypesSupported(); 1152 1153 case SCI_ALLOCATESUBSTYLES: 1154 return DocumentLexState()->AllocateSubStyles(static_cast<int>(wParam), static_cast<int>(lParam)); 1155 1156 case SCI_GETSUBSTYLESSTART: 1157 return DocumentLexState()->SubStylesStart(static_cast<int>(wParam)); 1158 1159 case SCI_GETSUBSTYLESLENGTH: 1160 return DocumentLexState()->SubStylesLength(static_cast<int>(wParam)); 1161 1162 case SCI_GETSTYLEFROMSUBSTYLE: 1163 return DocumentLexState()->StyleFromSubStyle(static_cast<int>(wParam)); 1164 1165 case SCI_GETPRIMARYSTYLEFROMSTYLE: 1166 return DocumentLexState()->PrimaryStyleFromStyle(static_cast<int>(wParam)); 1167 1168 case SCI_FREESUBSTYLES: 1169 DocumentLexState()->FreeSubStyles(); 1170 break; 1171 1172 case SCI_SETIDENTIFIERS: 1173 DocumentLexState()->SetIdentifiers(static_cast<int>(wParam), 1174 ConstCharPtrFromSPtr(lParam)); 1175 break; 1176 1177 case SCI_DISTANCETOSECONDARYSTYLES: 1178 return DocumentLexState()->DistanceToSecondaryStyles(); 1179 1180 case SCI_GETSUBSTYLEBASES: 1181 return StringResult(lParam, DocumentLexState()->GetSubStyleBases()); 1182 1183 case SCI_GETNAMEDSTYLES: 1184 return DocumentLexState()->NamedStyles(); 1185 1186 case SCI_NAMEOFSTYLE: 1187 return StringResult(lParam, DocumentLexState()-> 1188 NameOfStyle(static_cast<int>(wParam))); 1189 1190 case SCI_TAGSOFSTYLE: 1191 return StringResult(lParam, DocumentLexState()-> 1192 TagsOfStyle(static_cast<int>(wParam))); 1193 1194 case SCI_DESCRIPTIONOFSTYLE: 1195 return StringResult(lParam, DocumentLexState()-> 1196 DescriptionOfStyle(static_cast<int>(wParam))); 1197 1198 default: 1199 return Editor::WndProc(iMessage, wParam, lParam); 1200 } 1201 return 0; 1202 } 1203