// Scintilla source code edit control // ScintillaBase.cxx - an enhanced subclass of Editor with calltips, autocomplete and context menu // Copyright 1998-2000 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include "Platform.h" #include "Scintilla.h" #ifdef SCI_LEXER #include "SciLexer.h" #include "PropSet.h" #include "Accessor.h" #include "KeyWords.h" #endif #include "ContractionState.h" #include "SVector.h" #include "CellBuffer.h" #include "CallTip.h" #include "KeyMap.h" #include "Indicator.h" #include "LineMarker.h" #include "Style.h" #include "ViewStyle.h" #include "AutoComplete.h" #include "Document.h" #include "Editor.h" #include "ScintillaBase.h" ScintillaBase::ScintillaBase() { #ifdef SCI_LEXER lexLanguage = SCLEX_CONTAINER; for (int wl=0;wl= rcClient.right - widthLB) { HorizontalScrollTo(xOffset + pt.x - rcClient.right + widthLB); Redraw(); pt = LocationFromPosition(currentPos); } PRectangle rcac; rcac.left = pt.x - 5; 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[0].font); int maxStrLen = 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.GetPosition(); int heightAlloced = rcList.bottom - rcList.top; // Make an allowance for large strings in list rcList.left = pt.x - 5; rcList.right = rcList.left + Platform::Maximum(widthLB, maxStrLen * 8 + 16); if (pt.y >= rcClient.bottom - heightLB && // Wont fit below. pt.y >= (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); //lbAutoComplete.SetPosition(rcList); ac.Show(); } void ScintillaBase::AutoCompleteCancel() { ac.Cancel(); } void ScintillaBase::AutoCompleteMove(int delta) { ac.Move(delta); } void ScintillaBase::AutoCompleteChanged(char ch) { if (currentPos <= ac.posStart) { ac.Cancel(); } else if (ac.IsStopChar(ch)) { ac.Cancel(); } else { char wordCurrent[1000]; int i; int startWord = ac.posStart - ac.startLen; for (i = startWord; i < currentPos; i++) wordCurrent[i - startWord] = pdoc->CharAt(i); wordCurrent[i - startWord] = '\0'; ac.Select(wordCurrent); } } void ScintillaBase::AutoCompleteCompleted() { int item = ac.lb.GetSelection(); char selected[200]; if (item != -1) { ac.lb.GetValue(item, selected, sizeof(selected)); } ac.Cancel(); if (currentPos != ac.posStart) { pdoc->DeleteChars(ac.posStart, currentPos - ac.posStart); } SetEmptySelection(ac.posStart); if (item != -1) { pdoc->InsertString(currentPos, selected + ac.startLen); SetEmptySelection(currentPos + strlen(selected + ac.startLen)); } } void ScintillaBase::ContextMenu(Point pt) { popup.CreatePopUp(); AddToPopUp("Undo", idcmdUndo, pdoc->CanUndo()); AddToPopUp("Redo", idcmdRedo, pdoc->CanRedo()); AddToPopUp(""); AddToPopUp("Cut", idcmdCut, currentPos != anchor); AddToPopUp("Copy", idcmdCopy, currentPos != anchor); AddToPopUp("Paste", idcmdPaste, WndProc(EM_CANPASTE, 0, 0)); AddToPopUp("Delete", idcmdDelete, currentPos != anchor); AddToPopUp(""); AddToPopUp("Select All", idcmdSelectAll); popup.Show(pt, wMain); } void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) { AutoCompleteCancel(); ct.CallTipCancel(); Editor::ButtonDown(pt, curTime, shift, ctrl, alt); } #ifdef SCI_LEXER void ScintillaBase::Colourise(int start, int end) { int lengthDoc = Platform::SendScintilla(wMain.GetID(), SCI_GETLENGTH, 0, 0); if (end == -1) end = lengthDoc; int len = end - start; StylingContext styler(wMain.GetID(), props); int styleStart = 0; if (start > 0) styleStart = styler.StyleAt(start - 1); styler.SetCodePage(pdoc->dbcsCodePage); LexerModule::Colourise(start, len, styleStart, lexLanguage, keyWordLists, styler); styler.Flush(); } #endif void ScintillaBase::NotifyStyleNeeded(int endStyleNeeded) { #ifdef SCI_LEXER if (lexLanguage != SCLEX_CONTAINER) { int endStyled = Platform::SendScintilla(wMain.GetID(), SCI_GETENDSTYLED, 0, 0); int lineEndStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEFROMCHAR, endStyled, 0); endStyled = Platform::SendScintilla(wMain.GetID(), EM_LINEINDEX, lineEndStyled, 0); Colourise(endStyled, endStyleNeeded); return; } #endif Editor::NotifyStyleNeeded(endStyleNeeded); } LRESULT ScintillaBase::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case SCI_AUTOCSHOW: AutoCompleteStart(wParam, reinterpret_cast(lParam)); break; case SCI_AUTOCCANCEL: AutoCompleteCancel(); break; case SCI_AUTOCACTIVE: return ac.Active(); case SCI_AUTOCPOSSTART: return ac.posStart; case SCI_AUTOCCOMPLETE: AutoCompleteCompleted(); break; case SCI_AUTOCSTOPS: ac.SetStopChars(reinterpret_cast(lParam)); break; case SCI_CALLTIPSHOW: { AutoCompleteCancel(); if (!ct.wCallTip.Created()) { PRectangle rc = ct.CallTipStart(currentPos, LocationFromPosition(wParam), reinterpret_cast(lParam), vs.styles[0].fontName, vs.styles[0].size); // If the call-tip window would be out of the client // space, adjust so it displays above the text. PRectangle rcClient = GetClientRectangle(); if (rc.bottom > rcClient.bottom) { int offset = vs.lineHeight + rc.Height(); rc.top -= offset; rc.bottom -= offset; } // Now display the window. CreateCallTipWindow(rc); ct.wCallTip.SetPositionRelative(rc, wDraw); ct.wCallTip.Show(); } } break; case SCI_CALLTIPCANCEL: ct.CallTipCancel(); break; case SCI_CALLTIPACTIVE: return ct.inCallTipMode; case SCI_CALLTIPPOSSTART: return ct.posStartCallTip; case SCI_CALLTIPSETHLT: ct.SetHighlight(wParam, lParam); break; case SCI_CALLTIPSETBACK: ct.colourBG = Colour(wParam); InvalidateStyleRedraw(); break; #ifdef SCI_LEXER case SCI_SETLEXER: lexLanguage = wParam; break; case SCI_GETLEXER: return lexLanguage; case SCI_COLOURISE: Colourise(wParam, lParam); break; case SCI_SETPROPERTY: props.Set(reinterpret_cast(wParam), reinterpret_cast(lParam)); break; case SCI_SETKEYWORDS: if ((wParam >= 0) && (wParam < numWordLists)) { keyWordLists[wParam]->Clear(); keyWordLists[wParam]->Set(reinterpret_cast(lParam)); } break; #endif default: return Editor::WndProc(iMessage, wParam, lParam); } return 0l; }