📄 scintillawin.cxx
字号:
ansiText.SetClip(CF_TEXT);
}
}
if (selectedText.rectangular) {
::SetClipboardData(cfColumnSelect, 0);
}
::CloseClipboard();
}
void ScintillaWin::ScrollMessage(WPARAM wParam) {
//DWORD dwStart = timeGetTime();
//Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam);
SCROLLINFO sci;
memset(&sci, 0, sizeof(sci));
sci.cbSize = sizeof(sci);
sci.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &sci);
//Platform::DebugPrintf("ScrollInfo %d mask=%x min=%d max=%d page=%d pos=%d track=%d\n", b,sci.fMask,
//sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
int topLineNew = topLine;
switch (LoWord(wParam)) {
case SB_LINEUP:
topLineNew -= 1;
break;
case SB_LINEDOWN:
topLineNew += 1;
break;
case SB_PAGEUP:
topLineNew -= LinesToScroll(); break;
case SB_PAGEDOWN: topLineNew += LinesToScroll(); break;
case SB_TOP: topLineNew = 0; break;
case SB_BOTTOM: topLineNew = MaxScrollPos(); break;
case SB_THUMBPOSITION: topLineNew = sci.nTrackPos; break;
case SB_THUMBTRACK: topLineNew = sci.nTrackPos; break;
}
ScrollTo(topLineNew);
}
void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
int xPos = xOffset;
PRectangle rcText = GetTextRectangle();
int pageWidth = rcText.Width() * 2 / 3;
switch (LoWord(wParam)) {
case SB_LINEUP:
xPos -= 20;
break;
case SB_LINEDOWN: // May move past the logical end
xPos += 20;
break;
case SB_PAGEUP:
xPos -= pageWidth;
break;
case SB_PAGEDOWN:
xPos += pageWidth;
if (xPos > scrollWidth - rcText.Width()) { // Hit the end exactly
xPos = scrollWidth - rcText.Width();
}
break;
case SB_TOP:
xPos = 0;
break;
case SB_BOTTOM:
xPos = scrollWidth;
break;
case SB_THUMBPOSITION:
xPos = HiWord(wParam);
break;
case SB_THUMBTRACK:
xPos = HiWord(wParam);
break;
}
HorizontalScrollTo(xPos);
}
void ScintillaWin::RealizeWindowPalette(bool inBackGround) {
RefreshStyleData();
HDC hdc = ::GetDC(MainHWND());
// Select a stock font to prevent warnings from BoundsChecker
::SelectObject(hdc, GetStockFont(DEFAULT_GUI_FONT));
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
int changes = surfaceWindow->SetPalette(&palette, inBackGround);
if (changes > 0)
Redraw();
surfaceWindow->Release();
}
::ReleaseDC(MainHWND(), hdc);
}
/**
* Redraw all of text area.
* This paint will not be abandoned.
*/
void ScintillaWin::FullPaint() {
HDC hdc = ::GetDC(MainHWND());
FullPaintDC(hdc);
::ReleaseDC(MainHWND(), hdc);
}
/**
* Redraw all of text area on the specified DC.
* This paint will not be abandoned.
*/
void ScintillaWin::FullPaintDC(HDC hdc) {
paintState = painting;
rcPaint = GetClientRectangle();
paintingAllText = true;
AutoSurface surfaceWindow(hdc, this);
if (surfaceWindow) {
Paint(surfaceWindow, rcPaint);
surfaceWindow->Release();
}
paintState = notPainting;
}
static bool CompareDevCap(HDC hdc, HDC hOtherDC, int nIndex) {
return ::GetDeviceCaps(hdc, nIndex) == ::GetDeviceCaps(hOtherDC, nIndex);
}
bool ScintillaWin::IsCompatibleDC(HDC hOtherDC) {
HDC hdc = ::GetDC(MainHWND());
bool isCompatible =
CompareDevCap(hdc, hOtherDC, TECHNOLOGY) &&
CompareDevCap(hdc, hOtherDC, LOGPIXELSY) &&
CompareDevCap(hdc, hOtherDC, LOGPIXELSX) &&
CompareDevCap(hdc, hOtherDC, BITSPIXEL) &&
CompareDevCap(hdc, hOtherDC, PLANES);
::ReleaseDC(MainHWND(), hdc);
return isCompatible;
}
/// Implement IUnknown
STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
*ppv = NULL;
if (riid == IID_IUnknown)
*ppv = reinterpret_cast<IDropTarget *>(&dt);
if (riid == IID_IDropSource)
*ppv = reinterpret_cast<IDropSource *>(&ds);
if (riid == IID_IDropTarget)
*ppv = reinterpret_cast<IDropTarget *>(&dt);
if (riid == IID_IDataObject)
*ppv = reinterpret_cast<IDataObject *>(&dob);
if (!*ppv)
return E_NOINTERFACE;
return S_OK;
}
STDMETHODIMP_(ULONG) ScintillaWin::AddRef() {
return 1;
}
STDMETHODIMP_(ULONG) ScintillaWin::Release() {
return 1;
}
/// Implement IDropTarget
STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL, PDWORD pdwEffect) {
if (pIDataSource == NULL)
return E_POINTER;
if (IsUnicodeMode()) {
FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
hasOKText = (hrHasUText == S_OK);
}
if (!hasOKText) {
FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
HRESULT hrHasText = pIDataSource->QueryGetData(&fmte);
hasOKText = (hrHasText == S_OK);
}
if (!hasOKText) {
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
return S_OK;
}
STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
if (!hasOKText || pdoc->IsReadOnly()) {
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
// These are the Wordpad semantics.
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
// Update the cursor.
POINT rpt = {pt.x, pt.y};
::ScreenToClient(MainHWND(), &rpt);
SetDragPosition(PositionFromLocation(Point(rpt.x, rpt.y)));
return S_OK;
}
STDMETHODIMP ScintillaWin::DragLeave() {
SetDragPosition(invalidPosition);
return S_OK;
}
STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL pt, PDWORD pdwEffect) {
if (inDragDrop) // Internal defaults to move
*pdwEffect = DROPEFFECT_MOVE;
else
*pdwEffect = DROPEFFECT_COPY;
if (grfKeyState & MK_ALT)
*pdwEffect = DROPEFFECT_MOVE;
if (grfKeyState & MK_CONTROL)
*pdwEffect = DROPEFFECT_COPY;
if (pIDataSource == NULL)
return E_POINTER;
SetDragPosition(invalidPosition);
STGMEDIUM medium={0,{0},0};
HRESULT hr = S_OK;
char *data = 0;
bool dataAllocated = false;
if (IsUnicodeMode()) {
FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
hr = pIDataSource->GetData(&fmtu, &medium);
if (SUCCEEDED(hr) && medium.hGlobal) {
wchar_t *udata = static_cast<wchar_t *>(::GlobalLock(medium.hGlobal));
int tlen = ::GlobalSize(medium.hGlobal);
// Convert UCS-2 to UTF-8
int dataLen = UTF8Length(udata, tlen/2);
data = new char[dataLen+1];
if (data) {
UTF8FromUCS2(udata, tlen/2, data, dataLen);
dataAllocated = true;
}
}
}
if (!data) {
FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
hr = pIDataSource->GetData(&fmte, &medium);
if (SUCCEEDED(hr) && medium.hGlobal) {
data = static_cast<char *>(::GlobalLock(medium.hGlobal));
}
}
if (!data) {
//Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
return hr;
}
FORMATETC fmtr = {cfColumnSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
POINT rpt = {pt.x, pt.y};
::ScreenToClient(MainHWND(), &rpt);
int movePos = PositionFromLocation(Point(rpt.x, rpt.y));
DropAt(movePos, data, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);
::GlobalUnlock(medium.hGlobal);
// Free data
if (medium.pUnkForRelease != NULL)
medium.pUnkForRelease->Release();
else
::GlobalFree(medium.hGlobal);
if (dataAllocated)
delete []data;
return S_OK;
}
/// Implement important part of IDataObject
STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
bool formatOK = (pFEIn->cfFormat == CF_TEXT) ||
((pFEIn->cfFormat == CF_UNICODETEXT) && IsUnicodeMode());
if (!formatOK ||
pFEIn->ptd != 0 ||
(pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
pFEIn->lindex != -1 ||
(pFEIn->tymed & TYMED_HGLOBAL) == 0
) {
//Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
return DATA_E_FORMATETC;
}
pSTM->tymed = TYMED_HGLOBAL;
//Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
GlobalMemory text;
if (pFEIn->cfFormat == CF_UNICODETEXT) {
int uchars = UCS2Length(drag.s, drag.len);
text.Allocate(2 * uchars);
if (text) {
UCS2FromUTF8(drag.s, drag.len, static_cast<wchar_t *>(text.ptr), uchars);
}
} else {
text.Allocate(drag.len);
if (text) {
memcpy(static_cast<char *>(text.ptr), drag.s, drag.len);
}
}
pSTM->hGlobal = text ? text.Unlock() : 0;
pSTM->pUnkForRelease = 0;
return S_OK;
}
bool ScintillaWin::Register(HINSTANCE hInstance_) {
hInstance = hInstance_;
bool result;
#if 0
// Register the Scintilla class
if (IsNT()) {
//if (0) {
// Register Scintilla as a wide character window
WNDCLASSEXW wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = L"Scintilla";
wndclass.hIconSm = 0;
result = ::RegisterClassExW(&wndclass);
} else {
#endif
// Register Scintilla as a normal character window
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = ::ScintillaWin::SWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = sizeof(ScintillaWin *);
wndclass.hInstance = hInstance;
wndclass.hIcon = NULL;
wndclass.hCursor = NULL;
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = scintillaClassName;
wndclass.hIconSm = 0;
result = ::RegisterClassEx(&wndclass) != 0;
//}
if (result) {
// Register the CallTip class
WNDCLASSEX wndclassc;
wndclassc.cbSize = sizeof(wndclassc);
wndclassc.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
wndclassc.cbClsExtra = 0;
wndclassc.cbWndExtra = sizeof(ScintillaWin *);
wndclassc.hInstance = hInstance;
wndclassc.hIcon = NULL;
wndclassc.hbrBackground = NULL;
wndclassc.lpszMenuName = NULL;
wndclassc.lpfnWndProc = ScintillaWin::CTWndProc;
wndclassc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wndclassc.lpszClassName = callClassName;
wndclassc.hIconSm = 0;
result = ::RegisterClassEx(&wndclassc) != 0;
}
return result;
}
bool ScintillaWin::Unregister() {
bool result = ::UnregisterClass(scintillaClassName, hInstance) != 0;
if (::UnregisterClass(callClassName, hInstance) == 0)
result = false;
return result;
}
bool ScintillaWin::HasCaretSizeChanged() {
if (
( (0 != vs.caretWidth) && (sysCaretWidth != vs.caretWidth) )
|| (0 != vs.lineHeight) && (sysCaretHeight != vs.lineHeight)
) {
return true;
}
return false;
}
BOOL ScintillaWin::CreateSystemCaret() {
sysCaretWidth = vs.caretWidth;
if (0 == sysCaretWidth) {
sysCaretWidth = 1;
}
sysCaretHeight = vs.lineHeight;
int bitmapSize = (((sysCaretWidth + 15) & ~15) >> 3) *
sysCaretHeight;
char *bits = new char[bitmapSize];
memset(bits, 0, bitmapSize);
sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1,
1, reinterpret_cast<BYTE *>(bits));
delete []bits;
BOOL retval = ::CreateCaret(
MainHWND(), sysCaretBitmap,
sysCaretWidth, sysCaretHeight);
::ShowCaret(MainHWND());
return retval;
}
BOOL ScintillaWin::DestroySystemCaret() {
::HideCaret(MainHWND());
BOOL retval = ::DestroyCaret();
if (sysCaretBitmap) {
::DeleteObject(sysCaretBitmap);
sysCaretBitmap = 0;
}
return retval;
}
// Take care of 32/64 bit pointers
#ifdef GetWindowLongPtr
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLongPtr(hWnd, 0, reinterpret_cast<LONG_PTR>(ptr));
}
#else
static void *PointerFromWindow(HWND hWnd) {
return reinterpret_cast<void *>(::GetWindowLong(hWnd, 0));
}
static void SetWindowPointer(HWND hWnd, void *ptr) {
::SetWindowLong(hWnd, 0, reinterpret_cast<LONG>(ptr));
}
#endif
sptr_t PASCAL ScintillaWin::CTWndProc(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -