⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scintillawin.cxx

📁 最强源代码编辑控件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) {
#ifdef TOTAL_CONTROL
	HMENU hmenuPopup = reinterpret_cast<HMENU>(popup.GetID());
	if (!label[0])
		::AppendMenu(hmenuPopup, MF_SEPARATOR, 0, "");
	else if (enabled)
		::AppendMenu(hmenuPopup, MF_STRING, cmd, label);
	else
		::AppendMenu(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
#endif
}

void ScintillaWin::ClaimSelection() {
	// Windows does not have a primary selection
}

#ifdef SCI_LEXER

/*

  Initial Windows-Only implementation of the external lexer
  system in ScintillaWin class. Intention is to create a LexerModule
  subclass (?) to have lex and fold methods which will call out to their
  relevant DLLs...

*/

void ScintillaWin::SetLexer(uptr_t wParam) {
	lexLanguage = wParam;
	lexCurrent = LexerModule::Find(lexLanguage);
	if (!lexCurrent)
		lexCurrent = LexerModule::Find(SCLEX_NULL);
}

void ScintillaWin::SetLexerLanguage(const char *languageName) {
	lexLanguage = SCLEX_CONTAINER;
	lexCurrent = LexerModule::Find(languageName);
	if (!lexCurrent)
		lexCurrent = LexerModule::Find(SCLEX_NULL);
	if (lexCurrent)
		lexLanguage = lexCurrent->GetLanguage();
}

#endif

/// Implement IUnknown

STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("EFE QI");
	*ppv = NULL;
	if (riid == IID_IUnknown)
		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
	if (riid == IID_IEnumFORMATETC)
		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
	if (!*ppv)
		return E_NOINTERFACE;
	FormatEnumerator_AddRef(fe);
	return S_OK;
}
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
	return ++fe->ref;
}
STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
	fe->ref--;
	if (fe->ref > 0)
		return fe->ref;
	delete fe;
	return 0;
}
/// Implement IEnumFORMATETC
STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
	//Platform::DebugPrintf("EFE Next %d %d", fe->pos, celt);
	if (rgelt == NULL) return E_POINTER;
	// We only support one format, so this is simple.
	unsigned int putPos = 0;
	while ((fe->pos < fe->formatsLen) && (putPos < celt)) {
		rgelt->cfFormat = fe->formats[fe->pos];
		rgelt->ptd = 0;
		rgelt->dwAspect = DVASPECT_CONTENT;
		rgelt->lindex = -1;
		rgelt->tymed = TYMED_HGLOBAL;
		fe->pos++;
		putPos++;
	}
	if (pceltFetched)
		*pceltFetched = putPos;
	return putPos ? S_OK : S_FALSE;
}
STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
	fe->pos += celt;
	return S_OK;
}
STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
	fe->pos = 0;
	return S_OK;
}
STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
	FormatEnumerator *pfe = new FormatEnumerator(fe->pos, fe->formats, fe->formatsLen);
	return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
	                                       reinterpret_cast<void **>(ppenum));
}

static void *vtFormatEnumerator[] = {
	(void *)(FormatEnumerator_QueryInterface),
	(void *)(FormatEnumerator_AddRef),
	(void *)(FormatEnumerator_Release),
	(void *)(FormatEnumerator_Next),
	(void *)(FormatEnumerator_Skip),
	(void *)(FormatEnumerator_Reset),
	(void *)(FormatEnumerator_Clone)
};

FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_) {
	vtbl = vtFormatEnumerator;
	ref = 0;   // First QI adds first reference...
	pos = pos_;
	formatsLen = formatsLen_;
	for (int i=0;i<formatsLen;i++)
		formats[i] = formats_[i];
}

/// Implement IUnknown
STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
	return ds->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
	return ds->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
	return ds->sci->Release();
}

/// Implement IDropSource
STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
	if (fEsc)
		return DRAGDROP_S_CANCEL;
	if (!(grfKeyState & MK_LBUTTON))
		return DRAGDROP_S_DROP;
	return S_OK;
}

STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
	return DRAGDROP_S_USEDEFAULTCURSORS;
}

static void *vtDropSource[] = {
	(void *)(DropSource_QueryInterface),
	(void *)(DropSource_AddRef),
	(void *)(DropSource_Release),
	(void *)(DropSource_QueryContinueDrag),
	(void *)(DropSource_GiveFeedback)
};

DropSource::DropSource() {
	vtbl = vtDropSource;
	sci = 0;
}

/// Implement IUnkown
STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("DO QI %x\n", pd);
	return pd->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
	return pd->sci->AddRef();
}
STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
	return pd->sci->Release();
}
/// Implement IDataObject
STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
	return pd->sci->GetData(pFEIn, pSTM);
}

STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
	//Platform::DebugPrintf("DOB GetDataHere\n");
	return E_NOTIMPL;
}

STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
	if (pd->sci->DragIsRectangularOK(pFE->cfFormat) &&
	    pFE->ptd == 0 &&
	    (pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
	    pFE->lindex == -1 &&
	    (pFE->tymed & TYMED_HGLOBAL) != 0
	) {
		return S_OK;
	}

	bool formatOK = (pFE->cfFormat == CF_TEXT) ||
		((pFE->cfFormat == CF_UNICODETEXT) && pd->sci->IsUnicodeMode());
	if (!formatOK ||
	    pFE->ptd != 0 ||
	    (pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
	    pFE->lindex != -1 ||
	    (pFE->tymed & TYMED_HGLOBAL) == 0
	) {
		//Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
		//return DATA_E_FORMATETC;
		return S_FALSE;
	}
	//Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
	return S_OK;
}

STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *pd, FORMATETC *, FORMATETC *pFEOut) {
	//Platform::DebugPrintf("DOB GetCanon\n");
	if (pd->sci->IsUnicodeMode())
		pFEOut->cfFormat = CF_UNICODETEXT;
	else
		pFEOut->cfFormat = CF_TEXT;
	pFEOut->ptd = 0;
	pFEOut->dwAspect = DVASPECT_CONTENT;
	pFEOut->lindex = -1;
	pFEOut->tymed = TYMED_HGLOBAL;
	return S_OK;
}

STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
	//Platform::DebugPrintf("DOB SetData\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
	//Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
	if (dwDirection != DATADIR_GET) {
		*ppEnum = 0;
		return E_FAIL;
	}
	FormatEnumerator *pfe;
	if (pd->sci->IsUnicodeMode()) {
		CLIPFORMAT formats[] = {CF_UNICODETEXT, CF_TEXT};
		pfe = new FormatEnumerator(0, formats, 2);
	} else {
		CLIPFORMAT formats[] = {CF_TEXT};
		pfe = new FormatEnumerator(0, formats, 1);
	}
	return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
	                                       reinterpret_cast<void **>(ppEnum));
}

STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
	//Platform::DebugPrintf("DOB DAdvise\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
	//Platform::DebugPrintf("DOB DUnadvise\n");
	return E_FAIL;
}

STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
	//Platform::DebugPrintf("DOB EnumDAdvise\n");
	return E_FAIL;
}

static void *vtDataObject[] = {
	(void *)(DataObject_QueryInterface),
	(void *)(DataObject_AddRef),
	(void *)(DataObject_Release),
	(void *)(DataObject_GetData),
	(void *)(DataObject_GetDataHere),
	(void *)(DataObject_QueryGetData),
	(void *)(DataObject_GetCanonicalFormatEtc),
	(void *)(DataObject_SetData),
	(void *)(DataObject_EnumFormatEtc),
	(void *)(DataObject_DAdvise),
	(void *)(DataObject_DUnadvise),
	(void *)(DataObject_EnumDAdvise)
};

DataObject::DataObject() {
	vtbl = vtDataObject;
	sci = 0;
}

/// Implement IUnknown
STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
	//Platform::DebugPrintf("DT QI %x\n", dt);
	return dt->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
	return dt->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
	return dt->sci->Release();
}

/// Implement IDropTarget by forwarding to Scintilla
STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                                  POINTL pt, PDWORD pdwEffect) {
	return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
}
STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
	return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
}
STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
	return dt->sci->DragLeave();
}
STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
                             POINTL pt, PDWORD pdwEffect) {
	return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
}

static void *vtDropTarget[] = {
	(void *)(DropTarget_QueryInterface),
	(void *)(DropTarget_AddRef),
	(void *)(DropTarget_Release),
	(void *)(DropTarget_DragEnter),
	(void *)(DropTarget_DragOver),
	(void *)(DropTarget_DragLeave),
	(void *)(DropTarget_Drop)
};

DropTarget::DropTarget() {
	vtbl = vtDropTarget;
	sci = 0;
}

/**
 * DBCS: support Input Method Editor (IME).
 * Called when IME Window opened.
 */
void ScintillaWin::ImeStartComposition() {
#ifndef __DMC__
	// Digital Mars compiler does not include Imm library
	if (caret.active) {
		// Move IME Window to current caret position
		HIMC hIMC = ::ImmGetContext(MainHWND());
		Point pos = LocationFromPosition(currentPos);
		COMPOSITIONFORM CompForm;
		CompForm.dwStyle = CFS_POINT;
		CompForm.ptCurrentPos.x = pos.x;
		CompForm.ptCurrentPos.y = pos.y;

		::ImmSetCompositionWindow(hIMC, &CompForm);

		// Set font of IME window to same as surrounded text.
		if (stylesValid) {
			// Since the style creation code has been made platform independent,
			// The logfont for the IME is recreated here.
			int styleHere = (pdoc->StyleAt(currentPos)) & 31;
			LOGFONT lf = {0,0,0,0,0,0,0,0,0,0,0,0,0,TEXT("")};
			int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;
			if (sizeZoomed <= 2)	// Hangs if sizeZoomed <= 1
				sizeZoomed = 2;
			AutoSurface surface(this);
			int deviceHeight = sizeZoomed;
			if (surface) {
				deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72;
			}
			// The negative is to allow for leading
			lf.lfHeight = -(abs(deviceHeight));
			lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL;
			lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
			lf.lfCharSet = DEFAULT_CHARSET;
			lf.lfFaceName[0] = '\0';
			if (vs.styles[styleHere].fontName)
				strcpy(lf.lfFaceName, vs.styles[styleHere].fontName);

			::ImmSetCompositionFont(hIMC, &lf);
		}
		::ImmReleaseContext(MainHWND(), hIMC);
		// Caret is displayed in IME window. So, caret in Scintilla is useless.
		DropCaret();
	}
#endif
}

/** Called when IME Window closed. */
void ScintillaWin::ImeEndComposition() {
	ShowCaretAtCurrentPosition();
}

void ScintillaWin::AddCharBytes(char b0, char b1) {

	int inputCodePage = InputCodePage();
	if (inputCodePage && IsUnicodeMode()) {
		char utfval[4]="\0\0\0";
		char ansiChars[3];
		wchar_t wcs[2];
		if (b0) {	// Two bytes from IME
			ansiChars[0] = b0;
			ansiChars[1] = b1;
			ansiChars[2] = '\0';
			::MultiByteToWideChar(inputCodePage, 0, ansiChars, 2, wcs, 1);
		} else {
			ansiChars[0] = b1;
			ansiChars[1] = '\0';
			::MultiByteToWideChar(inputCodePage, 0, ansiChars, 1, wcs, 1);
		}
		unsigned int len = UTF8Length(wcs, 1);
		UTF8FromUCS2(wcs, 1, utfval, len);
		utfval[len] = '\0';
		AddCharUTF(utfval, len ? len : 1);
	} else if (b0) {
		char dbcsChars[3];
		dbcsChars[0] = b0;
		dbcsChars[1] = b1;
		dbcsChars[2] = '\0';
		AddCharUTF(dbcsChars, 2, true);
	} else {
		AddChar(b1);
	}
}

void ScintillaWin::GetIntelliMouseParameters() {
	// This retrieves the number of lines per scroll as configured inthe Mouse Properties sheet in Control Panel
	::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
}

void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
	if (!::OpenClipboard(MainHWND()))
		return ;
	::EmptyClipboard();

	GlobalMemory uniText;

	// Default Scintilla behaviour in Unicode mode
	if (IsUnicodeMode()) {
		int uchars = UCS2Length(selectedText.s, selectedText.len);
		uniText.Allocate(2 * uchars);
		if (uniText) {
			UCS2FromUTF8(selectedText.s, selectedText.len, static_cast<wchar_t *>(uniText.ptr), uchars);
		}
	} else {
		// Not Unicode mode
		// Convert to Unicode using the current Scintilla code page
		UINT cpSrc = CodePageFromCharSet(
					selectedText.characterSet, selectedText.codePage);
		uniText.Allocate(2 * selectedText.len);
		if (uniText) {
			::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len,
				static_cast<wchar_t *>(uniText.ptr), selectedText.len);
		}
	}

	if (uniText) {
		if (!IsNT()) {
			// Copy ANSI text to clipboard on Windows 9x
			// Convert from Unicode text, so other ANSI programs can
			// paste the text
			// Windows NT, 2k, XP automatically generates CF_TEXT
			GlobalMemory ansiText;
			ansiText.Allocate(selectedText.len);
			if (ansiText) {
				::WideCharToMultiByte(CP_ACP, 0, static_cast<wchar_t *>(uniText.ptr), -1,
					static_cast<char *>(ansiText.ptr), selectedText.len, NULL, NULL);
				ansiText.SetClip(CF_TEXT);
			}
		}
		uniText.SetClip(CF_UNICODETEXT);
	} else {
		// There was a failure - try to copy at least ANSI text
		GlobalMemory ansiText;
		ansiText.Allocate(selectedText.len);
		if (ansiText) {
			memcpy(static_cast<char *>(ansiText.ptr), selectedText.s, selectedText.len);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -