diff options
Diffstat (limited to 'src/ScintillaBase.cxx')
| -rw-r--r-- | src/ScintillaBase.cxx | 397 | 
1 files changed, 397 insertions, 0 deletions
| diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx new file mode 100644 index 000000000..0ca299bd2 --- /dev/null +++ b/src/ScintillaBase.cxx @@ -0,0 +1,397 @@ +// Scintilla source code edit control +// ScintillaBase.cxx - an enhanced subclass of Editor with calltips, autocomplete and context menu +// Copyright 1998-2000 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" +#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<numWordLists;wl++) +		keyWordLists[wl] = new WordList; +#endif +} + +ScintillaBase::~ScintillaBase() {} + +void ScintillaBase::Finalise() { +	popup.Destroy(); +} + +void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) { +	Editor::RefreshColourPalette(pal, want); +	ct.RefreshColourPalette(pal, want); +} + +void ScintillaBase::AddChar(char ch) { +	bool acActiveBeforeCharAdded = ac.Active(); +	Editor::AddChar(ch); +	if (acActiveBeforeCharAdded) +		AutoCompleteChanged(ch); +} + +void ScintillaBase::Command(int cmdId) { + +	switch (cmdId) { + +	case idAutoComplete: 	// Nothing to do +		break; + +	case idCallTip: 	// Nothing to do +		break; + +	case idcmdUndo: +		WndProc(WM_UNDO, 0, 0); +		break; + +	case idcmdRedo: +		WndProc(SCI_REDO, 0, 0); +		break; + +	case idcmdCut: +		WndProc(WM_CUT, 0, 0); +		break; + +	case idcmdCopy: +		WndProc(WM_COPY, 0, 0); +		break; + +	case idcmdPaste: +		WndProc(WM_PASTE, 0, 0); +		break; + +	case idcmdDelete: +		WndProc(WM_CLEAR, 0, 0); +		break; + +	case idcmdSelectAll: +		WndProc(SCI_SELECTALL, 0, 0); +		break; +	} +} + +int ScintillaBase::KeyCommand(UINT 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(); +			AutoCompleteChanged(); +			EnsureCaretVisible(); +			return 0; +		case SCI_TAB: +			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) +		) { +			ct.CallTipCancel(); +		} +		if (iMessage == SCI_DELETEBACK) { +			if (currentPos <= ct.posStartCallTip) { +				ct.CallTipCancel(); +			} +		} +	} +	return Editor::KeyCommand(iMessage); +} + +void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { +	//Platform::DebugPrintf("AutoCOmplete %s\n", list); +	ct.CallTipCancel(); + +	ac.Start(wDraw, idAutoComplete, currentPos, lenEntered); + +	PRectangle rcClient = GetClientRectangle(); +	Point pt = LocationFromPosition(currentPos-lenEntered); + +	//Platform::DebugPrintf("Auto complete %x\n", lbAutoComplete); +	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 - 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); + +	ColouriseDoc(pdoc->dbcsCodePage, 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<const char *>(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<char *>(lParam)); +		break; + +	case SCI_CALLTIPSHOW: { +			AutoCompleteCancel(); +			if (!ct.wCallTip.Created()) { +				PRectangle rc = ct.CallTipStart(currentPos, LocationFromPosition(wParam), +				                                reinterpret_cast<char *>(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<const char *>(wParam),  +			reinterpret_cast<const char *>(lParam)); +		break; +		 +	case SCI_SETKEYWORDS: +		if ((wParam >= 0) && (wParam < numWordLists)) { +			keyWordLists[wParam]->Clear(); +			keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam)); +		} +		break; +#endif + +	default: +		return Editor::WndProc(iMessage, wParam, lParam); +	} +	return 0l; +} | 
