📄 scintillawin.cxx
字号:
}
bool ScintillaWin::CanPaste() {
if (!Editor::CanPaste())
return false;
if (::IsClipboardFormatAvailable(CF_TEXT))
return true;
if (IsUnicodeMode())
return ::IsClipboardFormatAvailable(CF_UNICODETEXT) != 0;
return false;
}
void ScintillaWin::Paste() {
pdoc->BeginUndoAction();
int selStart = SelectionStart();
ClearSelection();
::OpenClipboard(MainHWND());
bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0;
HGLOBAL hmemUSelection = 0;
if (IsUnicodeMode()) {
hmemUSelection = ::GetClipboardData(CF_UNICODETEXT);
if (hmemUSelection) {
wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(hmemUSelection));
if (uptr) {
unsigned int bytes = ::GlobalSize(hmemUSelection);
unsigned int len = UTF8Length(uptr, bytes/2);
char *putf = new char[len+1];
if (putf) {
UTF8FromUCS2(uptr, bytes/2, putf, len);
if (isRectangular) {
PasteRectangular(selStart, putf, len);
} else {
if (pdoc->InsertString(currentPos, putf, len)) {
SetEmptySelection(currentPos + len);
}
}
delete []putf;
}
}
::GlobalUnlock(hmemUSelection);
}
}
if (!hmemUSelection) {
HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT);
if (hmemSelection) {
char *ptr = static_cast<char *>(
::GlobalLock(hmemSelection));
if (ptr) {
unsigned int bytes = ::GlobalSize(hmemSelection);
unsigned int len = bytes;
for (unsigned int i = 0; i < bytes; i++) {
if ((len == bytes) && (0 == ptr[i]))
len = i;
}
if (isRectangular) {
PasteRectangular(selStart, ptr, len);
} else {
pdoc->InsertString(currentPos, ptr, len);
SetEmptySelection(currentPos + len);
}
}
::GlobalUnlock(hmemSelection);
}
}
::CloseClipboard();
pdoc->EndUndoAction();
NotifyChange();
Redraw();
}
void ScintillaWin::CreateCallTipWindow(PRectangle) {
#ifdef TOTAL_CONTROL
if (!ct.wCallTip.Created()) {
ct.wCallTip = ::CreateWindow(callClassName, "ACallTip",
WS_POPUP, 100, 100, 150, 20,
MainHWND(), 0,
GetWindowInstance(MainHWND()),
this);
ct.wDraw = ct.wCallTip;
}
#endif
}
void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) {
#ifdef TOTAL_CONTROL
HMENU hmenuPopup = reinterpret_cast<HMENU>(popup.GetID());
if (!label[0])
::AppendMenu(hmenuPopup, MF_SEPARATOR, 0, "");
else if (enabled)
::AppendMenu(hmenuPopup, MF_STRING, cmd, label);
else
::AppendMenu(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label);
#endif
}
void ScintillaWin::ClaimSelection() {
// Windows does not have a primary selection
}
#ifdef SCI_LEXER
/*
Initial Windows-Only implementation of the external lexer
system in ScintillaWin class. Intention is to create a LexerModule
subclass (?) to have lex and fold methods which will call out to their
relevant DLLs...
*/
void ScintillaWin::SetLexer(uptr_t wParam) {
lexLanguage = wParam;
lexCurrent = LexerModule::Find(lexLanguage);
if (!lexCurrent)
lexCurrent = LexerModule::Find(SCLEX_NULL);
}
void ScintillaWin::SetLexerLanguage(const char *languageName) {
lexLanguage = SCLEX_CONTAINER;
lexCurrent = LexerModule::Find(languageName);
if (!lexCurrent)
lexCurrent = LexerModule::Find(SCLEX_NULL);
if (lexCurrent)
lexLanguage = lexCurrent->GetLanguage();
}
#endif
/// Implement IUnknown
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("EFE QI");
*ppv = NULL;
if (riid == IID_IUnknown)
*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
if (riid == IID_IEnumFORMATETC)
*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
if (!*ppv)
return E_NOINTERFACE;
FormatEnumerator_AddRef(fe);
return S_OK;
}
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) {
return ++fe->ref;
}
STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) {
fe->ref--;
if (fe->ref > 0)
return fe->ref;
delete fe;
return 0;
}
/// Implement IEnumFORMATETC
STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
//Platform::DebugPrintf("EFE Next %d %d", fe->pos, celt);
if (rgelt == NULL) return E_POINTER;
// We only support one format, so this is simple.
unsigned int putPos = 0;
while ((fe->pos < fe->formatsLen) && (putPos < celt)) {
rgelt->cfFormat = fe->formats[fe->pos];
rgelt->ptd = 0;
rgelt->dwAspect = DVASPECT_CONTENT;
rgelt->lindex = -1;
rgelt->tymed = TYMED_HGLOBAL;
fe->pos++;
putPos++;
}
if (pceltFetched)
*pceltFetched = putPos;
return putPos ? S_OK : S_FALSE;
}
STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) {
fe->pos += celt;
return S_OK;
}
STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) {
fe->pos = 0;
return S_OK;
}
STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) {
FormatEnumerator *pfe = new FormatEnumerator(fe->pos, fe->formats, fe->formatsLen);
return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
reinterpret_cast<void **>(ppenum));
}
static void *vtFormatEnumerator[] = {
(void *)(FormatEnumerator_QueryInterface),
(void *)(FormatEnumerator_AddRef),
(void *)(FormatEnumerator_Release),
(void *)(FormatEnumerator_Next),
(void *)(FormatEnumerator_Skip),
(void *)(FormatEnumerator_Reset),
(void *)(FormatEnumerator_Clone)
};
FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], int formatsLen_) {
vtbl = vtFormatEnumerator;
ref = 0; // First QI adds first reference...
pos = pos_;
formatsLen = formatsLen_;
for (int i=0;i<formatsLen;i++)
formats[i] = formats_[i];
}
/// Implement IUnknown
STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) {
return ds->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) {
return ds->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) {
return ds->sci->Release();
}
/// Implement IDropSource
STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) {
if (fEsc)
return DRAGDROP_S_CANCEL;
if (!(grfKeyState & MK_LBUTTON))
return DRAGDROP_S_DROP;
return S_OK;
}
STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) {
return DRAGDROP_S_USEDEFAULTCURSORS;
}
static void *vtDropSource[] = {
(void *)(DropSource_QueryInterface),
(void *)(DropSource_AddRef),
(void *)(DropSource_Release),
(void *)(DropSource_QueryContinueDrag),
(void *)(DropSource_GiveFeedback)
};
DropSource::DropSource() {
vtbl = vtDropSource;
sci = 0;
}
/// Implement IUnkown
STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("DO QI %x\n", pd);
return pd->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) {
return pd->sci->AddRef();
}
STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) {
return pd->sci->Release();
}
/// Implement IDataObject
STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) {
return pd->sci->GetData(pFEIn, pSTM);
}
STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) {
//Platform::DebugPrintf("DOB GetDataHere\n");
return E_NOTIMPL;
}
STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
if (pd->sci->DragIsRectangularOK(pFE->cfFormat) &&
pFE->ptd == 0 &&
(pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
pFE->lindex == -1 &&
(pFE->tymed & TYMED_HGLOBAL) != 0
) {
return S_OK;
}
bool formatOK = (pFE->cfFormat == CF_TEXT) ||
((pFE->cfFormat == CF_UNICODETEXT) && pd->sci->IsUnicodeMode()) ||
(pFE->cfFormat == CF_HDROP);
if (!formatOK ||
pFE->ptd != 0 ||
(pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
pFE->lindex != -1 ||
(pFE->tymed & TYMED_HGLOBAL) == 0
) {
//Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
//return DATA_E_FORMATETC;
return S_FALSE;
}
//Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
return S_OK;
}
STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *pd, FORMATETC *, FORMATETC *pFEOut) {
//Platform::DebugPrintf("DOB GetCanon\n");
if (pd->sci->IsUnicodeMode())
pFEOut->cfFormat = CF_UNICODETEXT;
else
pFEOut->cfFormat = CF_TEXT;
pFEOut->ptd = 0;
pFEOut->dwAspect = DVASPECT_CONTENT;
pFEOut->lindex = -1;
pFEOut->tymed = TYMED_HGLOBAL;
return S_OK;
}
STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) {
//Platform::DebugPrintf("DOB SetData\n");
return E_FAIL;
}
STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) {
//Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
if (dwDirection != DATADIR_GET) {
*ppEnum = 0;
return E_FAIL;
}
FormatEnumerator *pfe;
if (pd->sci->IsUnicodeMode()) {
CLIPFORMAT formats[] = {CF_UNICODETEXT, CF_TEXT};
pfe = new FormatEnumerator(0, formats, 2);
} else {
CLIPFORMAT formats[] = {CF_TEXT};
pfe = new FormatEnumerator(0, formats, 1);
}
return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
reinterpret_cast<void **>(ppEnum));
}
STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
//Platform::DebugPrintf("DOB DAdvise\n");
return E_FAIL;
}
STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) {
//Platform::DebugPrintf("DOB DUnadvise\n");
return E_FAIL;
}
STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) {
//Platform::DebugPrintf("DOB EnumDAdvise\n");
return E_FAIL;
}
static void *vtDataObject[] = {
(void *)(DataObject_QueryInterface),
(void *)(DataObject_AddRef),
(void *)(DataObject_Release),
(void *)(DataObject_GetData),
(void *)(DataObject_GetDataHere),
(void *)(DataObject_QueryGetData),
(void *)(DataObject_GetCanonicalFormatEtc),
(void *)(DataObject_SetData),
(void *)(DataObject_EnumFormatEtc),
(void *)(DataObject_DAdvise),
(void *)(DataObject_DUnadvise),
(void *)(DataObject_EnumDAdvise)
};
DataObject::DataObject() {
vtbl = vtDataObject;
sci = 0;
}
/// Implement IUnknown
STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("DT QI %x\n", dt);
return dt->sci->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) {
return dt->sci->AddRef();
}
STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) {
return dt->sci->Release();
}
/// Implement IDropTarget by forwarding to Scintilla
STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL pt, PDWORD pdwEffect) {
return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
}
STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
return dt->sci->DragOver(grfKeyState, pt, pdwEffect);
}
STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) {
return dt->sci->DragLeave();
}
STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL pt, PDWORD pdwEffect) {
return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
}
static void *vtDropTarget[] = {
(void *)(DropTarget_QueryInterface),
(void *)(DropTarget_AddRef),
(void *)(DropTarget_Release),
(void *)(DropTarget_DragEnter),
(void *)(DropTarget_DragOver),
(void *)(DropTarget_DragLeave),
(void *)(DropTarget_Drop)
};
DropTarget::DropTarget() {
vtbl = vtDropTarget;
sci = 0;
}
/**
* DBCS: support Input Method Editor (IME).
* Called when IME Window opened.
*/
void ScintillaWin::ImeStartComposition() {
#ifndef __DMC__
// Digital Mars compiler does not include Imm library
if (caret.active) {
// Move IME Window to current caret position
HIMC hIMC = ::ImmGetContext(MainHWND());
Point pos = LocationFromPosition(currentPos);
COMPOSITIONFORM CompForm;
CompForm.dwStyle = CFS_POINT;
CompForm.ptCurrentPos.x = pos.x;
CompForm.ptCurrentPos.y = pos.y;
::ImmSetCompositionWindow(hIMC, &CompForm);
// Set font of IME window to same as surrounded text.
if (stylesValid) {
// Since the style creation code has been made platform independent,
// The logfont for the IME is recreated here.
int styleHere = (pdoc->StyleAt(currentPos)) & 31;
LOGFONT lf = {0,0,0,0,0,0,0,0,0,0,0,0,0,""};
int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel;
if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1
sizeZoomed = 2;
AutoSurface surface(this);
int deviceHeight = sizeZoomed;
if (surface) {
deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72;
}
// The negative is to allow for leading
lf.lfHeight = -(abs(deviceHeight));
lf.lfWeight = vs.styles[styleHere].bold ? FW_BOLD : FW_NORMAL;
lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfFaceName[0] = '\0';
if (vs.styles[styleHere].fontName)
strcpy(lf.lfFaceName, vs.styles[styleHere].fontName);
::ImmSetCompositionFont(hIMC, &lf);
}
::ImmReleaseContext(MainHWND(), hIMC);
// Caret is displayed in IME window. So, caret in Scintilla is useless.
DropCaret();
}
#endif
}
/** Called when IME Window closed. */
void ScintillaWin::ImeEndComposition() {
ShowCaretAtCurrentPosition();
}
void ScintillaWin::AddCharBytes(char b0, char b1) {
int inputCodePage = InputCodePage();
if (inputCodePage && IsUnicodeMode()) {
char utfval[4]="\0\0\0";
char ansiChars[3];
ansiChars[0] = b0;
ansiChars[1] = b1;
ansiChars[2] = '\0';
wchar_t wcs[2];
::MultiByteToWideChar(inputCodePage, 0, ansiChars, 2, wcs, 1);
unsigned int len = UTF8Length(wcs, 1);
UTF8FromUCS2(wcs, 1, utfval, len);
utfval[len] = '\0';
AddCharUTF(utfval,len);
} else if (b1) {
char dbcsChars[3];
dbcsChars[0] = b0;
dbcsChars[1] = b1;
dbcsChars[2] = '\0';
AddCharUTF(dbcsChars, 2, true);
} else {
AddChar(b0);
}
}
void ScintillaWin::GetIntelliMouseParameters() {
// This retrieves the number of lines per scroll as configured inthe Mouse Properties sheet in Control Panel
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
}
void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
::OpenClipboard(MainHWND());
::EmptyClipboard();
HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
selectedText.len + 1);
if (hand) {
char *ptr = static_cast<char *>(::GlobalLock(hand));
memcpy(ptr, selectedText.s, selectedText.len);
ptr[selectedText.len] = '\0';
::GlobalUnlock(hand);
}
::SetClipboardData(CF_TEXT, hand);
if (IsUnicodeMode()) {
int uchars = UCS2Length(selectedText.s, selectedText.len);
HGLOBAL uhand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
2 * (uchars + 1));
if (uhand) {
wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(uhand));
UCS2FromUTF8(selectedText.s, selectedText.len, uptr, uchars);
uptr[uchars] = 0;
::GlobalUnlock(uhand);
}
::SetClipboardData(CF_UNICODETEXT, uhand);
}
if (selectedText.rectangular) {
::SetClipboardData(cfColumnSelect, 0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -