From a33833212f040272fc6c97047c8cb335b6f5405a Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 24 Jul 2012 06:41:19 +0000 Subject: SimpleAR, SimpleStatusMsg, SmileyAdd, SpellChecker: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1149 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SpellChecker/src/RichEdit.cpp | 332 ++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 plugins/SpellChecker/src/RichEdit.cpp (limited to 'plugins/SpellChecker/src/RichEdit.cpp') diff --git a/plugins/SpellChecker/src/RichEdit.cpp b/plugins/SpellChecker/src/RichEdit.cpp new file mode 100644 index 0000000000..102b1acfde --- /dev/null +++ b/plugins/SpellChecker/src/RichEdit.cpp @@ -0,0 +1,332 @@ +#include "commons.h" + + +RichEdit::RichEdit(HWND hwnd) + : hwnd(NULL), ole(NULL), textDocument(NULL), stopped(0), undoEnabled(TRUE) +{ + SetHWND(hwnd); +} + +RichEdit::~RichEdit() +{ + SetHWND(NULL); +} + +bool RichEdit::IsValid() const +{ + return ole != NULL; +} + +HWND RichEdit::GetHWND() const +{ + return hwnd; +} + +void RichEdit::SetHWND(HWND hwnd) +{ + if (textDocument != NULL) + { + textDocument->Release(); + textDocument = NULL; + } + if (ole != NULL) + { + ole->Release(); + ole = NULL; + } + + this->hwnd = hwnd; + + if (hwnd == NULL) + return; + + SendMessage(EM_GETOLEINTERFACE, 0, (LPARAM) &ole); + if (ole == NULL) + return; + + if (ole->QueryInterface(IID_ITextDocument, (void**) &textDocument) != S_OK) + textDocument = NULL; +} + +LRESULT RichEdit::SendMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const +{ + return ::SendMessage(hwnd, Msg, wParam, lParam); +} + +bool RichEdit::IsReadOnly() const +{ + return (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) == ES_READONLY; +} + +void RichEdit::SuspendUndo() +{ + if (textDocument != NULL) + { + textDocument->Undo(tomSuspend, NULL); + undoEnabled = FALSE; + } +} + +void RichEdit::ResumeUndo() +{ + if (textDocument != NULL) + { + textDocument->Undo(tomResume, NULL); + undoEnabled = TRUE; + } +} + +void RichEdit::Stop() +{ + stopped++; + if (stopped != 1) + return; + + SuspendUndo(); + +// HideCaret(hwnd); + SendMessage(WM_SETREDRAW, FALSE, 0); + + SendMessage(EM_GETSCROLLPOS, 0, (LPARAM) &old_scroll_pos); + SendMessage(EM_EXGETSEL, 0, (LPARAM) &old_sel); + GetCaretPos(&caretPos); + + old_mask = SendMessage(EM_GETEVENTMASK, 0, 0); + SendMessage(EM_SETEVENTMASK, 0, old_mask & ~ENM_CHANGE); + + inverse = (old_sel.cpMin >= LOWORD(SendMessage(EM_CHARFROMPOS, 0, (LPARAM) &caretPos))); +} + +void RichEdit::Start() +{ + stopped--; + + if (stopped < 0) + { + stopped = 0; + return; + } + else if (stopped > 0) + return; + + if (inverse) + { + LONG tmp = old_sel.cpMin; + old_sel.cpMin = old_sel.cpMax; + old_sel.cpMax = tmp; + } + + SendMessage(EM_SETEVENTMASK, 0, old_mask); + SendMessage(EM_EXSETSEL, 0, (LPARAM) &old_sel); + SendMessage(EM_SETSCROLLPOS, 0, (LPARAM) &old_scroll_pos); + + SendMessage(WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwnd, NULL, FALSE); +// ShowCaret(hwnd); + + ResumeUndo(); +} + +BOOL RichEdit::IsStopped() +{ + return stopped > 0; +} + +int RichEdit::GetCharFromPos(const POINT &pt) +{ + return LOWORD(SendMessage(EM_CHARFROMPOS, 0, (LPARAM) &pt)); +} + +int RichEdit::GetLineCount() const +{ + return SendMessage(EM_GETLINECOUNT, 0, 0); +} + +void RichEdit::GetLine(int line, TCHAR *text, size_t text_len) const +{ + *((WORD*)text) = text_len - 1; + unsigned size = (unsigned) SendMessage(EM_GETLINE, (WPARAM) line, (LPARAM) text); + // Sometimes it likes to return size = lineLen+1, adding an \n at the end, so we remove it here + // to make both implementations return same size + int lineLen = GetLineLength(line); + size = (unsigned) max(0, min((int)text_len - 1, min((int) size, lineLen))); + text[size] = _T('\0'); + +/* + int len = GetLineLength(line); + if (len < 1) + { + text[0] = 0; + return; + } + + int first = GetFirstCharOfLine(line); + TCHAR *tmp = GetText(first, first + GetLineLength(line)); + lstrcpyn(text, tmp, text_len); + mir_free(tmp); +*/ +} + +int RichEdit::GetLineLength(int line) const +{ + return SendMessage(EM_LINELENGTH, GetFirstCharOfLine(line), 0); +} + +int RichEdit::GetFirstCharOfLine(int line) const +{ + return SendMessage(EM_LINEINDEX, (WPARAM) line, 0); +} + +int RichEdit::GetLineFromChar(int charPos) const +{ + return SendMessage(EM_LINEFROMCHAR, charPos, 0); +} + +CHARRANGE RichEdit::GetSel() const +{ + CHARRANGE sel; + SendMessage(EM_EXGETSEL, 0, (LPARAM) &sel); + return sel; +} + +void RichEdit::SetSel(int start, int end) +{ + CHARRANGE sel = { start, end }; + SetSel(sel); +} + +void RichEdit::SetSel(const CHARRANGE &sel) +{ + SendMessage(EM_EXSETSEL, 0, (LPARAM) &sel); +} + +int RichEdit::GetTextLength() const +{ + return GetWindowTextLength(hwnd); +} + +TCHAR *RichEdit::GetText(int start, int end) const +{ + if (end <= start) + end = GetTextLength(); + + if (textDocument != NULL) + { + ITextRange *range; + if (textDocument->Range(start, end, &range) != S_OK) + return mir_tstrdup(_T("")); + + BSTR text = NULL; + if (range->GetText(&text) != S_OK || text == NULL) + { + range->Release(); + return mir_tstrdup(_T("")); + } + + TCHAR *ret = mir_u2t(text); + + SysFreeString(text); + + range->Release(); + + return ret; + } + else + { + int len = GetTextLength(); + TCHAR *tmp = (TCHAR *) mir_alloc(len * sizeof(TCHAR)); + GetWindowText(hwnd, tmp, len); + tmp[len] = 0; + + TCHAR *ret = (TCHAR *) mir_alloc((end - start + 1) * sizeof(TCHAR)); + memmove(ret, &tmp[start], (end - start) * sizeof(TCHAR)); + ret[end - start] = 0; + + mir_free(tmp); + return ret; + } +} + +void RichEdit::ReplaceSel(const TCHAR *new_text) +{ + if (stopped) + { + CHARRANGE sel = GetSel(); + + ResumeUndo(); + + SendMessage(EM_REPLACESEL, undoEnabled, (LPARAM) new_text); + + SuspendUndo(); + + FixSel(&old_sel, sel, lstrlen(new_text)); + + SendMessage(WM_SETREDRAW, FALSE, 0); + SendMessage(EM_SETEVENTMASK, 0, old_mask & ~ENM_CHANGE); + } + else + { + SendMessage(EM_REPLACESEL, undoEnabled, (LPARAM) new_text); + } +} + +int RichEdit::Replace(int start, int end, const TCHAR *new_text) +{ + CHARRANGE sel = GetSel(); + CHARRANGE replace_sel = { start, end }; + SetSel(replace_sel); + + ReplaceSel(new_text); + + int dif = FixSel(&sel, replace_sel, lstrlen(new_text)); + SetSel(sel); + return dif; +} + +int RichEdit::Insert(int pos, const TCHAR *text) +{ + CHARRANGE sel = GetSel(); + CHARRANGE replace_sel = { pos, pos }; + SetSel(replace_sel); + + ReplaceSel(text); + + int dif = FixSel(&sel, replace_sel, lstrlen(text)); + SetSel(sel); + return dif; +} + +int RichEdit::Delete(int start, int end) +{ + CHARRANGE sel = GetSel(); + CHARRANGE replace_sel = { start, end }; + SetSel(replace_sel); + + ReplaceSel(_T("")); + + int dif = FixSel(&sel, replace_sel, 0); + SetSel(sel); + return dif; +} + +int RichEdit::FixSel(CHARRANGE *to_fix, CHARRANGE sel_changed, int new_len) +{ + int dif = new_len - (sel_changed.cpMax - sel_changed.cpMin); + + if (to_fix->cpMax <= sel_changed.cpMin) + return dif; + + int newMax = sel_changed.cpMax + dif; + + if (to_fix->cpMin >= sel_changed.cpMax) + to_fix->cpMin += dif; + else if (to_fix->cpMin >= newMax) // For dif < 0, pos beetween sel_changed.cpMax + dif and sel_changed.cpMax + to_fix->cpMin = newMax; + + if (to_fix->cpMax >= sel_changed.cpMax) + to_fix->cpMax += dif; + else if (to_fix->cpMax >= newMax) // For dif < 0, pos beetween sel_changed.cpMax + dif and sel_changed.cpMax + to_fix->cpMax = newMax; + + return dif; +} -- cgit v1.2.3