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

📄 scintillawin.cxx

📁 最强源代码编辑控件
💻 CXX
📖 第 1 页 / 共 5 页
字号:
				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 + -