📄 scintillabase.cxx
字号:
// Scintilla source code edit control/** @file ScintillaBase.cxx ** An enhanced subclass of Editor with calltips, autocomplete and context menu. **/// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>// The License.txt file describes the conditions under which this software may be distributed.#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>#include "Platform.h"#include "Scintilla.h"#include "PropSet.h"#ifdef SCI_LEXER#include "SciLexer.h"#include "Accessor.h"#include "DocumentAccessor.h"#include "KeyWords.h"#endif#include "ContractionState.h"#include "SVector.h"#include "CellBuffer.h"#include "CallTip.h"#include "KeyMap.h"#include "Indicator.h"#include "XPM.h"#include "LineMarker.h"#include "Style.h"#include "ViewStyle.h"#include "AutoComplete.h"#include "CharClassify.h"#include "Document.h"#include "Editor.h"#include "ScintillaBase.h"ScintillaBase::ScintillaBase() { displayPopupMenu = true; listType = 0; maxListWidth = 0;#ifdef SCI_LEXER lexLanguage = SCLEX_CONTAINER; performingStyle = false; lexCurrent = 0; for (int wl = 0;wl < numWordLists;wl++) keyWordLists[wl] = new WordList; keyWordLists[numWordLists] = 0;#endif}ScintillaBase::~ScintillaBase() {#ifdef SCI_LEXER for (int wl = 0;wl < numWordLists;wl++) delete keyWordLists[wl];#endif}void ScintillaBase::Finalise() { Editor::Finalise(); popup.Destroy();}void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) { Editor::RefreshColourPalette(pal, want); ct.RefreshColourPalette(pal, want);}void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { bool isFillUp = ac.Active() && ac.IsFillUpChar(*s); if (!isFillUp) { Editor::AddCharUTF(s, len, treatAsDBCS); } if (ac.Active()) { AutoCompleteCharacterAdded(s[0]); // For fill ups add the character after the autocompletion has // triggered so containers see the key so can display a calltip. if (isFillUp) { Editor::AddCharUTF(s, len, treatAsDBCS); } }}void ScintillaBase::Command(int cmdId) { switch (cmdId) { case idAutoComplete: // Nothing to do break; case idCallTip: // Nothing to do break; case idcmdUndo: WndProc(SCI_UNDO, 0, 0); break; case idcmdRedo: WndProc(SCI_REDO, 0, 0); break; case idcmdCut: WndProc(SCI_CUT, 0, 0); break; case idcmdCopy: WndProc(SCI_COPY, 0, 0); break; case idcmdPaste: WndProc(SCI_PASTE, 0, 0); break; case idcmdDelete: WndProc(SCI_CLEAR, 0, 0); break; case idcmdSelectAll: WndProc(SCI_SELECTALL, 0, 0); break; }}int ScintillaBase::KeyCommand(unsigned int iMessage) { // Most key commands cancel autocompletion mode if (ac.Active()) { switch (iMessage) { // Except for these case SCI_LINEDOWN: AutoCompleteMove(1); return 0; case SCI_LINEUP: AutoCompleteMove( -1); return 0; case SCI_PAGEDOWN: AutoCompleteMove(5); return 0; case SCI_PAGEUP: AutoCompleteMove( -5); return 0; case SCI_VCHOME: AutoCompleteMove( -5000); return 0; case SCI_LINEEND: AutoCompleteMove(5000); return 0; case SCI_DELETEBACK: DelCharBack(true); AutoCompleteCharacterDeleted(); EnsureCaretVisible(); return 0; case SCI_DELETEBACKNOTLINE: DelCharBack(false); AutoCompleteCharacterDeleted(); EnsureCaretVisible(); return 0; case SCI_TAB: AutoCompleteCompleted(); return 0; case SCI_NEWLINE: AutoCompleteCompleted(); return 0; default: ac.Cancel(); } } if (ct.inCallTipMode) { if ( (iMessage != SCI_CHARLEFT) && (iMessage != SCI_CHARLEFTEXTEND) && (iMessage != SCI_CHARRIGHT) && (iMessage != SCI_CHARLEFTEXTEND) && (iMessage != SCI_EDITTOGGLEOVERTYPE) && (iMessage != SCI_DELETEBACK) && (iMessage != SCI_DELETEBACKNOTLINE) ) { ct.CallTipCancel(); } if ((iMessage == SCI_DELETEBACK) || (iMessage == SCI_DELETEBACKNOTLINE)) { if (currentPos <= ct.posStartCallTip) { ct.CallTipCancel(); } } } return Editor::KeyCommand(iMessage);}void ScintillaBase::AutoCompleteDoubleClick(void* p) { ScintillaBase* sci = reinterpret_cast<ScintillaBase*>(p); sci->AutoCompleteCompleted();}void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { //Platform::DebugPrintf("AutoComplete %s\n", list); ct.CallTipCancel(); if (ac.chooseSingle && (listType == 0)) { if (list && !strchr(list, ac.GetSeparator())) { const char *typeSep = strchr(list, ac.GetTypesep()); size_t lenInsert = (typeSep) ? (typeSep-list) : strlen(list); if (ac.ignoreCase) { SetEmptySelection(currentPos - lenEntered); pdoc->DeleteChars(currentPos, lenEntered); SetEmptySelection(currentPos); pdoc->InsertString(currentPos, list, lenInsert); SetEmptySelection(currentPos + lenInsert); } else { SetEmptySelection(currentPos); pdoc->InsertString(currentPos, list + lenEntered, lenInsert - lenEntered); SetEmptySelection(currentPos + lenInsert - lenEntered); } return; } } ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos), lenEntered, vs.lineHeight, IsUnicodeMode()); PRectangle rcClient = GetClientRectangle(); Point pt = LocationFromPosition(currentPos - lenEntered); int heightLB = 100; int widthLB = 100; if (pt.x >= rcClient.right - widthLB) { HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB); Redraw(); pt = LocationFromPosition(currentPos); } PRectangle rcac; rcac.left = pt.x - ac.lb->CaretFromEdge(); if (pt.y >= rcClient.bottom - heightLB && // Wont fit below. pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above. rcac.top = pt.y - heightLB; if (rcac.top < 0) { heightLB += rcac.top; rcac.top = 0; } } else { rcac.top = pt.y + vs.lineHeight; } rcac.right = rcac.left + widthLB; rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom); ac.lb->SetPositionRelative(rcac, wMain); ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font); unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth; ac.lb->SetAverageCharWidth(aveCharWidth); ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this); ac.SetList(list); // Fiddle the position of the list so it is right next to the target and wide enough for all its strings PRectangle rcList = ac.lb->GetDesiredRect(); int heightAlloced = rcList.bottom - rcList.top; widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left); if (maxListWidth != 0) widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth); // Make an allowance for large strings in list rcList.left = pt.x - ac.lb->CaretFromEdge(); rcList.right = rcList.left + widthLB; if (((pt.y + vs.lineHeight) >= (rcClient.bottom - heightAlloced)) && // Wont fit below. ((pt.y + vs.lineHeight / 2) >= (rcClient.bottom + rcClient.top) / 2)) { // and there is more room above. rcList.top = pt.y - heightAlloced; } else { rcList.top = pt.y + vs.lineHeight; } rcList.bottom = rcList.top + heightAlloced; ac.lb->SetPositionRelative(rcList, wMain); ac.Show(true); if (lenEntered != 0) { AutoCompleteMoveToCurrentWord(); }}void ScintillaBase::AutoCompleteCancel() { ac.Cancel();}void ScintillaBase::AutoCompleteMove(int delta) { ac.Move(delta);}void ScintillaBase::AutoCompleteMoveToCurrentWord() { char wordCurrent[1000]; int i; int startWord = ac.posStart - ac.startLen; for (i = startWord; i < currentPos && i - startWord < 1000; i++) wordCurrent[i - startWord] = pdoc->CharAt(i); wordCurrent[Platform::Minimum(i - startWord, 999)] = '\0'; ac.Select(wordCurrent);}void ScintillaBase::AutoCompleteCharacterAdded(char ch) { if (ac.IsFillUpChar(ch)) { AutoCompleteCompleted(); } else if (ac.IsStopChar(ch)) { ac.Cancel(); } else { AutoCompleteMoveToCurrentWord(); }}void ScintillaBase::AutoCompleteCharacterDeleted() { if (currentPos < ac.posStart - ac.startLen) { ac.Cancel(); } else if (ac.cancelAtStartPos && (currentPos <= ac.posStart)) { ac.Cancel(); } else { AutoCompleteMoveToCurrentWord(); }}void ScintillaBase::AutoCompleteCompleted() { int item = ac.lb->GetSelection(); char selected[1000]; selected[0] = '\0'; if (item != -1) { ac.lb->GetValue(item, selected, sizeof(selected)); } else { ac.Cancel(); return; } ac.Show(false); listSelected = selected; SCNotification scn = {0}; scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION; scn.message = 0; scn.wParam = listType; scn.listType = listType; Position firstPos = ac.posStart - ac.startLen; scn.lParam = firstPos; scn.text = listSelected.c_str(); NotifyParent(scn); if (!ac.Active()) return; ac.Cancel(); if (listType > 0) return; Position endPos = currentPos; if (ac.dropRestOfWord) endPos = pdoc->ExtendWordSelect(endPos, 1, true); if (endPos < firstPos) return; pdoc->BeginUndoAction(); if (endPos != firstPos) { pdoc->DeleteChars(firstPos, endPos - firstPos); } SetEmptySelection(ac.posStart); if (item != -1) { SString piece = selected; pdoc->InsertString(firstPos, piece.c_str()); SetEmptySelection(firstPos + static_cast<int>(piece.length())); } pdoc->EndUndoAction();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -