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

📄 scintillawin.cxx

📁 最强源代码编辑控件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
// Scintilla source code edit control
/** @file ScintillaWin.cxx
 ** Windows specific subclass of ScintillaBase.
 **/
// 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 <assert.h>
#include <limits.h>

#define _WIN32_WINNT  0x0500
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <windowsx.h>

#include "Platform.h"

#include "Scintilla.h"
#include "SString.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#endif
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Document.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"

#ifdef SCI_LEXER
#include "ExternalLexer.h"
#endif

#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES   104
#endif

#ifndef WM_UNICHAR
#define WM_UNICHAR                      0x0109
#endif

#ifndef UNICODE_NOCHAR
#define UNICODE_NOCHAR                  0xFFFF
#endif

#ifndef WM_IME_STARTCOMPOSITION
#include <imm.h>
#endif

#include <commctrl.h>
#ifndef __BORLANDC__
#ifndef __DMC__
#include <zmouse.h>
#endif
#endif
#include <ole2.h>

#ifndef MK_ALT
#define MK_ALT 32
#endif

#define SC_WIN_IDLE 5001

// Functions imported from PlatWin
extern bool IsNT();
extern void Platform_Initialise(void *hInstance);
extern void Platform_Finalise();

/** TOTAL_CONTROL ifdef surrounds code that will only work when ScintillaWin
 * is derived from ScintillaBase (all features) rather than directly from Editor
 * (lightweight editor).
 */
#define TOTAL_CONTROL

// GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.

const TCHAR scintillaClassName[] = TEXT("Scintilla");
const TCHAR callClassName[] = TEXT("CallTip");

class ScintillaWin; 	// Forward declaration for COM interface subobjects

/**
 */
class FormatEnumerator {
public:
	void **vtbl;
	int ref;
	int pos;
	CLIPFORMAT formats[2];
	int formatsLen;
	FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_);
};

/**
 */
class DropSource {
public:
	void **vtbl;
	ScintillaWin *sci;
	DropSource();
};

/**
 */
class DataObject {
public:
	void **vtbl;
	ScintillaWin *sci;
	DataObject();
};

/**
 */
class DropTarget {
public:
	void **vtbl;
	ScintillaWin *sci;
	DropTarget();
};

/**
 */
class ScintillaWin :
	public ScintillaBase {

	bool lastKeyDownConsumed;

	bool capturedMouse;

	unsigned int linesPerScroll;	///< Intellimouse support
	int wheelDelta; ///< Wheel delta from roll

	HRGN hRgnUpdate;

	bool hasOKText;

	CLIPFORMAT cfColumnSelect;

	DropSource ds;
	DataObject dob;
	DropTarget dt;

	static HINSTANCE hInstance;

	ScintillaWin(HWND hwnd);
	ScintillaWin(const ScintillaWin &) : ScintillaBase() {}
	virtual ~ScintillaWin();
	ScintillaWin &operator=(const ScintillaWin &) { return *this; }

	virtual void Initialise();
	virtual void Finalise();
	HWND MainHWND();

	static sptr_t DirectFunction(
		    ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam);
	static sptr_t PASCAL SWndProc(
		    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);
	static sptr_t PASCAL CTWndProc(
		    HWND hWnd, UINT iMessage, WPARAM wParam, sptr_t lParam);

	enum { invalidTimerID, standardTimerID, idleTimerID };

	virtual void StartDrag();
	sptr_t WndPaint(uptr_t wParam);
	sptr_t HandleComposition(uptr_t wParam, sptr_t lParam);
	virtual bool ValidCodePage(int codePage) const;
	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
	virtual bool SetIdle(bool on);
	virtual void SetTicking(bool on);
	virtual void SetMouseCapture(bool on);
	virtual bool HaveMouseCapture();
	virtual bool PaintContains(PRectangle rc);
	virtual void ScrollText(int linesToMove);
	virtual void UpdateSystemCaret();
	virtual void SetVerticalScrollPos();
	virtual void SetHorizontalScrollPos();
	virtual bool ModifyScrollBars(int nMax, int nPage);
	virtual void NotifyChange();
	virtual void NotifyFocus(bool focus);
	virtual int GetCtrlID();
	virtual void NotifyParent(SCNotification scn);
	virtual void NotifyDoubleClick(Point pt, bool shift);
	virtual void Copy();
	virtual bool CanPaste();
	virtual void Paste();
	virtual void CreateCallTipWindow(PRectangle rc);
	virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
	virtual void ClaimSelection();

	// DBCS
	void ImeStartComposition();
	void ImeEndComposition();

	void AddCharBytes(char b0, char b1);

	void GetIntelliMouseParameters();
	virtual void CopyToClipboard(const SelectionText &selectedText);
	void ScrollMessage(WPARAM wParam);
	void HorizontalScrollMessage(WPARAM wParam);
	void RealizeWindowPalette(bool inBackGround);
	void FullPaint();
	void FullPaintDC(HDC dc);
	bool IsCompatibleDC(HDC dc);

	virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw);
	virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi);
	void ChangeScrollPos(int barType, int pos);

	void InsertPasteText(const char *text, int len, int selStart, bool isRectangular);

public:
	// Public for benefit of Scintilla_DirectFunction
	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);

	/// Implement IUnknown
	STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
	STDMETHODIMP_(ULONG)AddRef();
	STDMETHODIMP_(ULONG)Release();

	/// Implement IDropTarget
	STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
	                       POINTL pt, PDWORD pdwEffect);
	STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect);
	STDMETHODIMP DragLeave();
	STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
	                  POINTL pt, PDWORD pdwEffect);

	/// Implement important part of IDataObject
	STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);

	// External Lexers
#ifdef SCI_LEXER
	void SetLexerLanguage(const char *languageName);
	void SetLexer(uptr_t wParam);
#endif

	static bool Register(HINSTANCE hInstance_);
	static bool Unregister();

	friend class DropSource;
	friend class DataObject;
	friend class DropTarget;
	bool DragIsRectangularOK(CLIPFORMAT fmt) {
		return drag.rectangular && (fmt == cfColumnSelect);
	}

private:
	// For use in creating a system caret
	bool HasCaretSizeChanged();
	BOOL CreateSystemCaret();
	BOOL DestroySystemCaret();
	HBITMAP sysCaretBitmap;
	int sysCaretWidth;
	int sysCaretHeight;
};

HINSTANCE ScintillaWin::hInstance = 0;

ScintillaWin::ScintillaWin(HWND hwnd) {

	lastKeyDownConsumed = false;

	capturedMouse = false;
	linesPerScroll = 0;
	wheelDelta = 0;   // Wheel delta from roll

	hRgnUpdate = 0;

	hasOKText = false;

	// There does not seem to be a real standard for indicating that the clipboard
	// contains a rectangular selection, so copy Developer Studio.
	cfColumnSelect = static_cast<CLIPFORMAT>(
		::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));

	wMain = hwnd;

	dob.sci = this;
	ds.sci = this;
	dt.sci = this;

	sysCaretBitmap = 0;
	sysCaretWidth = 0;
	sysCaretHeight = 0;

	Initialise();
}

ScintillaWin::~ScintillaWin() {}

void ScintillaWin::Initialise() {
	// Initialize COM.  If the app has already done this it will have
	// no effect.  If the app hasnt, we really shouldnt ask them to call
	// it just so this internal feature works.
	::OleInitialize(NULL);
}

void ScintillaWin::Finalise() {
	ScintillaBase::Finalise();
	SetTicking(false);
	SetIdle(false);
	DestroySystemCaret();
	::RevokeDragDrop(MainHWND());
	::OleUninitialize();
}

HWND ScintillaWin::MainHWND() {
	return reinterpret_cast<HWND>(wMain.GetID());
}

void ScintillaWin::StartDrag() {
	DWORD dwEffect = 0;
	dropWentOutside = true;
	IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob);
	IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds);
	//Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
	HRESULT hr = ::DoDragDrop(
	                 pDataObject,
	                 pDropSource,
	                 DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
	//Platform::DebugPrintf("DoDragDrop = %x\n", hr);
	if (SUCCEEDED(hr)) {
		if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) {
			// Remove dragged out text
			ClearSelection();
		}
	}
	inDragDrop = false;
	SetDragPosition(invalidPosition);
}

// Avoid warnings everywhere for old style casts by concentrating them here
static WORD LoWord(DWORD l) {
	return LOWORD(l);
}

static WORD HiWord(DWORD l) {
	return HIWORD(l);
}

static int InputCodePage() {
	HKL inputLocale = ::GetKeyboardLayout(0);
	LANGID inputLang = LOWORD(inputLocale);
	char sCodePage[10];
	int res = ::GetLocaleInfo(MAKELCID(inputLang, SORT_DEFAULT),
	  LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage));
	if (!res)
		return 0;
	return atoi(sCodePage);
}

#ifndef VK_OEM_2
static const int VK_OEM_2=0xbf;
static const int VK_OEM_3=0xc0;
static const int VK_OEM_4=0xdb;
static const int VK_OEM_5=0xdc;
static const int VK_OEM_6=0xdd;
#endif

/** Map the key codes to their equivalent SCK_ form. */
static int KeyTranslate(int keyIn) {
//PLATFORM_ASSERT(!keyIn);
	switch (keyIn) {
		case VK_DOWN:		return SCK_DOWN;
		case VK_UP:		return SCK_UP;
		case VK_LEFT:		return SCK_LEFT;
		case VK_RIGHT:		return SCK_RIGHT;
		case VK_HOME:		return SCK_HOME;
		case VK_END:		return SCK_END;
		case VK_PRIOR:		return SCK_PRIOR;
		case VK_NEXT:		return SCK_NEXT;
		case VK_DELETE:	return SCK_DELETE;
		case VK_INSERT:		return SCK_INSERT;
		case VK_ESCAPE:	return SCK_ESCAPE;
		case VK_BACK:		return SCK_BACK;
		case VK_TAB:		return SCK_TAB;
		case VK_RETURN:	return SCK_RETURN;
		case VK_ADD:		return SCK_ADD;
		case VK_SUBTRACT:	return SCK_SUBTRACT;
		case VK_DIVIDE:		return SCK_DIVIDE;
		case VK_LWIN:		return SCK_WIN;
		case VK_RWIN:		return SCK_RWIN;
		case VK_APPS:		return SCK_MENU;
		case VK_OEM_2:		return '/';
		case VK_OEM_3:		return '`';
		case VK_OEM_4:		return '[';
		case VK_OEM_5:		return '\\';
		case VK_OEM_6:		return ']';
		default:			return keyIn;
	}
}

LRESULT ScintillaWin::WndPaint(uptr_t wParam) {
	//ElapsedTime et;

	// Redirect assertions to debug output and save current state
	bool assertsPopup = Platform::ShowAssertionPopUps(false);
	paintState = painting;
	PAINTSTRUCT ps;
	PAINTSTRUCT *pps;

	bool IsOcxCtrl = (wParam != 0); // if wParam != 0, it contains
								   // a PAINSTRUCT* from the OCX
	// Removed since this interferes with reporting other assertions as it occurs repeatedly
	//PLATFORM_ASSERT(hRgnUpdate == NULL);
	hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0);
	if (IsOcxCtrl) {
		pps = reinterpret_cast<PAINTSTRUCT*>(wParam);
	} else {
		::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE);
		pps = &ps;
		::BeginPaint(MainHWND(), pps);
	}
	AutoSurface surfaceWindow(pps->hdc, this);
	if (surfaceWindow) {
		rcPaint = PRectangle(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom);
		PRectangle rcClient = GetClientRectangle();
		paintingAllText = rcPaint.Contains(rcClient);
		if (paintingAllText) {
			//Platform::DebugPrintf("Performing full text paint\n");
		} else {
			//Platform::DebugPrintf("Performing partial paint %d .. %d\n", rcPaint.top, rcPaint.bottom);
		}
		Paint(surfaceWindow, rcPaint);
		surfaceWindow->Release();
	}
	if (hRgnUpdate) {
		::DeleteRgn(hRgnUpdate);
		hRgnUpdate = 0;
	}

	if(!IsOcxCtrl)
		::EndPaint(MainHWND(), pps);
	if (paintState == paintAbandoned) {
		// Painting area was insufficient to cover new styling or brace highlight positions
		FullPaint();
	}
	paintState = notPainting;

⌨️ 快捷键说明

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