📄 scintillawin.cxx
字号:
SetSelection(nEnd, nStart);
} else {
SetSelection(nStart, nEnd);
}
EnsureCaretVisible();
}
break;
case EM_EXSETSEL: {
if (lParam == 0) {
return 0;
}
CharacterRange *pCR = reinterpret_cast<CharacterRange *>(lParam);
selType = selStream;
if (pCR->cpMin == 0 && pCR->cpMax == -1) {
SetSelection(pCR->cpMin, pdoc->Length());
} else {
SetSelection(pCR->cpMin, pCR->cpMax);
}
EnsureCaretVisible();
return pdoc->LineFromPosition(SelectionStart());
}
case SCI_GETDIRECTFUNCTION:
return reinterpret_cast<sptr_t>(DirectFunction);
case SCI_GETDIRECTPOINTER:
return reinterpret_cast<sptr_t>(this);
case SCI_GRABFOCUS:
::SetFocus(MainHWND());
break;
#ifdef SCI_LEXER
case SCI_LOADLEXERLIBRARY:
LexerManager::GetInstance()->Load(reinterpret_cast<const char*>(lParam));
break;
#endif
default:
return ScintillaBase::WndProc(iMessage, wParam, lParam);
}
return 0l;
}
bool ScintillaWin::ValidCodePage(int codePage) const {
return codePage == 0 || codePage == SC_CP_UTF8 ||
codePage == 932 || codePage == 936 || codePage == 949 ||
codePage == 950 || codePage == 1361;
}
sptr_t ScintillaWin::DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
}
void ScintillaWin::SetTicking(bool on) {
if (timer.ticking != on) {
timer.ticking = on;
if (timer.ticking) {
timer.tickerID = ::SetTimer(MainHWND(), standardTimerID, timer.tickSize, NULL)
? reinterpret_cast<TickerID>(standardTimerID) : 0;
} else {
::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(timer.tickerID));
timer.tickerID = 0;
}
}
timer.ticksToWait = caret.period;
}
bool ScintillaWin::SetIdle(bool on) {
// On Win32 the Idler is implemented as a Timer on the Scintilla window. This
// takes advantage of the fact that WM_TIMER messages are very low priority,
// and are only posted when the message queue is empty, i.e. during idle time.
if (idler.state != on) {
if (on) {
idler.idlerID = ::SetTimer(MainHWND(), idleTimerID, 10, NULL)
? reinterpret_cast<IdlerID>(idleTimerID) : 0;
} else {
::KillTimer(MainHWND(), reinterpret_cast<uptr_t>(idler.idlerID));
idler.idlerID = 0;
}
idler.state = idler.idlerID != 0;
}
return idler.state;
}
void ScintillaWin::SetMouseCapture(bool on) {
if (mouseDownCaptures) {
if (on) {
::SetCapture(MainHWND());
} else {
::ReleaseCapture();
}
}
capturedMouse = on;
}
bool ScintillaWin::HaveMouseCapture() {
// Cannot just see if GetCapture is this window as the scroll bar also sets capture for the window
return capturedMouse;
//return capturedMouse && (::GetCapture() == MainHWND());
}
bool ScintillaWin::PaintContains(PRectangle rc) {
bool contains = true;
if (paintState == painting) {
if (!rcPaint.Contains(rc)) {
contains = false;
} else {
// In bounding rectangle so check more accurately using region
HRGN hRgnRange = ::CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
if (hRgnRange) {
HRGN hRgnDest = ::CreateRectRgn(0, 0, 0, 0);
if (hRgnDest) {
int combination = ::CombineRgn(hRgnDest, hRgnRange, hRgnUpdate, RGN_DIFF);
if (combination != NULLREGION) {
contains = false;
}
::DeleteRgn(hRgnDest);
}
::DeleteRgn(hRgnRange);
}
}
}
return contains;
}
void ScintillaWin::ScrollText(int linesToMove) {
//Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove);
::ScrollWindow(MainHWND(), 0,
vs.lineHeight * linesToMove, 0, 0);
::UpdateWindow(MainHWND());
}
void ScintillaWin::UpdateSystemCaret() {
if (hasFocus) {
if (HasCaretSizeChanged()) {
DestroySystemCaret();
CreateSystemCaret();
}
Point pos = LocationFromPosition(currentPos);
::SetCaretPos(pos.x, pos.y);
}
}
int ScintillaWin::SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw) {
return ::SetScrollInfo(MainHWND(), nBar, lpsi, bRedraw);
}
bool ScintillaWin::GetScrollInfo(int nBar, LPSCROLLINFO lpsi) {
return ::GetScrollInfo(MainHWND(), nBar, lpsi) ? true : false;
}
// Change the scroll position but avoid repaint if changing to same value
void ScintillaWin::ChangeScrollPos(int barType, int pos) {
SCROLLINFO sci = {
sizeof(sci),0,0,0,0,0,0
};
sci.fMask = SIF_POS;
GetScrollInfo(barType, &sci);
if (sci.nPos != pos) {
DwellEnd(true);
sci.nPos = pos;
SetScrollInfo(barType, &sci, TRUE);
}
}
void ScintillaWin::SetVerticalScrollPos() {
ChangeScrollPos(SB_VERT, topLine);
}
void ScintillaWin::SetHorizontalScrollPos() {
ChangeScrollPos(SB_HORZ, xOffset);
}
bool ScintillaWin::ModifyScrollBars(int nMax, int nPage) {
bool modified = false;
SCROLLINFO sci = {
sizeof(sci),0,0,0,0,0,0
};
sci.fMask = SIF_PAGE | SIF_RANGE;
GetScrollInfo(SB_VERT, &sci);
int vertEndPreferred = nMax;
if (!verticalScrollBarVisible)
vertEndPreferred = 0;
if ((sci.nMin != 0) ||
(sci.nMax != vertEndPreferred) ||
(sci.nPage != static_cast<unsigned int>(nPage)) ||
(sci.nPos != 0)) {
//Platform::DebugPrintf("Scroll info changed %d %d %d %d %d\n",
// sci.nMin, sci.nMax, sci.nPage, sci.nPos, sci.nTrackPos);
sci.fMask = SIF_PAGE | SIF_RANGE;
sci.nMin = 0;
sci.nMax = vertEndPreferred;
sci.nPage = nPage;
sci.nPos = 0;
sci.nTrackPos = 1;
SetScrollInfo(SB_VERT, &sci, TRUE);
modified = true;
}
PRectangle rcText = GetTextRectangle();
int horizEndPreferred = scrollWidth;
if (horizEndPreferred < 0)
horizEndPreferred = 0;
if (!horizontalScrollBarVisible || (wrapState != eWrapNone))
horizEndPreferred = 0;
unsigned int pageWidth = rcText.Width();
sci.fMask = SIF_PAGE | SIF_RANGE;
GetScrollInfo(SB_HORZ, &sci);
if ((sci.nMin != 0) ||
(sci.nMax != horizEndPreferred) ||
(sci.nPage != pageWidth) ||
(sci.nPos != 0)) {
sci.fMask = SIF_PAGE | SIF_RANGE;
sci.nMin = 0;
sci.nMax = horizEndPreferred;
sci.nPage = pageWidth;
sci.nPos = 0;
sci.nTrackPos = 1;
SetScrollInfo(SB_HORZ, &sci, TRUE);
modified = true;
if (scrollWidth < static_cast<int>(pageWidth)) {
HorizontalScrollTo(0);
}
}
return modified;
}
void ScintillaWin::NotifyChange() {
::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
MAKELONG(GetCtrlID(), SCEN_CHANGE),
reinterpret_cast<LPARAM>(MainHWND()));
}
void ScintillaWin::NotifyFocus(bool focus) {
::SendMessage(::GetParent(MainHWND()), WM_COMMAND,
MAKELONG(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
reinterpret_cast<LPARAM>(MainHWND()));
}
int ScintillaWin::GetCtrlID() {
return ::GetDlgCtrlID(reinterpret_cast<HWND>(wMain.GetID()));
}
void ScintillaWin::NotifyParent(SCNotification scn) {
scn.nmhdr.hwndFrom = MainHWND();
scn.nmhdr.idFrom = GetCtrlID();
::SendMessage(::GetParent(MainHWND()), WM_NOTIFY,
GetCtrlID(), reinterpret_cast<LPARAM>(&scn));
}
void ScintillaWin::NotifyDoubleClick(Point pt, bool shift) {
//Platform::DebugPrintf("ScintillaWin Double click 0\n");
ScintillaBase::NotifyDoubleClick(pt, shift);
// Send myself a WM_LBUTTONDBLCLK, so the container can handle it too.
::SendMessage(MainHWND(),
WM_LBUTTONDBLCLK,
shift ? MK_SHIFT : 0,
MAKELPARAM(pt.x, pt.y));
}
void ScintillaWin::Copy() {
//Platform::DebugPrintf("Copy\n");
if (currentPos != anchor) {
SelectionText selectedText;
CopySelectionRange(&selectedText);
CopyToClipboard(selectedText);
}
}
bool ScintillaWin::CanPaste() {
if (!Editor::CanPaste())
return false;
if (::IsClipboardFormatAvailable(CF_TEXT))
return true;
if (IsUnicodeMode())
return ::IsClipboardFormatAvailable(CF_UNICODETEXT) != 0;
return false;
}
static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {
CHARSETINFO ci = { 0, 0, { { 0, 0, 0, 0 }, { 0, 0 } } };
BOOL bci = ::TranslateCharsetInfo((DWORD*)characterSet,
&ci, TCI_SRCCHARSET);
UINT cp;
if (bci)
cp = ci.ciACP;
else
cp = documentCodePage;
CPINFO cpi;
if (!IsValidCodePage(cp) && !GetCPInfo(cp, &cpi))
cp = CP_ACP;
return cp;
}
class GlobalMemory {
HGLOBAL hand;
public:
void *ptr;
GlobalMemory() : hand(0), ptr(0) {
}
GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) {
if (hand) {
ptr = ::GlobalLock(hand);
}
}
~GlobalMemory() {
PLATFORM_ASSERT(!ptr);
}
void Allocate(size_t bytes) {
hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes);
if (hand) {
ptr = ::GlobalLock(hand);
}
}
HGLOBAL Unlock() {
PLATFORM_ASSERT(ptr);
HGLOBAL handCopy = hand;
::GlobalUnlock(hand);
ptr = 0;
hand = 0;
return handCopy;
}
void SetClip(UINT uFormat) {
::SetClipboardData(uFormat, Unlock());
}
operator bool() {
return ptr != 0;
}
SIZE_T Size() {
return ::GlobalSize(hand);
}
};
void ScintillaWin::InsertPasteText(const char *text, int len, int selStart, bool isRectangular) {
if (isRectangular) {
PasteRectangular(selStart, text, len);
} else {
if (convertPastes) {
// Convert line endings of the paste into our local line-endings mode
char *convertedString = Document::TransformLineEnds(&len, text, len, pdoc->eolMode);
if (pdoc->InsertString(currentPos, convertedString, len)) {
SetEmptySelection(currentPos + len);
}
delete []convertedString;
} else {
if (pdoc->InsertString(currentPos, text, len)) {
SetEmptySelection(currentPos + len);
}
}
}
}
void ScintillaWin::Paste() {
if (!::OpenClipboard(MainHWND()))
return;
pdoc->BeginUndoAction();
ClearSelection();
int selStart = SelectionStart();
bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
// Always use CF_UNICODETEXT if available
GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT));
if (memUSelection) {
wchar_t *uptr = static_cast<wchar_t *>(memUSelection.ptr);
if (uptr) {
unsigned int len;
char *putf;
// Default Scintilla behaviour in Unicode mode
if (IsUnicodeMode()) {
unsigned int bytes = memUSelection.Size();
len = UTF8Length(uptr, bytes / 2);
putf = new char[len + 1];
if (putf) {
UTF8FromUCS2(uptr, bytes / 2, putf, len);
}
} else {
// CF_UNICODETEXT available, but not in Unicode mode
// Convert from Unicode to current Scintilla code page
UINT cpDest = CodePageFromCharSet(
vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage);
len = ::WideCharToMultiByte(cpDest, 0, uptr, -1,
NULL, 0, NULL, NULL) - 1; // subtract 0 terminator
putf = new char[len + 1];
if (putf) {
::WideCharToMultiByte(cpDest, 0, uptr, -1,
putf, len + 1, NULL, NULL);
}
}
if (putf) {
InsertPasteText(putf, len, selStart, isRectangular);
delete []putf;
}
}
memUSelection.Unlock();
} else {
// CF_UNICODETEXT not available, paste ANSI text
GlobalMemory memSelection(::GetClipboardData(CF_TEXT));
if (memSelection) {
char *ptr = static_cast<char *>(memSelection.ptr);
if (ptr) {
unsigned int bytes = memSelection.Size();
unsigned int len = bytes;
for (unsigned int i = 0; i < bytes; i++) {
if ((len == bytes) && (0 == ptr[i]))
len = i;
}
// In Unicode mode, convert clipboard text to UTF-8
if (IsUnicodeMode()) {
wchar_t *uptr = new wchar_t[len+1];
unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0,
ptr, len, uptr, len+1);
unsigned int mlen = UTF8Length(uptr, ulen);
char *putf = new char[mlen + 1];
if (putf) {
// CP_UTF8 not available on Windows 95, so use UTF8FromUCS2()
UTF8FromUCS2(uptr, ulen, putf, mlen);
}
delete []uptr;
if (putf) {
InsertPasteText(putf, mlen, selStart, isRectangular);
delete []putf;
}
} else {
InsertPasteText(ptr, len, selStart, isRectangular);
}
}
memSelection.Unlock();
}
}
::CloseClipboard();
pdoc->EndUndoAction();
NotifyChange();
Redraw();
}
void ScintillaWin::CreateCallTipWindow(PRectangle) {
#ifdef TOTAL_CONTROL
if (!ct.wCallTip.Created()) {
ct.wCallTip = ::CreateWindow(callClassName, TEXT("ACallTip"),
WS_POPUP, 100, 100, 150, 20,
MainHWND(), 0,
GetWindowInstance(MainHWND()),
this);
ct.wDraw = ct.wCallTip;
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -