xref: /MusicPlayer2/scintilla/win32/ScintillaWin.cxx (revision f9763b28e6d019e8b836e436b68c871dc5256bb4)
18af74909SZhong Yang // Scintilla source code edit control
28af74909SZhong Yang /** @file ScintillaWin.cxx
38af74909SZhong Yang  ** Windows specific subclass of ScintillaBase.
48af74909SZhong Yang  **/
58af74909SZhong Yang // Copyright 1998-2003 by Neil Hodgson <[email protected]>
68af74909SZhong Yang // The License.txt file describes the conditions under which this software may be distributed.
78af74909SZhong Yang 
88af74909SZhong Yang #include <cstddef>
98af74909SZhong Yang #include <cstdlib>
108af74909SZhong Yang #include <cassert>
118af74909SZhong Yang #include <cstring>
128af74909SZhong Yang #include <cstdio>
138af74909SZhong Yang #include <cmath>
148af74909SZhong Yang #include <climits>
158af74909SZhong Yang 
168af74909SZhong Yang #include <stdexcept>
178af74909SZhong Yang #include <new>
188af74909SZhong Yang #include <string>
198af74909SZhong Yang #include <string_view>
208af74909SZhong Yang #include <vector>
218af74909SZhong Yang #include <map>
228af74909SZhong Yang #include <algorithm>
238af74909SZhong Yang #include <memory>
248af74909SZhong Yang #include <chrono>
258af74909SZhong Yang #include <mutex>
268af74909SZhong Yang 
278af74909SZhong Yang // Want to use std::min and std::max so don't want Windows.h version of min and max
288af74909SZhong Yang #if !defined(NOMINMAX)
298af74909SZhong Yang #define NOMINMAX
308af74909SZhong Yang #endif
318af74909SZhong Yang #undef _WIN32_WINNT
328af74909SZhong Yang #define _WIN32_WINNT 0x0500
338af74909SZhong Yang #undef WINVER
348af74909SZhong Yang #define WINVER 0x0500
358af74909SZhong Yang #include <windows.h>
368af74909SZhong Yang #include <commctrl.h>
378af74909SZhong Yang #include <richedit.h>
388af74909SZhong Yang #include <windowsx.h>
398af74909SZhong Yang #include <zmouse.h>
408af74909SZhong Yang #include <ole2.h>
418af74909SZhong Yang 
428af74909SZhong Yang #if !defined(DISABLE_D2D)
438af74909SZhong Yang #define USE_D2D 1
448af74909SZhong Yang #endif
458af74909SZhong Yang 
468af74909SZhong Yang #if defined(USE_D2D)
478af74909SZhong Yang #include <d2d1.h>
488af74909SZhong Yang #include <dwrite.h>
498af74909SZhong Yang #endif
508af74909SZhong Yang 
518af74909SZhong Yang #include "Platform.h"
528af74909SZhong Yang 
538af74909SZhong Yang #include "ILoader.h"
548af74909SZhong Yang #include "ILexer.h"
558af74909SZhong Yang #include "Scintilla.h"
568af74909SZhong Yang 
578af74909SZhong Yang #include "CharacterCategory.h"
588af74909SZhong Yang #include "Position.h"
598af74909SZhong Yang #include "UniqueString.h"
608af74909SZhong Yang #include "SplitVector.h"
618af74909SZhong Yang #include "Partitioning.h"
628af74909SZhong Yang #include "RunStyles.h"
638af74909SZhong Yang #include "ContractionState.h"
648af74909SZhong Yang #include "CellBuffer.h"
658af74909SZhong Yang #include "CallTip.h"
668af74909SZhong Yang #include "KeyMap.h"
678af74909SZhong Yang #include "Indicator.h"
688af74909SZhong Yang #include "LineMarker.h"
698af74909SZhong Yang #include "Style.h"
708af74909SZhong Yang #include "ViewStyle.h"
718af74909SZhong Yang #include "CharClassify.h"
728af74909SZhong Yang #include "Decoration.h"
738af74909SZhong Yang #include "CaseFolder.h"
748af74909SZhong Yang #include "Document.h"
758af74909SZhong Yang #include "CaseConvert.h"
768af74909SZhong Yang #include "UniConversion.h"
778af74909SZhong Yang #include "Selection.h"
788af74909SZhong Yang #include "PositionCache.h"
798af74909SZhong Yang #include "EditModel.h"
808af74909SZhong Yang #include "MarginView.h"
818af74909SZhong Yang #include "EditView.h"
828af74909SZhong Yang #include "Editor.h"
838af74909SZhong Yang #include "ElapsedPeriod.h"
848af74909SZhong Yang 
858af74909SZhong Yang #include "AutoComplete.h"
868af74909SZhong Yang #include "ScintillaBase.h"
878af74909SZhong Yang 
888af74909SZhong Yang #include "PlatWin.h"
898af74909SZhong Yang #include "HanjaDic.h"
908af74909SZhong Yang #include "ScintillaWin.h"
918af74909SZhong Yang 
928af74909SZhong Yang #ifndef SPI_GETWHEELSCROLLLINES
938af74909SZhong Yang #define SPI_GETWHEELSCROLLLINES   104
948af74909SZhong Yang #endif
958af74909SZhong Yang 
968af74909SZhong Yang #ifndef WM_UNICHAR
978af74909SZhong Yang #define WM_UNICHAR                      0x0109
988af74909SZhong Yang #endif
998af74909SZhong Yang 
1008af74909SZhong Yang #ifndef WM_DPICHANGED
1018af74909SZhong Yang #define WM_DPICHANGED 0x02E0
1028af74909SZhong Yang #endif
1038af74909SZhong Yang #ifndef WM_DPICHANGED_AFTERPARENT
1048af74909SZhong Yang #define WM_DPICHANGED_AFTERPARENT 0x02E3
1058af74909SZhong Yang #endif
1068af74909SZhong Yang 
1078af74909SZhong Yang #ifndef UNICODE_NOCHAR
1088af74909SZhong Yang #define UNICODE_NOCHAR                  0xFFFF
1098af74909SZhong Yang #endif
1108af74909SZhong Yang 
1118af74909SZhong Yang #ifndef IS_HIGH_SURROGATE
1128af74909SZhong Yang #define IS_HIGH_SURROGATE(x)            ((x) >= SURROGATE_LEAD_FIRST && (x) <= SURROGATE_LEAD_LAST)
1138af74909SZhong Yang #endif
1148af74909SZhong Yang 
1158af74909SZhong Yang #ifndef IS_LOW_SURROGATE
1168af74909SZhong Yang #define IS_LOW_SURROGATE(x)             ((x) >= SURROGATE_TRAIL_FIRST && (x) <= SURROGATE_TRAIL_LAST)
1178af74909SZhong Yang #endif
1188af74909SZhong Yang 
1198af74909SZhong Yang #ifndef MK_ALT
1208af74909SZhong Yang #define MK_ALT 32
1218af74909SZhong Yang #endif
1228af74909SZhong Yang 
1238af74909SZhong Yang // Two idle messages SC_WIN_IDLE and SC_WORK_IDLE.
1248af74909SZhong Yang 
1258af74909SZhong Yang // SC_WIN_IDLE is low priority so should occur after the next WM_PAINT
1268af74909SZhong Yang // It is for lengthy actions like wrapping and background styling
1278af74909SZhong Yang constexpr UINT SC_WIN_IDLE = 5001;
1288af74909SZhong Yang // SC_WORK_IDLE is high priority and should occur before the next WM_PAINT
1298af74909SZhong Yang // It is for shorter actions like restyling the text just inserted
1308af74909SZhong Yang // and delivering SCN_UPDATEUI
1318af74909SZhong Yang constexpr UINT SC_WORK_IDLE = 5002;
1328af74909SZhong Yang 
1338af74909SZhong Yang #define SC_INDICATOR_INPUT INDICATOR_IME
1348af74909SZhong Yang #define SC_INDICATOR_TARGET INDICATOR_IME+1
1358af74909SZhong Yang #define SC_INDICATOR_CONVERTED INDICATOR_IME+2
1368af74909SZhong Yang #define SC_INDICATOR_UNKNOWN INDICATOR_IME_MAX
1378af74909SZhong Yang 
1388af74909SZhong Yang #ifndef SCS_CAP_SETRECONVERTSTRING
1398af74909SZhong Yang #define SCS_CAP_SETRECONVERTSTRING 0x00000004
1408af74909SZhong Yang #define SCS_QUERYRECONVERTSTRING 0x00020000
1418af74909SZhong Yang #define SCS_SETRECONVERTSTRING 0x00010000
1428af74909SZhong Yang #endif
1438af74909SZhong Yang 
1448af74909SZhong Yang typedef UINT_PTR (WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent,
1458af74909SZhong Yang 	UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay);
1468af74909SZhong Yang 
1478af74909SZhong Yang // GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables.
1488af74909SZhong Yang 
1498af74909SZhong Yang using namespace Scintilla;
1508af74909SZhong Yang 
1518af74909SZhong Yang namespace {
1528af74909SZhong Yang 
1538af74909SZhong Yang const TCHAR callClassName[] = TEXT("CallTip");
1548af74909SZhong Yang 
SetWindowID(HWND hWnd,int identifier)1558af74909SZhong Yang void SetWindowID(HWND hWnd, int identifier) noexcept {
1568af74909SZhong Yang 	::SetWindowLongPtr(hWnd, GWLP_ID, identifier);
1578af74909SZhong Yang }
1588af74909SZhong Yang 
PointFromLParam(sptr_t lpoint)1598af74909SZhong Yang Point PointFromLParam(sptr_t lpoint) noexcept {
1608af74909SZhong Yang 	return Point::FromInts(GET_X_LPARAM(lpoint), GET_Y_LPARAM(lpoint));
1618af74909SZhong Yang }
1628af74909SZhong Yang 
KeyboardIsKeyDown(int key)1638af74909SZhong Yang bool KeyboardIsKeyDown(int key) noexcept {
1648af74909SZhong Yang 	return (::GetKeyState(key) & 0x80000000) != 0;
1658af74909SZhong Yang }
1668af74909SZhong Yang 
KeyboardIsNumericKeypadFunction(uptr_t wParam,sptr_t lParam)1678af74909SZhong Yang constexpr bool KeyboardIsNumericKeypadFunction(uptr_t wParam, sptr_t lParam) {
1688af74909SZhong Yang 	// Bit 24 is the extended keyboard flag and the numeric keypad is non-extended
1698af74909SZhong Yang 	if ((lParam & (1 << 24)) != 0) {
1708af74909SZhong Yang 		// Not from the numeric keypad
1718af74909SZhong Yang 		return false;
1728af74909SZhong Yang 	}
1738af74909SZhong Yang 
1748af74909SZhong Yang 	switch (wParam) {
1758af74909SZhong Yang 	case VK_INSERT:	// 0
1768af74909SZhong Yang 	case VK_END:	// 1
1778af74909SZhong Yang 	case VK_DOWN:	// 2
1788af74909SZhong Yang 	case VK_NEXT:	// 3
1798af74909SZhong Yang 	case VK_LEFT:	// 4
1808af74909SZhong Yang 	case VK_CLEAR:	// 5
1818af74909SZhong Yang 	case VK_RIGHT:	// 6
1828af74909SZhong Yang 	case VK_HOME:	// 7
1838af74909SZhong Yang 	case VK_UP:		// 8
1848af74909SZhong Yang 	case VK_PRIOR:	// 9
1858af74909SZhong Yang 		return true;
1868af74909SZhong Yang 	default:
1878af74909SZhong Yang 		return false;
1888af74909SZhong Yang 	}
1898af74909SZhong Yang }
1908af74909SZhong Yang 
1918af74909SZhong Yang }
1928af74909SZhong Yang 
1938af74909SZhong Yang class ScintillaWin; 	// Forward declaration for COM interface subobjects
1948af74909SZhong Yang 
1958af74909SZhong Yang typedef void VFunction(void);
1968af74909SZhong Yang 
1978af74909SZhong Yang 
1988af74909SZhong Yang /**
1998af74909SZhong Yang  */
2008af74909SZhong Yang class FormatEnumerator {
2018af74909SZhong Yang public:
2028af74909SZhong Yang 	VFunction **vtbl;
2038af74909SZhong Yang 	ULONG ref;
2048af74909SZhong Yang 	ULONG pos;
2058af74909SZhong Yang 	std::vector<CLIPFORMAT> formats;
2068af74909SZhong Yang 	FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_);
2078af74909SZhong Yang };
2088af74909SZhong Yang 
2098af74909SZhong Yang /**
2108af74909SZhong Yang  */
2118af74909SZhong Yang class DropSource {
2128af74909SZhong Yang public:
2138af74909SZhong Yang 	VFunction **vtbl;
2148af74909SZhong Yang 	ScintillaWin *sci;
2158af74909SZhong Yang 	DropSource() noexcept;
2168af74909SZhong Yang };
2178af74909SZhong Yang 
2188af74909SZhong Yang /**
2198af74909SZhong Yang  */
2208af74909SZhong Yang class DataObject {
2218af74909SZhong Yang public:
2228af74909SZhong Yang 	VFunction **vtbl;
2238af74909SZhong Yang 	ScintillaWin *sci;
2248af74909SZhong Yang 	DataObject() noexcept;
2258af74909SZhong Yang };
2268af74909SZhong Yang 
2278af74909SZhong Yang /**
2288af74909SZhong Yang  */
2298af74909SZhong Yang class DropTarget {
2308af74909SZhong Yang public:
2318af74909SZhong Yang 	VFunction **vtbl;
2328af74909SZhong Yang 	ScintillaWin *sci;
2338af74909SZhong Yang 	DropTarget() noexcept;
2348af74909SZhong Yang };
2358af74909SZhong Yang 
2368af74909SZhong Yang namespace {
2378af74909SZhong Yang 
2388af74909SZhong Yang class IMContext {
2398af74909SZhong Yang 	HWND hwnd;
2408af74909SZhong Yang public:
2418af74909SZhong Yang 	HIMC hIMC;
IMContext(HWND hwnd_)2428af74909SZhong Yang 	IMContext(HWND hwnd_) noexcept :
2438af74909SZhong Yang 		hwnd(hwnd_), hIMC(::ImmGetContext(hwnd_)) {
2448af74909SZhong Yang 	}
2458af74909SZhong Yang 	// Deleted so IMContext objects can not be copied.
2468af74909SZhong Yang 	IMContext(const IMContext &) = delete;
2478af74909SZhong Yang 	IMContext(IMContext &&) = delete;
2488af74909SZhong Yang 	IMContext &operator=(const IMContext &) = delete;
2498af74909SZhong Yang 	IMContext &operator=(IMContext &&) = delete;
~IMContext()2508af74909SZhong Yang 	~IMContext() {
2518af74909SZhong Yang 		if (hIMC)
2528af74909SZhong Yang 			::ImmReleaseContext(hwnd, hIMC);
2538af74909SZhong Yang 	}
2548af74909SZhong Yang 
GetImeCaretPos() const2558af74909SZhong Yang 	unsigned int GetImeCaretPos() const noexcept {
2568af74909SZhong Yang 		return ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, nullptr, 0);
2578af74909SZhong Yang 	}
2588af74909SZhong Yang 
GetImeAttributes()2598af74909SZhong Yang 	std::vector<BYTE> GetImeAttributes() {
2608af74909SZhong Yang 		const int attrLen = ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, nullptr, 0);
2618af74909SZhong Yang 		std::vector<BYTE> attr(attrLen, 0);
2628af74909SZhong Yang 		::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, &attr[0], static_cast<DWORD>(attr.size()));
2638af74909SZhong Yang 		return attr;
2648af74909SZhong Yang 	}
2658af74909SZhong Yang 
GetCompositionString(DWORD dwIndex)2668af74909SZhong Yang 	std::wstring GetCompositionString(DWORD dwIndex) {
2678af74909SZhong Yang 		const LONG byteLen = ::ImmGetCompositionStringW(hIMC, dwIndex, nullptr, 0);
2688af74909SZhong Yang 		std::wstring wcs(byteLen / 2, 0);
2698af74909SZhong Yang 		::ImmGetCompositionStringW(hIMC, dwIndex, &wcs[0], byteLen);
2708af74909SZhong Yang 		return wcs;
2718af74909SZhong Yang 	}
2728af74909SZhong Yang };
2738af74909SZhong Yang 
2748af74909SZhong Yang class GlobalMemory;
2758af74909SZhong Yang 
2768af74909SZhong Yang class ReverseArrowCursor {
2778af74909SZhong Yang 	UINT dpi = USER_DEFAULT_SCREEN_DPI;
2788af74909SZhong Yang 	HCURSOR cursor {};
2798af74909SZhong Yang 
2808af74909SZhong Yang public:
ReverseArrowCursor()2818af74909SZhong Yang 	ReverseArrowCursor() noexcept {}
2828af74909SZhong Yang 	// Deleted so ReverseArrowCursor objects can not be copied.
2838af74909SZhong Yang 	ReverseArrowCursor(const ReverseArrowCursor &) = delete;
2848af74909SZhong Yang 	ReverseArrowCursor(ReverseArrowCursor &&) = delete;
2858af74909SZhong Yang 	ReverseArrowCursor &operator=(const ReverseArrowCursor &) = delete;
2868af74909SZhong Yang 	ReverseArrowCursor &operator=(ReverseArrowCursor &&) = delete;
~ReverseArrowCursor()2878af74909SZhong Yang 	~ReverseArrowCursor() {
2888af74909SZhong Yang 		if (cursor) {
2898af74909SZhong Yang 			::DestroyCursor(cursor);
2908af74909SZhong Yang 		}
2918af74909SZhong Yang 	}
2928af74909SZhong Yang 
Load(UINT dpi_)2938af74909SZhong Yang 	HCURSOR Load(UINT dpi_) noexcept {
2948af74909SZhong Yang 		if (cursor)	 {
2958af74909SZhong Yang 			if (dpi == dpi_) {
2968af74909SZhong Yang 				return cursor;
2978af74909SZhong Yang 			}
2988af74909SZhong Yang 			::DestroyCursor(cursor);
2998af74909SZhong Yang 		}
3008af74909SZhong Yang 
3018af74909SZhong Yang 		dpi = dpi_;
3028af74909SZhong Yang 		cursor = LoadReverseArrowCursor(dpi_);
3038af74909SZhong Yang 		return cursor ? cursor : ::LoadCursor({}, IDC_ARROW);
3048af74909SZhong Yang 	}
3058af74909SZhong Yang };
3068af74909SZhong Yang 
3078af74909SZhong Yang }
3088af74909SZhong Yang 
3098af74909SZhong Yang /**
3108af74909SZhong Yang  */
3118af74909SZhong Yang class ScintillaWin :
3128af74909SZhong Yang 	public ScintillaBase {
3138af74909SZhong Yang 
3148af74909SZhong Yang 	bool lastKeyDownConsumed;
3158af74909SZhong Yang 	wchar_t lastHighSurrogateChar;
3168af74909SZhong Yang 
3178af74909SZhong Yang 	bool capturedMouse;
3188af74909SZhong Yang 	bool trackedMouseLeave;
3198af74909SZhong Yang 	SetCoalescableTimerSig SetCoalescableTimerFn;
3208af74909SZhong Yang 
3218af74909SZhong Yang 	unsigned int linesPerScroll;	///< Intellimouse support
3228af74909SZhong Yang 	int wheelDelta; ///< Wheel delta from roll
3238af74909SZhong Yang 
3248af74909SZhong Yang 	UINT dpi = USER_DEFAULT_SCREEN_DPI;
3258af74909SZhong Yang 	ReverseArrowCursor reverseArrowCursor;
3268af74909SZhong Yang 
3278af74909SZhong Yang 	HRGN hRgnUpdate;
3288af74909SZhong Yang 
3298af74909SZhong Yang 	bool hasOKText;
3308af74909SZhong Yang 
3318af74909SZhong Yang 	CLIPFORMAT cfColumnSelect;
3328af74909SZhong Yang 	CLIPFORMAT cfBorlandIDEBlockType;
3338af74909SZhong Yang 	CLIPFORMAT cfLineSelect;
3348af74909SZhong Yang 	CLIPFORMAT cfVSLineTag;
3358af74909SZhong Yang 
3368af74909SZhong Yang 	HRESULT hrOle;
3378af74909SZhong Yang 	DropSource ds;
3388af74909SZhong Yang 	DataObject dob;
3398af74909SZhong Yang 	DropTarget dt;
3408af74909SZhong Yang 
3418af74909SZhong Yang 	static HINSTANCE hInstance;
3428af74909SZhong Yang 	static ATOM scintillaClassAtom;
3438af74909SZhong Yang 	static ATOM callClassAtom;
3448af74909SZhong Yang 
3458af74909SZhong Yang #if defined(USE_D2D)
3468af74909SZhong Yang 	ID2D1RenderTarget *pRenderTarget;
3478af74909SZhong Yang 	bool renderTargetValid;
3488af74909SZhong Yang #endif
3498af74909SZhong Yang 
3508af74909SZhong Yang 	explicit ScintillaWin(HWND hwnd);
3518af74909SZhong Yang 	// Deleted so ScintillaWin objects can not be copied.
3528af74909SZhong Yang 	ScintillaWin(const ScintillaWin &) = delete;
3538af74909SZhong Yang 	ScintillaWin(ScintillaWin &&) = delete;
3548af74909SZhong Yang 	ScintillaWin &operator=(const ScintillaWin &) = delete;
3558af74909SZhong Yang 	ScintillaWin &operator=(ScintillaWin &&) = delete;
3568af74909SZhong Yang 	// ~ScintillaWin() in public section
3578af74909SZhong Yang 
3588af74909SZhong Yang 	void Init();
3598af74909SZhong Yang 	void Finalise() override;
3608af74909SZhong Yang #if defined(USE_D2D)
3618af74909SZhong Yang 	void EnsureRenderTarget(HDC hdc);
3628af74909SZhong Yang 	void DropRenderTarget();
3638af74909SZhong Yang #endif
3648af74909SZhong Yang 	HWND MainHWND() const noexcept;
3658af74909SZhong Yang 
3668af74909SZhong Yang 	static sptr_t DirectFunction(
3678af74909SZhong Yang 		    sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam);
3688af74909SZhong Yang 	static LRESULT PASCAL SWndProc(
3698af74909SZhong Yang 		    HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
3708af74909SZhong Yang 	static LRESULT PASCAL CTWndProc(
3718af74909SZhong Yang 		    HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
3728af74909SZhong Yang 
3738af74909SZhong Yang 	enum : UINT_PTR { invalidTimerID, standardTimerID, idleTimerID, fineTimerStart };
3748af74909SZhong Yang 
3758af74909SZhong Yang 	void DisplayCursor(Window::Cursor c) override;
3768af74909SZhong Yang 	bool DragThreshold(Point ptStart, Point ptNow) override;
3778af74909SZhong Yang 	void StartDrag() override;
3788af74909SZhong Yang 	static int MouseModifiers(uptr_t wParam) noexcept;
3798af74909SZhong Yang 
3808af74909SZhong Yang 	Sci::Position TargetAsUTF8(char *text) const;
3818af74909SZhong Yang 	Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const;
3828af74909SZhong Yang 
3838af74909SZhong Yang 	bool PaintDC(HDC hdc);
3848af74909SZhong Yang 	sptr_t WndPaint();
3858af74909SZhong Yang 
3868af74909SZhong Yang 	// DBCS
3878af74909SZhong Yang 	void ImeStartComposition();
3888af74909SZhong Yang 	void ImeEndComposition();
3898af74909SZhong Yang 	LRESULT ImeOnReconvert(LPARAM lParam);
3908af74909SZhong Yang 	sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam);
3918af74909SZhong Yang 	sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam);
3928af74909SZhong Yang 	static bool KoreanIME() noexcept;
3938af74909SZhong Yang 	void MoveImeCarets(Sci::Position offset);
3948af74909SZhong Yang 	void DrawImeIndicator(int indicator, Sci::Position len);
3958af74909SZhong Yang 	void SetCandidateWindowPos();
3968af74909SZhong Yang 	void SelectionToHangul();
3978af74909SZhong Yang 	void EscapeHanja();
3988af74909SZhong Yang 	void ToggleHanja();
3998af74909SZhong Yang 	void AddWString(std::wstring_view wsv, CharacterSource charSource);
4008af74909SZhong Yang 
4018af74909SZhong Yang 	UINT CodePageOfDocument() const noexcept;
4028af74909SZhong Yang 	bool ValidCodePage(int codePage) const override;
4038af74909SZhong Yang 	std::string EncodeWString(std::wstring_view wsv);
4048af74909SZhong Yang 	sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) override;
4058af74909SZhong Yang 	void IdleWork() override;
4068af74909SZhong Yang 	void QueueIdleWork(WorkNeeded::workItems items, Sci::Position upTo) override;
4078af74909SZhong Yang 	bool SetIdle(bool on) override;
4088af74909SZhong Yang 	UINT_PTR timers[tickDwell+1] {};
4098af74909SZhong Yang 	bool FineTickerRunning(TickReason reason) override;
4108af74909SZhong Yang 	void FineTickerStart(TickReason reason, int millis, int tolerance) override;
4118af74909SZhong Yang 	void FineTickerCancel(TickReason reason) override;
4128af74909SZhong Yang 	void SetMouseCapture(bool on) override;
4138af74909SZhong Yang 	bool HaveMouseCapture() override;
4148af74909SZhong Yang 	void SetTrackMouseLeaveEvent(bool on) noexcept;
4158af74909SZhong Yang 	bool PaintContains(PRectangle rc) override;
4168af74909SZhong Yang 	void ScrollText(Sci::Line linesToMove) override;
4178af74909SZhong Yang 	void NotifyCaretMove() override;
4188af74909SZhong Yang 	void UpdateSystemCaret() override;
4198af74909SZhong Yang 	void SetVerticalScrollPos() override;
4208af74909SZhong Yang 	void SetHorizontalScrollPos() override;
4218af74909SZhong Yang 	bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) override;
4228af74909SZhong Yang 	void NotifyChange() override;
4238af74909SZhong Yang 	void NotifyFocus(bool focus) override;
4248af74909SZhong Yang 	void SetCtrlID(int identifier) override;
4258af74909SZhong Yang 	int GetCtrlID() override;
4268af74909SZhong Yang 	void NotifyParent(SCNotification scn) override;
4278af74909SZhong Yang 	void NotifyDoubleClick(Point pt, int modifiers) override;
4288af74909SZhong Yang 	CaseFolder *CaseFolderForEncoding() override;
4298af74909SZhong Yang 	std::string CaseMapString(const std::string &s, int caseMapping) override;
4308af74909SZhong Yang 	void Copy() override;
4318af74909SZhong Yang 	bool CanPaste() override;
4328af74909SZhong Yang 	void Paste() override;
4338af74909SZhong Yang 	void CreateCallTipWindow(PRectangle rc) override;
434*f9763b28Slrisora 	void AddToPopUp(const wchar_t *label, int cmd = 0, bool enabled = true) override;
4358af74909SZhong Yang 	void ClaimSelection() override;
4368af74909SZhong Yang 
4378af74909SZhong Yang 	void GetIntelliMouseParameters() noexcept;
4388af74909SZhong Yang 	void CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText);
4398af74909SZhong Yang 	void CopyToClipboard(const SelectionText &selectedText) override;
4408af74909SZhong Yang 	void ScrollMessage(WPARAM wParam);
4418af74909SZhong Yang 	void HorizontalScrollMessage(WPARAM wParam);
4428af74909SZhong Yang 	void FullPaint();
4438af74909SZhong Yang 	void FullPaintDC(HDC hdc);
4448af74909SZhong Yang 	bool IsCompatibleDC(HDC hOtherDC) noexcept;
4458af74909SZhong Yang 	DWORD EffectFromState(DWORD grfKeyState) const noexcept;
4468af74909SZhong Yang 
4478af74909SZhong Yang 	int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) noexcept;
4488af74909SZhong Yang 	bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi) noexcept;
4498af74909SZhong Yang 	void ChangeScrollPos(int barType, Sci::Position pos);
4508af74909SZhong Yang 	sptr_t GetTextLength();
4518af74909SZhong Yang 	sptr_t GetText(uptr_t wParam, sptr_t lParam);
4528af74909SZhong Yang 	Window::Cursor ContextCursor(Point pt);
4538af74909SZhong Yang 	sptr_t ShowContextMenu(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4548af74909SZhong Yang 	void SizeWindow();
4558af74909SZhong Yang 	sptr_t MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4568af74909SZhong Yang 	sptr_t KeyMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4578af74909SZhong Yang 	sptr_t FocusMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4588af74909SZhong Yang 	sptr_t IMEMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4598af74909SZhong Yang 	sptr_t EditMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4608af74909SZhong Yang 	sptr_t IdleMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4618af74909SZhong Yang 	sptr_t SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
4628af74909SZhong Yang 
4638af74909SZhong Yang public:
4648af74909SZhong Yang 	~ScintillaWin() override;
4658af74909SZhong Yang 
4668af74909SZhong Yang 	// Public for benefit of Scintilla_DirectFunction
4678af74909SZhong Yang 	sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) override;
4688af74909SZhong Yang 
4698af74909SZhong Yang 	/// Implement IUnknown
4708af74909SZhong Yang 	STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv);
4718af74909SZhong Yang 	STDMETHODIMP_(ULONG)AddRef();
4728af74909SZhong Yang 	STDMETHODIMP_(ULONG)Release();
4738af74909SZhong Yang 
4748af74909SZhong Yang 	/// Implement IDropTarget
4758af74909SZhong Yang 	STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
4768af74909SZhong Yang 	                       POINTL pt, PDWORD pdwEffect);
4778af74909SZhong Yang 	STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect);
4788af74909SZhong Yang 	STDMETHODIMP DragLeave();
4798af74909SZhong Yang 	STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
4808af74909SZhong Yang 	                  POINTL pt, PDWORD pdwEffect);
4818af74909SZhong Yang 
4828af74909SZhong Yang 	/// Implement important part of IDataObject
4838af74909SZhong Yang 	STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM);
4848af74909SZhong Yang 
4858af74909SZhong Yang 	static void Prepare() noexcept;
4868af74909SZhong Yang 	static bool Register(HINSTANCE hInstance_) noexcept;
4878af74909SZhong Yang 	static bool Unregister() noexcept;
4888af74909SZhong Yang 
4898af74909SZhong Yang 	friend class DropSource;
4908af74909SZhong Yang 	friend class DataObject;
4918af74909SZhong Yang 	friend class DropTarget;
DragIsRectangularOK(CLIPFORMAT fmt) const4928af74909SZhong Yang 	bool DragIsRectangularOK(CLIPFORMAT fmt) const noexcept {
4938af74909SZhong Yang 		return drag.rectangular && (fmt == cfColumnSelect);
4948af74909SZhong Yang 	}
4958af74909SZhong Yang 
4968af74909SZhong Yang private:
4978af74909SZhong Yang 	// For use in creating a system caret
4988af74909SZhong Yang 	bool HasCaretSizeChanged() const noexcept;
4998af74909SZhong Yang 	BOOL CreateSystemCaret();
5008af74909SZhong Yang 	BOOL DestroySystemCaret() noexcept;
5018af74909SZhong Yang 	HBITMAP sysCaretBitmap;
5028af74909SZhong Yang 	int sysCaretWidth;
5038af74909SZhong Yang 	int sysCaretHeight;
5048af74909SZhong Yang 	bool styleIdleInQueue;
5058af74909SZhong Yang };
5068af74909SZhong Yang 
5078af74909SZhong Yang HINSTANCE ScintillaWin::hInstance {};
5088af74909SZhong Yang ATOM ScintillaWin::scintillaClassAtom = 0;
5098af74909SZhong Yang ATOM ScintillaWin::callClassAtom = 0;
5108af74909SZhong Yang 
ScintillaWin(HWND hwnd)5118af74909SZhong Yang ScintillaWin::ScintillaWin(HWND hwnd) {
5128af74909SZhong Yang 
5138af74909SZhong Yang 	lastKeyDownConsumed = false;
5148af74909SZhong Yang 	lastHighSurrogateChar = 0;
5158af74909SZhong Yang 
5168af74909SZhong Yang 	capturedMouse = false;
5178af74909SZhong Yang 	trackedMouseLeave = false;
5188af74909SZhong Yang 	SetCoalescableTimerFn = nullptr;
5198af74909SZhong Yang 
5208af74909SZhong Yang 	linesPerScroll = 0;
5218af74909SZhong Yang 	wheelDelta = 0;   // Wheel delta from roll
5228af74909SZhong Yang 
5238af74909SZhong Yang 	dpi = DpiForWindow(hwnd);
5248af74909SZhong Yang 
5258af74909SZhong Yang 	hRgnUpdate = {};
5268af74909SZhong Yang 
5278af74909SZhong Yang 	hasOKText = false;
5288af74909SZhong Yang 
5298af74909SZhong Yang 	// There does not seem to be a real standard for indicating that the clipboard
5308af74909SZhong Yang 	// contains a rectangular selection, so copy Developer Studio and Borland Delphi.
5318af74909SZhong Yang 	cfColumnSelect = static_cast<CLIPFORMAT>(
5328af74909SZhong Yang 		::RegisterClipboardFormat(TEXT("MSDEVColumnSelect")));
5338af74909SZhong Yang 	cfBorlandIDEBlockType = static_cast<CLIPFORMAT>(
5348af74909SZhong Yang 		::RegisterClipboardFormat(TEXT("Borland IDE Block Type")));
5358af74909SZhong Yang 
5368af74909SZhong Yang 	// Likewise for line-copy (copies a full line when no text is selected)
5378af74909SZhong Yang 	cfLineSelect = static_cast<CLIPFORMAT>(
5388af74909SZhong Yang 		::RegisterClipboardFormat(TEXT("MSDEVLineSelect")));
5398af74909SZhong Yang 	cfVSLineTag = static_cast<CLIPFORMAT>(
5408af74909SZhong Yang 		::RegisterClipboardFormat(TEXT("VisualStudioEditorOperationsLineCutCopyClipboardTag")));
5418af74909SZhong Yang 	hrOle = E_FAIL;
5428af74909SZhong Yang 
5438af74909SZhong Yang 	wMain = hwnd;
5448af74909SZhong Yang 
5458af74909SZhong Yang 	dob.sci = this;
5468af74909SZhong Yang 	ds.sci = this;
5478af74909SZhong Yang 	dt.sci = this;
5488af74909SZhong Yang 
5498af74909SZhong Yang 	sysCaretBitmap = {};
5508af74909SZhong Yang 	sysCaretWidth = 0;
5518af74909SZhong Yang 	sysCaretHeight = 0;
5528af74909SZhong Yang 
5538af74909SZhong Yang 	styleIdleInQueue = false;
5548af74909SZhong Yang 
5558af74909SZhong Yang #if defined(USE_D2D)
5568af74909SZhong Yang 	pRenderTarget = nullptr;
5578af74909SZhong Yang 	renderTargetValid = true;
5588af74909SZhong Yang #endif
5598af74909SZhong Yang 
5608af74909SZhong Yang 	caret.period = ::GetCaretBlinkTime();
5618af74909SZhong Yang 	if (caret.period < 0)
5628af74909SZhong Yang 		caret.period = 0;
5638af74909SZhong Yang 
5648af74909SZhong Yang 	Init();
5658af74909SZhong Yang }
5668af74909SZhong Yang 
~ScintillaWin()5678af74909SZhong Yang ScintillaWin::~ScintillaWin() {}
5688af74909SZhong Yang 
Init()5698af74909SZhong Yang void ScintillaWin::Init() {
5708af74909SZhong Yang 	// Initialize COM.  If the app has already done this it will have
5718af74909SZhong Yang 	// no effect.  If the app hasn't, we really shouldn't ask them to call
5728af74909SZhong Yang 	// it just so this internal feature works.
5738af74909SZhong Yang 	hrOle = ::OleInitialize(nullptr);
5748af74909SZhong Yang 
5758af74909SZhong Yang 	// Find SetCoalescableTimer which is only available from Windows 8+
5768af74909SZhong Yang 	HMODULE user32 = ::GetModuleHandleW(L"user32.dll");
5778af74909SZhong Yang 	SetCoalescableTimerFn = DLLFunction<SetCoalescableTimerSig>(user32, "SetCoalescableTimer");
5788af74909SZhong Yang 
5798af74909SZhong Yang 	vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff));
5808af74909SZhong Yang 	vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff));
5818af74909SZhong Yang 	vs.indicators[SC_INDICATOR_CONVERTED] = Indicator(INDIC_COMPOSITIONTHICK, ColourDesired(0, 0, 0xff));
5828af74909SZhong Yang 	vs.indicators[SC_INDICATOR_TARGET] = Indicator(INDIC_STRAIGHTBOX, ColourDesired(0, 0, 0xff));
5838af74909SZhong Yang }
5848af74909SZhong Yang 
Finalise()5858af74909SZhong Yang void ScintillaWin::Finalise() {
5868af74909SZhong Yang 	ScintillaBase::Finalise();
5878af74909SZhong Yang 	for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast<TickReason>(tr + 1)) {
5888af74909SZhong Yang 		FineTickerCancel(tr);
5898af74909SZhong Yang 	}
5908af74909SZhong Yang 	SetIdle(false);
5918af74909SZhong Yang #if defined(USE_D2D)
5928af74909SZhong Yang 	DropRenderTarget();
5938af74909SZhong Yang #endif
5948af74909SZhong Yang 	::RevokeDragDrop(MainHWND());
5958af74909SZhong Yang 	if (SUCCEEDED(hrOle)) {
5968af74909SZhong Yang 		::OleUninitialize();
5978af74909SZhong Yang 	}
5988af74909SZhong Yang }
5998af74909SZhong Yang 
6008af74909SZhong Yang #if defined(USE_D2D)
6018af74909SZhong Yang 
EnsureRenderTarget(HDC hdc)6028af74909SZhong Yang void ScintillaWin::EnsureRenderTarget(HDC hdc) {
6038af74909SZhong Yang 	if (!renderTargetValid) {
6048af74909SZhong Yang 		DropRenderTarget();
6058af74909SZhong Yang 		renderTargetValid = true;
6068af74909SZhong Yang 	}
6078af74909SZhong Yang 	if (pD2DFactory && !pRenderTarget) {
6088af74909SZhong Yang 		HWND hw = MainHWND();
6098af74909SZhong Yang 		RECT rc;
6108af74909SZhong Yang 		GetClientRect(hw, &rc);
6118af74909SZhong Yang 
6128af74909SZhong Yang 		const D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
6138af74909SZhong Yang 
6148af74909SZhong Yang 		// Create a Direct2D render target.
6158af74909SZhong Yang #if 1
6168af74909SZhong Yang 		D2D1_RENDER_TARGET_PROPERTIES drtp;
6178af74909SZhong Yang 		drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
6188af74909SZhong Yang 		drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
6198af74909SZhong Yang 		drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
6208af74909SZhong Yang 		drtp.dpiX = 96.0;
6218af74909SZhong Yang 		drtp.dpiY = 96.0;
6228af74909SZhong Yang 		drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE;
6238af74909SZhong Yang 		drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
6248af74909SZhong Yang 
6258af74909SZhong Yang 		if (technology == SC_TECHNOLOGY_DIRECTWRITEDC) {
6268af74909SZhong Yang 			// Explicit pixel format needed.
6278af74909SZhong Yang 			drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
6288af74909SZhong Yang 				D2D1_ALPHA_MODE_IGNORE);
6298af74909SZhong Yang 
6308af74909SZhong Yang 			ID2D1DCRenderTarget *pDCRT = nullptr;
6318af74909SZhong Yang 			const HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pDCRT);
6328af74909SZhong Yang 			if (SUCCEEDED(hr)) {
6338af74909SZhong Yang 				pRenderTarget = pDCRT;
6348af74909SZhong Yang 			} else {
6358af74909SZhong Yang 				Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%lx\n", hr);
6368af74909SZhong Yang 				pRenderTarget = nullptr;
6378af74909SZhong Yang 			}
6388af74909SZhong Yang 
6398af74909SZhong Yang 		} else {
6408af74909SZhong Yang 			D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp;
6418af74909SZhong Yang 			dhrtp.hwnd = hw;
6428af74909SZhong Yang 			dhrtp.pixelSize = size;
6438af74909SZhong Yang 			dhrtp.presentOptions = (technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ?
6448af74909SZhong Yang 			D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE;
6458af74909SZhong Yang 
6468af74909SZhong Yang 			ID2D1HwndRenderTarget *pHwndRenderTarget = nullptr;
6478af74909SZhong Yang 			const HRESULT hr = pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pHwndRenderTarget);
6488af74909SZhong Yang 			if (SUCCEEDED(hr)) {
6498af74909SZhong Yang 				pRenderTarget = pHwndRenderTarget;
6508af74909SZhong Yang 			} else {
6518af74909SZhong Yang 				Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%lx\n", hr);
6528af74909SZhong Yang 				pRenderTarget = nullptr;
6538af74909SZhong Yang 			}
6548af74909SZhong Yang 		}
6558af74909SZhong Yang #else
6568af74909SZhong Yang 		pD2DFactory->CreateHwndRenderTarget(
6578af74909SZhong Yang 			D2D1::RenderTargetProperties(
6588af74909SZhong Yang 				D2D1_RENDER_TARGET_TYPE_DEFAULT ,
6598af74909SZhong Yang 				D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
6608af74909SZhong Yang 				96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT),
6618af74909SZhong Yang 			D2D1::HwndRenderTargetProperties(hw, size),
6628af74909SZhong Yang 			&pRenderTarget);
6638af74909SZhong Yang #endif
6648af74909SZhong Yang 		// Pixmaps were created to be compatible with previous render target so
6658af74909SZhong Yang 		// need to be recreated.
6668af74909SZhong Yang 		DropGraphics(false);
6678af74909SZhong Yang 	}
6688af74909SZhong Yang 
6698af74909SZhong Yang 	if ((technology == SC_TECHNOLOGY_DIRECTWRITEDC) && pRenderTarget) {
6708af74909SZhong Yang 		RECT rcWindow;
6718af74909SZhong Yang 		GetClientRect(MainHWND(), &rcWindow);
6728af74909SZhong Yang 		const HRESULT hr = static_cast<ID2D1DCRenderTarget*>(pRenderTarget)->BindDC(hdc, &rcWindow);
6738af74909SZhong Yang 		if (FAILED(hr)) {
6748af74909SZhong Yang 			Platform::DebugPrintf("BindDC failed 0x%lx\n", hr);
6758af74909SZhong Yang 			DropRenderTarget();
6768af74909SZhong Yang 		}
6778af74909SZhong Yang 	}
6788af74909SZhong Yang }
6798af74909SZhong Yang 
DropRenderTarget()6808af74909SZhong Yang void ScintillaWin::DropRenderTarget() {
6818af74909SZhong Yang 	ReleaseUnknown(pRenderTarget);
6828af74909SZhong Yang }
6838af74909SZhong Yang 
6848af74909SZhong Yang #endif
6858af74909SZhong Yang 
MainHWND() const6868af74909SZhong Yang HWND ScintillaWin::MainHWND() const noexcept {
6878af74909SZhong Yang 	return HwndFromWindow(wMain);
6888af74909SZhong Yang }
6898af74909SZhong Yang 
DisplayCursor(Window::Cursor c)6908af74909SZhong Yang void ScintillaWin::DisplayCursor(Window::Cursor c) {
6918af74909SZhong Yang 	if (cursorMode != SC_CURSORNORMAL) {
6928af74909SZhong Yang 		c = static_cast<Window::Cursor>(cursorMode);
6938af74909SZhong Yang 	}
6948af74909SZhong Yang 	if (c == Window::cursorReverseArrow) {
6958af74909SZhong Yang 		::SetCursor(reverseArrowCursor.Load(dpi));
6968af74909SZhong Yang 	} else {
6978af74909SZhong Yang 		wMain.SetCursor(c);
6988af74909SZhong Yang 	}
6998af74909SZhong Yang }
7008af74909SZhong Yang 
DragThreshold(Point ptStart,Point ptNow)7018af74909SZhong Yang bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) {
7028af74909SZhong Yang 	const Point ptDifference = ptStart - ptNow;
7038af74909SZhong Yang 	const XYPOSITION xMove = std::trunc(std::abs(ptDifference.x));
7048af74909SZhong Yang 	const XYPOSITION yMove = std::trunc(std::abs(ptDifference.y));
7058af74909SZhong Yang 	return (xMove > SystemMetricsForDpi(SM_CXDRAG, dpi)) ||
7068af74909SZhong Yang 		(yMove > SystemMetricsForDpi(SM_CYDRAG, dpi));
7078af74909SZhong Yang }
7088af74909SZhong Yang 
StartDrag()7098af74909SZhong Yang void ScintillaWin::StartDrag() {
7108af74909SZhong Yang 	inDragDrop = ddDragging;
7118af74909SZhong Yang 	DWORD dwEffect = 0;
7128af74909SZhong Yang 	dropWentOutside = true;
7138af74909SZhong Yang 	IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob);
7148af74909SZhong Yang 	IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds);
7158af74909SZhong Yang 	//Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
7168af74909SZhong Yang 	const HRESULT hr = ::DoDragDrop(
7178af74909SZhong Yang 	                 pDataObject,
7188af74909SZhong Yang 	                 pDropSource,
7198af74909SZhong Yang 	                 DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect);
7208af74909SZhong Yang 	//Platform::DebugPrintf("DoDragDrop = %x\n", hr);
7218af74909SZhong Yang 	if (SUCCEEDED(hr)) {
7228af74909SZhong Yang 		if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) {
7238af74909SZhong Yang 			// Remove dragged out text
7248af74909SZhong Yang 			ClearSelection();
7258af74909SZhong Yang 		}
7268af74909SZhong Yang 	}
7278af74909SZhong Yang 	inDragDrop = ddNone;
7288af74909SZhong Yang 	SetDragPosition(SelectionPosition(Sci::invalidPosition));
7298af74909SZhong Yang }
7308af74909SZhong Yang 
MouseModifiers(uptr_t wParam)7318af74909SZhong Yang int ScintillaWin::MouseModifiers(uptr_t wParam) noexcept {
7328af74909SZhong Yang 	return ModifierFlags((wParam & MK_SHIFT) != 0,
7338af74909SZhong Yang 		(wParam & MK_CONTROL) != 0,
7348af74909SZhong Yang 		KeyboardIsKeyDown(VK_MENU));
7358af74909SZhong Yang }
7368af74909SZhong Yang 
7378af74909SZhong Yang namespace {
7388af74909SZhong Yang 
InputCodePage()7398af74909SZhong Yang int InputCodePage() noexcept {
7408af74909SZhong Yang 	HKL inputLocale = ::GetKeyboardLayout(0);
7418af74909SZhong Yang 	const LANGID inputLang = LOWORD(inputLocale);
7428af74909SZhong Yang 	char sCodePage[10];
7438af74909SZhong Yang 	const int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT),
7448af74909SZhong Yang 	  LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage));
7458af74909SZhong Yang 	if (!res)
7468af74909SZhong Yang 		return 0;
7478af74909SZhong Yang 	return atoi(sCodePage);
7488af74909SZhong Yang }
7498af74909SZhong Yang 
7508af74909SZhong Yang /** Map the key codes to their equivalent SCK_ form. */
KeyTranslate(int keyIn)7518af74909SZhong Yang int KeyTranslate(int keyIn) noexcept {
7528af74909SZhong Yang //PLATFORM_ASSERT(!keyIn);
7538af74909SZhong Yang 	switch (keyIn) {
7548af74909SZhong Yang 		case VK_DOWN:		return SCK_DOWN;
7558af74909SZhong Yang 		case VK_UP:		return SCK_UP;
7568af74909SZhong Yang 		case VK_LEFT:		return SCK_LEFT;
7578af74909SZhong Yang 		case VK_RIGHT:		return SCK_RIGHT;
7588af74909SZhong Yang 		case VK_HOME:		return SCK_HOME;
7598af74909SZhong Yang 		case VK_END:		return SCK_END;
7608af74909SZhong Yang 		case VK_PRIOR:		return SCK_PRIOR;
7618af74909SZhong Yang 		case VK_NEXT:		return SCK_NEXT;
7628af74909SZhong Yang 		case VK_DELETE:	return SCK_DELETE;
7638af74909SZhong Yang 		case VK_INSERT:		return SCK_INSERT;
7648af74909SZhong Yang 		case VK_ESCAPE:	return SCK_ESCAPE;
7658af74909SZhong Yang 		case VK_BACK:		return SCK_BACK;
7668af74909SZhong Yang 		case VK_TAB:		return SCK_TAB;
7678af74909SZhong Yang 		case VK_RETURN:	return SCK_RETURN;
7688af74909SZhong Yang 		case VK_ADD:		return SCK_ADD;
7698af74909SZhong Yang 		case VK_SUBTRACT:	return SCK_SUBTRACT;
7708af74909SZhong Yang 		case VK_DIVIDE:		return SCK_DIVIDE;
7718af74909SZhong Yang 		case VK_LWIN:		return SCK_WIN;
7728af74909SZhong Yang 		case VK_RWIN:		return SCK_RWIN;
7738af74909SZhong Yang 		case VK_APPS:		return SCK_MENU;
7748af74909SZhong Yang 		case VK_OEM_2:		return '/';
7758af74909SZhong Yang 		case VK_OEM_3:		return '`';
7768af74909SZhong Yang 		case VK_OEM_4:		return '[';
7778af74909SZhong Yang 		case VK_OEM_5:		return '\\';
7788af74909SZhong Yang 		case VK_OEM_6:		return ']';
7798af74909SZhong Yang 		default:			return keyIn;
7808af74909SZhong Yang 	}
7818af74909SZhong Yang }
7828af74909SZhong Yang 
BoundsContains(PRectangle rcBounds,HRGN hRgnBounds,PRectangle rcCheck)7838af74909SZhong Yang bool BoundsContains(PRectangle rcBounds, HRGN hRgnBounds, PRectangle rcCheck) noexcept {
7848af74909SZhong Yang 	bool contains = true;
7858af74909SZhong Yang 	if (!rcCheck.Empty()) {
7868af74909SZhong Yang 		if (!rcBounds.Contains(rcCheck)) {
7878af74909SZhong Yang 			contains = false;
7888af74909SZhong Yang 		} else if (hRgnBounds) {
7898af74909SZhong Yang 			// In bounding rectangle so check more accurately using region
7908af74909SZhong Yang 			const RECT rcw = RectFromPRectangle(rcCheck);
7918af74909SZhong Yang 			HRGN hRgnCheck = ::CreateRectRgnIndirect(&rcw);
7928af74909SZhong Yang 			if (hRgnCheck) {
7938af74909SZhong Yang 				HRGN hRgnDifference = ::CreateRectRgn(0, 0, 0, 0);
7948af74909SZhong Yang 				if (hRgnDifference) {
7958af74909SZhong Yang 					const int combination = ::CombineRgn(hRgnDifference, hRgnCheck, hRgnBounds, RGN_DIFF);
7968af74909SZhong Yang 					if (combination != NULLREGION) {
7978af74909SZhong Yang 						contains = false;
7988af74909SZhong Yang 					}
7998af74909SZhong Yang 					::DeleteRgn(hRgnDifference);
8008af74909SZhong Yang 				}
8018af74909SZhong Yang 				::DeleteRgn(hRgnCheck);
8028af74909SZhong Yang 			}
8038af74909SZhong Yang 		}
8048af74909SZhong Yang 	}
8058af74909SZhong Yang 	return contains;
8068af74909SZhong Yang }
8078af74909SZhong Yang 
8088af74909SZhong Yang // Simplify calling WideCharToMultiByte and MultiByteToWideChar by providing default parameters and using string view.
8098af74909SZhong Yang 
MultiByteFromWideChar(UINT codePage,std::wstring_view wsv,LPSTR lpMultiByteStr,ptrdiff_t cbMultiByte)8108af74909SZhong Yang int MultiByteFromWideChar(UINT codePage, std::wstring_view wsv, LPSTR lpMultiByteStr, ptrdiff_t cbMultiByte) noexcept {
8118af74909SZhong Yang 	return ::WideCharToMultiByte(codePage, 0, wsv.data(), static_cast<int>(wsv.length()), lpMultiByteStr, static_cast<int>(cbMultiByte), nullptr, nullptr);
8128af74909SZhong Yang }
8138af74909SZhong Yang 
MultiByteLenFromWideChar(UINT codePage,std::wstring_view wsv)8148af74909SZhong Yang int MultiByteLenFromWideChar(UINT codePage, std::wstring_view wsv) noexcept {
8158af74909SZhong Yang 	return MultiByteFromWideChar(codePage, wsv, nullptr, 0);
8168af74909SZhong Yang }
8178af74909SZhong Yang 
WideCharFromMultiByte(UINT codePage,std::string_view sv,LPWSTR lpWideCharStr,ptrdiff_t cchWideChar)8188af74909SZhong Yang int WideCharFromMultiByte(UINT codePage, std::string_view sv, LPWSTR lpWideCharStr, ptrdiff_t cchWideChar) noexcept {
8198af74909SZhong Yang 	return ::MultiByteToWideChar(codePage, 0, sv.data(), static_cast<int>(sv.length()), lpWideCharStr, static_cast<int>(cchWideChar));
8208af74909SZhong Yang }
8218af74909SZhong Yang 
WideCharLenFromMultiByte(UINT codePage,std::string_view sv)8228af74909SZhong Yang int WideCharLenFromMultiByte(UINT codePage, std::string_view sv) noexcept {
8238af74909SZhong Yang 	return WideCharFromMultiByte(codePage, sv, nullptr, 0);
8248af74909SZhong Yang }
8258af74909SZhong Yang 
StringEncode(std::wstring_view wsv,int codePage)8268af74909SZhong Yang std::string StringEncode(std::wstring_view wsv, int codePage) {
8278af74909SZhong Yang 	const int cchMulti = wsv.length() ? MultiByteLenFromWideChar(codePage, wsv) : 0;
8288af74909SZhong Yang 	std::string sMulti(cchMulti, 0);
8298af74909SZhong Yang 	if (cchMulti) {
8308af74909SZhong Yang 		MultiByteFromWideChar(codePage, wsv, sMulti.data(), cchMulti);
8318af74909SZhong Yang 	}
8328af74909SZhong Yang 	return sMulti;
8338af74909SZhong Yang }
8348af74909SZhong Yang 
StringDecode(std::string_view sv,int codePage)8358af74909SZhong Yang std::wstring StringDecode(std::string_view sv, int codePage) {
8368af74909SZhong Yang 	const int cchWide = sv.length() ? WideCharLenFromMultiByte(codePage, sv) : 0;
8378af74909SZhong Yang 	std::wstring sWide(cchWide, 0);
8388af74909SZhong Yang 	if (cchWide) {
8398af74909SZhong Yang 		WideCharFromMultiByte(codePage, sv, sWide.data(), cchWide);
8408af74909SZhong Yang 	}
8418af74909SZhong Yang 	return sWide;
8428af74909SZhong Yang }
8438af74909SZhong Yang 
StringMapCase(std::wstring_view wsv,DWORD mapFlags)8448af74909SZhong Yang std::wstring StringMapCase(std::wstring_view wsv, DWORD mapFlags) {
8458af74909SZhong Yang 	const int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
8468af74909SZhong Yang 		wsv.data(), static_cast<int>(wsv.length()), nullptr, 0);
8478af74909SZhong Yang 	std::wstring wsConverted(charsConverted, 0);
8488af74909SZhong Yang 	if (charsConverted) {
8498af74909SZhong Yang 		::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
8508af74909SZhong Yang 			wsv.data(), static_cast<int>(wsv.length()), wsConverted.data(), charsConverted);
8518af74909SZhong Yang 	}
8528af74909SZhong Yang 	return wsConverted;
8538af74909SZhong Yang }
8548af74909SZhong Yang 
8558af74909SZhong Yang }
8568af74909SZhong Yang 
8578af74909SZhong Yang // Returns the target converted to UTF8.
8588af74909SZhong Yang // Return the length in bytes.
TargetAsUTF8(char * text) const8598af74909SZhong Yang Sci::Position ScintillaWin::TargetAsUTF8(char *text) const {
8608af74909SZhong Yang 	const Sci::Position targetLength = targetRange.Length();
8618af74909SZhong Yang 	if (IsUnicodeMode()) {
8628af74909SZhong Yang 		if (text) {
8638af74909SZhong Yang 			pdoc->GetCharRange(text, targetRange.start.Position(), targetLength);
8648af74909SZhong Yang 		}
8658af74909SZhong Yang 	} else {
8668af74909SZhong Yang 		// Need to convert
8678af74909SZhong Yang 		const std::string s = RangeText(targetRange.start.Position(), targetRange.end.Position());
8688af74909SZhong Yang 		const std::wstring characters = StringDecode(s, CodePageOfDocument());
8698af74909SZhong Yang 		const int utf8Len = MultiByteLenFromWideChar(CP_UTF8, characters);
8708af74909SZhong Yang 		if (text) {
8718af74909SZhong Yang 			MultiByteFromWideChar(CP_UTF8, characters, text, utf8Len);
8728af74909SZhong Yang 			text[utf8Len] = '\0';
8738af74909SZhong Yang 		}
8748af74909SZhong Yang 		return utf8Len;
8758af74909SZhong Yang 	}
8768af74909SZhong Yang 	return targetLength;
8778af74909SZhong Yang }
8788af74909SZhong Yang 
8798af74909SZhong Yang // Translates a nul terminated UTF8 string into the document encoding.
8808af74909SZhong Yang // Return the length of the result in bytes.
EncodedFromUTF8(const char * utf8,char * encoded) const8818af74909SZhong Yang Sci::Position ScintillaWin::EncodedFromUTF8(const char *utf8, char *encoded) const {
8828af74909SZhong Yang 	const Sci::Position inputLength = (lengthForEncode >= 0) ? lengthForEncode : strlen(utf8);
8838af74909SZhong Yang 	if (IsUnicodeMode()) {
8848af74909SZhong Yang 		if (encoded) {
8858af74909SZhong Yang 			memcpy(encoded, utf8, inputLength);
8868af74909SZhong Yang 		}
8878af74909SZhong Yang 		return inputLength;
8888af74909SZhong Yang 	} else {
8898af74909SZhong Yang 		// Need to convert
8908af74909SZhong Yang 		const std::string_view utf8Input(utf8, inputLength);
8918af74909SZhong Yang 		const int charsLen = WideCharLenFromMultiByte(CP_UTF8, utf8Input);
8928af74909SZhong Yang 		std::wstring characters(charsLen, L'\0');
8938af74909SZhong Yang 		WideCharFromMultiByte(CP_UTF8, utf8Input, &characters[0], charsLen);
8948af74909SZhong Yang 
8958af74909SZhong Yang 		const int encodedLen = MultiByteLenFromWideChar(CodePageOfDocument(), characters);
8968af74909SZhong Yang 		if (encoded) {
8978af74909SZhong Yang 			MultiByteFromWideChar(CodePageOfDocument(), characters, encoded, encodedLen);
8988af74909SZhong Yang 			encoded[encodedLen] = '\0';
8998af74909SZhong Yang 		}
9008af74909SZhong Yang 		return encodedLen;
9018af74909SZhong Yang 	}
9028af74909SZhong Yang }
9038af74909SZhong Yang 
PaintDC(HDC hdc)9048af74909SZhong Yang bool ScintillaWin::PaintDC(HDC hdc) {
9058af74909SZhong Yang 	if (technology == SC_TECHNOLOGY_DEFAULT) {
9068af74909SZhong Yang 		AutoSurface surfaceWindow(hdc, this);
9078af74909SZhong Yang 		if (surfaceWindow) {
9088af74909SZhong Yang 			Paint(surfaceWindow, rcPaint);
9098af74909SZhong Yang 			surfaceWindow->Release();
9108af74909SZhong Yang 		}
9118af74909SZhong Yang 	} else {
9128af74909SZhong Yang #if defined(USE_D2D)
9138af74909SZhong Yang 		EnsureRenderTarget(hdc);
9148af74909SZhong Yang 		if (pRenderTarget) {
9158af74909SZhong Yang 			AutoSurface surfaceWindow(pRenderTarget, this);
9168af74909SZhong Yang 			if (surfaceWindow) {
9178af74909SZhong Yang 				pRenderTarget->BeginDraw();
9188af74909SZhong Yang 				Paint(surfaceWindow, rcPaint);
9198af74909SZhong Yang 				surfaceWindow->Release();
9208af74909SZhong Yang 				const HRESULT hr = pRenderTarget->EndDraw();
9218af74909SZhong Yang 				if (hr == static_cast<HRESULT>(D2DERR_RECREATE_TARGET)) {
9228af74909SZhong Yang 					DropRenderTarget();
9238af74909SZhong Yang 					return false;
9248af74909SZhong Yang 				}
9258af74909SZhong Yang 			}
9268af74909SZhong Yang 		}
9278af74909SZhong Yang #endif
9288af74909SZhong Yang 	}
9298af74909SZhong Yang 
9308af74909SZhong Yang 	return true;
9318af74909SZhong Yang }
9328af74909SZhong Yang 
WndPaint()9338af74909SZhong Yang sptr_t ScintillaWin::WndPaint() {
9348af74909SZhong Yang 	//ElapsedPeriod ep;
9358af74909SZhong Yang 
9368af74909SZhong Yang 	// Redirect assertions to debug output and save current state
9378af74909SZhong Yang 	const bool assertsPopup = Platform::ShowAssertionPopUps(false);
9388af74909SZhong Yang 	paintState = painting;
9398af74909SZhong Yang 	PAINTSTRUCT ps = {};
9408af74909SZhong Yang 
9418af74909SZhong Yang 	// Removed since this interferes with reporting other assertions as it occurs repeatedly
9428af74909SZhong Yang 	//PLATFORM_ASSERT(hRgnUpdate == NULL);
9438af74909SZhong Yang 	hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0);
9448af74909SZhong Yang 	::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE);
9458af74909SZhong Yang 	::BeginPaint(MainHWND(), &ps);
9468af74909SZhong Yang 	rcPaint = PRectangle::FromInts(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
9478af74909SZhong Yang 	const PRectangle rcClient = GetClientRectangle();
9488af74909SZhong Yang 	paintingAllText = BoundsContains(rcPaint, hRgnUpdate, rcClient);
9498af74909SZhong Yang 	if (!PaintDC(ps.hdc)) {
9508af74909SZhong Yang 		paintState = paintAbandoned;
9518af74909SZhong Yang 	}
9528af74909SZhong Yang 	if (hRgnUpdate) {
9538af74909SZhong Yang 		::DeleteRgn(hRgnUpdate);
9548af74909SZhong Yang 		hRgnUpdate = {};
9558af74909SZhong Yang 	}
9568af74909SZhong Yang 
9578af74909SZhong Yang 	::EndPaint(MainHWND(), &ps);
9588af74909SZhong Yang 	if (paintState == paintAbandoned) {
9598af74909SZhong Yang 		// Painting area was insufficient to cover new styling or brace highlight positions
9608af74909SZhong Yang 		FullPaint();
9618af74909SZhong Yang 		::ValidateRect(MainHWND(), nullptr);
9628af74909SZhong Yang 	}
9638af74909SZhong Yang 	paintState = notPainting;
9648af74909SZhong Yang 
9658af74909SZhong Yang 	// Restore debug output state
9668af74909SZhong Yang 	Platform::ShowAssertionPopUps(assertsPopup);
9678af74909SZhong Yang 
9688af74909SZhong Yang 	//Platform::DebugPrintf("Paint took %g\n", ep.Duration());
9698af74909SZhong Yang 	return 0;
9708af74909SZhong Yang }
9718af74909SZhong Yang 
HandleCompositionWindowed(uptr_t wParam,sptr_t lParam)9728af74909SZhong Yang sptr_t ScintillaWin::HandleCompositionWindowed(uptr_t wParam, sptr_t lParam) {
9738af74909SZhong Yang 	if (lParam & GCS_RESULTSTR) {
9748af74909SZhong Yang 		IMContext imc(MainHWND());
9758af74909SZhong Yang 		if (imc.hIMC) {
9768af74909SZhong Yang 			AddWString(imc.GetCompositionString(GCS_RESULTSTR), CharacterSource::imeResult);
9778af74909SZhong Yang 
9788af74909SZhong Yang 			// Set new position after converted
9798af74909SZhong Yang 			const Point pos = PointMainCaret();
9808af74909SZhong Yang 			COMPOSITIONFORM CompForm;
9818af74909SZhong Yang 			CompForm.dwStyle = CFS_POINT;
9828af74909SZhong Yang 			CompForm.ptCurrentPos = POINTFromPoint(pos);
9838af74909SZhong Yang 			::ImmSetCompositionWindow(imc.hIMC, &CompForm);
9848af74909SZhong Yang 		}
9858af74909SZhong Yang 		return 0;
9868af74909SZhong Yang 	}
9878af74909SZhong Yang 	return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam);
9888af74909SZhong Yang }
9898af74909SZhong Yang 
KoreanIME()9908af74909SZhong Yang bool ScintillaWin::KoreanIME() noexcept {
9918af74909SZhong Yang 	const int codePage = InputCodePage();
9928af74909SZhong Yang 	return codePage == 949 || codePage == 1361;
9938af74909SZhong Yang }
9948af74909SZhong Yang 
MoveImeCarets(Sci::Position offset)9958af74909SZhong Yang void ScintillaWin::MoveImeCarets(Sci::Position offset) {
9968af74909SZhong Yang 	// Move carets relatively by bytes.
9978af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
9988af74909SZhong Yang 		const Sci::Position positionInsert = sel.Range(r).Start().Position();
9998af74909SZhong Yang 		sel.Range(r).caret.SetPosition(positionInsert + offset);
10008af74909SZhong Yang 		sel.Range(r).anchor.SetPosition(positionInsert + offset);
10018af74909SZhong Yang 	}
10028af74909SZhong Yang }
10038af74909SZhong Yang 
DrawImeIndicator(int indicator,Sci::Position len)10048af74909SZhong Yang void ScintillaWin::DrawImeIndicator(int indicator, Sci::Position len) {
10058af74909SZhong Yang 	// Emulate the visual style of IME characters with indicators.
10068af74909SZhong Yang 	// Draw an indicator on the character before caret by the character bytes of len
10078af74909SZhong Yang 	// so it should be called after InsertCharacter().
10088af74909SZhong Yang 	// It does not affect caret positions.
10098af74909SZhong Yang 	if (indicator < 8 || indicator > INDICATOR_MAX) {
10108af74909SZhong Yang 		return;
10118af74909SZhong Yang 	}
10128af74909SZhong Yang 	pdoc->DecorationSetCurrentIndicator(indicator);
10138af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
10148af74909SZhong Yang 		const Sci::Position positionInsert = sel.Range(r).Start().Position();
10158af74909SZhong Yang 		pdoc->DecorationFillRange(positionInsert - len, 1, len);
10168af74909SZhong Yang 	}
10178af74909SZhong Yang }
10188af74909SZhong Yang 
SetCandidateWindowPos()10198af74909SZhong Yang void ScintillaWin::SetCandidateWindowPos() {
10208af74909SZhong Yang 	IMContext imc(MainHWND());
10218af74909SZhong Yang 	if (imc.hIMC) {
10228af74909SZhong Yang 		const Point pos = PointMainCaret();
10238af74909SZhong Yang 		const PRectangle rcClient = GetTextRectangle();
10248af74909SZhong Yang 		CANDIDATEFORM CandForm{};
10258af74909SZhong Yang 		CandForm.dwIndex = 0;
10268af74909SZhong Yang 		CandForm.dwStyle = CFS_EXCLUDE;
10278af74909SZhong Yang 		CandForm.ptCurrentPos.x = static_cast<int>(pos.x);
10288af74909SZhong Yang 		CandForm.ptCurrentPos.y = static_cast<int>(pos.y + std::max(4, vs.lineHeight/4));
10298af74909SZhong Yang 		// Exclude the area of the whole caret line
10308af74909SZhong Yang 		CandForm.rcArea.top = static_cast<int>(pos.y);
10318af74909SZhong Yang 		CandForm.rcArea.bottom = static_cast<int>(pos.y + vs.lineHeight);
10328af74909SZhong Yang 		CandForm.rcArea.left = static_cast<int>(rcClient.left);
10338af74909SZhong Yang 		CandForm.rcArea.right = static_cast<int>(rcClient.right);
10348af74909SZhong Yang 		::ImmSetCandidateWindow(imc.hIMC, &CandForm);
10358af74909SZhong Yang 	}
10368af74909SZhong Yang }
10378af74909SZhong Yang 
SelectionToHangul()10388af74909SZhong Yang void ScintillaWin::SelectionToHangul() {
10398af74909SZhong Yang 	// Convert every hanja to hangul within the main range.
10408af74909SZhong Yang 	const Sci::Position selStart = sel.RangeMain().Start().Position();
10418af74909SZhong Yang 	const Sci::Position documentStrLen = sel.RangeMain().Length();
10428af74909SZhong Yang 	const Sci::Position selEnd = selStart + documentStrLen;
10438af74909SZhong Yang 	const Sci::Position utf16Len = pdoc->CountUTF16(selStart, selEnd);
10448af74909SZhong Yang 
10458af74909SZhong Yang 	if (utf16Len > 0) {
10468af74909SZhong Yang 		std::string documentStr(documentStrLen, '\0');
10478af74909SZhong Yang 		pdoc->GetCharRange(&documentStr[0], selStart, documentStrLen);
10488af74909SZhong Yang 
10498af74909SZhong Yang 		std::wstring uniStr = StringDecode(documentStr, CodePageOfDocument());
10508af74909SZhong Yang 		const int converted = HanjaDict::GetHangulOfHanja(&uniStr[0]);
10518af74909SZhong Yang 		documentStr = StringEncode(uniStr, CodePageOfDocument());
10528af74909SZhong Yang 
10538af74909SZhong Yang 		if (converted > 0) {
10548af74909SZhong Yang 			pdoc->BeginUndoAction();
10558af74909SZhong Yang 			ClearSelection();
10568af74909SZhong Yang 			InsertPaste(&documentStr[0], documentStr.size());
10578af74909SZhong Yang 			pdoc->EndUndoAction();
10588af74909SZhong Yang 		}
10598af74909SZhong Yang 	}
10608af74909SZhong Yang }
10618af74909SZhong Yang 
EscapeHanja()10628af74909SZhong Yang void ScintillaWin::EscapeHanja() {
10638af74909SZhong Yang 	// The candidate box pops up to user to select a hanja.
10648af74909SZhong Yang 	// It comes into WM_IME_COMPOSITION with GCS_RESULTSTR.
10658af74909SZhong Yang 	// The existing hangul or hanja is replaced with it.
10668af74909SZhong Yang 	if (sel.Count() > 1) {
10678af74909SZhong Yang 		return; // Do not allow multi carets.
10688af74909SZhong Yang 	}
10698af74909SZhong Yang 	const Sci::Position currentPos = CurrentPosition();
10708af74909SZhong Yang 	const int oneCharLen = pdoc->LenChar(currentPos);
10718af74909SZhong Yang 
10728af74909SZhong Yang 	if (oneCharLen < 2) {
10738af74909SZhong Yang 		return; // No need to handle SBCS.
10748af74909SZhong Yang 	}
10758af74909SZhong Yang 
10768af74909SZhong Yang 	// ImmEscapeW() may overwrite uniChar[] with a null terminated string.
10778af74909SZhong Yang 	// So enlarge it enough to Maximum 4 as in UTF-8.
10788af74909SZhong Yang 	constexpr size_t safeLength = UTF8MaxBytes + 1;
10798af74909SZhong Yang 	std::string oneChar(safeLength, '\0');
10808af74909SZhong Yang 	pdoc->GetCharRange(&oneChar[0], currentPos, oneCharLen);
10818af74909SZhong Yang 
10828af74909SZhong Yang 	std::wstring uniChar = StringDecode(oneChar, CodePageOfDocument());
10838af74909SZhong Yang 
10848af74909SZhong Yang 	IMContext imc(MainHWND());
10858af74909SZhong Yang 	if (imc.hIMC) {
10868af74909SZhong Yang 		// Set the candidate box position since IME may show it.
10878af74909SZhong Yang 		SetCandidateWindowPos();
10888af74909SZhong Yang 		// IME_ESC_HANJA_MODE appears to receive the first character only.
10898af74909SZhong Yang 		if (::ImmEscapeW(GetKeyboardLayout(0), imc.hIMC, IME_ESC_HANJA_MODE, &uniChar[0])) {
10908af74909SZhong Yang 			SetSelection(currentPos, currentPos + oneCharLen);
10918af74909SZhong Yang 		}
10928af74909SZhong Yang 	}
10938af74909SZhong Yang }
10948af74909SZhong Yang 
ToggleHanja()10958af74909SZhong Yang void ScintillaWin::ToggleHanja() {
10968af74909SZhong Yang 	// If selection, convert every hanja to hangul within the main range.
10978af74909SZhong Yang 	// If no selection, commit to IME.
10988af74909SZhong Yang 	if (sel.Count() > 1) {
10998af74909SZhong Yang 		return; // Do not allow multi carets.
11008af74909SZhong Yang 	}
11018af74909SZhong Yang 
11028af74909SZhong Yang 	if (sel.Empty()) {
11038af74909SZhong Yang 		EscapeHanja();
11048af74909SZhong Yang 	} else {
11058af74909SZhong Yang 		SelectionToHangul();
11068af74909SZhong Yang 	}
11078af74909SZhong Yang }
11088af74909SZhong Yang 
11098af74909SZhong Yang namespace {
11108af74909SZhong Yang 
MapImeIndicators(std::vector<BYTE> inputStyle)11118af74909SZhong Yang std::vector<int> MapImeIndicators(std::vector<BYTE> inputStyle) {
11128af74909SZhong Yang 	std::vector<int> imeIndicator(inputStyle.size(), SC_INDICATOR_UNKNOWN);
11138af74909SZhong Yang 	for (size_t i = 0; i < inputStyle.size(); i++) {
11148af74909SZhong Yang 		switch (static_cast<int>(inputStyle.at(i))) {
11158af74909SZhong Yang 		case ATTR_INPUT:
11168af74909SZhong Yang 			imeIndicator[i] = SC_INDICATOR_INPUT;
11178af74909SZhong Yang 			break;
11188af74909SZhong Yang 		case ATTR_TARGET_NOTCONVERTED:
11198af74909SZhong Yang 		case ATTR_TARGET_CONVERTED:
11208af74909SZhong Yang 			imeIndicator[i] = SC_INDICATOR_TARGET;
11218af74909SZhong Yang 			break;
11228af74909SZhong Yang 		case ATTR_CONVERTED:
11238af74909SZhong Yang 			imeIndicator[i] = SC_INDICATOR_CONVERTED;
11248af74909SZhong Yang 			break;
11258af74909SZhong Yang 		default:
11268af74909SZhong Yang 			imeIndicator[i] = SC_INDICATOR_UNKNOWN;
11278af74909SZhong Yang 			break;
11288af74909SZhong Yang 		}
11298af74909SZhong Yang 	}
11308af74909SZhong Yang 	return imeIndicator;
11318af74909SZhong Yang }
11328af74909SZhong Yang 
11338af74909SZhong Yang }
11348af74909SZhong Yang 
AddWString(std::wstring_view wsv,CharacterSource charSource)11358af74909SZhong Yang void ScintillaWin::AddWString(std::wstring_view wsv, CharacterSource charSource) {
11368af74909SZhong Yang 	if (wsv.empty())
11378af74909SZhong Yang 		return;
11388af74909SZhong Yang 
11398af74909SZhong Yang 	const int codePage = CodePageOfDocument();
11408af74909SZhong Yang 	for (size_t i = 0; i < wsv.size(); ) {
11418af74909SZhong Yang 		const size_t ucWidth = UTF16CharLength(wsv[i]);
11428af74909SZhong Yang 		const std::string docChar = StringEncode(wsv.substr(i, ucWidth), codePage);
11438af74909SZhong Yang 
11448af74909SZhong Yang 		InsertCharacter(docChar, charSource);
11458af74909SZhong Yang 		i += ucWidth;
11468af74909SZhong Yang 	}
11478af74909SZhong Yang }
11488af74909SZhong Yang 
HandleCompositionInline(uptr_t,sptr_t lParam)11498af74909SZhong Yang sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) {
11508af74909SZhong Yang 	// Copy & paste by johnsonj with a lot of helps of Neil.
11518af74909SZhong Yang 	// Great thanks for my foreruners, jiniya and BLUEnLIVE.
11528af74909SZhong Yang 
11538af74909SZhong Yang 	IMContext imc(MainHWND());
11548af74909SZhong Yang 	if (!imc.hIMC)
11558af74909SZhong Yang 		return 0;
11568af74909SZhong Yang 	if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
11578af74909SZhong Yang 		::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
11588af74909SZhong Yang 		return 0;
11598af74909SZhong Yang 	}
11608af74909SZhong Yang 
11618af74909SZhong Yang 	bool initialCompose = false;
11628af74909SZhong Yang 	if (pdoc->TentativeActive()) {
11638af74909SZhong Yang 		pdoc->TentativeUndo();
11648af74909SZhong Yang 	} else {
11658af74909SZhong Yang 		// No tentative undo means start of this composition so
11668af74909SZhong Yang 		// fill in any virtual spaces.
11678af74909SZhong Yang 		initialCompose = true;
11688af74909SZhong Yang 	}
11698af74909SZhong Yang 
11708af74909SZhong Yang 	view.imeCaretBlockOverride = false;
11718af74909SZhong Yang 
11728af74909SZhong Yang 	if (lParam & GCS_RESULTSTR) {
11738af74909SZhong Yang 		AddWString(imc.GetCompositionString(GCS_RESULTSTR), CharacterSource::imeResult);
11748af74909SZhong Yang 	}
11758af74909SZhong Yang 
11768af74909SZhong Yang 	if (lParam & GCS_COMPSTR) {
11778af74909SZhong Yang 		const std::wstring wcs = imc.GetCompositionString(GCS_COMPSTR);
11788af74909SZhong Yang 		if (wcs.empty()) {
11798af74909SZhong Yang 			ShowCaretAtCurrentPosition();
11808af74909SZhong Yang 			return 0;
11818af74909SZhong Yang 		}
11828af74909SZhong Yang 
11838af74909SZhong Yang 		if (initialCompose) {
11848af74909SZhong Yang 			ClearBeforeTentativeStart();
11858af74909SZhong Yang 		}
11868af74909SZhong Yang 
11878af74909SZhong Yang 		// Set candidate window left aligned to beginning of preedit string.
11888af74909SZhong Yang 		SetCandidateWindowPos();
11898af74909SZhong Yang 		pdoc->TentativeStart(); // TentativeActive from now on.
11908af74909SZhong Yang 
11918af74909SZhong Yang 		std::vector<int> imeIndicator = MapImeIndicators(imc.GetImeAttributes());
11928af74909SZhong Yang 
11938af74909SZhong Yang 		const int codePage = CodePageOfDocument();
11948af74909SZhong Yang 		const std::wstring_view wsv = wcs;
11958af74909SZhong Yang 		for (size_t i = 0; i < wsv.size(); ) {
11968af74909SZhong Yang 			const size_t ucWidth = UTF16CharLength(wsv[i]);
11978af74909SZhong Yang 			const std::string docChar = StringEncode(wsv.substr(i, ucWidth), codePage);
11988af74909SZhong Yang 
11998af74909SZhong Yang 			InsertCharacter(docChar, CharacterSource::tentativeInput);
12008af74909SZhong Yang 
12018af74909SZhong Yang 			DrawImeIndicator(imeIndicator[i], docChar.size());
12028af74909SZhong Yang 			i += ucWidth;
12038af74909SZhong Yang 		}
12048af74909SZhong Yang 
12058af74909SZhong Yang 		// Japanese IME after pressing Tab replaces input string with first candidate item (target string);
12068af74909SZhong Yang 		// when selecting other candidate item, previous item will be replaced with current one.
12078af74909SZhong Yang 		// After candidate item been added, it's looks like been full selected, it's better to keep caret
12088af74909SZhong Yang 		// at end of "selection" (end of input) instead of jump to beginning of input ("selection").
12098af74909SZhong Yang 		const bool onlyTarget = std::all_of(imeIndicator.begin(), imeIndicator.end(), [](int i) noexcept {
12108af74909SZhong Yang 			return i == SC_INDICATOR_TARGET;
12118af74909SZhong Yang 		});
12128af74909SZhong Yang 		if (!onlyTarget) {
12138af74909SZhong Yang 			// CS_NOMOVECARET: keep caret at beginning of composition string which already moved in InsertCharacter().
12148af74909SZhong Yang 			// GCS_CURSORPOS: current caret position is provided by IME.
12158af74909SZhong Yang 			Sci::Position imeEndToImeCaretU16 = -static_cast<Sci::Position>(wcs.size());
12168af74909SZhong Yang 			if (!(lParam & CS_NOMOVECARET) && (lParam & GCS_CURSORPOS)) {
12178af74909SZhong Yang 				imeEndToImeCaretU16 += imc.GetImeCaretPos();
12188af74909SZhong Yang 			}
12198af74909SZhong Yang 			if (imeEndToImeCaretU16 != 0) {
12208af74909SZhong Yang 				// Move back IME caret from current last position to imeCaretPos.
12218af74909SZhong Yang 				const Sci::Position currentPos = CurrentPosition();
12228af74909SZhong Yang 				const Sci::Position imeCaretPosDoc = pdoc->GetRelativePositionUTF16(currentPos, imeEndToImeCaretU16);
12238af74909SZhong Yang 
12248af74909SZhong Yang 				MoveImeCarets(-currentPos + imeCaretPosDoc);
12258af74909SZhong Yang 
12268af74909SZhong Yang 				if (std::find(imeIndicator.begin(), imeIndicator.end(), SC_INDICATOR_TARGET) != imeIndicator.end()) {
12278af74909SZhong Yang 					// set candidate window left aligned to beginning of target string.
12288af74909SZhong Yang 					SetCandidateWindowPos();
12298af74909SZhong Yang 				}
12308af74909SZhong Yang 			}
12318af74909SZhong Yang 		}
12328af74909SZhong Yang 
12338af74909SZhong Yang 		if (KoreanIME()) {
12348af74909SZhong Yang 			view.imeCaretBlockOverride = true;
12358af74909SZhong Yang 		}
12368af74909SZhong Yang 	}
12378af74909SZhong Yang 	EnsureCaretVisible();
12388af74909SZhong Yang 	ShowCaretAtCurrentPosition();
12398af74909SZhong Yang 	return 0;
12408af74909SZhong Yang }
12418af74909SZhong Yang 
12428af74909SZhong Yang namespace {
12438af74909SZhong Yang 
12448af74909SZhong Yang // Translate message IDs from WM_* and EM_* to SCI_* so can partly emulate Windows Edit control
SciMessageFromEM(unsigned int iMessage)12458af74909SZhong Yang unsigned int SciMessageFromEM(unsigned int iMessage) noexcept {
12468af74909SZhong Yang 	switch (iMessage) {
12478af74909SZhong Yang 	case EM_CANPASTE: return SCI_CANPASTE;
12488af74909SZhong Yang 	case EM_CANUNDO: return SCI_CANUNDO;
12498af74909SZhong Yang 	case EM_EMPTYUNDOBUFFER: return SCI_EMPTYUNDOBUFFER;
12508af74909SZhong Yang 	case EM_FINDTEXTEX: return SCI_FINDTEXT;
12518af74909SZhong Yang 	case EM_FORMATRANGE: return SCI_FORMATRANGE;
12528af74909SZhong Yang 	case EM_GETFIRSTVISIBLELINE: return SCI_GETFIRSTVISIBLELINE;
12538af74909SZhong Yang 	case EM_GETLINECOUNT: return SCI_GETLINECOUNT;
12548af74909SZhong Yang 	case EM_GETSELTEXT: return SCI_GETSELTEXT;
12558af74909SZhong Yang 	case EM_GETTEXTRANGE: return SCI_GETTEXTRANGE;
12568af74909SZhong Yang 	case EM_HIDESELECTION: return SCI_HIDESELECTION;
12578af74909SZhong Yang 	case EM_LINEINDEX: return SCI_POSITIONFROMLINE;
12588af74909SZhong Yang 	case EM_LINESCROLL: return SCI_LINESCROLL;
12598af74909SZhong Yang 	case EM_REPLACESEL: return SCI_REPLACESEL;
12608af74909SZhong Yang 	case EM_SCROLLCARET: return SCI_SCROLLCARET;
12618af74909SZhong Yang 	case EM_SETREADONLY: return SCI_SETREADONLY;
12628af74909SZhong Yang 	case WM_CLEAR: return SCI_CLEAR;
12638af74909SZhong Yang 	case WM_COPY: return SCI_COPY;
12648af74909SZhong Yang 	case WM_CUT: return SCI_CUT;
12658af74909SZhong Yang 	case WM_SETTEXT: return SCI_SETTEXT;
12668af74909SZhong Yang 	case WM_PASTE: return SCI_PASTE;
12678af74909SZhong Yang 	case WM_UNDO: return SCI_UNDO;
12688af74909SZhong Yang 	}
12698af74909SZhong Yang 	return iMessage;
12708af74909SZhong Yang }
12718af74909SZhong Yang 
12728af74909SZhong Yang }
12738af74909SZhong Yang 
12748af74909SZhong Yang namespace Scintilla {
12758af74909SZhong Yang 
CodePageFromCharSet(DWORD characterSet,UINT documentCodePage)12768af74909SZhong Yang UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) noexcept {
12778af74909SZhong Yang 	if (documentCodePage == SC_CP_UTF8) {
12788af74909SZhong Yang 		return SC_CP_UTF8;
12798af74909SZhong Yang 	}
12808af74909SZhong Yang 	switch (characterSet) {
12818af74909SZhong Yang 	case SC_CHARSET_ANSI: return 1252;
12828af74909SZhong Yang 	case SC_CHARSET_DEFAULT: return documentCodePage ? documentCodePage : 1252;
12838af74909SZhong Yang 	case SC_CHARSET_BALTIC: return 1257;
12848af74909SZhong Yang 	case SC_CHARSET_CHINESEBIG5: return 950;
12858af74909SZhong Yang 	case SC_CHARSET_EASTEUROPE: return 1250;
12868af74909SZhong Yang 	case SC_CHARSET_GB2312: return 936;
12878af74909SZhong Yang 	case SC_CHARSET_GREEK: return 1253;
12888af74909SZhong Yang 	case SC_CHARSET_HANGUL: return 949;
12898af74909SZhong Yang 	case SC_CHARSET_MAC: return 10000;
12908af74909SZhong Yang 	case SC_CHARSET_OEM: return 437;
12918af74909SZhong Yang 	case SC_CHARSET_RUSSIAN: return 1251;
12928af74909SZhong Yang 	case SC_CHARSET_SHIFTJIS: return 932;
12938af74909SZhong Yang 	case SC_CHARSET_TURKISH: return 1254;
12948af74909SZhong Yang 	case SC_CHARSET_JOHAB: return 1361;
12958af74909SZhong Yang 	case SC_CHARSET_HEBREW: return 1255;
12968af74909SZhong Yang 	case SC_CHARSET_ARABIC: return 1256;
12978af74909SZhong Yang 	case SC_CHARSET_VIETNAMESE: return 1258;
12988af74909SZhong Yang 	case SC_CHARSET_THAI: return 874;
12998af74909SZhong Yang 	case SC_CHARSET_8859_15: return 28605;
13008af74909SZhong Yang 	// Not supported
13018af74909SZhong Yang 	case SC_CHARSET_CYRILLIC: return documentCodePage;
13028af74909SZhong Yang 	case SC_CHARSET_SYMBOL: return documentCodePage;
13038af74909SZhong Yang 	}
13048af74909SZhong Yang 	return documentCodePage;
13058af74909SZhong Yang }
13068af74909SZhong Yang 
13078af74909SZhong Yang }
13088af74909SZhong Yang 
CodePageOfDocument() const13098af74909SZhong Yang UINT ScintillaWin::CodePageOfDocument() const noexcept {
13108af74909SZhong Yang 	return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage);
13118af74909SZhong Yang }
13128af74909SZhong Yang 
EncodeWString(std::wstring_view wsv)13138af74909SZhong Yang std::string ScintillaWin::EncodeWString(std::wstring_view wsv) {
13148af74909SZhong Yang 	if (IsUnicodeMode()) {
13158af74909SZhong Yang 		const size_t len = UTF8Length(wsv);
13168af74909SZhong Yang 		std::string putf(len, 0);
13178af74909SZhong Yang 		UTF8FromUTF16(wsv, putf.data(), len);
13188af74909SZhong Yang 		return putf;
13198af74909SZhong Yang 	} else {
13208af74909SZhong Yang 		// Not in Unicode mode so convert from Unicode to current Scintilla code page
13218af74909SZhong Yang 		return StringEncode(wsv, CodePageOfDocument());
13228af74909SZhong Yang 	}
13238af74909SZhong Yang }
13248af74909SZhong Yang 
GetTextLength()13258af74909SZhong Yang sptr_t ScintillaWin::GetTextLength() {
13268af74909SZhong Yang 	return pdoc->CountUTF16(0, pdoc->Length());
13278af74909SZhong Yang }
13288af74909SZhong Yang 
GetText(uptr_t wParam,sptr_t lParam)13298af74909SZhong Yang sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) {
13308af74909SZhong Yang 	if (lParam == 0) {
13318af74909SZhong Yang 		return pdoc->CountUTF16(0, pdoc->Length());
13328af74909SZhong Yang 	}
13338af74909SZhong Yang 	if (wParam == 0) {
13348af74909SZhong Yang 		return 0;
13358af74909SZhong Yang 	}
13368af74909SZhong Yang 	wchar_t *ptr = static_cast<wchar_t *>(PtrFromSPtr(lParam));
13378af74909SZhong Yang 	if (pdoc->Length() == 0) {
13388af74909SZhong Yang 		*ptr = L'\0';
13398af74909SZhong Yang 		return 0;
13408af74909SZhong Yang 	}
13418af74909SZhong Yang 	const Sci::Position lengthWanted = wParam - 1;
13428af74909SZhong Yang 	Sci::Position sizeRequestedRange = pdoc->GetRelativePositionUTF16(0, lengthWanted);
13438af74909SZhong Yang 	if (sizeRequestedRange < 0) {
13448af74909SZhong Yang 		// Requested more text than there is in the document.
13458af74909SZhong Yang 		sizeRequestedRange = pdoc->Length();
13468af74909SZhong Yang 	}
13478af74909SZhong Yang 	std::string docBytes(sizeRequestedRange, '\0');
13488af74909SZhong Yang 	pdoc->GetCharRange(&docBytes[0], 0, sizeRequestedRange);
13498af74909SZhong Yang 	if (IsUnicodeMode()) {
13508af74909SZhong Yang 		const size_t uLen = UTF16FromUTF8(docBytes, ptr, lengthWanted);
13518af74909SZhong Yang 		ptr[uLen] = L'\0';
13528af74909SZhong Yang 		return uLen;
13538af74909SZhong Yang 	} else {
13548af74909SZhong Yang 		// Not Unicode mode
13558af74909SZhong Yang 		// Convert to Unicode using the current Scintilla code page
13568af74909SZhong Yang 		const UINT cpSrc = CodePageOfDocument();
13578af74909SZhong Yang 		int lengthUTF16 = WideCharLenFromMultiByte(cpSrc, docBytes);
13588af74909SZhong Yang 		if (lengthUTF16 > lengthWanted)
13598af74909SZhong Yang 			lengthUTF16 = static_cast<int>(lengthWanted);
13608af74909SZhong Yang 		WideCharFromMultiByte(cpSrc, docBytes, ptr, lengthUTF16);
13618af74909SZhong Yang 		ptr[lengthUTF16] = L'\0';
13628af74909SZhong Yang 		return lengthUTF16;
13638af74909SZhong Yang 	}
13648af74909SZhong Yang }
13658af74909SZhong Yang 
ContextCursor(Point pt)13668af74909SZhong Yang Window::Cursor ScintillaWin::ContextCursor(Point pt) {
13678af74909SZhong Yang 	if (inDragDrop == ddDragging) {
13688af74909SZhong Yang 		return Window::cursorUp;
13698af74909SZhong Yang 	} else {
13708af74909SZhong Yang 		// Display regular (drag) cursor over selection
13718af74909SZhong Yang 		if (PointInSelMargin(pt)) {
13728af74909SZhong Yang 			return GetMarginCursor(pt);
13738af74909SZhong Yang 		} else if (!SelectionEmpty() && PointInSelection(pt)) {
13748af74909SZhong Yang 			return Window::cursorArrow;
13758af74909SZhong Yang 		} else if (PointIsHotspot(pt)) {
13768af74909SZhong Yang 			return Window::cursorHand;
13778af74909SZhong Yang 		} else if (hoverIndicatorPos != Sci::invalidPosition) {
13788af74909SZhong Yang 			const Sci::Position pos = PositionFromLocation(pt, true, true);
13798af74909SZhong Yang 			if (pos != Sci::invalidPosition) {
13808af74909SZhong Yang 				return Window::cursorHand;
13818af74909SZhong Yang 			}
13828af74909SZhong Yang 		}
13838af74909SZhong Yang 	}
13848af74909SZhong Yang 	return Window::cursorText;
13858af74909SZhong Yang }
13868af74909SZhong Yang 
ShowContextMenu(unsigned int iMessage,uptr_t wParam,sptr_t lParam)13878af74909SZhong Yang sptr_t ScintillaWin::ShowContextMenu(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
13888af74909SZhong Yang 	Point pt = PointFromLParam(lParam);
13898af74909SZhong Yang 	POINT rpt = POINTFromPoint(pt);
13908af74909SZhong Yang 	::ScreenToClient(MainHWND(), &rpt);
13918af74909SZhong Yang 	const Point ptClient = PointFromPOINT(rpt);
13928af74909SZhong Yang 	if (ShouldDisplayPopup(ptClient)) {
13938af74909SZhong Yang 		if ((pt.x == -1) && (pt.y == -1)) {
13948af74909SZhong Yang 			// Caused by keyboard so display menu near caret
13958af74909SZhong Yang 			pt = PointMainCaret();
13968af74909SZhong Yang 			POINT spt = POINTFromPoint(pt);
13978af74909SZhong Yang 			::ClientToScreen(MainHWND(), &spt);
13988af74909SZhong Yang 			pt = PointFromPOINT(spt);
13998af74909SZhong Yang 		}
14008af74909SZhong Yang 		ContextMenu(pt);
14018af74909SZhong Yang 		return 0;
14028af74909SZhong Yang 	}
14038af74909SZhong Yang 	return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
14048af74909SZhong Yang }
14058af74909SZhong Yang 
SizeWindow()14068af74909SZhong Yang void ScintillaWin::SizeWindow() {
14078af74909SZhong Yang #if defined(USE_D2D)
14088af74909SZhong Yang 	if (paintState == notPainting) {
14098af74909SZhong Yang 		DropRenderTarget();
14108af74909SZhong Yang 	} else {
14118af74909SZhong Yang 		renderTargetValid = false;
14128af74909SZhong Yang 	}
14138af74909SZhong Yang #endif
14148af74909SZhong Yang 	//Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam));
14158af74909SZhong Yang 	ChangeSize();
14168af74909SZhong Yang }
14178af74909SZhong Yang 
MouseMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)14188af74909SZhong Yang sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
14198af74909SZhong Yang 	switch (iMessage) {
14208af74909SZhong Yang 	case WM_LBUTTONDOWN: {
14218af74909SZhong Yang 			// For IME, set the composition string as the result string.
14228af74909SZhong Yang 			IMContext imc(MainHWND());
14238af74909SZhong Yang 			if (imc.hIMC) {
14248af74909SZhong Yang 				::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
14258af74909SZhong Yang 			}
14268af74909SZhong Yang 			//
14278af74909SZhong Yang 			//Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam,
14288af74909SZhong Yang 			//	KeyboardIsKeyDown(VK_SHIFT),
14298af74909SZhong Yang 			//	KeyboardIsKeyDown(VK_CONTROL),
14308af74909SZhong Yang 			//	KeyboardIsKeyDown(VK_MENU));
14318af74909SZhong Yang 			::SetFocus(MainHWND());
14328af74909SZhong Yang 			ButtonDownWithModifiers(PointFromLParam(lParam), ::GetMessageTime(),
14338af74909SZhong Yang 						MouseModifiers(wParam));
14348af74909SZhong Yang 		}
14358af74909SZhong Yang 		break;
14368af74909SZhong Yang 
14378af74909SZhong Yang 	case WM_LBUTTONUP:
14388af74909SZhong Yang 		ButtonUpWithModifiers(PointFromLParam(lParam),
14398af74909SZhong Yang 				      ::GetMessageTime(), MouseModifiers(wParam));
14408af74909SZhong Yang 		break;
14418af74909SZhong Yang 
14428af74909SZhong Yang 	case WM_RBUTTONDOWN: {
14438af74909SZhong Yang 			::SetFocus(MainHWND());
14448af74909SZhong Yang 			const Point pt = PointFromLParam(lParam);
14458af74909SZhong Yang 			if (!PointInSelection(pt)) {
14468af74909SZhong Yang 				CancelModes();
14478af74909SZhong Yang 				SetEmptySelection(PositionFromLocation(PointFromLParam(lParam)));
14488af74909SZhong Yang 			}
14498af74909SZhong Yang 
14508af74909SZhong Yang 			RightButtonDownWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam));
14518af74909SZhong Yang 		}
14528af74909SZhong Yang 		break;
14538af74909SZhong Yang 
14548af74909SZhong Yang 	case WM_MOUSEMOVE: {
14558af74909SZhong Yang 			const Point pt = PointFromLParam(lParam);
14568af74909SZhong Yang 
14578af74909SZhong Yang 			// Windows might send WM_MOUSEMOVE even though the mouse has not been moved:
14588af74909SZhong Yang 			// http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx
14598af74909SZhong Yang 			if (ptMouseLast != pt) {
14608af74909SZhong Yang 				SetTrackMouseLeaveEvent(true);
14618af74909SZhong Yang 				ButtonMoveWithModifiers(pt, ::GetMessageTime(), MouseModifiers(wParam));
14628af74909SZhong Yang 			}
14638af74909SZhong Yang 		}
14648af74909SZhong Yang 		break;
14658af74909SZhong Yang 
14668af74909SZhong Yang 	case WM_MOUSELEAVE:
14678af74909SZhong Yang 		SetTrackMouseLeaveEvent(false);
14688af74909SZhong Yang 		MouseLeave();
14698af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
14708af74909SZhong Yang 
14718af74909SZhong Yang 	case WM_MOUSEWHEEL:
14728af74909SZhong Yang 		if (!mouseWheelCaptures) {
14738af74909SZhong Yang 			// if the mouse wheel is not captured, test if the mouse
14748af74909SZhong Yang 			// pointer is over the editor window and if not, don't
14758af74909SZhong Yang 			// handle the message but pass it on.
14768af74909SZhong Yang 			RECT rc;
14778af74909SZhong Yang 			GetWindowRect(MainHWND(), &rc);
14788af74909SZhong Yang 			const POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
14798af74909SZhong Yang 			if (!PtInRect(&rc, pt))
14808af74909SZhong Yang 				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
14818af74909SZhong Yang 		}
14828af74909SZhong Yang 		// if autocomplete list active then send mousewheel message to it
14838af74909SZhong Yang 		if (ac.Active()) {
14848af74909SZhong Yang 			HWND hWnd = HwndFromWindow(*(ac.lb));
14858af74909SZhong Yang 			::SendMessage(hWnd, iMessage, wParam, lParam);
14868af74909SZhong Yang 			break;
14878af74909SZhong Yang 		}
14888af74909SZhong Yang 
14898af74909SZhong Yang 		// Don't handle datazoom.
14908af74909SZhong Yang 		// (A good idea for datazoom would be to "fold" or "unfold" details.
14918af74909SZhong Yang 		// i.e. if datazoomed out only class structures are visible, when datazooming in the control
14928af74909SZhong Yang 		// structures appear, then eventually the individual statements...)
14938af74909SZhong Yang 		if (wParam & MK_SHIFT) {
14948af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
14958af74909SZhong Yang 		}
14968af74909SZhong Yang 		// Either SCROLL or ZOOM. We handle the wheel steppings calculation
14978af74909SZhong Yang 		wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
14988af74909SZhong Yang 		if (std::abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) {
14998af74909SZhong Yang 			Sci::Line linesToScroll = linesPerScroll;
15008af74909SZhong Yang 			if (linesPerScroll == WHEEL_PAGESCROLL)
15018af74909SZhong Yang 				linesToScroll = LinesOnScreen() - 1;
15028af74909SZhong Yang 			if (linesToScroll == 0) {
15038af74909SZhong Yang 				linesToScroll = 1;
15048af74909SZhong Yang 			}
15058af74909SZhong Yang 			linesToScroll *= (wheelDelta / WHEEL_DELTA);
15068af74909SZhong Yang 			if (wheelDelta >= 0)
15078af74909SZhong Yang 				wheelDelta = wheelDelta % WHEEL_DELTA;
15088af74909SZhong Yang 			else
15098af74909SZhong Yang 				wheelDelta = -(-wheelDelta % WHEEL_DELTA);
15108af74909SZhong Yang 
15118af74909SZhong Yang 			if (wParam & MK_CONTROL) {
15128af74909SZhong Yang 				// Zoom! We play with the font sizes in the styles.
15138af74909SZhong Yang 				// Number of steps/line is ignored, we just care if sizing up or down
15148af74909SZhong Yang 				if (linesToScroll < 0) {
15158af74909SZhong Yang 					KeyCommand(SCI_ZOOMIN);
15168af74909SZhong Yang 				} else {
15178af74909SZhong Yang 					KeyCommand(SCI_ZOOMOUT);
15188af74909SZhong Yang 				}
15198af74909SZhong Yang 			} else {
15208af74909SZhong Yang 				// Scroll
15218af74909SZhong Yang 				ScrollTo(topLine + linesToScroll);
15228af74909SZhong Yang 			}
15238af74909SZhong Yang 		}
15248af74909SZhong Yang 		return 0;
15258af74909SZhong Yang 	}
15268af74909SZhong Yang 	return 0;
15278af74909SZhong Yang }
15288af74909SZhong Yang 
KeyMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)15298af74909SZhong Yang sptr_t ScintillaWin::KeyMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
15308af74909SZhong Yang 	switch (iMessage) {
15318af74909SZhong Yang 
15328af74909SZhong Yang 	case WM_SYSKEYDOWN:
15338af74909SZhong Yang 	case WM_KEYDOWN: {
15348af74909SZhong Yang 			// Platform::DebugPrintf("Keydown %c %c%c%c%c %x %x\n",
15358af74909SZhong Yang 			// iMessage == WM_KEYDOWN ? 'K' : 'S',
15368af74909SZhong Yang 			// (lParam & (1 << 24)) ? 'E' : '-',
15378af74909SZhong Yang 			// KeyboardIsKeyDown(VK_SHIFT) ? 'S' : '-',
15388af74909SZhong Yang 			// KeyboardIsKeyDown(VK_CONTROL) ? 'C' : '-',
15398af74909SZhong Yang 			// KeyboardIsKeyDown(VK_MENU) ? 'A' : '-',
15408af74909SZhong Yang 			// wParam, lParam);
15418af74909SZhong Yang 			lastKeyDownConsumed = false;
15428af74909SZhong Yang 			const bool altDown = KeyboardIsKeyDown(VK_MENU);
15438af74909SZhong Yang 			if (altDown && KeyboardIsNumericKeypadFunction(wParam, lParam)) {
15448af74909SZhong Yang 				// Don't interpret these as they may be characters entered by number.
15458af74909SZhong Yang 				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
15468af74909SZhong Yang 			}
15478af74909SZhong Yang 			const int ret = KeyDownWithModifiers(KeyTranslate(static_cast<int>(wParam)),
15488af74909SZhong Yang 							     ModifierFlags(KeyboardIsKeyDown(VK_SHIFT),
15498af74909SZhong Yang 									     KeyboardIsKeyDown(VK_CONTROL),
15508af74909SZhong Yang 									     altDown),
15518af74909SZhong Yang 							     &lastKeyDownConsumed);
15528af74909SZhong Yang 			if (!ret && !lastKeyDownConsumed) {
15538af74909SZhong Yang 				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
15548af74909SZhong Yang 			}
15558af74909SZhong Yang 			break;
15568af74909SZhong Yang 		}
15578af74909SZhong Yang 
15588af74909SZhong Yang 	case WM_KEYUP:
15598af74909SZhong Yang 		//Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam);
15608af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
15618af74909SZhong Yang 
15628af74909SZhong Yang 	case WM_CHAR:
15638af74909SZhong Yang 		if (((wParam >= 128) || !iscntrl(static_cast<int>(wParam))) || !lastKeyDownConsumed) {
15648af74909SZhong Yang 			wchar_t wcs[3] = { static_cast<wchar_t>(wParam), 0 };
15658af74909SZhong Yang 			unsigned int wclen = 1;
15668af74909SZhong Yang 			if (IS_HIGH_SURROGATE(wcs[0])) {
15678af74909SZhong Yang 				// If this is a high surrogate character, we need a second one
15688af74909SZhong Yang 				lastHighSurrogateChar = wcs[0];
15698af74909SZhong Yang 				return 0;
15708af74909SZhong Yang 			} else if (IS_LOW_SURROGATE(wcs[0])) {
15718af74909SZhong Yang 				wcs[1] = wcs[0];
15728af74909SZhong Yang 				wcs[0] = lastHighSurrogateChar;
15738af74909SZhong Yang 				lastHighSurrogateChar = 0;
15748af74909SZhong Yang 				wclen = 2;
15758af74909SZhong Yang 			}
15768af74909SZhong Yang 			AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput);
15778af74909SZhong Yang 		}
15788af74909SZhong Yang 		return 0;
15798af74909SZhong Yang 
15808af74909SZhong Yang 	case WM_UNICHAR:
15818af74909SZhong Yang 		if (wParam == UNICODE_NOCHAR) {
15828af74909SZhong Yang 			return TRUE;
15838af74909SZhong Yang 		} else if (lastKeyDownConsumed) {
15848af74909SZhong Yang 			return 1;
15858af74909SZhong Yang 		} else {
15868af74909SZhong Yang 			wchar_t wcs[3] = { 0 };
15878af74909SZhong Yang 			const size_t wclen = UTF16FromUTF32Character(static_cast<unsigned int>(wParam), wcs);
15888af74909SZhong Yang 			AddWString(std::wstring_view(wcs, wclen), CharacterSource::directInput);
15898af74909SZhong Yang 			return FALSE;
15908af74909SZhong Yang 		}
15918af74909SZhong Yang 	}
15928af74909SZhong Yang 
15938af74909SZhong Yang 	return 0;
15948af74909SZhong Yang }
15958af74909SZhong Yang 
FocusMessage(unsigned int iMessage,uptr_t wParam,sptr_t)15968af74909SZhong Yang sptr_t ScintillaWin::FocusMessage(unsigned int iMessage, uptr_t wParam, sptr_t) {
15978af74909SZhong Yang 	switch (iMessage) {
15988af74909SZhong Yang 	case WM_KILLFOCUS: {
15998af74909SZhong Yang 		HWND wOther = reinterpret_cast<HWND>(wParam);
16008af74909SZhong Yang 		HWND wThis = MainHWND();
16018af74909SZhong Yang 		const HWND wCT = HwndFromWindow(ct.wCallTip);
16028af74909SZhong Yang 		if (!wParam ||
16038af74909SZhong Yang 			!(::IsChild(wThis, wOther) || (wOther == wCT))) {
16048af74909SZhong Yang 			SetFocusState(false);
16058af74909SZhong Yang 			DestroySystemCaret();
16068af74909SZhong Yang 		}
16078af74909SZhong Yang 		// Explicitly complete any IME composition
16088af74909SZhong Yang 		IMContext imc(MainHWND());
16098af74909SZhong Yang 		if (imc.hIMC) {
16108af74909SZhong Yang 			::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
16118af74909SZhong Yang 		}
16128af74909SZhong Yang 		break;
16138af74909SZhong Yang 	}
16148af74909SZhong Yang 
16158af74909SZhong Yang 	case WM_SETFOCUS:
16168af74909SZhong Yang 		SetFocusState(true);
16178af74909SZhong Yang 		DestroySystemCaret();
16188af74909SZhong Yang 		CreateSystemCaret();
16198af74909SZhong Yang 		break;
16208af74909SZhong Yang 	}
16218af74909SZhong Yang 	return 0;
16228af74909SZhong Yang }
16238af74909SZhong Yang 
IMEMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)16248af74909SZhong Yang sptr_t ScintillaWin::IMEMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
16258af74909SZhong Yang 	switch (iMessage) {
16268af74909SZhong Yang 
16278af74909SZhong Yang 	case WM_INPUTLANGCHANGE:
16288af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16298af74909SZhong Yang 
16308af74909SZhong Yang 	case WM_INPUTLANGCHANGEREQUEST:
16318af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16328af74909SZhong Yang 
16338af74909SZhong Yang 	case WM_IME_KEYDOWN: {
16348af74909SZhong Yang 			if (wParam == VK_HANJA) {
16358af74909SZhong Yang 				ToggleHanja();
16368af74909SZhong Yang 			}
16378af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16388af74909SZhong Yang 		}
16398af74909SZhong Yang 
16408af74909SZhong Yang 	case WM_IME_REQUEST: {
16418af74909SZhong Yang 			if (wParam == IMR_RECONVERTSTRING) {
16428af74909SZhong Yang 				return ImeOnReconvert(lParam);
16438af74909SZhong Yang 			}
16448af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16458af74909SZhong Yang 		}
16468af74909SZhong Yang 
16478af74909SZhong Yang 	case WM_IME_STARTCOMPOSITION:
16488af74909SZhong Yang 		if (KoreanIME() || imeInteraction == imeInline) {
16498af74909SZhong Yang 			return 0;
16508af74909SZhong Yang 		} else {
16518af74909SZhong Yang 			ImeStartComposition();
16528af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16538af74909SZhong Yang 		}
16548af74909SZhong Yang 
16558af74909SZhong Yang 	case WM_IME_ENDCOMPOSITION:
16568af74909SZhong Yang 		ImeEndComposition();
16578af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16588af74909SZhong Yang 
16598af74909SZhong Yang 	case WM_IME_COMPOSITION:
16608af74909SZhong Yang 		if (KoreanIME() || imeInteraction == imeInline) {
16618af74909SZhong Yang 			return HandleCompositionInline(wParam, lParam);
16628af74909SZhong Yang 		} else {
16638af74909SZhong Yang 			return HandleCompositionWindowed(wParam, lParam);
16648af74909SZhong Yang 		}
16658af74909SZhong Yang 
16668af74909SZhong Yang 	case WM_IME_SETCONTEXT:
16678af74909SZhong Yang 		if (KoreanIME() || imeInteraction == imeInline) {
16688af74909SZhong Yang 			if (wParam) {
16698af74909SZhong Yang 				LPARAM NoImeWin = lParam;
16708af74909SZhong Yang 				NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW);
16718af74909SZhong Yang 				return ::DefWindowProc(MainHWND(), iMessage, wParam, NoImeWin);
16728af74909SZhong Yang 			}
16738af74909SZhong Yang 		}
16748af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16758af74909SZhong Yang 
16768af74909SZhong Yang 	case WM_IME_NOTIFY:
16778af74909SZhong Yang 		return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
16788af74909SZhong Yang 
16798af74909SZhong Yang 	}
16808af74909SZhong Yang 	return 0;
16818af74909SZhong Yang }
16828af74909SZhong Yang 
EditMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)16838af74909SZhong Yang sptr_t ScintillaWin::EditMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
16848af74909SZhong Yang 	switch (iMessage) {
16858af74909SZhong Yang 
16868af74909SZhong Yang 	case EM_LINEFROMCHAR:
16878af74909SZhong Yang 		if (static_cast<Sci::Position>(wParam) < 0) {
16888af74909SZhong Yang 			wParam = SelectionStart().Position();
16898af74909SZhong Yang 		}
16908af74909SZhong Yang 		return pdoc->LineFromPosition(wParam);
16918af74909SZhong Yang 
16928af74909SZhong Yang 	case EM_EXLINEFROMCHAR:
16938af74909SZhong Yang 		return pdoc->LineFromPosition(lParam);
16948af74909SZhong Yang 
16958af74909SZhong Yang 	case EM_GETSEL:
16968af74909SZhong Yang 		if (wParam) {
16978af74909SZhong Yang 			*reinterpret_cast<DWORD *>(wParam) = static_cast<DWORD>(SelectionStart().Position());
16988af74909SZhong Yang 		}
16998af74909SZhong Yang 		if (lParam) {
17008af74909SZhong Yang 			*reinterpret_cast<DWORD *>(lParam) = static_cast<DWORD>(SelectionEnd().Position());
17018af74909SZhong Yang 		}
17028af74909SZhong Yang 		return MAKELRESULT(SelectionStart().Position(), SelectionEnd().Position());
17038af74909SZhong Yang 
17048af74909SZhong Yang 	case EM_EXGETSEL: {
17058af74909SZhong Yang 			if (lParam == 0) {
17068af74909SZhong Yang 				return 0;
17078af74909SZhong Yang 			}
17088af74909SZhong Yang 			CHARRANGE *pCR = reinterpret_cast<CHARRANGE *>(lParam);
17098af74909SZhong Yang 			pCR->cpMin = static_cast<LONG>(SelectionStart().Position());
17108af74909SZhong Yang 			pCR->cpMax = static_cast<LONG>(SelectionEnd().Position());
17118af74909SZhong Yang 		}
17128af74909SZhong Yang 		break;
17138af74909SZhong Yang 
17148af74909SZhong Yang 	case EM_SETSEL: {
17158af74909SZhong Yang 			Sci::Position nStart = wParam;
17168af74909SZhong Yang 			Sci::Position nEnd = lParam;
17178af74909SZhong Yang 			if (nStart == 0 && nEnd == -1) {
17188af74909SZhong Yang 				nEnd = pdoc->Length();
17198af74909SZhong Yang 			}
17208af74909SZhong Yang 			if (nStart == -1) {
17218af74909SZhong Yang 				nStart = nEnd;	// Remove selection
17228af74909SZhong Yang 			}
17238af74909SZhong Yang 			SetSelection(nEnd, nStart);
17248af74909SZhong Yang 			EnsureCaretVisible();
17258af74909SZhong Yang 		}
17268af74909SZhong Yang 		break;
17278af74909SZhong Yang 
17288af74909SZhong Yang 	case EM_EXSETSEL: {
17298af74909SZhong Yang 			if (lParam == 0) {
17308af74909SZhong Yang 				return 0;
17318af74909SZhong Yang 			}
17328af74909SZhong Yang 			const CHARRANGE *pCR = reinterpret_cast<const CHARRANGE *>(lParam);
17338af74909SZhong Yang 			sel.selType = Selection::selStream;
17348af74909SZhong Yang 			if (pCR->cpMin == 0 && pCR->cpMax == -1) {
17358af74909SZhong Yang 				SetSelection(pCR->cpMin, pdoc->Length());
17368af74909SZhong Yang 			} else {
17378af74909SZhong Yang 				SetSelection(pCR->cpMin, pCR->cpMax);
17388af74909SZhong Yang 			}
17398af74909SZhong Yang 			EnsureCaretVisible();
17408af74909SZhong Yang 			return pdoc->LineFromPosition(SelectionStart().Position());
17418af74909SZhong Yang 		}
17428af74909SZhong Yang 	}
17438af74909SZhong Yang 	return 0;
17448af74909SZhong Yang }
17458af74909SZhong Yang 
IdleMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)17468af74909SZhong Yang sptr_t ScintillaWin::IdleMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
17478af74909SZhong Yang 	switch (iMessage) {
17488af74909SZhong Yang 	case SC_WIN_IDLE:
17498af74909SZhong Yang 		// wParam=dwTickCountInitial, or 0 to initialize.  lParam=bSkipUserInputTest
17508af74909SZhong Yang 		if (idler.state) {
17518af74909SZhong Yang 			if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, nullptr, 0, 0, QS_INPUT | QS_HOTKEY))) {
17528af74909SZhong Yang 				if (Idle()) {
17538af74909SZhong Yang 					// User input was given priority above, but all events do get a turn.  Other
17548af74909SZhong Yang 					// messages, notifications, etc. will get interleaved with the idle messages.
17558af74909SZhong Yang 
17568af74909SZhong Yang 					// However, some things like WM_PAINT are a lower priority, and will not fire
17578af74909SZhong Yang 					// when there's a message posted.  So, several times a second, we stop and let
17588af74909SZhong Yang 					// the low priority events have a turn (after which the timer will fire again).
17598af74909SZhong Yang 
17608af74909SZhong Yang 					// Suppress a warning from Code Analysis that the GetTickCount function
17618af74909SZhong Yang 					// wraps after 49 days. The WM_TIMER will kick off another SC_WIN_IDLE
17628af74909SZhong Yang 					// after the wrap.
17638af74909SZhong Yang #ifdef _MSC_VER
17648af74909SZhong Yang #pragma warning(suppress: 28159)
17658af74909SZhong Yang #endif
17668af74909SZhong Yang 					const DWORD dwCurrent = GetTickCount();
17678af74909SZhong Yang 					const DWORD dwStart = wParam ? static_cast<DWORD>(wParam) : dwCurrent;
17688af74909SZhong Yang 					constexpr DWORD maxWorkTime = 50;
17698af74909SZhong Yang 
17708af74909SZhong Yang 					if (dwCurrent >= dwStart && dwCurrent > maxWorkTime &&dwCurrent - maxWorkTime < dwStart)
17718af74909SZhong Yang 						PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0);
17728af74909SZhong Yang 				} else {
17738af74909SZhong Yang 					SetIdle(false);
17748af74909SZhong Yang 				}
17758af74909SZhong Yang 			}
17768af74909SZhong Yang 		}
17778af74909SZhong Yang 		break;
17788af74909SZhong Yang 
17798af74909SZhong Yang 	case SC_WORK_IDLE:
17808af74909SZhong Yang 		IdleWork();
17818af74909SZhong Yang 		break;
17828af74909SZhong Yang 	}
17838af74909SZhong Yang 	return 0;
17848af74909SZhong Yang }
17858af74909SZhong Yang 
SciMessage(unsigned int iMessage,uptr_t wParam,sptr_t lParam)17868af74909SZhong Yang sptr_t ScintillaWin::SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
17878af74909SZhong Yang 	switch (iMessage) {
17888af74909SZhong Yang 	case SCI_GETDIRECTFUNCTION:
17898af74909SZhong Yang 		return reinterpret_cast<sptr_t>(DirectFunction);
17908af74909SZhong Yang 
17918af74909SZhong Yang 	case SCI_GETDIRECTPOINTER:
17928af74909SZhong Yang 		return reinterpret_cast<sptr_t>(this);
17938af74909SZhong Yang 
17948af74909SZhong Yang 	case SCI_GRABFOCUS:
17958af74909SZhong Yang 		::SetFocus(MainHWND());
17968af74909SZhong Yang 		break;
17978af74909SZhong Yang 
17988af74909SZhong Yang #ifdef INCLUDE_DEPRECATED_FEATURES
17998af74909SZhong Yang 	case SCI_SETKEYSUNICODE:
18008af74909SZhong Yang 		break;
18018af74909SZhong Yang 
18028af74909SZhong Yang 	case SCI_GETKEYSUNICODE:
18038af74909SZhong Yang 		return true;
18048af74909SZhong Yang #endif
18058af74909SZhong Yang 
18068af74909SZhong Yang 	case SCI_SETTECHNOLOGY:
18078af74909SZhong Yang 		if ((wParam == SC_TECHNOLOGY_DEFAULT) ||
18088af74909SZhong Yang 			(wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) ||
18098af74909SZhong Yang 			(wParam == SC_TECHNOLOGY_DIRECTWRITEDC) ||
18108af74909SZhong Yang 			(wParam == SC_TECHNOLOGY_DIRECTWRITE)) {
18118af74909SZhong Yang 			const int technologyNew = static_cast<int>(wParam);
18128af74909SZhong Yang 			if (technology != technologyNew) {
18138af74909SZhong Yang 				if (technologyNew > SC_TECHNOLOGY_DEFAULT) {
18148af74909SZhong Yang #if defined(USE_D2D)
18158af74909SZhong Yang 					if (!LoadD2D())
18168af74909SZhong Yang 						// Failed to load Direct2D or DirectWrite so no effect
18178af74909SZhong Yang 						return 0;
18188af74909SZhong Yang #else
18198af74909SZhong Yang 					return 0;
18208af74909SZhong Yang #endif
18218af74909SZhong Yang 				} else {
18228af74909SZhong Yang 					bidirectional = EditModel::Bidirectional::bidiDisabled;
18238af74909SZhong Yang 				}
18248af74909SZhong Yang #if defined(USE_D2D)
18258af74909SZhong Yang 				DropRenderTarget();
18268af74909SZhong Yang #endif
18278af74909SZhong Yang 				technology = technologyNew;
18288af74909SZhong Yang 				// Invalidate all cached information including layout.
18298af74909SZhong Yang 				DropGraphics(true);
18308af74909SZhong Yang 				InvalidateStyleRedraw();
18318af74909SZhong Yang 			}
18328af74909SZhong Yang 		}
18338af74909SZhong Yang 		break;
18348af74909SZhong Yang 
18358af74909SZhong Yang 	case SCI_SETBIDIRECTIONAL:
18368af74909SZhong Yang 		if (technology == SC_TECHNOLOGY_DEFAULT) {
18378af74909SZhong Yang 			bidirectional = EditModel::Bidirectional::bidiDisabled;
18388af74909SZhong Yang 		} else if (wParam <= SC_BIDIRECTIONAL_R2L) {
18398af74909SZhong Yang 			bidirectional = static_cast<EditModel::Bidirectional>(wParam);
18408af74909SZhong Yang 		}
18418af74909SZhong Yang 		// Invalidate all cached information including layout.
18428af74909SZhong Yang 		DropGraphics(true);
18438af74909SZhong Yang 		InvalidateStyleRedraw();
18448af74909SZhong Yang 		break;
18458af74909SZhong Yang 
18468af74909SZhong Yang 	case SCI_TARGETASUTF8:
18478af74909SZhong Yang 		return TargetAsUTF8(CharPtrFromSPtr(lParam));
18488af74909SZhong Yang 
18498af74909SZhong Yang 	case SCI_ENCODEDFROMUTF8:
18508af74909SZhong Yang 		return EncodedFromUTF8(ConstCharPtrFromUPtr(wParam),
18518af74909SZhong Yang 			CharPtrFromSPtr(lParam));
18528af74909SZhong Yang 
18538af74909SZhong Yang 	}
18548af74909SZhong Yang 	return 0;
18558af74909SZhong Yang }
18568af74909SZhong Yang 
WndProc(unsigned int iMessage,uptr_t wParam,sptr_t lParam)18578af74909SZhong Yang sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
18588af74909SZhong Yang 	try {
18598af74909SZhong Yang 		//Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam);
18608af74909SZhong Yang 		iMessage = SciMessageFromEM(iMessage);
18618af74909SZhong Yang 		switch (iMessage) {
18628af74909SZhong Yang 
18638af74909SZhong Yang 		case WM_CREATE:
18648af74909SZhong Yang 			ctrlID = ::GetDlgCtrlID(HwndFromWindow(wMain));
18658af74909SZhong Yang 			// Get Intellimouse scroll line parameters
18668af74909SZhong Yang 			GetIntelliMouseParameters();
18678af74909SZhong Yang 			::RegisterDragDrop(MainHWND(), reinterpret_cast<IDropTarget *>(&dt));
18688af74909SZhong Yang 			break;
18698af74909SZhong Yang 
18708af74909SZhong Yang 		case WM_COMMAND:
18718af74909SZhong Yang 			Command(LOWORD(wParam));
18728af74909SZhong Yang 			break;
18738af74909SZhong Yang 
18748af74909SZhong Yang 		case WM_PAINT:
18758af74909SZhong Yang 			return WndPaint();
18768af74909SZhong Yang 
18778af74909SZhong Yang 		case WM_PRINTCLIENT: {
18788af74909SZhong Yang 				HDC hdc = reinterpret_cast<HDC>(wParam);
18798af74909SZhong Yang 				if (!IsCompatibleDC(hdc)) {
18808af74909SZhong Yang 					return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
18818af74909SZhong Yang 				}
18828af74909SZhong Yang 				FullPaintDC(hdc);
18838af74909SZhong Yang 			}
18848af74909SZhong Yang 			break;
18858af74909SZhong Yang 
18868af74909SZhong Yang 		case WM_VSCROLL:
18878af74909SZhong Yang 			ScrollMessage(wParam);
18888af74909SZhong Yang 			break;
18898af74909SZhong Yang 
18908af74909SZhong Yang 		case WM_HSCROLL:
18918af74909SZhong Yang 			HorizontalScrollMessage(wParam);
18928af74909SZhong Yang 			break;
18938af74909SZhong Yang 
18948af74909SZhong Yang 		case WM_SIZE:
18958af74909SZhong Yang 			SizeWindow();
18968af74909SZhong Yang 			break;
18978af74909SZhong Yang 
18988af74909SZhong Yang 		case WM_TIMER:
18998af74909SZhong Yang 			if (wParam == idleTimerID && idler.state) {
19008af74909SZhong Yang 				SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1);
19018af74909SZhong Yang 			} else {
19028af74909SZhong Yang 				TickFor(static_cast<TickReason>(wParam - fineTimerStart));
19038af74909SZhong Yang 			}
19048af74909SZhong Yang 			break;
19058af74909SZhong Yang 
19068af74909SZhong Yang 		case SC_WIN_IDLE:
19078af74909SZhong Yang 		case SC_WORK_IDLE:
19088af74909SZhong Yang 			return IdleMessage(iMessage, wParam, lParam);
19098af74909SZhong Yang 
19108af74909SZhong Yang 		case WM_GETMINMAXINFO:
19118af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
19128af74909SZhong Yang 
19138af74909SZhong Yang 		case WM_LBUTTONDOWN:
19148af74909SZhong Yang 		case WM_LBUTTONUP:
19158af74909SZhong Yang 		case WM_RBUTTONDOWN:
19168af74909SZhong Yang 		case WM_MOUSEMOVE:
19178af74909SZhong Yang 		case WM_MOUSELEAVE:
19188af74909SZhong Yang 		case WM_MOUSEWHEEL:
19198af74909SZhong Yang 			return MouseMessage(iMessage, wParam, lParam);
19208af74909SZhong Yang 
19218af74909SZhong Yang 		case WM_SETCURSOR:
19228af74909SZhong Yang 			if (LOWORD(lParam) == HTCLIENT) {
19238af74909SZhong Yang 				POINT pt;
19248af74909SZhong Yang 				if (::GetCursorPos(&pt)) {
19258af74909SZhong Yang 					::ScreenToClient(MainHWND(), &pt);
19268af74909SZhong Yang 					DisplayCursor(ContextCursor(PointFromPOINT(pt)));
19278af74909SZhong Yang 				}
19288af74909SZhong Yang 				return TRUE;
19298af74909SZhong Yang 			} else {
19308af74909SZhong Yang 				return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
19318af74909SZhong Yang 			}
19328af74909SZhong Yang 
19338af74909SZhong Yang 		case WM_SYSKEYDOWN:
19348af74909SZhong Yang 		case WM_KEYDOWN:
19358af74909SZhong Yang 		case WM_KEYUP:
19368af74909SZhong Yang 		case WM_CHAR:
19378af74909SZhong Yang 		case WM_UNICHAR:
19388af74909SZhong Yang 			return KeyMessage(iMessage, wParam, lParam);
19398af74909SZhong Yang 
19408af74909SZhong Yang 		case WM_SETTINGCHANGE:
19418af74909SZhong Yang 			//Platform::DebugPrintf("Setting Changed\n");
19428af74909SZhong Yang 			InvalidateStyleData();
19438af74909SZhong Yang 			// Get Intellimouse scroll line parameters
19448af74909SZhong Yang 			GetIntelliMouseParameters();
19458af74909SZhong Yang 			break;
19468af74909SZhong Yang 
19478af74909SZhong Yang 		case WM_GETDLGCODE:
19488af74909SZhong Yang 			return DLGC_HASSETSEL | DLGC_WANTALLKEYS;
19498af74909SZhong Yang 
19508af74909SZhong Yang 		case WM_KILLFOCUS:
19518af74909SZhong Yang 		case WM_SETFOCUS:
19528af74909SZhong Yang 			return FocusMessage(iMessage, wParam, lParam);
19538af74909SZhong Yang 
19548af74909SZhong Yang 		case WM_SYSCOLORCHANGE:
19558af74909SZhong Yang 			//Platform::DebugPrintf("Setting Changed\n");
19568af74909SZhong Yang 			InvalidateStyleData();
19578af74909SZhong Yang 			break;
19588af74909SZhong Yang 
19598af74909SZhong Yang 		case WM_DPICHANGED:
19608af74909SZhong Yang 			dpi = HIWORD(wParam);
19618af74909SZhong Yang 			InvalidateStyleRedraw();
19628af74909SZhong Yang 			break;
19638af74909SZhong Yang 
19648af74909SZhong Yang 		case WM_DPICHANGED_AFTERPARENT: {
19658af74909SZhong Yang 				const UINT dpiNow = DpiForWindow(wMain.GetID());
19668af74909SZhong Yang 				if (dpi != dpiNow) {
19678af74909SZhong Yang 					dpi = dpiNow;
19688af74909SZhong Yang 					InvalidateStyleRedraw();
19698af74909SZhong Yang 				}
19708af74909SZhong Yang 			}
19718af74909SZhong Yang 			break;
19728af74909SZhong Yang 
19738af74909SZhong Yang 		case WM_CONTEXTMENU:
19748af74909SZhong Yang 			return ShowContextMenu(iMessage, wParam, lParam);
19758af74909SZhong Yang 
19768af74909SZhong Yang 		case WM_ERASEBKGND:
19778af74909SZhong Yang 			return 1;   // Avoid any background erasure as whole window painted.
19788af74909SZhong Yang 
19798af74909SZhong Yang 		case WM_CAPTURECHANGED:
19808af74909SZhong Yang 			capturedMouse = false;
19818af74909SZhong Yang 			return 0;
19828af74909SZhong Yang 
19838af74909SZhong Yang 		// These are not handled in Scintilla and its faster to dispatch them here.
19848af74909SZhong Yang 		// Also moves time out to here so profile doesn't count lots of empty message calls.
19858af74909SZhong Yang 
19868af74909SZhong Yang 		case WM_MOVE:
19878af74909SZhong Yang 		case WM_MOUSEACTIVATE:
19888af74909SZhong Yang 		case WM_NCHITTEST:
19898af74909SZhong Yang 		case WM_NCCALCSIZE:
19908af74909SZhong Yang 		case WM_NCPAINT:
19918af74909SZhong Yang 		case WM_NCMOUSEMOVE:
19928af74909SZhong Yang 		case WM_NCLBUTTONDOWN:
19938af74909SZhong Yang 		case WM_SYSCOMMAND:
19948af74909SZhong Yang 		case WM_WINDOWPOSCHANGING:
19958af74909SZhong Yang 		case WM_WINDOWPOSCHANGED:
19968af74909SZhong Yang 			return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
19978af74909SZhong Yang 
19988af74909SZhong Yang 		case WM_GETTEXTLENGTH:
19998af74909SZhong Yang 			return GetTextLength();
20008af74909SZhong Yang 
20018af74909SZhong Yang 		case WM_GETTEXT:
20028af74909SZhong Yang 			return GetText(wParam, lParam);
20038af74909SZhong Yang 
20048af74909SZhong Yang 		case WM_INPUTLANGCHANGE:
20058af74909SZhong Yang 		case WM_INPUTLANGCHANGEREQUEST:
20068af74909SZhong Yang 		case WM_IME_KEYDOWN:
20078af74909SZhong Yang 		case WM_IME_REQUEST:
20088af74909SZhong Yang 		case WM_IME_STARTCOMPOSITION:
20098af74909SZhong Yang 		case WM_IME_ENDCOMPOSITION:
20108af74909SZhong Yang 		case WM_IME_COMPOSITION:
20118af74909SZhong Yang 		case WM_IME_SETCONTEXT:
20128af74909SZhong Yang 		case WM_IME_NOTIFY:
20138af74909SZhong Yang 			return IMEMessage(iMessage, wParam, lParam);
20148af74909SZhong Yang 
20158af74909SZhong Yang 		case EM_LINEFROMCHAR:
20168af74909SZhong Yang 		case EM_EXLINEFROMCHAR:
20178af74909SZhong Yang 		case EM_GETSEL:
20188af74909SZhong Yang 		case EM_EXGETSEL:
20198af74909SZhong Yang 		case EM_SETSEL:
20208af74909SZhong Yang 		case EM_EXSETSEL:
20218af74909SZhong Yang 			return EditMessage(iMessage, wParam, lParam);
20228af74909SZhong Yang 
20238af74909SZhong Yang 		case SCI_GETDIRECTFUNCTION:
20248af74909SZhong Yang 		case SCI_GETDIRECTPOINTER:
20258af74909SZhong Yang 		case SCI_GRABFOCUS:
20268af74909SZhong Yang #ifdef INCLUDE_DEPRECATED_FEATURES
20278af74909SZhong Yang 		case SCI_SETKEYSUNICODE:
20288af74909SZhong Yang 		case SCI_GETKEYSUNICODE:
20298af74909SZhong Yang #endif
20308af74909SZhong Yang 		case SCI_SETTECHNOLOGY:
20318af74909SZhong Yang 		case SCI_SETBIDIRECTIONAL:
20328af74909SZhong Yang 		case SCI_TARGETASUTF8:
20338af74909SZhong Yang 		case SCI_ENCODEDFROMUTF8:
20348af74909SZhong Yang 			return SciMessage(iMessage, wParam, lParam);
20358af74909SZhong Yang 
20368af74909SZhong Yang 		default:
20378af74909SZhong Yang 			return ScintillaBase::WndProc(iMessage, wParam, lParam);
20388af74909SZhong Yang 		}
20398af74909SZhong Yang 	} catch (std::bad_alloc &) {
20408af74909SZhong Yang 		errorStatus = SC_STATUS_BADALLOC;
20418af74909SZhong Yang 	} catch (...) {
20428af74909SZhong Yang 		errorStatus = SC_STATUS_FAILURE;
20438af74909SZhong Yang 	}
20448af74909SZhong Yang 	return 0;
20458af74909SZhong Yang }
20468af74909SZhong Yang 
ValidCodePage(int codePage) const20478af74909SZhong Yang bool ScintillaWin::ValidCodePage(int codePage) const {
20488af74909SZhong Yang 	return codePage == 0 || codePage == SC_CP_UTF8 ||
20498af74909SZhong Yang 	       codePage == 932 || codePage == 936 || codePage == 949 ||
20508af74909SZhong Yang 	       codePage == 950 || codePage == 1361;
20518af74909SZhong Yang }
20528af74909SZhong Yang 
DefWndProc(unsigned int iMessage,uptr_t wParam,sptr_t lParam)20538af74909SZhong Yang sptr_t ScintillaWin::DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
20548af74909SZhong Yang 	return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
20558af74909SZhong Yang }
20568af74909SZhong Yang 
FineTickerRunning(TickReason reason)20578af74909SZhong Yang bool ScintillaWin::FineTickerRunning(TickReason reason) {
20588af74909SZhong Yang 	return timers[reason] != 0;
20598af74909SZhong Yang }
20608af74909SZhong Yang 
FineTickerStart(TickReason reason,int millis,int tolerance)20618af74909SZhong Yang void ScintillaWin::FineTickerStart(TickReason reason, int millis, int tolerance) {
20628af74909SZhong Yang 	FineTickerCancel(reason);
20638af74909SZhong Yang 	const UINT_PTR eventID = static_cast<UINT_PTR>(fineTimerStart) + reason;
20648af74909SZhong Yang 	if (SetCoalescableTimerFn && tolerance) {
20658af74909SZhong Yang 		timers[reason] = SetCoalescableTimerFn(MainHWND(), eventID, millis, nullptr, tolerance);
20668af74909SZhong Yang 	} else {
20678af74909SZhong Yang 		timers[reason] = ::SetTimer(MainHWND(), eventID, millis, nullptr);
20688af74909SZhong Yang 	}
20698af74909SZhong Yang }
20708af74909SZhong Yang 
FineTickerCancel(TickReason reason)20718af74909SZhong Yang void ScintillaWin::FineTickerCancel(TickReason reason) {
20728af74909SZhong Yang 	if (timers[reason]) {
20738af74909SZhong Yang 		::KillTimer(MainHWND(), timers[reason]);
20748af74909SZhong Yang 		timers[reason] = 0;
20758af74909SZhong Yang 	}
20768af74909SZhong Yang }
20778af74909SZhong Yang 
20788af74909SZhong Yang 
SetIdle(bool on)20798af74909SZhong Yang bool ScintillaWin::SetIdle(bool on) {
20808af74909SZhong Yang 	// On Win32 the Idler is implemented as a Timer on the Scintilla window.  This
20818af74909SZhong Yang 	// takes advantage of the fact that WM_TIMER messages are very low priority,
20828af74909SZhong Yang 	// and are only posted when the message queue is empty, i.e. during idle time.
20838af74909SZhong Yang 	if (idler.state != on) {
20848af74909SZhong Yang 		if (on) {
20858af74909SZhong Yang 			idler.idlerID = ::SetTimer(MainHWND(), idleTimerID, 10, nullptr)
20868af74909SZhong Yang 				? reinterpret_cast<IdlerID>(idleTimerID) : 0;
20878af74909SZhong Yang 		} else {
20888af74909SZhong Yang 			::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(idler.idlerID));
20898af74909SZhong Yang 			idler.idlerID = 0;
20908af74909SZhong Yang 		}
20918af74909SZhong Yang 		idler.state = idler.idlerID != 0;
20928af74909SZhong Yang 	}
20938af74909SZhong Yang 	return idler.state;
20948af74909SZhong Yang }
20958af74909SZhong Yang 
IdleWork()20968af74909SZhong Yang void ScintillaWin::IdleWork() {
20978af74909SZhong Yang 	styleIdleInQueue = false;
20988af74909SZhong Yang 	Editor::IdleWork();
20998af74909SZhong Yang }
21008af74909SZhong Yang 
QueueIdleWork(WorkNeeded::workItems items,Sci::Position upTo)21018af74909SZhong Yang void ScintillaWin::QueueIdleWork(WorkNeeded::workItems items, Sci::Position upTo) {
21028af74909SZhong Yang 	Editor::QueueIdleWork(items, upTo);
21038af74909SZhong Yang 	if (!styleIdleInQueue) {
21048af74909SZhong Yang 		if (PostMessage(MainHWND(), SC_WORK_IDLE, 0, 0)) {
21058af74909SZhong Yang 			styleIdleInQueue = true;
21068af74909SZhong Yang 		}
21078af74909SZhong Yang 	}
21088af74909SZhong Yang }
21098af74909SZhong Yang 
SetMouseCapture(bool on)21108af74909SZhong Yang void ScintillaWin::SetMouseCapture(bool on) {
21118af74909SZhong Yang 	if (mouseDownCaptures) {
21128af74909SZhong Yang 		if (on) {
21138af74909SZhong Yang 			::SetCapture(MainHWND());
21148af74909SZhong Yang 		} else {
21158af74909SZhong Yang 			::ReleaseCapture();
21168af74909SZhong Yang 		}
21178af74909SZhong Yang 	}
21188af74909SZhong Yang 	capturedMouse = on;
21198af74909SZhong Yang }
21208af74909SZhong Yang 
HaveMouseCapture()21218af74909SZhong Yang bool ScintillaWin::HaveMouseCapture() {
21228af74909SZhong Yang 	// Cannot just see if GetCapture is this window as the scroll bar also sets capture for the window
21238af74909SZhong Yang 	return capturedMouse;
21248af74909SZhong Yang 	//return capturedMouse && (::GetCapture() == MainHWND());
21258af74909SZhong Yang }
21268af74909SZhong Yang 
SetTrackMouseLeaveEvent(bool on)21278af74909SZhong Yang void ScintillaWin::SetTrackMouseLeaveEvent(bool on) noexcept {
21288af74909SZhong Yang 	if (on && !trackedMouseLeave) {
21298af74909SZhong Yang 		TRACKMOUSEEVENT tme;
21308af74909SZhong Yang 		tme.cbSize = sizeof(tme);
21318af74909SZhong Yang 		tme.dwFlags = TME_LEAVE;
21328af74909SZhong Yang 		tme.hwndTrack = MainHWND();
21338af74909SZhong Yang 		tme.dwHoverTime = HOVER_DEFAULT;	// Unused but triggers Dr. Memory if not initialized
21348af74909SZhong Yang 		TrackMouseEvent(&tme);
21358af74909SZhong Yang 	}
21368af74909SZhong Yang 	trackedMouseLeave = on;
21378af74909SZhong Yang }
21388af74909SZhong Yang 
PaintContains(PRectangle rc)21398af74909SZhong Yang bool ScintillaWin::PaintContains(PRectangle rc) {
21408af74909SZhong Yang 	if (paintState == painting) {
21418af74909SZhong Yang 		return BoundsContains(rcPaint, hRgnUpdate, rc);
21428af74909SZhong Yang 	}
21438af74909SZhong Yang 	return true;
21448af74909SZhong Yang }
21458af74909SZhong Yang 
ScrollText(Sci::Line)21468af74909SZhong Yang void ScintillaWin::ScrollText(Sci::Line /* linesToMove */) {
21478af74909SZhong Yang 	//Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
21488af74909SZhong Yang 	//::ScrollWindow(MainHWND(), 0,
21498af74909SZhong Yang 	//	vs.lineHeight * linesToMove, 0, 0);
21508af74909SZhong Yang 	//::UpdateWindow(MainHWND());
21518af74909SZhong Yang 	Redraw();
21528af74909SZhong Yang 	UpdateSystemCaret();
21538af74909SZhong Yang }
21548af74909SZhong Yang 
NotifyCaretMove()21558af74909SZhong Yang void ScintillaWin::NotifyCaretMove() {
21568af74909SZhong Yang 	NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, MainHWND(), OBJID_CARET, CHILDID_SELF);
21578af74909SZhong Yang }
21588af74909SZhong Yang 
UpdateSystemCaret()21598af74909SZhong Yang void ScintillaWin::UpdateSystemCaret() {
21608af74909SZhong Yang 	if (hasFocus) {
21618af74909SZhong Yang 		if (pdoc->TentativeActive()) {
21628af74909SZhong Yang 			// ongoing inline mode IME composition, don't inform IME of system caret position.
21638af74909SZhong Yang 			// fix candidate window for Google Japanese IME moved on typing on Win7.
21648af74909SZhong Yang 			return;
21658af74909SZhong Yang 		}
21668af74909SZhong Yang 		if (HasCaretSizeChanged()) {
21678af74909SZhong Yang 			DestroySystemCaret();
21688af74909SZhong Yang 			CreateSystemCaret();
21698af74909SZhong Yang 		}
21708af74909SZhong Yang 		const Point pos = PointMainCaret();
21718af74909SZhong Yang 		::SetCaretPos(static_cast<int>(pos.x), static_cast<int>(pos.y));
21728af74909SZhong Yang 	}
21738af74909SZhong Yang }
21748af74909SZhong Yang 
SetScrollInfo(int nBar,LPCSCROLLINFO lpsi,BOOL bRedraw)21758af74909SZhong Yang int ScintillaWin::SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) noexcept {
21768af74909SZhong Yang 	return ::SetScrollInfo(MainHWND(), nBar, lpsi, bRedraw);
21778af74909SZhong Yang }
21788af74909SZhong Yang 
GetScrollInfo(int nBar,LPSCROLLINFO lpsi)21798af74909SZhong Yang bool ScintillaWin::GetScrollInfo(int nBar, LPSCROLLINFO lpsi) noexcept {
21808af74909SZhong Yang 	return ::GetScrollInfo(MainHWND(), nBar, lpsi) ? true : false;
21818af74909SZhong Yang }
21828af74909SZhong Yang 
21838af74909SZhong Yang // Change the scroll position but avoid repaint if changing to same value
ChangeScrollPos(int barType,Sci::Position pos)21848af74909SZhong Yang void ScintillaWin::ChangeScrollPos(int barType, Sci::Position pos) {
21858af74909SZhong Yang 	SCROLLINFO sci = {
21868af74909SZhong Yang 		sizeof(sci), 0, 0, 0, 0, 0, 0
21878af74909SZhong Yang 	};
21888af74909SZhong Yang 	sci.fMask = SIF_POS;
21898af74909SZhong Yang 	GetScrollInfo(barType, &sci);
21908af74909SZhong Yang 	if (sci.nPos != pos) {
21918af74909SZhong Yang 		DwellEnd(true);
21928af74909SZhong Yang 		sci.nPos = static_cast<int>(pos);
21938af74909SZhong Yang 		SetScrollInfo(barType, &sci, TRUE);
21948af74909SZhong Yang 	}
21958af74909SZhong Yang }
21968af74909SZhong Yang 
SetVerticalScrollPos()21978af74909SZhong Yang void ScintillaWin::SetVerticalScrollPos() {
21988af74909SZhong Yang 	ChangeScrollPos(SB_VERT, topLine);
21998af74909SZhong Yang }
22008af74909SZhong Yang 
SetHorizontalScrollPos()22018af74909SZhong Yang void ScintillaWin::SetHorizontalScrollPos() {
22028af74909SZhong Yang 	ChangeScrollPos(SB_HORZ, xOffset);
22038af74909SZhong Yang }
22048af74909SZhong Yang 
ModifyScrollBars(Sci::Line nMax,Sci::Line nPage)22058af74909SZhong Yang bool ScintillaWin::ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) {
22068af74909SZhong Yang 	bool modified = false;
22078af74909SZhong Yang 	SCROLLINFO sci = {
22088af74909SZhong Yang 		sizeof(sci), 0, 0, 0, 0, 0, 0
22098af74909SZhong Yang 	};
22108af74909SZhong Yang 	sci.fMask = SIF_PAGE | SIF_RANGE;
22118af74909SZhong Yang 	GetScrollInfo(SB_VERT, &sci);
22128af74909SZhong Yang 	const Sci::Line vertEndPreferred = nMax;
22138af74909SZhong Yang 	if (!verticalScrollBarVisible)
22148af74909SZhong Yang 		nPage = vertEndPreferred + 1;
22158af74909SZhong Yang 	if ((sci.nMin != 0) ||
22168af74909SZhong Yang 		(sci.nMax != vertEndPreferred) ||
22178af74909SZhong Yang 	        (sci.nPage != static_cast<unsigned int>(nPage)) ||
22188af74909SZhong Yang 	        (sci.nPos != 0)) {
22198af74909SZhong Yang 		sci.fMask = SIF_PAGE | SIF_RANGE;
22208af74909SZhong Yang 		sci.nMin = 0;
22218af74909SZhong Yang 		sci.nMax = static_cast<int>(vertEndPreferred);
22228af74909SZhong Yang 		sci.nPage = static_cast<UINT>(nPage);
22238af74909SZhong Yang 		sci.nPos = 0;
22248af74909SZhong Yang 		sci.nTrackPos = 1;
22258af74909SZhong Yang 		SetScrollInfo(SB_VERT, &sci, TRUE);
22268af74909SZhong Yang 		modified = true;
22278af74909SZhong Yang 	}
22288af74909SZhong Yang 
22298af74909SZhong Yang 	const PRectangle rcText = GetTextRectangle();
22308af74909SZhong Yang 	int horizEndPreferred = scrollWidth;
22318af74909SZhong Yang 	if (horizEndPreferred < 0)
22328af74909SZhong Yang 		horizEndPreferred = 0;
22338af74909SZhong Yang 	int pageWidth = static_cast<int>(rcText.Width());
22348af74909SZhong Yang 	if (!horizontalScrollBarVisible || Wrapping())
22358af74909SZhong Yang 		pageWidth = horizEndPreferred + 1;
22368af74909SZhong Yang 	sci.fMask = SIF_PAGE | SIF_RANGE;
22378af74909SZhong Yang 	GetScrollInfo(SB_HORZ, &sci);
22388af74909SZhong Yang 	if ((sci.nMin != 0) ||
22398af74909SZhong Yang 		(sci.nMax != horizEndPreferred) ||
22408af74909SZhong Yang 		(sci.nPage != static_cast<unsigned int>(pageWidth)) ||
22418af74909SZhong Yang 	        (sci.nPos != 0)) {
22428af74909SZhong Yang 		sci.fMask = SIF_PAGE | SIF_RANGE;
22438af74909SZhong Yang 		sci.nMin = 0;
22448af74909SZhong Yang 		sci.nMax = horizEndPreferred;
22458af74909SZhong Yang 		sci.nPage = pageWidth;
22468af74909SZhong Yang 		sci.nPos = 0;
22478af74909SZhong Yang 		sci.nTrackPos = 1;
22488af74909SZhong Yang 		SetScrollInfo(SB_HORZ, &sci, TRUE);
22498af74909SZhong Yang 		modified = true;
22508af74909SZhong Yang 		if (scrollWidth < pageWidth) {
22518af74909SZhong Yang 			HorizontalScrollTo(0);
22528af74909SZhong Yang 		}
22538af74909SZhong Yang 	}
22548af74909SZhong Yang 	return modified;
22558af74909SZhong Yang }
22568af74909SZhong Yang 
NotifyChange()22578af74909SZhong Yang void ScintillaWin::NotifyChange() {
22588af74909SZhong Yang 	::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
22598af74909SZhong Yang 	        MAKEWPARAM(GetCtrlID(), SCEN_CHANGE),
22608af74909SZhong Yang 		reinterpret_cast<LPARAM>(MainHWND()));
22618af74909SZhong Yang }
22628af74909SZhong Yang 
NotifyFocus(bool focus)22638af74909SZhong Yang void ScintillaWin::NotifyFocus(bool focus) {
22648af74909SZhong Yang 	if (commandEvents) {
22658af74909SZhong Yang 		::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
22668af74909SZhong Yang 			MAKEWPARAM(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
22678af74909SZhong Yang 			reinterpret_cast<LPARAM>(MainHWND()));
22688af74909SZhong Yang 	}
22698af74909SZhong Yang 	Editor::NotifyFocus(focus);
22708af74909SZhong Yang }
22718af74909SZhong Yang 
SetCtrlID(int identifier)22728af74909SZhong Yang void ScintillaWin::SetCtrlID(int identifier) {
22738af74909SZhong Yang 	::SetWindowID(HwndFromWindow(wMain), identifier);
22748af74909SZhong Yang }
22758af74909SZhong Yang 
GetCtrlID()22768af74909SZhong Yang int ScintillaWin::GetCtrlID() {
22778af74909SZhong Yang 	return ::GetDlgCtrlID(HwndFromWindow(wMain));
22788af74909SZhong Yang }
22798af74909SZhong Yang 
NotifyParent(SCNotification scn)22808af74909SZhong Yang void ScintillaWin::NotifyParent(SCNotification scn) {
22818af74909SZhong Yang 	scn.nmhdr.hwndFrom = MainHWND();
22828af74909SZhong Yang 	scn.nmhdr.idFrom = GetCtrlID();
22838af74909SZhong Yang 	::SendMessage(::GetParent(MainHWND()), WM_NOTIFY,
22848af74909SZhong Yang 	              GetCtrlID(), reinterpret_cast<LPARAM>(&scn));
22858af74909SZhong Yang }
22868af74909SZhong Yang 
NotifyDoubleClick(Point pt,int modifiers)22878af74909SZhong Yang void ScintillaWin::NotifyDoubleClick(Point pt, int modifiers) {
22888af74909SZhong Yang 	//Platform::DebugPrintf("ScintillaWin Double click 0\n");
22898af74909SZhong Yang 	ScintillaBase::NotifyDoubleClick(pt, modifiers);
22908af74909SZhong Yang 	// Send myself a WM_LBUTTONDBLCLK, so the container can handle it too.
22918af74909SZhong Yang 	::SendMessage(MainHWND(),
22928af74909SZhong Yang 			  WM_LBUTTONDBLCLK,
22938af74909SZhong Yang 			  (modifiers & SCI_SHIFT) ? MK_SHIFT : 0,
22948af74909SZhong Yang 			  MAKELPARAM(pt.x, pt.y));
22958af74909SZhong Yang }
22968af74909SZhong Yang 
22978af74909SZhong Yang class CaseFolderDBCS : public CaseFolderTable {
22988af74909SZhong Yang 	// Allocate the expandable storage here so that it does not need to be reallocated
22998af74909SZhong Yang 	// for each call to Fold.
23008af74909SZhong Yang 	std::vector<wchar_t> utf16Mixed;
23018af74909SZhong Yang 	std::vector<wchar_t> utf16Folded;
23028af74909SZhong Yang 	UINT cp;
23038af74909SZhong Yang public:
CaseFolderDBCS(UINT cp_)23048af74909SZhong Yang 	explicit CaseFolderDBCS(UINT cp_) : cp(cp_) {
23058af74909SZhong Yang 		StandardASCII();
23068af74909SZhong Yang 	}
Fold(char * folded,size_t sizeFolded,const char * mixed,size_t lenMixed)23078af74909SZhong Yang 	size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override {
23088af74909SZhong Yang 		if ((lenMixed == 1) && (sizeFolded > 0)) {
23098af74909SZhong Yang 			folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
23108af74909SZhong Yang 			return 1;
23118af74909SZhong Yang 		} else {
23128af74909SZhong Yang 			if (lenMixed > utf16Mixed.size()) {
23138af74909SZhong Yang 				utf16Mixed.resize(lenMixed + 8);
23148af74909SZhong Yang 			}
23158af74909SZhong Yang 			const size_t nUtf16Mixed = WideCharFromMultiByte(cp,
23168af74909SZhong Yang 				std::string_view(mixed, lenMixed),
23178af74909SZhong Yang 				&utf16Mixed[0],
23188af74909SZhong Yang 				utf16Mixed.size());
23198af74909SZhong Yang 
23208af74909SZhong Yang 			if (nUtf16Mixed == 0) {
23218af74909SZhong Yang 				// Failed to convert -> bad input
23228af74909SZhong Yang 				folded[0] = '\0';
23238af74909SZhong Yang 				return 1;
23248af74909SZhong Yang 			}
23258af74909SZhong Yang 
23268af74909SZhong Yang 			size_t lenFlat = 0;
23278af74909SZhong Yang 			for (size_t mixIndex=0; mixIndex < nUtf16Mixed; mixIndex++) {
23288af74909SZhong Yang 				if ((lenFlat + 20) > utf16Folded.size())
23298af74909SZhong Yang 					utf16Folded.resize(lenFlat + 60);
23308af74909SZhong Yang 				const char *foldedUTF8 = CaseConvert(utf16Mixed[mixIndex], CaseConversionFold);
23318af74909SZhong Yang 				if (foldedUTF8) {
23328af74909SZhong Yang 					// Maximum length of a case conversion is 6 bytes, 3 characters
23338af74909SZhong Yang 					wchar_t wFolded[20];
23348af74909SZhong Yang 					const size_t charsConverted = UTF16FromUTF8(std::string_view(foldedUTF8),
23358af74909SZhong Yang 							wFolded, std::size(wFolded));
23368af74909SZhong Yang 					for (size_t j=0; j<charsConverted; j++)
23378af74909SZhong Yang 						utf16Folded[lenFlat++] = wFolded[j];
23388af74909SZhong Yang 				} else {
23398af74909SZhong Yang 					utf16Folded[lenFlat++] = utf16Mixed[mixIndex];
23408af74909SZhong Yang 				}
23418af74909SZhong Yang 			}
23428af74909SZhong Yang 
23438af74909SZhong Yang 			const std::wstring_view wsvFolded(&utf16Folded[0], lenFlat);
23448af74909SZhong Yang 			const size_t lenOut = MultiByteLenFromWideChar(cp, wsvFolded);
23458af74909SZhong Yang 
23468af74909SZhong Yang 			if (lenOut < sizeFolded) {
23478af74909SZhong Yang 				MultiByteFromWideChar(cp, wsvFolded, folded, lenOut);
23488af74909SZhong Yang 				return lenOut;
23498af74909SZhong Yang 			} else {
23508af74909SZhong Yang 				return 0;
23518af74909SZhong Yang 			}
23528af74909SZhong Yang 		}
23538af74909SZhong Yang 	}
23548af74909SZhong Yang };
23558af74909SZhong Yang 
CaseFolderForEncoding()23568af74909SZhong Yang CaseFolder *ScintillaWin::CaseFolderForEncoding() {
23578af74909SZhong Yang 	const UINT cpDest = CodePageOfDocument();
23588af74909SZhong Yang 	if (cpDest == SC_CP_UTF8) {
23598af74909SZhong Yang 		return new CaseFolderUnicode();
23608af74909SZhong Yang 	} else {
23618af74909SZhong Yang 		if (pdoc->dbcsCodePage == 0) {
23628af74909SZhong Yang 			CaseFolderTable *pcf = new CaseFolderTable();
23638af74909SZhong Yang 			pcf->StandardASCII();
23648af74909SZhong Yang 			// Only for single byte encodings
23658af74909SZhong Yang 			for (int i=0x80; i<0x100; i++) {
23668af74909SZhong Yang 				char sCharacter[2] = "A";
23678af74909SZhong Yang 				sCharacter[0] = static_cast<char>(i);
23688af74909SZhong Yang 				wchar_t wCharacter[20];
23698af74909SZhong Yang 				const unsigned int lengthUTF16 = WideCharFromMultiByte(cpDest, sCharacter,
23708af74909SZhong Yang 					wCharacter, std::size(wCharacter));
23718af74909SZhong Yang 				if (lengthUTF16 == 1) {
23728af74909SZhong Yang 					const char *caseFolded = CaseConvert(wCharacter[0], CaseConversionFold);
23738af74909SZhong Yang 					if (caseFolded) {
23748af74909SZhong Yang 						wchar_t wLower[20];
23758af74909SZhong Yang 						const size_t charsConverted = UTF16FromUTF8(std::string_view(caseFolded),
23768af74909SZhong Yang 							wLower, std::size(wLower));
23778af74909SZhong Yang 						if (charsConverted == 1) {
23788af74909SZhong Yang 							char sCharacterLowered[20];
23798af74909SZhong Yang 							const unsigned int lengthConverted = MultiByteFromWideChar(cpDest,
23808af74909SZhong Yang 								std::wstring_view(wLower, charsConverted),
23818af74909SZhong Yang 								sCharacterLowered, std::size(sCharacterLowered));
23828af74909SZhong Yang 							if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
23838af74909SZhong Yang 								pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
23848af74909SZhong Yang 							}
23858af74909SZhong Yang 						}
23868af74909SZhong Yang 					}
23878af74909SZhong Yang 				}
23888af74909SZhong Yang 			}
23898af74909SZhong Yang 			return pcf;
23908af74909SZhong Yang 		} else {
23918af74909SZhong Yang 			return new CaseFolderDBCS(cpDest);
23928af74909SZhong Yang 		}
23938af74909SZhong Yang 	}
23948af74909SZhong Yang }
23958af74909SZhong Yang 
CaseMapString(const std::string & s,int caseMapping)23968af74909SZhong Yang std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) {
23978af74909SZhong Yang 	if ((s.size() == 0) || (caseMapping == cmSame))
23988af74909SZhong Yang 		return s;
23998af74909SZhong Yang 
24008af74909SZhong Yang 	const UINT cpDoc = CodePageOfDocument();
24018af74909SZhong Yang 	if (cpDoc == SC_CP_UTF8) {
24028af74909SZhong Yang 		return CaseConvertString(s, (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower);
24038af74909SZhong Yang 	}
24048af74909SZhong Yang 
24058af74909SZhong Yang 	// Change text to UTF-16
24068af74909SZhong Yang 	const std::wstring wsText = StringDecode(s, cpDoc);
24078af74909SZhong Yang 
24088af74909SZhong Yang 	const DWORD mapFlags = LCMAP_LINGUISTIC_CASING |
24098af74909SZhong Yang 		((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE);
24108af74909SZhong Yang 
24118af74909SZhong Yang 	// Change case
24128af74909SZhong Yang 	const std::wstring wsConverted = StringMapCase(wsText, mapFlags);
24138af74909SZhong Yang 
24148af74909SZhong Yang 	// Change back to document encoding
24158af74909SZhong Yang 	std::string sConverted = StringEncode(wsConverted, cpDoc);
24168af74909SZhong Yang 
24178af74909SZhong Yang 	return sConverted;
24188af74909SZhong Yang }
24198af74909SZhong Yang 
Copy()24208af74909SZhong Yang void ScintillaWin::Copy() {
24218af74909SZhong Yang 	//Platform::DebugPrintf("Copy\n");
24228af74909SZhong Yang 	if (!sel.Empty()) {
24238af74909SZhong Yang 		SelectionText selectedText;
24248af74909SZhong Yang 		CopySelectionRange(&selectedText);
24258af74909SZhong Yang 		CopyToClipboard(selectedText);
24268af74909SZhong Yang 	}
24278af74909SZhong Yang }
24288af74909SZhong Yang 
CanPaste()24298af74909SZhong Yang bool ScintillaWin::CanPaste() {
24308af74909SZhong Yang 	if (!Editor::CanPaste())
24318af74909SZhong Yang 		return false;
24328af74909SZhong Yang 	return ::IsClipboardFormatAvailable(CF_UNICODETEXT) != FALSE;
24338af74909SZhong Yang }
24348af74909SZhong Yang 
24358af74909SZhong Yang namespace {
24368af74909SZhong Yang 
24378af74909SZhong Yang class GlobalMemory {
24388af74909SZhong Yang 	HGLOBAL hand {};
24398af74909SZhong Yang public:
24408af74909SZhong Yang 	void *ptr {};
GlobalMemory()24418af74909SZhong Yang 	GlobalMemory() noexcept {
24428af74909SZhong Yang 	}
GlobalMemory(HGLOBAL hand_)24438af74909SZhong Yang 	explicit GlobalMemory(HGLOBAL hand_) noexcept : hand(hand_) {
24448af74909SZhong Yang 		if (hand) {
24458af74909SZhong Yang 			ptr = ::GlobalLock(hand);
24468af74909SZhong Yang 		}
24478af74909SZhong Yang 	}
24488af74909SZhong Yang 	// Deleted so GlobalMemory objects can not be copied.
24498af74909SZhong Yang 	GlobalMemory(const GlobalMemory &) = delete;
24508af74909SZhong Yang 	GlobalMemory(GlobalMemory &&) = delete;
24518af74909SZhong Yang 	GlobalMemory &operator=(const GlobalMemory &) = delete;
24528af74909SZhong Yang 	GlobalMemory &operator=(GlobalMemory &&) = delete;
~GlobalMemory()24538af74909SZhong Yang 	~GlobalMemory() {
24548af74909SZhong Yang 		assert(!ptr);
24558af74909SZhong Yang 		assert(!hand);
24568af74909SZhong Yang 	}
Allocate(size_t bytes)24578af74909SZhong Yang 	void Allocate(size_t bytes) noexcept {
24588af74909SZhong Yang 		assert(!hand);
24598af74909SZhong Yang 		hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes);
24608af74909SZhong Yang 		if (hand) {
24618af74909SZhong Yang 			ptr = ::GlobalLock(hand);
24628af74909SZhong Yang 		}
24638af74909SZhong Yang 	}
Unlock()24648af74909SZhong Yang 	HGLOBAL Unlock() noexcept {
24658af74909SZhong Yang 		assert(ptr);
24668af74909SZhong Yang 		HGLOBAL handCopy = hand;
24678af74909SZhong Yang 		::GlobalUnlock(hand);
24688af74909SZhong Yang 		ptr = nullptr;
24698af74909SZhong Yang 		hand = {};
24708af74909SZhong Yang 		return handCopy;
24718af74909SZhong Yang 	}
SetClip(UINT uFormat)24728af74909SZhong Yang 	void SetClip(UINT uFormat) noexcept {
24738af74909SZhong Yang 		::SetClipboardData(uFormat, Unlock());
24748af74909SZhong Yang 	}
operator bool() const24758af74909SZhong Yang 	operator bool() const noexcept {
24768af74909SZhong Yang 		return ptr != nullptr;
24778af74909SZhong Yang 	}
Size() const24788af74909SZhong Yang 	SIZE_T Size() const noexcept {
24798af74909SZhong Yang 		return ::GlobalSize(hand);
24808af74909SZhong Yang 	}
24818af74909SZhong Yang };
24828af74909SZhong Yang 
24838af74909SZhong Yang // OpenClipboard may fail if another application has opened the clipboard.
24848af74909SZhong Yang // Try up to 8 times, with an initial delay of 1 ms and an exponential back off
24858af74909SZhong Yang // for a maximum total delay of 127 ms (1+2+4+8+16+32+64).
OpenClipboardRetry(HWND hwnd)24868af74909SZhong Yang bool OpenClipboardRetry(HWND hwnd) noexcept {
24878af74909SZhong Yang 	for (int attempt=0; attempt<8; attempt++) {
24888af74909SZhong Yang 		if (attempt > 0) {
24898af74909SZhong Yang 			::Sleep(1 << (attempt-1));
24908af74909SZhong Yang 		}
24918af74909SZhong Yang 		if (::OpenClipboard(hwnd)) {
24928af74909SZhong Yang 			return true;
24938af74909SZhong Yang 		}
24948af74909SZhong Yang 	}
24958af74909SZhong Yang 	return false;
24968af74909SZhong Yang }
24978af74909SZhong Yang 
IsValidFormatEtc(const FORMATETC * pFE)24988af74909SZhong Yang bool IsValidFormatEtc(const FORMATETC *pFE) noexcept {
24998af74909SZhong Yang 	return pFE->ptd == nullptr &&
25008af74909SZhong Yang 		(pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
25018af74909SZhong Yang 		pFE->lindex == -1 &&
25028af74909SZhong Yang 		(pFE->tymed & TYMED_HGLOBAL) != 0;
25038af74909SZhong Yang }
25048af74909SZhong Yang 
SupportedFormat(const FORMATETC * pFE)25058af74909SZhong Yang bool SupportedFormat(const FORMATETC *pFE) noexcept {
25068af74909SZhong Yang 	return pFE->cfFormat == CF_UNICODETEXT &&
25078af74909SZhong Yang 		IsValidFormatEtc(pFE);
25088af74909SZhong Yang }
25098af74909SZhong Yang 
25108af74909SZhong Yang }
25118af74909SZhong Yang 
Paste()25128af74909SZhong Yang void ScintillaWin::Paste() {
25138af74909SZhong Yang 	if (!::OpenClipboardRetry(MainHWND())) {
25148af74909SZhong Yang 		return;
25158af74909SZhong Yang 	}
25168af74909SZhong Yang 	UndoGroup ug(pdoc);
25178af74909SZhong Yang 	const bool isLine = SelectionEmpty() &&
25188af74909SZhong Yang 		(::IsClipboardFormatAvailable(cfLineSelect) || ::IsClipboardFormatAvailable(cfVSLineTag));
25198af74909SZhong Yang 	ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
25208af74909SZhong Yang 	bool isRectangular = (::IsClipboardFormatAvailable(cfColumnSelect) != 0);
25218af74909SZhong Yang 
25228af74909SZhong Yang 	if (!isRectangular) {
25238af74909SZhong Yang 		// Evaluate "Borland IDE Block Type" explicitly
25248af74909SZhong Yang 		GlobalMemory memBorlandSelection(::GetClipboardData(cfBorlandIDEBlockType));
25258af74909SZhong Yang 		if (memBorlandSelection) {
25268af74909SZhong Yang 			isRectangular = (memBorlandSelection.Size() == 1) && (static_cast<BYTE *>(memBorlandSelection.ptr)[0] == 0x02);
25278af74909SZhong Yang 			memBorlandSelection.Unlock();
25288af74909SZhong Yang 		}
25298af74909SZhong Yang 	}
25308af74909SZhong Yang 	const PasteShape pasteShape = isRectangular ? pasteRectangular : (isLine ? pasteLine : pasteStream);
25318af74909SZhong Yang 
25328af74909SZhong Yang 	// Use CF_UNICODETEXT if available
25338af74909SZhong Yang 	GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT));
25348af74909SZhong Yang 	if (const wchar_t *uptr = static_cast<const wchar_t *>(memUSelection.ptr)) {
25358af74909SZhong Yang 		const std::string putf = EncodeWString(uptr);
25368af74909SZhong Yang 		InsertPasteShape(putf.c_str(), putf.length(), pasteShape);
25378af74909SZhong Yang 		memUSelection.Unlock();
25388af74909SZhong Yang 	}
25398af74909SZhong Yang 	::CloseClipboard();
25408af74909SZhong Yang 	Redraw();
25418af74909SZhong Yang }
25428af74909SZhong Yang 
CreateCallTipWindow(PRectangle)25438af74909SZhong Yang void ScintillaWin::CreateCallTipWindow(PRectangle) {
25448af74909SZhong Yang 	if (!ct.wCallTip.Created()) {
25458af74909SZhong Yang 		HWND wnd = ::CreateWindow(callClassName, TEXT("ACallTip"),
25468af74909SZhong Yang 					     WS_POPUP, 100, 100, 150, 20,
25478af74909SZhong Yang 					     MainHWND(), 0,
25488af74909SZhong Yang 					     GetWindowInstance(MainHWND()),
25498af74909SZhong Yang 					     this);
25508af74909SZhong Yang 		ct.wCallTip = wnd;
25518af74909SZhong Yang 		ct.wDraw = wnd;
25528af74909SZhong Yang 	}
25538af74909SZhong Yang }
25548af74909SZhong Yang 
AddToPopUp(const wchar_t * label,int cmd,bool enabled)2555*f9763b28Slrisora void ScintillaWin::AddToPopUp(const wchar_t* label, int cmd, bool enabled) {
25568af74909SZhong Yang 	HMENU hmenuPopup = static_cast<HMENU>(popup.GetID());
25578af74909SZhong Yang 	if (!label[0])
2558*f9763b28Slrisora 		::AppendMenu(hmenuPopup, MF_SEPARATOR, 0, L"");
25598af74909SZhong Yang 	else if (enabled)
25608af74909SZhong Yang 		::AppendMenu(hmenuPopup, MF_STRING, cmd, label);
25618af74909SZhong Yang 	else
25628af74909SZhong Yang 		::AppendMenu(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
25638af74909SZhong Yang }
25648af74909SZhong Yang 
ClaimSelection()25658af74909SZhong Yang void ScintillaWin::ClaimSelection() {
25668af74909SZhong Yang 	// Windows does not have a primary selection
25678af74909SZhong Yang }
25688af74909SZhong Yang 
25698af74909SZhong Yang /// Implement IUnknown
25708af74909SZhong Yang 
25718af74909SZhong Yang STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
FormatEnumerator_QueryInterface(FormatEnumerator * fe,REFIID riid,PVOID * ppv)25728af74909SZhong Yang STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
25738af74909SZhong Yang 	//Platform::DebugPrintf("EFE QI");
25748af74909SZhong Yang 	*ppv = nullptr;
25758af74909SZhong Yang 	if (riid == IID_IUnknown)
25768af74909SZhong Yang 		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
25778af74909SZhong Yang 	if (riid == IID_IEnumFORMATETC)
25788af74909SZhong Yang 		*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
25798af74909SZhong Yang 	if (!*ppv)
25808af74909SZhong Yang 		return E_NOINTERFACE;
25818af74909SZhong Yang 	FormatEnumerator_AddRef(fe);
25828af74909SZhong Yang 	return S_OK;
25838af74909SZhong Yang }
FormatEnumerator_AddRef(FormatEnumerator * fe)25848af74909SZhong Yang STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
25858af74909SZhong Yang 	return ++fe->ref;
25868af74909SZhong Yang }
FormatEnumerator_Release(FormatEnumerator * fe)25878af74909SZhong Yang STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
25888af74909SZhong Yang 	fe->ref--;
25898af74909SZhong Yang 	if (fe->ref > 0)
25908af74909SZhong Yang 		return fe->ref;
25918af74909SZhong Yang 	delete fe;
25928af74909SZhong Yang 	return 0;
25938af74909SZhong Yang }
25948af74909SZhong Yang /// Implement IEnumFORMATETC
FormatEnumerator_Next(FormatEnumerator * fe,ULONG celt,FORMATETC * rgelt,ULONG * pceltFetched)25958af74909SZhong Yang STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
25968af74909SZhong Yang 	if (!rgelt) return E_POINTER;
25978af74909SZhong Yang 	ULONG putPos = 0;
25988af74909SZhong Yang 	while ((fe->pos < fe->formats.size()) && (putPos < celt)) {
25998af74909SZhong Yang 		rgelt->cfFormat = fe->formats[fe->pos];
26008af74909SZhong Yang 		rgelt->ptd = nullptr;
26018af74909SZhong Yang 		rgelt->dwAspect = DVASPECT_CONTENT;
26028af74909SZhong Yang 		rgelt->lindex = -1;
26038af74909SZhong Yang 		rgelt->tymed = TYMED_HGLOBAL;
26048af74909SZhong Yang 		rgelt++;
26058af74909SZhong Yang 		fe->pos++;
26068af74909SZhong Yang 		putPos++;
26078af74909SZhong Yang 	}
26088af74909SZhong Yang 	if (pceltFetched)
26098af74909SZhong Yang 		*pceltFetched = putPos;
26108af74909SZhong Yang 	return putPos ? S_OK : S_FALSE;
26118af74909SZhong Yang }
FormatEnumerator_Skip(FormatEnumerator * fe,ULONG celt)26128af74909SZhong Yang STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
26138af74909SZhong Yang 	fe->pos += celt;
26148af74909SZhong Yang 	return S_OK;
26158af74909SZhong Yang }
FormatEnumerator_Reset(FormatEnumerator * fe)26168af74909SZhong Yang STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
26178af74909SZhong Yang 	fe->pos = 0;
26188af74909SZhong Yang 	return S_OK;
26198af74909SZhong Yang }
FormatEnumerator_Clone(FormatEnumerator * fe,IEnumFORMATETC ** ppenum)26208af74909SZhong Yang STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
26218af74909SZhong Yang 	FormatEnumerator *pfe;
26228af74909SZhong Yang 	try {
26238af74909SZhong Yang 		pfe = new FormatEnumerator(fe->pos, &fe->formats[0], fe->formats.size());
26248af74909SZhong Yang 	} catch (...) {
26258af74909SZhong Yang 		return E_OUTOFMEMORY;
26268af74909SZhong Yang 	}
26278af74909SZhong Yang 	return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
26288af74909SZhong Yang 	                                       reinterpret_cast<void **>(ppenum));
26298af74909SZhong Yang }
26308af74909SZhong Yang 
26318af74909SZhong Yang static VFunction *vtFormatEnumerator[] = {
26328af74909SZhong Yang 	(VFunction *)(FormatEnumerator_QueryInterface),
26338af74909SZhong Yang 	(VFunction *)(FormatEnumerator_AddRef),
26348af74909SZhong Yang 	(VFunction *)(FormatEnumerator_Release),
26358af74909SZhong Yang 	(VFunction *)(FormatEnumerator_Next),
26368af74909SZhong Yang 	(VFunction *)(FormatEnumerator_Skip),
26378af74909SZhong Yang 	(VFunction *)(FormatEnumerator_Reset),
26388af74909SZhong Yang 	(VFunction *)(FormatEnumerator_Clone)
26398af74909SZhong Yang };
26408af74909SZhong Yang 
FormatEnumerator(ULONG pos_,const CLIPFORMAT formats_[],size_t formatsLen_)26418af74909SZhong Yang FormatEnumerator::FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_) {
26428af74909SZhong Yang 	vtbl = vtFormatEnumerator;
26438af74909SZhong Yang 	ref = 0;   // First QI adds first reference...
26448af74909SZhong Yang 	pos = pos_;
26458af74909SZhong Yang 	formats.insert(formats.begin(), formats_, formats_+formatsLen_);
26468af74909SZhong Yang }
26478af74909SZhong Yang 
26488af74909SZhong Yang /// Implement IUnknown
DropSource_QueryInterface(DropSource * ds,REFIID riid,PVOID * ppv)26498af74909SZhong Yang STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
26508af74909SZhong Yang 	return ds->sci->QueryInterface(riid, ppv);
26518af74909SZhong Yang }
DropSource_AddRef(DropSource * ds)26528af74909SZhong Yang STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
26538af74909SZhong Yang 	return ds->sci->AddRef();
26548af74909SZhong Yang }
DropSource_Release(DropSource * ds)26558af74909SZhong Yang STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
26568af74909SZhong Yang 	return ds->sci->Release();
26578af74909SZhong Yang }
26588af74909SZhong Yang 
26598af74909SZhong Yang /// Implement IDropSource
DropSource_QueryContinueDrag(DropSource *,BOOL fEsc,DWORD grfKeyState)26608af74909SZhong Yang STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
26618af74909SZhong Yang 	if (fEsc)
26628af74909SZhong Yang 		return DRAGDROP_S_CANCEL;
26638af74909SZhong Yang 	if (!(grfKeyState & MK_LBUTTON))
26648af74909SZhong Yang 		return DRAGDROP_S_DROP;
26658af74909SZhong Yang 	return S_OK;
26668af74909SZhong Yang }
26678af74909SZhong Yang 
DropSource_GiveFeedback(DropSource *,DWORD)26688af74909SZhong Yang STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
26698af74909SZhong Yang 	return DRAGDROP_S_USEDEFAULTCURSORS;
26708af74909SZhong Yang }
26718af74909SZhong Yang 
26728af74909SZhong Yang static VFunction *vtDropSource[] = {
26738af74909SZhong Yang 	(VFunction *)(DropSource_QueryInterface),
26748af74909SZhong Yang 	(VFunction *)(DropSource_AddRef),
26758af74909SZhong Yang 	(VFunction *)(DropSource_Release),
26768af74909SZhong Yang 	(VFunction *)(DropSource_QueryContinueDrag),
26778af74909SZhong Yang 	(VFunction *)(DropSource_GiveFeedback)
26788af74909SZhong Yang };
26798af74909SZhong Yang 
DropSource()26808af74909SZhong Yang DropSource::DropSource() noexcept {
26818af74909SZhong Yang 	vtbl = vtDropSource;
26828af74909SZhong Yang 	sci = nullptr;
26838af74909SZhong Yang }
26848af74909SZhong Yang 
26858af74909SZhong Yang /// Implement IUnkown
DataObject_QueryInterface(DataObject * pd,REFIID riid,PVOID * ppv)26868af74909SZhong Yang STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
26878af74909SZhong Yang 	//Platform::DebugPrintf("DO QI %x\n", pd);
26888af74909SZhong Yang 	return pd->sci->QueryInterface(riid, ppv);
26898af74909SZhong Yang }
DataObject_AddRef(DataObject * pd)26908af74909SZhong Yang STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
26918af74909SZhong Yang 	return pd->sci->AddRef();
26928af74909SZhong Yang }
DataObject_Release(DataObject * pd)26938af74909SZhong Yang STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
26948af74909SZhong Yang 	return pd->sci->Release();
26958af74909SZhong Yang }
26968af74909SZhong Yang /// Implement IDataObject
DataObject_GetData(DataObject * pd,FORMATETC * pFEIn,STGMEDIUM * pSTM)26978af74909SZhong Yang STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
26988af74909SZhong Yang 	return pd->sci->GetData(pFEIn, pSTM);
26998af74909SZhong Yang }
27008af74909SZhong Yang 
DataObject_GetDataHere(DataObject *,FORMATETC *,STGMEDIUM *)27018af74909SZhong Yang STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
27028af74909SZhong Yang 	//Platform::DebugPrintf("DOB GetDataHere\n");
27038af74909SZhong Yang 	return E_NOTIMPL;
27048af74909SZhong Yang }
27058af74909SZhong Yang 
DataObject_QueryGetData(DataObject * pd,FORMATETC * pFE)27068af74909SZhong Yang STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
27078af74909SZhong Yang 	if (pd->sci->DragIsRectangularOK(pFE->cfFormat) && IsValidFormatEtc(pFE)) {
27088af74909SZhong Yang 		return S_OK;
27098af74909SZhong Yang 	}
27108af74909SZhong Yang 
27118af74909SZhong Yang 	if (SupportedFormat(pFE)) {
27128af74909SZhong Yang 		return S_OK;
27138af74909SZhong Yang 	} else {
27148af74909SZhong Yang 		return S_FALSE;
27158af74909SZhong Yang 	}
27168af74909SZhong Yang }
27178af74909SZhong Yang 
DataObject_GetCanonicalFormatEtc(DataObject *,FORMATETC *,FORMATETC * pFEOut)27188af74909SZhong Yang STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *, FORMATETC *, FORMATETC *pFEOut) {
27198af74909SZhong Yang 	//Platform::DebugPrintf("DOB GetCanon\n");
27208af74909SZhong Yang 	pFEOut->cfFormat = CF_UNICODETEXT;
27218af74909SZhong Yang 	pFEOut->ptd = nullptr;
27228af74909SZhong Yang 	pFEOut->dwAspect = DVASPECT_CONTENT;
27238af74909SZhong Yang 	pFEOut->lindex = -1;
27248af74909SZhong Yang 	pFEOut->tymed = TYMED_HGLOBAL;
27258af74909SZhong Yang 	return S_OK;
27268af74909SZhong Yang }
27278af74909SZhong Yang 
DataObject_SetData(DataObject *,FORMATETC *,STGMEDIUM *,BOOL)27288af74909SZhong Yang STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
27298af74909SZhong Yang 	//Platform::DebugPrintf("DOB SetData\n");
27308af74909SZhong Yang 	return E_FAIL;
27318af74909SZhong Yang }
27328af74909SZhong Yang 
DataObject_EnumFormatEtc(DataObject * pd,DWORD dwDirection,IEnumFORMATETC ** ppEnum)27338af74909SZhong Yang STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
27348af74909SZhong Yang 	try {
27358af74909SZhong Yang 		//Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
27368af74909SZhong Yang 		if (dwDirection != DATADIR_GET) {
27378af74909SZhong Yang 			*ppEnum = nullptr;
27388af74909SZhong Yang 			return E_FAIL;
27398af74909SZhong Yang 		}
27408af74909SZhong Yang 
27418af74909SZhong Yang 		const CLIPFORMAT formats[] = {CF_UNICODETEXT};
27428af74909SZhong Yang 		FormatEnumerator *pfe = new FormatEnumerator(0, formats, std::size(formats));
27438af74909SZhong Yang 		return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
27448af74909SZhong Yang 											   reinterpret_cast<void **>(ppEnum));
27458af74909SZhong Yang 	} catch (std::bad_alloc &) {
27468af74909SZhong Yang 		pd->sci->errorStatus = SC_STATUS_BADALLOC;
27478af74909SZhong Yang 		return E_OUTOFMEMORY;
27488af74909SZhong Yang 	} catch (...) {
27498af74909SZhong Yang 		pd->sci->errorStatus = SC_STATUS_FAILURE;
27508af74909SZhong Yang 		return E_FAIL;
27518af74909SZhong Yang 	}
27528af74909SZhong Yang }
27538af74909SZhong Yang 
DataObject_DAdvise(DataObject *,FORMATETC *,DWORD,IAdviseSink *,PDWORD)27548af74909SZhong Yang STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
27558af74909SZhong Yang 	//Platform::DebugPrintf("DOB DAdvise\n");
27568af74909SZhong Yang 	return E_FAIL;
27578af74909SZhong Yang }
27588af74909SZhong Yang 
DataObject_DUnadvise(DataObject *,DWORD)27598af74909SZhong Yang STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
27608af74909SZhong Yang 	//Platform::DebugPrintf("DOB DUnadvise\n");
27618af74909SZhong Yang 	return E_FAIL;
27628af74909SZhong Yang }
27638af74909SZhong Yang 
DataObject_EnumDAdvise(DataObject *,IEnumSTATDATA **)27648af74909SZhong Yang STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
27658af74909SZhong Yang 	//Platform::DebugPrintf("DOB EnumDAdvise\n");
27668af74909SZhong Yang 	return E_FAIL;
27678af74909SZhong Yang }
27688af74909SZhong Yang 
27698af74909SZhong Yang static VFunction *vtDataObject[] = {
27708af74909SZhong Yang 	(VFunction *)(DataObject_QueryInterface),
27718af74909SZhong Yang 	(VFunction *)(DataObject_AddRef),
27728af74909SZhong Yang 	(VFunction *)(DataObject_Release),
27738af74909SZhong Yang 	(VFunction *)(DataObject_GetData),
27748af74909SZhong Yang 	(VFunction *)(DataObject_GetDataHere),
27758af74909SZhong Yang 	(VFunction *)(DataObject_QueryGetData),
27768af74909SZhong Yang 	(VFunction *)(DataObject_GetCanonicalFormatEtc),
27778af74909SZhong Yang 	(VFunction *)(DataObject_SetData),
27788af74909SZhong Yang 	(VFunction *)(DataObject_EnumFormatEtc),
27798af74909SZhong Yang 	(VFunction *)(DataObject_DAdvise),
27808af74909SZhong Yang 	(VFunction *)(DataObject_DUnadvise),
27818af74909SZhong Yang 	(VFunction *)(DataObject_EnumDAdvise)
27828af74909SZhong Yang };
27838af74909SZhong Yang 
DataObject()27848af74909SZhong Yang DataObject::DataObject() noexcept {
27858af74909SZhong Yang 	vtbl = vtDataObject;
27868af74909SZhong Yang 	sci = nullptr;
27878af74909SZhong Yang }
27888af74909SZhong Yang 
27898af74909SZhong Yang /// Implement IUnknown
DropTarget_QueryInterface(DropTarget * dt,REFIID riid,PVOID * ppv)27908af74909SZhong Yang STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
27918af74909SZhong Yang 	//Platform::DebugPrintf("DT QI %x\n", dt);
27928af74909SZhong Yang 	return dt->sci->QueryInterface(riid, ppv);
27938af74909SZhong Yang }
DropTarget_AddRef(DropTarget * dt)27948af74909SZhong Yang STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
27958af74909SZhong Yang 	return dt->sci->AddRef();
27968af74909SZhong Yang }
DropTarget_Release(DropTarget * dt)27978af74909SZhong Yang STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
27988af74909SZhong Yang 	return dt->sci->Release();
27998af74909SZhong Yang }
28008af74909SZhong Yang 
28018af74909SZhong Yang /// Implement IDropTarget by forwarding to Scintilla
DropTarget_DragEnter(DropTarget * dt,LPDATAOBJECT pIDataSource,DWORD grfKeyState,POINTL pt,PDWORD pdwEffect)28028af74909SZhong Yang STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
28038af74909SZhong Yang                                   POINTL pt, PDWORD pdwEffect) {
28048af74909SZhong Yang 	try {
28058af74909SZhong Yang 		return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
28068af74909SZhong Yang 	} catch (...) {
28078af74909SZhong Yang 		dt->sci->errorStatus = SC_STATUS_FAILURE;
28088af74909SZhong Yang 	}
28098af74909SZhong Yang 	return E_FAIL;
28108af74909SZhong Yang }
DropTarget_DragOver(DropTarget * dt,DWORD grfKeyState,POINTL pt,PDWORD pdwEffect)28118af74909SZhong Yang STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
28128af74909SZhong Yang 	try {
28138af74909SZhong Yang 		return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
28148af74909SZhong Yang 	} catch (...) {
28158af74909SZhong Yang 		dt->sci->errorStatus = SC_STATUS_FAILURE;
28168af74909SZhong Yang 	}
28178af74909SZhong Yang 	return E_FAIL;
28188af74909SZhong Yang }
DropTarget_DragLeave(DropTarget * dt)28198af74909SZhong Yang STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
28208af74909SZhong Yang 	try {
28218af74909SZhong Yang 		return dt->sci->DragLeave();
28228af74909SZhong Yang 	} catch (...) {
28238af74909SZhong Yang 		dt->sci->errorStatus = SC_STATUS_FAILURE;
28248af74909SZhong Yang 	}
28258af74909SZhong Yang 	return E_FAIL;
28268af74909SZhong Yang }
DropTarget_Drop(DropTarget * dt,LPDATAOBJECT pIDataSource,DWORD grfKeyState,POINTL pt,PDWORD pdwEffect)28278af74909SZhong Yang STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
28288af74909SZhong Yang                              POINTL pt, PDWORD pdwEffect) {
28298af74909SZhong Yang 	try {
28308af74909SZhong Yang 		return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
28318af74909SZhong Yang 	} catch (...) {
28328af74909SZhong Yang 		dt->sci->errorStatus = SC_STATUS_FAILURE;
28338af74909SZhong Yang 	}
28348af74909SZhong Yang 	return E_FAIL;
28358af74909SZhong Yang }
28368af74909SZhong Yang 
28378af74909SZhong Yang static VFunction *vtDropTarget[] = {
28388af74909SZhong Yang 	(VFunction *)(DropTarget_QueryInterface),
28398af74909SZhong Yang 	(VFunction *)(DropTarget_AddRef),
28408af74909SZhong Yang 	(VFunction *)(DropTarget_Release),
28418af74909SZhong Yang 	(VFunction *)(DropTarget_DragEnter),
28428af74909SZhong Yang 	(VFunction *)(DropTarget_DragOver),
28438af74909SZhong Yang 	(VFunction *)(DropTarget_DragLeave),
28448af74909SZhong Yang 	(VFunction *)(DropTarget_Drop)
28458af74909SZhong Yang };
28468af74909SZhong Yang 
DropTarget()28478af74909SZhong Yang DropTarget::DropTarget() noexcept {
28488af74909SZhong Yang 	vtbl = vtDropTarget;
28498af74909SZhong Yang 	sci = nullptr;
28508af74909SZhong Yang }
28518af74909SZhong Yang 
28528af74909SZhong Yang /**
28538af74909SZhong Yang  * DBCS: support Input Method Editor (IME).
28548af74909SZhong Yang  * Called when IME Window opened.
28558af74909SZhong Yang  */
ImeStartComposition()28568af74909SZhong Yang void ScintillaWin::ImeStartComposition() {
28578af74909SZhong Yang 	if (caret.active) {
28588af74909SZhong Yang 		// Move IME Window to current caret position
28598af74909SZhong Yang 		IMContext imc(MainHWND());
28608af74909SZhong Yang 		const Point pos = PointMainCaret();
28618af74909SZhong Yang 		COMPOSITIONFORM CompForm;
28628af74909SZhong Yang 		CompForm.dwStyle = CFS_POINT;
28638af74909SZhong Yang 		CompForm.ptCurrentPos = POINTFromPoint(pos);
28648af74909SZhong Yang 
28658af74909SZhong Yang 		::ImmSetCompositionWindow(imc.hIMC, &CompForm);
28668af74909SZhong Yang 
28678af74909SZhong Yang 		// Set font of IME window to same as surrounded text.
28688af74909SZhong Yang 		if (stylesValid) {
28698af74909SZhong Yang 			// Since the style creation code has been made platform independent,
28708af74909SZhong Yang 			// The logfont for the IME is recreated here.
28718af74909SZhong Yang 			//const int styleHere = pdoc->StyleIndexAt(sel.MainCaret());
28728af74909SZhong Yang             const int styleHere = STYLE_DEFAULT;
28738af74909SZhong Yang 			LOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L""};
28748af74909SZhong Yang 			int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER;
28758af74909SZhong Yang 			if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER)	// Hangs if sizeZoomed <= 1
28768af74909SZhong Yang 				sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
28778af74909SZhong Yang 			// The negative is to allow for leading
28788af74909SZhong Yang 			lf.lfHeight = -::MulDiv(sizeZoomed, dpi, 72*SC_FONT_SIZE_MULTIPLIER);
28798af74909SZhong Yang 			lf.lfWeight = vs.styles[styleHere].weight;
28808af74909SZhong Yang 			lf.lfItalic = vs.styles[styleHere].italic ? 1 : 0;
28818af74909SZhong Yang 			lf.lfCharSet = DEFAULT_CHARSET;
28828af74909SZhong Yang 			lf.lfFaceName[0] = L'\0';
28838af74909SZhong Yang 			if (vs.styles[styleHere].fontName) {
28848af74909SZhong Yang 				const char* fontName = vs.styles[styleHere].fontName;
28858af74909SZhong Yang 				UTF16FromUTF8(std::string_view(fontName), lf.lfFaceName, LF_FACESIZE);
28868af74909SZhong Yang 			}
28878af74909SZhong Yang 
28888af74909SZhong Yang 			::ImmSetCompositionFontW(imc.hIMC, &lf);
28898af74909SZhong Yang 		}
28908af74909SZhong Yang 		// Caret is displayed in IME window. So, caret in Scintilla is useless.
28918af74909SZhong Yang 		DropCaret();
28928af74909SZhong Yang 	}
28938af74909SZhong Yang }
28948af74909SZhong Yang 
28958af74909SZhong Yang /** Called when IME Window closed. */
ImeEndComposition()28968af74909SZhong Yang void ScintillaWin::ImeEndComposition() {
28978af74909SZhong Yang 	// clear IME composition state.
28988af74909SZhong Yang 	view.imeCaretBlockOverride = false;
28998af74909SZhong Yang 	pdoc->TentativeUndo();
29008af74909SZhong Yang 	ShowCaretAtCurrentPosition();
29018af74909SZhong Yang }
29028af74909SZhong Yang 
ImeOnReconvert(LPARAM lParam)29038af74909SZhong Yang LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) {
29048af74909SZhong Yang 	// Reconversion on windows limits within one line without eol.
29058af74909SZhong Yang 	// Look around:   baseStart  <--  (|mainStart|  -- mainEnd)  --> baseEnd.
29068af74909SZhong Yang 	const Sci::Position mainStart = sel.RangeMain().Start().Position();
29078af74909SZhong Yang 	const Sci::Position mainEnd = sel.RangeMain().End().Position();
29088af74909SZhong Yang 	const Sci::Line curLine = pdoc->SciLineFromPosition(mainStart);
29098af74909SZhong Yang 	if (curLine != pdoc->LineFromPosition(mainEnd))
29108af74909SZhong Yang 		return 0;
29118af74909SZhong Yang 	const Sci::Position baseStart = pdoc->LineStart(curLine);
29128af74909SZhong Yang 	const Sci::Position baseEnd = pdoc->LineEnd(curLine);
29138af74909SZhong Yang 	if ((baseStart == baseEnd) || (mainEnd > baseEnd))
29148af74909SZhong Yang 		return 0;
29158af74909SZhong Yang 
29168af74909SZhong Yang 	const int codePage = CodePageOfDocument();
29178af74909SZhong Yang 	const std::wstring rcFeed = StringDecode(RangeText(baseStart, baseEnd), codePage);
29188af74909SZhong Yang 	const int rcFeedLen = static_cast<int>(rcFeed.length()) * sizeof(wchar_t);
29198af74909SZhong Yang 	const int rcSize = sizeof(RECONVERTSTRING) + rcFeedLen + sizeof(wchar_t);
29208af74909SZhong Yang 
29218af74909SZhong Yang 	RECONVERTSTRING *rc = static_cast<RECONVERTSTRING *>(PtrFromSPtr(lParam));
29228af74909SZhong Yang 	if (!rc)
29238af74909SZhong Yang 		return rcSize; // Immediately be back with rcSize of memory block.
29248af74909SZhong Yang 
29258af74909SZhong Yang 	wchar_t *rcFeedStart = reinterpret_cast<wchar_t*>(rc + 1);
29268af74909SZhong Yang 	memcpy(rcFeedStart, &rcFeed[0], rcFeedLen);
29278af74909SZhong Yang 
29288af74909SZhong Yang 	std::string rcCompString = RangeText(mainStart, mainEnd);
29298af74909SZhong Yang 	std::wstring rcCompWstring = StringDecode(rcCompString, codePage);
29308af74909SZhong Yang 	std::string rcCompStart = RangeText(baseStart, mainStart);
29318af74909SZhong Yang 	std::wstring rcCompWstart = StringDecode(rcCompStart, codePage);
29328af74909SZhong Yang 
29338af74909SZhong Yang 	// Map selection to dwCompStr.
29348af74909SZhong Yang 	// No selection assumes current caret as rcCompString without length.
29358af74909SZhong Yang 	rc->dwVersion = 0; // It should be absolutely 0.
29368af74909SZhong Yang 	rc->dwStrLen = static_cast<DWORD>(rcFeed.length());
29378af74909SZhong Yang 	rc->dwStrOffset = sizeof(RECONVERTSTRING);
29388af74909SZhong Yang 	rc->dwCompStrLen = static_cast<DWORD>(rcCompWstring.length());
29398af74909SZhong Yang 	rc->dwCompStrOffset = static_cast<DWORD>(rcCompWstart.length()) * sizeof(wchar_t);
29408af74909SZhong Yang 	rc->dwTargetStrLen = rc->dwCompStrLen;
29418af74909SZhong Yang 	rc->dwTargetStrOffset =rc->dwCompStrOffset;
29428af74909SZhong Yang 
29438af74909SZhong Yang 	IMContext imc(MainHWND());
29448af74909SZhong Yang 	if (!imc.hIMC)
29458af74909SZhong Yang 		return 0;
29468af74909SZhong Yang 
29478af74909SZhong Yang 	if (!::ImmSetCompositionStringW(imc.hIMC, SCS_QUERYRECONVERTSTRING, rc, rcSize, nullptr, 0))
29488af74909SZhong Yang 		return 0;
29498af74909SZhong Yang 
29508af74909SZhong Yang 	// No selection asks IME to fill target fields with its own value.
29518af74909SZhong Yang 	const int tgWlen = rc->dwTargetStrLen;
29528af74909SZhong Yang 	const int tgWstart = rc->dwTargetStrOffset / sizeof(wchar_t);
29538af74909SZhong Yang 
29548af74909SZhong Yang 	std::string tgCompStart = StringEncode(rcFeed.substr(0, tgWstart), codePage);
29558af74909SZhong Yang 	std::string tgComp = StringEncode(rcFeed.substr(tgWstart, tgWlen), codePage);
29568af74909SZhong Yang 
29578af74909SZhong Yang 	// No selection needs to adjust reconvert start position for IME set.
29588af74909SZhong Yang 	const int adjust = static_cast<int>(tgCompStart.length() - rcCompStart.length());
29598af74909SZhong Yang 	const int docCompLen = static_cast<int>(tgComp.length());
29608af74909SZhong Yang 
29618af74909SZhong Yang 	// Make place for next composition string to sit in.
29628af74909SZhong Yang 	for (size_t r=0; r<sel.Count(); r++) {
29638af74909SZhong Yang 		const Sci::Position rBase = sel.Range(r).Start().Position();
29648af74909SZhong Yang 		const Sci::Position docCompStart = rBase + adjust;
29658af74909SZhong Yang 
29668af74909SZhong Yang 		if (inOverstrike) { // the docCompLen of bytes will be overstriked.
29678af74909SZhong Yang 			sel.Range(r).caret.SetPosition(docCompStart);
29688af74909SZhong Yang 			sel.Range(r).anchor.SetPosition(docCompStart);
29698af74909SZhong Yang 		} else {
29708af74909SZhong Yang 			// Ensure docCompStart+docCompLen be not beyond lineEnd.
29718af74909SZhong Yang 			// since docCompLen by byte might break eol.
29728af74909SZhong Yang 			const Sci::Position lineEnd = pdoc->LineEnd(pdoc->LineFromPosition(rBase));
29738af74909SZhong Yang 			const Sci::Position overflow = (docCompStart + docCompLen) - lineEnd;
29748af74909SZhong Yang 			if (overflow > 0) {
29758af74909SZhong Yang 				pdoc->DeleteChars(docCompStart, docCompLen - overflow);
29768af74909SZhong Yang 			} else {
29778af74909SZhong Yang 				pdoc->DeleteChars(docCompStart, docCompLen);
29788af74909SZhong Yang 			}
29798af74909SZhong Yang 		}
29808af74909SZhong Yang 	}
29818af74909SZhong Yang 	// Immediately Target Input or candidate box choice with GCS_COMPSTR.
29828af74909SZhong Yang 	return rcSize;
29838af74909SZhong Yang }
29848af74909SZhong Yang 
GetIntelliMouseParameters()29858af74909SZhong Yang void ScintillaWin::GetIntelliMouseParameters() noexcept {
29868af74909SZhong Yang 	// This retrieves the number of lines per scroll as configured in the Mouse Properties sheet in Control Panel
29878af74909SZhong Yang 	::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
29888af74909SZhong Yang }
29898af74909SZhong Yang 
CopyToGlobal(GlobalMemory & gmUnicode,const SelectionText & selectedText)29908af74909SZhong Yang void ScintillaWin::CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText) {
29918af74909SZhong Yang 	const std::string_view svSelected(selectedText.Data(), selectedText.LengthWithTerminator());
29928af74909SZhong Yang 	if (IsUnicodeMode()) {
29938af74909SZhong Yang 		const size_t uchars = UTF16Length(svSelected);
29948af74909SZhong Yang 		gmUnicode.Allocate(2 * uchars);
29958af74909SZhong Yang 		if (gmUnicode) {
29968af74909SZhong Yang 			UTF16FromUTF8(svSelected,
29978af74909SZhong Yang 				static_cast<wchar_t *>(gmUnicode.ptr), uchars);
29988af74909SZhong Yang 		}
29998af74909SZhong Yang 	} else {
30008af74909SZhong Yang 		// Not Unicode mode
30018af74909SZhong Yang 		// Convert to Unicode using the current Scintilla code page
30028af74909SZhong Yang 		const UINT cpSrc = CodePageFromCharSet(
30038af74909SZhong Yang 			selectedText.characterSet, selectedText.codePage);
30048af74909SZhong Yang 		const size_t uLen = WideCharLenFromMultiByte(cpSrc, svSelected);
30058af74909SZhong Yang 		gmUnicode.Allocate(2 * uLen);
30068af74909SZhong Yang 		if (gmUnicode) {
30078af74909SZhong Yang 			WideCharFromMultiByte(cpSrc, svSelected,
30088af74909SZhong Yang 				static_cast<wchar_t *>(gmUnicode.ptr), uLen);
30098af74909SZhong Yang 		}
30108af74909SZhong Yang 	}
30118af74909SZhong Yang }
30128af74909SZhong Yang 
CopyToClipboard(const SelectionText & selectedText)30138af74909SZhong Yang void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
30148af74909SZhong Yang 	if (!::OpenClipboardRetry(MainHWND())) {
30158af74909SZhong Yang 		return;
30168af74909SZhong Yang 	}
30178af74909SZhong Yang 	::EmptyClipboard();
30188af74909SZhong Yang 
30198af74909SZhong Yang 	GlobalMemory uniText;
30208af74909SZhong Yang 	CopyToGlobal(uniText, selectedText);
30218af74909SZhong Yang 	if (uniText) {
30228af74909SZhong Yang 		uniText.SetClip(CF_UNICODETEXT);
30238af74909SZhong Yang 	}
30248af74909SZhong Yang 
30258af74909SZhong Yang 	if (selectedText.rectangular) {
30268af74909SZhong Yang 		::SetClipboardData(cfColumnSelect, 0);
30278af74909SZhong Yang 
30288af74909SZhong Yang 		GlobalMemory borlandSelection;
30298af74909SZhong Yang 		borlandSelection.Allocate(1);
30308af74909SZhong Yang 		if (borlandSelection) {
30318af74909SZhong Yang 			static_cast<BYTE *>(borlandSelection.ptr)[0] = 0x02;
30328af74909SZhong Yang 			borlandSelection.SetClip(cfBorlandIDEBlockType);
30338af74909SZhong Yang 		}
30348af74909SZhong Yang 	}
30358af74909SZhong Yang 
30368af74909SZhong Yang 	if (selectedText.lineCopy) {
30378af74909SZhong Yang 		::SetClipboardData(cfLineSelect, 0);
30388af74909SZhong Yang 		::SetClipboardData(cfVSLineTag, 0);
30398af74909SZhong Yang 	}
30408af74909SZhong Yang 
30418af74909SZhong Yang 	::CloseClipboard();
30428af74909SZhong Yang }
30438af74909SZhong Yang 
ScrollMessage(WPARAM wParam)30448af74909SZhong Yang void ScintillaWin::ScrollMessage(WPARAM wParam) {
30458af74909SZhong Yang 	//DWORD dwStart = timeGetTime();
30468af74909SZhong Yang 	//Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
30478af74909SZhong Yang 
30488af74909SZhong Yang 	SCROLLINFO sci = {};
30498af74909SZhong Yang 	sci.cbSize = sizeof(sci);
30508af74909SZhong Yang 	sci.fMask = SIF_ALL;
30518af74909SZhong Yang 
30528af74909SZhong Yang 	GetScrollInfo(SB_VERT, &sci);
30538af74909SZhong Yang 
30548af74909SZhong Yang 	//Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
30558af74909SZhong Yang 	//sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
30568af74909SZhong Yang 	Sci::Line topLineNew = topLine;
30578af74909SZhong Yang 	switch (LOWORD(wParam)) {
30588af74909SZhong Yang 	case SB_LINEUP:
30598af74909SZhong Yang 		topLineNew -= 1;
30608af74909SZhong Yang 		break;
30618af74909SZhong Yang 	case SB_LINEDOWN:
30628af74909SZhong Yang 		topLineNew += 1;
30638af74909SZhong Yang 		break;
30648af74909SZhong Yang 	case SB_PAGEUP:
30658af74909SZhong Yang 		topLineNew -= LinesToScroll(); break;
30668af74909SZhong Yang 	case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
30678af74909SZhong Yang 	case SB_TOP: topLineNew = 0; break;
30688af74909SZhong Yang 	case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
30698af74909SZhong Yang 	case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
30708af74909SZhong Yang 	case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
30718af74909SZhong Yang 	}
30728af74909SZhong Yang 	ScrollTo(topLineNew);
30738af74909SZhong Yang }
30748af74909SZhong Yang 
HorizontalScrollMessage(WPARAM wParam)30758af74909SZhong Yang void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
30768af74909SZhong Yang 	int xPos = xOffset;
30778af74909SZhong Yang 	const PRectangle rcText = GetTextRectangle();
30788af74909SZhong Yang 	const int pageWidth = static_cast<int>(rcText.Width() * 2 / 3);
30798af74909SZhong Yang 	switch (LOWORD(wParam)) {
30808af74909SZhong Yang 	case SB_LINEUP:
30818af74909SZhong Yang 		xPos -= 20;
30828af74909SZhong Yang 		break;
30838af74909SZhong Yang 	case SB_LINEDOWN:	// May move past the logical end
30848af74909SZhong Yang 		xPos += 20;
30858af74909SZhong Yang 		break;
30868af74909SZhong Yang 	case SB_PAGEUP:
30878af74909SZhong Yang 		xPos -= pageWidth;
30888af74909SZhong Yang 		break;
30898af74909SZhong Yang 	case SB_PAGEDOWN:
30908af74909SZhong Yang 		xPos += pageWidth;
30918af74909SZhong Yang 		if (xPos > scrollWidth - rcText.Width()) {	// Hit the end exactly
30928af74909SZhong Yang 			xPos = scrollWidth - static_cast<int>(rcText.Width());
30938af74909SZhong Yang 		}
30948af74909SZhong Yang 		break;
30958af74909SZhong Yang 	case SB_TOP:
30968af74909SZhong Yang 		xPos = 0;
30978af74909SZhong Yang 		break;
30988af74909SZhong Yang 	case SB_BOTTOM:
30998af74909SZhong Yang 		xPos = scrollWidth;
31008af74909SZhong Yang 		break;
31018af74909SZhong Yang 	case SB_THUMBPOSITION:
31028af74909SZhong Yang 	case SB_THUMBTRACK: {
31038af74909SZhong Yang 			// Do NOT use wParam, its 16 bit and not enough for very long lines. Its still possible to overflow the 32 bit but you have to try harder =]
31048af74909SZhong Yang 			SCROLLINFO si;
31058af74909SZhong Yang 			si.cbSize = sizeof(si);
31068af74909SZhong Yang 			si.fMask = SIF_TRACKPOS;
31078af74909SZhong Yang 			if (GetScrollInfo(SB_HORZ, &si)) {
31088af74909SZhong Yang 				xPos = si.nTrackPos;
31098af74909SZhong Yang 			}
31108af74909SZhong Yang 		}
31118af74909SZhong Yang 		break;
31128af74909SZhong Yang 	}
31138af74909SZhong Yang 	HorizontalScrollTo(xPos);
31148af74909SZhong Yang }
31158af74909SZhong Yang 
31168af74909SZhong Yang /**
31178af74909SZhong Yang  * Redraw all of text area.
31188af74909SZhong Yang  * This paint will not be abandoned.
31198af74909SZhong Yang  */
FullPaint()31208af74909SZhong Yang void ScintillaWin::FullPaint() {
31218af74909SZhong Yang 	if ((technology == SC_TECHNOLOGY_DEFAULT) || (technology == SC_TECHNOLOGY_DIRECTWRITEDC)) {
31228af74909SZhong Yang 		HDC hdc = ::GetDC(MainHWND());
31238af74909SZhong Yang 		FullPaintDC(hdc);
31248af74909SZhong Yang 		::ReleaseDC(MainHWND(), hdc);
31258af74909SZhong Yang 	} else {
31268af74909SZhong Yang 		FullPaintDC({});
31278af74909SZhong Yang 	}
31288af74909SZhong Yang }
31298af74909SZhong Yang 
31308af74909SZhong Yang /**
31318af74909SZhong Yang  * Redraw all of text area on the specified DC.
31328af74909SZhong Yang  * This paint will not be abandoned.
31338af74909SZhong Yang  */
FullPaintDC(HDC hdc)31348af74909SZhong Yang void ScintillaWin::FullPaintDC(HDC hdc) {
31358af74909SZhong Yang 	paintState = painting;
31368af74909SZhong Yang 	rcPaint = GetClientRectangle();
31378af74909SZhong Yang 	paintingAllText = true;
31388af74909SZhong Yang 	PaintDC(hdc);
31398af74909SZhong Yang 	paintState = notPainting;
31408af74909SZhong Yang }
31418af74909SZhong Yang 
31428af74909SZhong Yang namespace {
31438af74909SZhong Yang 
CompareDevCap(HDC hdc,HDC hOtherDC,int nIndex)31448af74909SZhong Yang bool CompareDevCap(HDC hdc, HDC hOtherDC, int nIndex) noexcept {
31458af74909SZhong Yang 	return ::GetDeviceCaps(hdc, nIndex) == ::GetDeviceCaps(hOtherDC, nIndex);
31468af74909SZhong Yang }
31478af74909SZhong Yang 
31488af74909SZhong Yang }
31498af74909SZhong Yang 
IsCompatibleDC(HDC hOtherDC)31508af74909SZhong Yang bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) noexcept {
31518af74909SZhong Yang 	HDC hdc = ::GetDC(MainHWND());
31528af74909SZhong Yang 	const bool isCompatible =
31538af74909SZhong Yang 		CompareDevCap(hdc, hOtherDC, TECHNOLOGY) &&
31548af74909SZhong Yang 		CompareDevCap(hdc, hOtherDC, LOGPIXELSY) &&
31558af74909SZhong Yang 		CompareDevCap(hdc, hOtherDC, LOGPIXELSX) &&
31568af74909SZhong Yang 		CompareDevCap(hdc, hOtherDC, BITSPIXEL) &&
31578af74909SZhong Yang 		CompareDevCap(hdc, hOtherDC, PLANES);
31588af74909SZhong Yang 	::ReleaseDC(MainHWND(), hdc);
31598af74909SZhong Yang 	return isCompatible;
31608af74909SZhong Yang }
31618af74909SZhong Yang 
EffectFromState(DWORD grfKeyState) const31628af74909SZhong Yang DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) const noexcept {
31638af74909SZhong Yang 	// These are the Wordpad semantics.
31648af74909SZhong Yang 	DWORD dwEffect;
31658af74909SZhong Yang 	if (inDragDrop == ddDragging)	// Internal defaults to move
31668af74909SZhong Yang 		dwEffect = DROPEFFECT_MOVE;
31678af74909SZhong Yang 	else
31688af74909SZhong Yang 		dwEffect = DROPEFFECT_COPY;
31698af74909SZhong Yang 	if (grfKeyState & MK_ALT)
31708af74909SZhong Yang 		dwEffect = DROPEFFECT_MOVE;
31718af74909SZhong Yang 	if (grfKeyState & MK_CONTROL)
31728af74909SZhong Yang 		dwEffect = DROPEFFECT_COPY;
31738af74909SZhong Yang 	return dwEffect;
31748af74909SZhong Yang }
31758af74909SZhong Yang 
31768af74909SZhong Yang /// Implement IUnknown
QueryInterface(REFIID riid,PVOID * ppv)31778af74909SZhong Yang STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
31788af74909SZhong Yang 	*ppv = nullptr;
31798af74909SZhong Yang 	if (riid == IID_IUnknown)
31808af74909SZhong Yang 		*ppv = reinterpret_cast<IDropTarget *>(&dt);
31818af74909SZhong Yang 	if (riid == IID_IDropSource)
31828af74909SZhong Yang 		*ppv = reinterpret_cast<IDropSource *>(&ds);
31838af74909SZhong Yang 	if (riid == IID_IDropTarget)
31848af74909SZhong Yang 		*ppv = reinterpret_cast<IDropTarget *>(&dt);
31858af74909SZhong Yang 	if (riid == IID_IDataObject)
31868af74909SZhong Yang 		*ppv = reinterpret_cast<IDataObject *>(&dob);
31878af74909SZhong Yang 	if (!*ppv)
31888af74909SZhong Yang 		return E_NOINTERFACE;
31898af74909SZhong Yang 	return S_OK;
31908af74909SZhong Yang }
31918af74909SZhong Yang 
STDMETHODIMP_(ULONG)31928af74909SZhong Yang STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
31938af74909SZhong Yang 	return 1;
31948af74909SZhong Yang }
31958af74909SZhong Yang 
STDMETHODIMP_(ULONG)31968af74909SZhong Yang STDMETHODIMP_(ULONG) ScintillaWin::Release() {
31978af74909SZhong Yang 	return 1;
31988af74909SZhong Yang }
31998af74909SZhong Yang 
32008af74909SZhong Yang /// Implement IDropTarget
DragEnter(LPDATAOBJECT pIDataSource,DWORD grfKeyState,POINTL,PDWORD pdwEffect)32018af74909SZhong Yang STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
32028af74909SZhong Yang                                      POINTL, PDWORD pdwEffect) {
32038af74909SZhong Yang 	if (!pIDataSource )
32048af74909SZhong Yang 		return E_POINTER;
32058af74909SZhong Yang 	FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
32068af74909SZhong Yang 	const HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
32078af74909SZhong Yang 	hasOKText = (hrHasUText == S_OK);
32088af74909SZhong Yang 	if (hasOKText) {
32098af74909SZhong Yang 		*pdwEffect = EffectFromState(grfKeyState);
32108af74909SZhong Yang 	} else {
32118af74909SZhong Yang 		*pdwEffect = DROPEFFECT_NONE;
32128af74909SZhong Yang 	}
32138af74909SZhong Yang 
32148af74909SZhong Yang 	return S_OK;
32158af74909SZhong Yang }
32168af74909SZhong Yang 
DragOver(DWORD grfKeyState,POINTL pt,PDWORD pdwEffect)32178af74909SZhong Yang STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
32188af74909SZhong Yang 	try {
32198af74909SZhong Yang 		if (!hasOKText || pdoc->IsReadOnly()) {
32208af74909SZhong Yang 			*pdwEffect = DROPEFFECT_NONE;
32218af74909SZhong Yang 			return S_OK;
32228af74909SZhong Yang 		}
32238af74909SZhong Yang 
32248af74909SZhong Yang 		*pdwEffect = EffectFromState(grfKeyState);
32258af74909SZhong Yang 
32268af74909SZhong Yang 		// Update the cursor.
32278af74909SZhong Yang 		POINT rpt = {pt.x, pt.y};
32288af74909SZhong Yang 		::ScreenToClient(MainHWND(), &rpt);
32298af74909SZhong Yang 		SetDragPosition(SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace()));
32308af74909SZhong Yang 
32318af74909SZhong Yang 		return S_OK;
32328af74909SZhong Yang 	} catch (...) {
32338af74909SZhong Yang 		errorStatus = SC_STATUS_FAILURE;
32348af74909SZhong Yang 	}
32358af74909SZhong Yang 	return E_FAIL;
32368af74909SZhong Yang }
32378af74909SZhong Yang 
DragLeave()32388af74909SZhong Yang STDMETHODIMP ScintillaWin::DragLeave() {
32398af74909SZhong Yang 	try {
32408af74909SZhong Yang 		SetDragPosition(SelectionPosition(Sci::invalidPosition));
32418af74909SZhong Yang 		return S_OK;
32428af74909SZhong Yang 	} catch (...) {
32438af74909SZhong Yang 		errorStatus = SC_STATUS_FAILURE;
32448af74909SZhong Yang 	}
32458af74909SZhong Yang 	return E_FAIL;
32468af74909SZhong Yang }
32478af74909SZhong Yang 
Drop(LPDATAOBJECT pIDataSource,DWORD grfKeyState,POINTL pt,PDWORD pdwEffect)32488af74909SZhong Yang STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
32498af74909SZhong Yang                                 POINTL pt, PDWORD pdwEffect) {
32508af74909SZhong Yang 	try {
32518af74909SZhong Yang 		*pdwEffect = EffectFromState(grfKeyState);
32528af74909SZhong Yang 
32538af74909SZhong Yang 		if (!pIDataSource)
32548af74909SZhong Yang 			return E_POINTER;
32558af74909SZhong Yang 
32568af74909SZhong Yang 		SetDragPosition(SelectionPosition(Sci::invalidPosition));
32578af74909SZhong Yang 
32588af74909SZhong Yang 		std::string putf;
32598af74909SZhong Yang 		FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
32608af74909SZhong Yang 		STGMEDIUM medium{};
32618af74909SZhong Yang 		const HRESULT hr = pIDataSource->GetData(&fmtu, &medium);
32628af74909SZhong Yang 		if (!SUCCEEDED(hr)) {
32638af74909SZhong Yang 			return hr;
32648af74909SZhong Yang 		}
32658af74909SZhong Yang 		if (medium.hGlobal) {
32668af74909SZhong Yang 			GlobalMemory memUDrop(medium.hGlobal);
32678af74909SZhong Yang 			if (const wchar_t *uptr = static_cast<const wchar_t *>(memUDrop.ptr)) {
32688af74909SZhong Yang 				putf = EncodeWString(uptr);
32698af74909SZhong Yang 			}
32708af74909SZhong Yang 			memUDrop.Unlock();
32718af74909SZhong Yang 		}
32728af74909SZhong Yang 
32738af74909SZhong Yang 		if (putf.empty()) {
32748af74909SZhong Yang 			return S_OK;
32758af74909SZhong Yang 		}
32768af74909SZhong Yang 
32778af74909SZhong Yang 		FORMATETC fmtr = {cfColumnSelect, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
32788af74909SZhong Yang 		const bool isRectangular = S_OK == pIDataSource->QueryGetData(&fmtr);
32798af74909SZhong Yang 
32808af74909SZhong Yang 		POINT rpt = {pt.x, pt.y};
32818af74909SZhong Yang 		::ScreenToClient(MainHWND(), &rpt);
32828af74909SZhong Yang 		const SelectionPosition movePos = SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace());
32838af74909SZhong Yang 
32848af74909SZhong Yang 		DropAt(movePos, putf.c_str(), putf.size(), *pdwEffect == DROPEFFECT_MOVE, isRectangular);
32858af74909SZhong Yang 
32868af74909SZhong Yang 		// Free data
32878af74909SZhong Yang 		::ReleaseStgMedium(&medium);
32888af74909SZhong Yang 
32898af74909SZhong Yang 		return S_OK;
32908af74909SZhong Yang 	} catch (...) {
32918af74909SZhong Yang 		errorStatus = SC_STATUS_FAILURE;
32928af74909SZhong Yang 	}
32938af74909SZhong Yang 	return E_FAIL;
32948af74909SZhong Yang }
32958af74909SZhong Yang 
32968af74909SZhong Yang /// Implement important part of IDataObject
GetData(FORMATETC * pFEIn,STGMEDIUM * pSTM)32978af74909SZhong Yang STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
32988af74909SZhong Yang 	if (!SupportedFormat(pFEIn)) {
32998af74909SZhong Yang 		//Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
33008af74909SZhong Yang 		return DATA_E_FORMATETC;
33018af74909SZhong Yang 	}
33028af74909SZhong Yang 
33038af74909SZhong Yang 	pSTM->tymed = TYMED_HGLOBAL;
33048af74909SZhong Yang 	//Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
33058af74909SZhong Yang 
33068af74909SZhong Yang 	GlobalMemory uniText;
33078af74909SZhong Yang 	CopyToGlobal(uniText, drag);
33088af74909SZhong Yang 	pSTM->hGlobal = uniText ? uniText.Unlock() : 0;
33098af74909SZhong Yang 	pSTM->pUnkForRelease = nullptr;
33108af74909SZhong Yang 	return S_OK;
33118af74909SZhong Yang }
33128af74909SZhong Yang 
Prepare()33138af74909SZhong Yang void ScintillaWin::Prepare() noexcept {
33148af74909SZhong Yang 	Platform_Initialise(hInstance);
33158af74909SZhong Yang 
33168af74909SZhong Yang 	// Register the CallTip class
33178af74909SZhong Yang 	WNDCLASSEX wndclassc{};
33188af74909SZhong Yang 	wndclassc.cbSize = sizeof(wndclassc);
33198af74909SZhong Yang 	wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
33208af74909SZhong Yang 	wndclassc.cbWndExtra = sizeof(ScintillaWin *);
33218af74909SZhong Yang 	wndclassc.hInstance = hInstance;
33228af74909SZhong Yang 	wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
33238af74909SZhong Yang 	wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
33248af74909SZhong Yang 	wndclassc.lpszClassName = callClassName;
33258af74909SZhong Yang 
33268af74909SZhong Yang 	callClassAtom = ::RegisterClassEx(&wndclassc);
33278af74909SZhong Yang }
33288af74909SZhong Yang 
Register(HINSTANCE hInstance_)33298af74909SZhong Yang bool ScintillaWin::Register(HINSTANCE hInstance_) noexcept {
33308af74909SZhong Yang 
33318af74909SZhong Yang 	hInstance = hInstance_;
33328af74909SZhong Yang 
33338af74909SZhong Yang 	// Register the Scintilla class
33348af74909SZhong Yang 	// Register Scintilla as a wide character window
33358af74909SZhong Yang 	WNDCLASSEXW wndclass {};
33368af74909SZhong Yang 	wndclass.cbSize = sizeof(wndclass);
33378af74909SZhong Yang 	wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
33388af74909SZhong Yang 	wndclass.lpfnWndProc = ScintillaWin::SWndProc;
33398af74909SZhong Yang 	wndclass.cbWndExtra = sizeof(ScintillaWin *);
33408af74909SZhong Yang 	wndclass.hInstance = hInstance;
33418af74909SZhong Yang 	wndclass.lpszClassName = L"Scintilla";
33428af74909SZhong Yang 	scintillaClassAtom = ::RegisterClassExW(&wndclass);
33438af74909SZhong Yang 	const bool result = 0 != scintillaClassAtom;
33448af74909SZhong Yang 
33458af74909SZhong Yang 	return result;
33468af74909SZhong Yang }
33478af74909SZhong Yang 
Unregister()33488af74909SZhong Yang bool ScintillaWin::Unregister() noexcept {
33498af74909SZhong Yang 	bool result = true;
33508af74909SZhong Yang 	if (0 != scintillaClassAtom) {
33518af74909SZhong Yang 		if (::UnregisterClass(MAKEINTATOM(scintillaClassAtom), hInstance) == 0) {
33528af74909SZhong Yang 			result = false;
33538af74909SZhong Yang 		}
33548af74909SZhong Yang 		scintillaClassAtom = 0;
33558af74909SZhong Yang 	}
33568af74909SZhong Yang 	if (0 != callClassAtom) {
33578af74909SZhong Yang 		if (::UnregisterClass(MAKEINTATOM(callClassAtom), hInstance) == 0) {
33588af74909SZhong Yang 			result = false;
33598af74909SZhong Yang 		}
33608af74909SZhong Yang 		callClassAtom = 0;
33618af74909SZhong Yang 	}
33628af74909SZhong Yang 	return result;
33638af74909SZhong Yang }
33648af74909SZhong Yang 
HasCaretSizeChanged() const33658af74909SZhong Yang bool ScintillaWin::HasCaretSizeChanged() const noexcept {
33668af74909SZhong Yang 	if (
33678af74909SZhong Yang 		( (0 != vs.caretWidth) && (sysCaretWidth != vs.caretWidth) )
33688af74909SZhong Yang 		|| ((0 != vs.lineHeight) && (sysCaretHeight != vs.lineHeight))
33698af74909SZhong Yang 		) {
33708af74909SZhong Yang 		return true;
33718af74909SZhong Yang 	}
33728af74909SZhong Yang 	return false;
33738af74909SZhong Yang }
33748af74909SZhong Yang 
CreateSystemCaret()33758af74909SZhong Yang BOOL ScintillaWin::CreateSystemCaret() {
33768af74909SZhong Yang 	sysCaretWidth = vs.caretWidth;
33778af74909SZhong Yang 	if (0 == sysCaretWidth) {
33788af74909SZhong Yang 		sysCaretWidth = 1;
33798af74909SZhong Yang 	}
33808af74909SZhong Yang 	sysCaretHeight = vs.lineHeight;
33818af74909SZhong Yang 	const int bitmapSize = (((sysCaretWidth + 15) & ~15) >> 3) *
33828af74909SZhong Yang 		sysCaretHeight;
33838af74909SZhong Yang 	std::vector<BYTE> bits(bitmapSize);
33848af74909SZhong Yang 	sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1,
33858af74909SZhong Yang 		1, &bits[0]);
33868af74909SZhong Yang 	const BOOL retval = ::CreateCaret(
33878af74909SZhong Yang 		MainHWND(), sysCaretBitmap,
33888af74909SZhong Yang 		sysCaretWidth, sysCaretHeight);
33898af74909SZhong Yang 	if (technology == SC_TECHNOLOGY_DEFAULT) {
33908af74909SZhong Yang 		// System caret interferes with Direct2D drawing so only show it for GDI.
33918af74909SZhong Yang 		::ShowCaret(MainHWND());
33928af74909SZhong Yang 	}
33938af74909SZhong Yang 	return retval;
33948af74909SZhong Yang }
33958af74909SZhong Yang 
DestroySystemCaret()33968af74909SZhong Yang BOOL ScintillaWin::DestroySystemCaret() noexcept {
33978af74909SZhong Yang 	::HideCaret(MainHWND());
33988af74909SZhong Yang 	const BOOL retval = ::DestroyCaret();
33998af74909SZhong Yang 	if (sysCaretBitmap) {
34008af74909SZhong Yang 		::DeleteObject(sysCaretBitmap);
34018af74909SZhong Yang 		sysCaretBitmap = {};
34028af74909SZhong Yang 	}
34038af74909SZhong Yang 	return retval;
34048af74909SZhong Yang }
34058af74909SZhong Yang 
CTWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)34068af74909SZhong Yang LRESULT PASCAL ScintillaWin::CTWndProc(
34078af74909SZhong Yang 	HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
34088af74909SZhong Yang 	// Find C++ object associated with window.
34098af74909SZhong Yang 	ScintillaWin *sciThis = static_cast<ScintillaWin *>(PointerFromWindow(hWnd));
34108af74909SZhong Yang 	try {
34118af74909SZhong Yang 		// ctp will be zero if WM_CREATE not seen yet
34128af74909SZhong Yang 		if (sciThis == nullptr) {
34138af74909SZhong Yang 			if (iMessage == WM_CREATE) {
34148af74909SZhong Yang 				// Associate CallTip object with window
34158af74909SZhong Yang 				CREATESTRUCT *pCreate = static_cast<CREATESTRUCT *>(PtrFromSPtr(lParam));
34168af74909SZhong Yang 				SetWindowPointer(hWnd, pCreate->lpCreateParams);
34178af74909SZhong Yang 				return 0;
34188af74909SZhong Yang 			} else {
34198af74909SZhong Yang 				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
34208af74909SZhong Yang 			}
34218af74909SZhong Yang 		} else {
34228af74909SZhong Yang 			if (iMessage == WM_NCDESTROY) {
34238af74909SZhong Yang 				SetWindowPointer(hWnd, nullptr);
34248af74909SZhong Yang 				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
34258af74909SZhong Yang 			} else if (iMessage == WM_PAINT) {
34268af74909SZhong Yang 				PAINTSTRUCT ps;
34278af74909SZhong Yang 				::BeginPaint(hWnd, &ps);
34288af74909SZhong Yang 				std::unique_ptr<Surface> surfaceWindow(Surface::Allocate(sciThis->technology));
34298af74909SZhong Yang #if defined(USE_D2D)
34308af74909SZhong Yang 				ID2D1HwndRenderTarget *pCTRenderTarget = nullptr;
34318af74909SZhong Yang #endif
34328af74909SZhong Yang 				RECT rc;
34338af74909SZhong Yang 				GetClientRect(hWnd, &rc);
34348af74909SZhong Yang 				// Create a Direct2D render target.
34358af74909SZhong Yang 				if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) {
34368af74909SZhong Yang 					surfaceWindow->Init(ps.hdc, hWnd);
34378af74909SZhong Yang 				} else {
34388af74909SZhong Yang #if defined(USE_D2D)
34398af74909SZhong Yang 					D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp;
34408af74909SZhong Yang 					dhrtp.hwnd = hWnd;
34418af74909SZhong Yang 					dhrtp.pixelSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
34428af74909SZhong Yang 					dhrtp.presentOptions = (sciThis->technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ?
34438af74909SZhong Yang 						D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE;
34448af74909SZhong Yang 
34458af74909SZhong Yang 					D2D1_RENDER_TARGET_PROPERTIES drtp;
34468af74909SZhong Yang 					drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
34478af74909SZhong Yang 					drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
34488af74909SZhong Yang 					drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
34498af74909SZhong Yang 					drtp.dpiX = 96.0;
34508af74909SZhong Yang 					drtp.dpiY = 96.0;
34518af74909SZhong Yang 					drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE;
34528af74909SZhong Yang 					drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT;
34538af74909SZhong Yang 
34548af74909SZhong Yang 					if (!SUCCEEDED(pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pCTRenderTarget))) {
34558af74909SZhong Yang 						surfaceWindow->Release();
34568af74909SZhong Yang 						::EndPaint(hWnd, &ps);
34578af74909SZhong Yang 						return 0;
34588af74909SZhong Yang 					}
34598af74909SZhong Yang 					// If above SUCCEEDED, then pCTRenderTarget not nullptr
34608af74909SZhong Yang 					assert(pCTRenderTarget);
34618af74909SZhong Yang 					if (pCTRenderTarget) {
34628af74909SZhong Yang 						surfaceWindow->Init(pCTRenderTarget, hWnd);
34638af74909SZhong Yang 						pCTRenderTarget->BeginDraw();
34648af74909SZhong Yang 					}
34658af74909SZhong Yang #endif
34668af74909SZhong Yang 				}
34678af74909SZhong Yang 				surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage);
34688af74909SZhong Yang 				surfaceWindow->SetDBCSMode(sciThis->ct.codePage);
34698af74909SZhong Yang 				surfaceWindow->SetBidiR2L(sciThis->BidirectionalR2L());
34708af74909SZhong Yang 				sciThis->ct.PaintCT(surfaceWindow.get());
34718af74909SZhong Yang #if defined(USE_D2D)
34728af74909SZhong Yang 				if (pCTRenderTarget)
34738af74909SZhong Yang 					pCTRenderTarget->EndDraw();
34748af74909SZhong Yang #endif
34758af74909SZhong Yang 				surfaceWindow->Release();
34768af74909SZhong Yang #if defined(USE_D2D)
34778af74909SZhong Yang 				ReleaseUnknown(pCTRenderTarget);
34788af74909SZhong Yang #endif
34798af74909SZhong Yang 				::EndPaint(hWnd, &ps);
34808af74909SZhong Yang 				return 0;
34818af74909SZhong Yang 			} else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) {
34828af74909SZhong Yang 				POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
34838af74909SZhong Yang 				ScreenToClient(hWnd, &pt);
34848af74909SZhong Yang 				sciThis->ct.MouseClick(PointFromPOINT(pt));
34858af74909SZhong Yang 				sciThis->CallTipClick();
34868af74909SZhong Yang 				return 0;
34878af74909SZhong Yang 			} else if (iMessage == WM_LBUTTONDOWN) {
34888af74909SZhong Yang 				// This does not fire due to the hit test code
34898af74909SZhong Yang 				sciThis->ct.MouseClick(PointFromLParam(lParam));
34908af74909SZhong Yang 				sciThis->CallTipClick();
34918af74909SZhong Yang 				return 0;
34928af74909SZhong Yang 			} else if (iMessage == WM_SETCURSOR) {
34938af74909SZhong Yang 				::SetCursor(::LoadCursor(NULL, IDC_ARROW));
34948af74909SZhong Yang 				return 0;
34958af74909SZhong Yang 			} else if (iMessage == WM_NCHITTEST) {
34968af74909SZhong Yang 				return HTCAPTION;
34978af74909SZhong Yang 			} else {
34988af74909SZhong Yang 				return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
34998af74909SZhong Yang 			}
35008af74909SZhong Yang 		}
35018af74909SZhong Yang 	} catch (...) {
35028af74909SZhong Yang 		sciThis->errorStatus = SC_STATUS_FAILURE;
35038af74909SZhong Yang 	}
35048af74909SZhong Yang 	return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
35058af74909SZhong Yang }
35068af74909SZhong Yang 
DirectFunction(sptr_t ptr,UINT iMessage,uptr_t wParam,sptr_t lParam)35078af74909SZhong Yang sptr_t ScintillaWin::DirectFunction(
35088af74909SZhong Yang     sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam) {
35098af74909SZhong Yang 	PLATFORM_ASSERT(::GetCurrentThreadId() == ::GetWindowThreadProcessId(reinterpret_cast<ScintillaWin *>(ptr)->MainHWND(), nullptr));
35108af74909SZhong Yang 	return reinterpret_cast<ScintillaWin *>(ptr)->WndProc(iMessage, wParam, lParam);
35118af74909SZhong Yang }
35128af74909SZhong Yang 
35138af74909SZhong Yang namespace Scintilla {
35148af74909SZhong Yang 
DirectFunction(ScintillaWin * sci,UINT iMessage,uptr_t wParam,sptr_t lParam)35158af74909SZhong Yang sptr_t DirectFunction(
35168af74909SZhong Yang     ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) {
35178af74909SZhong Yang 	return sci->WndProc(iMessage, wParam, lParam);
35188af74909SZhong Yang }
35198af74909SZhong Yang 
35208af74909SZhong Yang }
35218af74909SZhong Yang 
SWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)35228af74909SZhong Yang LRESULT PASCAL ScintillaWin::SWndProc(
35238af74909SZhong Yang 	HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
35248af74909SZhong Yang 	//Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);
35258af74909SZhong Yang 
35268af74909SZhong Yang 	// Find C++ object associated with window.
35278af74909SZhong Yang 	ScintillaWin *sci = static_cast<ScintillaWin *>(PointerFromWindow(hWnd));
35288af74909SZhong Yang 	// sci will be zero if WM_CREATE not seen yet
35298af74909SZhong Yang 	if (sci == nullptr) {
35308af74909SZhong Yang 		try {
35318af74909SZhong Yang 			if (iMessage == WM_CREATE) {
35328af74909SZhong Yang 				static std::once_flag once;
35338af74909SZhong Yang 				std::call_once(once, Prepare);
35348af74909SZhong Yang 				// Create C++ object associated with window
35358af74909SZhong Yang 				sci = new ScintillaWin(hWnd);
35368af74909SZhong Yang 				SetWindowPointer(hWnd, sci);
35378af74909SZhong Yang 				return sci->WndProc(iMessage, wParam, lParam);
35388af74909SZhong Yang 			}
35398af74909SZhong Yang 		} catch (...) {
35408af74909SZhong Yang 		}
35418af74909SZhong Yang 		return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
35428af74909SZhong Yang 	} else {
35438af74909SZhong Yang 		if (iMessage == WM_NCDESTROY) {
35448af74909SZhong Yang 			try {
35458af74909SZhong Yang 				sci->Finalise();
35468af74909SZhong Yang 				delete sci;
35478af74909SZhong Yang 			} catch (...) {
35488af74909SZhong Yang 			}
35498af74909SZhong Yang 			SetWindowPointer(hWnd, nullptr);
35508af74909SZhong Yang 			return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
35518af74909SZhong Yang 		} else {
35528af74909SZhong Yang 			return sci->WndProc(iMessage, wParam, lParam);
35538af74909SZhong Yang 		}
35548af74909SZhong Yang 	}
35558af74909SZhong Yang }
35568af74909SZhong Yang 
35578af74909SZhong Yang // This function is externally visible so it can be called from container when building statically.
35588af74909SZhong Yang // Must be called once only.
Scintilla_RegisterClasses(void * hInstance)35598af74909SZhong Yang int Scintilla_RegisterClasses(void *hInstance) {
35608af74909SZhong Yang 	const bool result = ScintillaWin::Register(static_cast<HINSTANCE>(hInstance));
35618af74909SZhong Yang 	return result;
35628af74909SZhong Yang }
35638af74909SZhong Yang 
35648af74909SZhong Yang namespace Scintilla {
35658af74909SZhong Yang 
ResourcesRelease(bool fromDllMain)35668af74909SZhong Yang int ResourcesRelease(bool fromDllMain) noexcept {
35678af74909SZhong Yang 	const bool result = ScintillaWin::Unregister();
35688af74909SZhong Yang 	Platform_Finalise(fromDllMain);
35698af74909SZhong Yang 	return result;
35708af74909SZhong Yang }
35718af74909SZhong Yang 
35728af74909SZhong Yang }
35738af74909SZhong Yang 
35748af74909SZhong Yang // This function is externally visible so it can be called from container when building statically.
Scintilla_ReleaseResources()35758af74909SZhong Yang int Scintilla_ReleaseResources() {
35768af74909SZhong Yang 	return Scintilla::ResourcesRelease(false);
35778af74909SZhong Yang }
3578