diff --git a/doc/Scintilla_ChangeLog.md b/doc/Scintilla_ChangeLog.md index 0fa0e2f9e..d1ad8267f 100644 --- a/doc/Scintilla_ChangeLog.md +++ b/doc/Scintilla_ChangeLog.md @@ -34,184 +34,186 @@ [**Implement wheel_action/proc_action**]: [Scintilla/include/Scintilla.h]: -typedef void ( * wheel_action ) ( int ); -typedef int ( * key_action ) ( int , int ); -extern wheel_action hl_wheel_action ; -extern key_action hl_proc_action; +typedef void (*wheel_action) (int); +typedef int (*key_action)(int , int); +extern wheel_action n2e_wheel_action; +extern key_action n2e_proc_action; +[/Scintilla/include/Scintilla.h]: [Scintilla/win32/ScintillaWin.cxx] -wheel_action hl_wheel_action = 0; -key_action hl_proc_action = 0; +wheel_action n2e_wheel_action = 0; +key_action n2e_proc_action = 0; ... - if (wParam & MK_CONTROL) - { - // Zoom! We play with the font sizes in the styles. - // Number of steps/line is ignored, we just care if sizing up or down - if ( hl_wheel_action ) { - hl_wheel_action ( linesToScroll ); - } else { - if ( linesToScroll < 0 ) { - KeyCommand ( SCI_ZOOMIN ); - } else { - KeyCommand ( SCI_ZOOMOUT ); - } - } - } + if (wParam & MK_CONTROL) { + // Zoom! We play with the font sizes in the styles. + // Number of steps/line is ignored, we just care if sizing up or down + if (n2e_wheel_action) { + n2e_wheel_action(linesToScroll); + } else { + if (linesToScroll < 0) { + KeyCommand(SCI_ZOOMIN); + } else { + KeyCommand(SCI_ZOOMOUT); + } + } + } else { ... - case WM_CHAR: - if (hl_proc_action) - { - - int ret = hl_proc_action(wParam, WM_CHAR); - - if (ret >= 0) - { - - return ret; - } + case WM_CHAR: + if (n2e_proc_action) { + int ret = n2e_proc_action(wParam, WM_CHAR); + if (ret >= 0) { + return ret; + } + } + if (((wParam >= 128) || !iscntrl(static_cast(wParam))) || !lastKeyDownConsumed) { - } ... - case WM_SYSKEYDOWN: - case WM_KEYDOWN: { - if (hl_proc_action) - - { - - int ret = hl_proc_action(wParam, WM_KEYDOWN); - - if (ret >= 0) - - { - - return ret; - - } - - } - + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + //Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL)); + if (n2e_proc_action) { + int ret = n2e_proc_action(wParam, WM_KEYDOWN); + if (ret >= 0) { + return ret; + } + } + lastKeyDownConsumed = false; +[/Scintilla/win32/ScintillaWin.cxx] [/**Implement wheel_action/proc_action**] [**Enable additional Lexers**]: [scintilla/src/Catalogue.cxx] -LINK_LEXER(lmAsn1); -LINK_LEXER(lmBash); -LINK_LEXER(lmCaml); -LINK_LEXER(lmCoffeeScript); -LINK_LEXER(lmD); -LINK_LEXER(lmLISP); -LINK_LEXER(lmTeX); + LINK_LEXER(lmAsn1); + LINK_LEXER(lmBash); + LINK_LEXER(lmCaml); + LINK_LEXER(lmCoffeeScript); + LINK_LEXER(lmD); + LINK_LEXER(lmLISP); + LINK_LEXER(lmTeX); +[/scintilla/src/Catalogue.cxx] + +The script lexlink.js is adjusted accordingly. + [/**Enable additional Lexers**] [**13. "No line selection on active selection"-feature**]: Remove triple-click handler in Editor::ButtonDown(): [scintilla/src/Editor.cxx] - if ( selectionType == selChar ) { - selectionType = selWord; - doubleClick = true; - } else if ( selectionType == selWord ) { - // do nothing on *triple* click - } else { - selectionType = selChar; - originalAnchorPos = sel.MainCaret(); - } + if (selectionType == selChar) { + selectionType = selWord; + doubleClick = true; + } else if (selectionType == selWord) { + // [n2e]: "No line selection on active selection"-feature: do nothing on *triple* click + } else { + selectionType = selChar; + originalAnchorPos = sel.MainCaret(); + } +[/scintilla/src/Editor.cxx] [/**13.**] [**6. "Scroll margin"-feature**]: New notification code added: [scintilla/include/Scintilla.h] -\#define SCN_CARETMOVED 2031 +\#define SCN_N2E_CARETMOVED 2031 +[/scintilla/include/Scintilla.h] New notification proc added: [scintilla/src/Editor.h] -void NotifyCaretMoved(); +void n2e_NotifyCaretMoved(); +[/scintilla/src/Editor.h] [scintilla/src/Editor.cxx] -void Editor::NotifyCaretMoved() +void Editor::n2e_NotifyCaretMoved() { - // Send notification - SCNotification scn = { 0 }; - scn.nmhdr.code = SCN_CARETMOVED; - NotifyParent(scn); + // Send notification + SCNotification scn = { 0 }; + scn.nmhdr.code = SCN_N2E_CARETMOVED; + NotifyParent(scn); } ... Corresponding calls added to Editor::KeyCommand(): - case SCI_PARADOWN: - ParaUpOrDown ( 1 ); - NotifyCaretMoved(); - break; - case SCI_PARADOWNEXTEND: - ParaUpOrDown ( 1, Selection::selStream ); - NotifyCaretMoved(); - break; + case SCI_PARADOWN: + ParaUpOrDown(1, Selection::noSel); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PARADOWNEXTEND: + ParaUpOrDown(1, Selection::selStream); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_LINESCROLLDOWN: ... - case SCI_PARAUP: - ParaUpOrDown ( -1 ); - NotifyCaretMoved(); - break; - case SCI_PARAUPEXTEND: - ParaUpOrDown ( -1, Selection::selStream ); - NotifyCaretMoved(); - break; + case SCI_PARAUP: + ParaUpOrDown(-1, Selection::noSel); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PARAUPEXTEND: + ParaUpOrDown(-1, Selection::selStream); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_LINESCROLLUP: ... - case SCI_PAGEUP: - PageMove ( -1 ); - NotifyCaretMoved(); - break; - case SCI_PAGEUPEXTEND: - PageMove ( -1, Selection::selStream ); - NotifyCaretMoved(); - break; - case SCI_PAGEUPRECTEXTEND: - PageMove ( -1, Selection::selRectangle ); - NotifyCaretMoved(); - break; - case SCI_PAGEDOWN: - PageMove ( 1 ); - NotifyCaretMoved(); - break; - case SCI_PAGEDOWNEXTEND: - PageMove ( 1, Selection::selStream ); - NotifyCaretMoved(); - break; - case SCI_PAGEDOWNRECTEXTEND: - PageMove ( 1, Selection::selRectangle ); - NotifyCaretMoved(); - break; + case SCI_PAGEUP: + PageMove(-1); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PAGEUPEXTEND: + PageMove(-1, Selection::selStream); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PAGEUPRECTEXTEND: + PageMove(-1, Selection::selRectangle); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PAGEDOWN: + PageMove(1); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PAGEDOWNEXTEND: + PageMove(1, Selection::selStream); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_PAGEDOWNRECTEXTEND: + PageMove(1, Selection::selRectangle); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + break; + case SCI_EDITTOGGLEOVERTYPE: +[/scintilla/src/Editor.cxx] [/**6.**] [**"Update gutter width"-feature**]: New notification code added: [scintilla/include/Scintilla.h] -\#define SCN_LINECOUNTCHANGED 2032 +\#define SCN_N2E_LINECOUNTCHANGED 2032 +[/scintilla/include/Scintilla.h] New notification proc added: [scintilla/src/Editor.h] -void NotifyLineCountChanged(); +void n2e_NotifyLineCountChanged(); +[/scintilla/src/Editor.h] [scintilla/src/Editor.cxx] -void Editor::NotifyLineCountChanged() +void Editor::n2e_NotifyLineCountChanged() { // Send notification SCNotification scn = { 0 }; - scn.nmhdr.code = SCN_LINECOUNTCHANGED; + scn.nmhdr.code = SCN_N2E_LINECOUNTCHANGED; NotifyParent(scn); } @@ -219,149 +221,146 @@ void Editor::NotifyLineCountChanged() Corresponding calls added to Editor::KeyCommand(): - case SCI_NEWLINE: - ... - NotifyLineCountChanged(); - break; - case SCI_LINEDELETE: - ... - NotifyLineCountChanged(); - break; - case SCI_CUT: - ... - NotifyLineCountChanged(); - break; - case SCI_PASTE: - ... - NotifyLineCountChanged(); - break; - case SCI_CLEAR: - ... - NotifyLineCountChanged(); - break; - case SCI_UNDO: - ... - NotifyLineCountChanged(); - break; - case SCI_REDO: - ... - NotifyLineCountChanged(); - break; + case SCI_NEWLINE: + ... + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature + break; + case SCI_LINEDELETE: + ... + n2e_NotifyLineCountChanged(); + break; + case SCI_CUT: + ... + n2e_NotifyLineCountChanged(); + break; + case SCI_PASTE: + ... + n2e_NotifyLineCountChanged(); + break; + case SCI_CLEAR: + ... + n2e_NotifyLineCountChanged(); + break; + case SCI_UNDO: + ... + n2e_NotifyLineCountChanged(); + break; + case SCI_REDO: + ... + n2e_NotifyLineCountChanged(); + break; +[/scintilla/src/Editor.cxx] [/**"Update gutter width"-feature**] [**Drag & drop improvement #63**] New code around DropAt()-call: [scintilla/win32/ScintillaWin.cxx] - const bool bIsTrailingLineEnd = (data.size() >= 3) && (data[data.size() - 3] == '\r') && (data[data.size() - 2] == '\n'); - const bool bAddNewLine = (inDragDrop != ddDragging) && (!bIsTrailingLineEnd && pdoc->IsLineStartPosition(movePos.Position()) && pdoc->IsLineEndPosition(movePos.Position())); - if (bAddNewLine) - { - data.insert(data.end() - 1, '\r'); - data.insert(data.end() - 1, '\n'); - } - DropAt(movePos, &data[0], data.size() - 1, \*pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK); - if (bAddNewLine) - { - KeyCommand(SCI_CHARRIGHT); - } + const bool bIsTrailingLineEnd = (data.size() >= 3) && (data[data.size() - 3] == '\r') && (data[data.size() - 2] == '\n'); + const bool bAddNewLine = (inDragDrop != ddDragging) && (!bIsTrailingLineEnd && pdoc->IsLineStartPosition(movePos.Position()) && pdoc->IsLineEndPosition(movePos.Position())); + if (bAddNewLine) + { + data.insert(data.end() - 1, '\r'); + data.insert(data.end() - 1, '\n'); + } + DropAt(movePos, &data[0], data.size() - 1, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK); + if (bAddNewLine) { + KeyCommand(SCI_CHARRIGHT); + } +[/scintilla/win32/ScintillaWin.cxx] [/**Drag & drop improvement #63**] [**Implement Notepad's right click behavior #54**] -Add new message SCI_MOVECARETONRCLICK: +Add new message SCI_N2E_MOVECARETONRCLICK: [scintilla/include/Scintilla.h] -\#define SCI_MOVECARETONRCLICK 2369 +\#define SCI_N2E_MOVECARETONRCLICK 2369 [/scintilla/include/Scintilla.h] [scintilla/src/ScintillaBase.h] - enum { maxLenInputIME = 200 }; + enum { maxLenInputIME = 200 }; - *bool moveCaretOnRClick;* - bool displayPopupMenu; + *bool n2e_moveCaretOnRClick;* + bool displayPopupMenu; [/scintilla/src/ScintillaBase.h] [scintilla/src/ScintillaBase.cxx] ScintillaBase::ScintillaBase() { - *moveCaretOnRClick = true;* - displayPopupMenu = true; + *n2e_moveCaretOnRClick = true;* + displayPopupMenu = true; ... - case SCI_MOVECARETONRCLICK: - moveCaretOnRClick = wParam != 0; - break;* + case SCI_N2E_MOVECARETONRCLICK: + n2e_moveCaretOnRClick = wParam != 0; + break;* - case SCI_USEPOPUP: - displayPopupMenu = wParam != 0; - break; + case SCI_USEPOPUP: [/scintilla/src/ScintillaBase.cxx] [scintilla/win32/ScintillaWin.cxx] - case WM_RBUTTONDOWN: - ::SetFocus(MainHWND()); - if ( *moveCaretOnRClick &&* !PointInSelection(Point::FromLong(static_cast(lParam)))) - { + case WM_RBUTTONDOWN: + ::SetFocus(MainHWND()); + if (*n2e_moveCaretOnRClick* && !PointInSelection(Point::FromLong(static_cast(lParam)))) { + CancelModes(); [/scintilla/win32/ScintillaWin.cxx] - [/**Implement Notepad's right click behavior #54**] [**Unindent and tabs #128**] [scintilla/src/Editor.cxx] Change the code in Editor::Indent(bool forwards): replace condition code block - if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) && - pdoc->tabIndents) { - int indentation = pdoc->GetLineIndentation(lineCurrentPos); - int indentationStep = pdoc->IndentSize(); - const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - sel.Range(r) = SelectionRange(posSelect); - } - + if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) && + pdoc->tabIndents) { + int indentation = pdoc->GetLineIndentation(lineCurrentPos); + int indentationStep = pdoc->IndentSize(); + const int posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); + sel.Range(r) = SelectionRange(posSelect); + } else { with: - if (pdoc->tabIndents) { - SelectionPosition posCaret(sel.Range(r).caret.Position()); - SelectionPosition posAnchor(sel.Range(r).anchor.Position()); - const int indentation = pdoc->GetLineIndentation(lineCurrentPos); - const int indentationStep = pdoc->IndentSize(); - bool adjustCaretPosition = false; - int tabsCount = 0; - if (pdoc->CharAt(pdoc->LineStart(lineCurrentPos)) == '\t') { - adjustCaretPosition = true; - for (int i = pdoc->LineStart(lineCurrentPos); i < posCaret.Position(); i++) { - if (pdoc->CharAt(i) != '\t') - break; - ++tabsCount; - } - } - pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - if (adjustCaretPosition) { - const int offset = (pdoc->useTabs ? std::max(1, tabsCount - 1) : tabsCount) * (indentationStep - 1); - posCaret.Add(offset); - posAnchor.Add(offset); - } - if ((posCaret.Position() - pdoc->LineStart(lineCurrentPos) >= indentationStep) && (indentation >= indentationStep)) { - posCaret.Add(-indentationStep); - posAnchor.Add(-indentationStep); - sel.Range(r) = SelectionRange(posCaret, posAnchor); - } - } - - -[scintilla/src/Editor.cxx] + if (pdoc->tabIndents) { + SelectionPosition posCaret(sel.Range(r).caret.Position()); + SelectionPosition posAnchor(sel.Range(r).anchor.Position()); + const int indentation = pdoc->GetLineIndentation(lineCurrentPos); + const int indentationStep = pdoc->IndentSize(); + bool adjustCaretPosition = false; + int tabsCount = 0; + if (pdoc->CharAt(pdoc->LineStart(lineCurrentPos)) == '\t') { + adjustCaretPosition = true; + for (int i = pdoc->LineStart(lineCurrentPos); i < posCaret.Position(); i++) { + if (pdoc->CharAt(i) != '\t') + break; + ++tabsCount; + } + } + pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); + if (adjustCaretPosition) { + const int offset = (pdoc->useTabs ? std::max(1, tabsCount - 1) : tabsCount) * (indentationStep - 1); + posCaret.Add(offset); + posAnchor.Add(offset); + } + if ((posCaret.Position() - pdoc->LineStart(lineCurrentPos) >= indentationStep) && (indentation >= indentationStep)) { + posCaret.Add(-indentationStep); + posAnchor.Add(-indentationStep); + sel.Range(r) = SelectionRange(posCaret, posAnchor); + } + } else { +[/scintilla/src/Editor.cxx] [/**Unindent and tabs #128**] [**ctrl+arrow behavior toggle #89**] -Add new message SCI_SETWORDNAVIGATIONMODE: +Add new message SCI_N2E_SETWORDNAVIGATIONMODE: [scintilla/include/Scintilla.h] -\#define SCI_SETWORDNAVIGATIONMODE 2379 +\#define SCI_N2E_SETWORDNAVIGATIONMODE 2379 [/scintilla/include/Scintilla.h] Add message handler in ScintillaBase::WndProc: [scintilla/src/ScintillaBase.cxx] - case SCI_SETWORDNAVIGATIONMODE: + case SCI_N2E_SETWORDNAVIGATIONMODE: pdoc->SetWordNavigationMode((int)wParam); break; + + case SCI_USEPOPUP: [/scintilla/src/ScintillaBase.cxx] Add method declaration/implemention to Document class: @@ -380,7 +379,7 @@ Add method declaration/implemention to Document class: int Document::NextWordStart(int pos, int delta) { if (delta < 0) { - // [2e]: ctrl+arrow behavior toggle #89 + // [n2e]: ctrl+arrow behavior toggle #89 switch (wordNavigationMode) { case 0: @@ -395,7 +394,6 @@ int Document::NextWordStart(int pos, int delta) { } break; case 1: - // [2e]: ctrl+arrow behavior toggle #89 // accelerated navigation { if (pos > 0) @@ -427,14 +425,12 @@ int Document::NextWordStart(int pos, int delta) { } } break; - // [/2e] default: // not implemented PLATFORM_ASSERT(false); break; } } else { - // [2e]: ctrl+arrow behavior toggle #89 switch (wordNavigationMode) { case 0: @@ -448,7 +444,6 @@ int Document::NextWordStart(int pos, int delta) { } break; case 1: - // [2e]: ctrl+arrow behavior toggle #89 // accelerated navigation { bool stopAtCurrentNewLine = false; @@ -480,6 +475,7 @@ int Document::NextWordStart(int pos, int delta) { PLATFORM_ASSERT(false); break; } + // [/n2e] } return pos; } @@ -488,7 +484,6 @@ void Document::SetWordNavigationMode(const int iMode) { wordNavigationMode = iMode; } - [/scintilla/src/Document.cxx] [/**ctrl+arrow behavior toggle #89**] @@ -500,175 +495,243 @@ Move class RESearchRange declaration/implementation from Document.cxx to Documen [**Increasingly slow to hex/base64/qp #142**] -Add new message SCI_SETSKIPUIUPDATE: +Add new message SCI_N2E_SETSKIPUIUPDATE: [scintilla/include/Scintilla.h] -#define SCI_GETSUBSTYLEBASES 4026 -*#define SCI_SETSKIPUIUPDATE 9000* +#define SCI_N2E_GETSUBSTYLEBASES 4026 +*#define SCI_N2E_SETSKIPUIUPDATE 9000* [/scintilla/include/Scintilla.h] Add corresponding flag to Editor class: [scintilla/src/Editor.h] - bool convertPastes; - *bool skipUIUpdate;* + bool convertPastes; + *bool n2e_skipUIUpdate;* [/scintilla/src/Editor.h] [scintilla/src/Editor.cxx] - convertPastes = true; - *skipUIUpdate = false;* + convertPastes = true; + *n2e_skipUIUpdate = false;* ... void Editor::RedrawRect(PRectangle rc) { - //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); - *if (skipUIUpdate) { - return; - }* + //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); + *if (n2e_skipUIUpdate) { + return; + }* ... void Editor::Redraw() { - //Platform::DebugPrintf("Redraw all\n"); - *if (skipUIUpdate) { - return; - }* + //Platform::DebugPrintf("Redraw all\n"); + *if (n2e_skipUIUpdate) { + return; + }* ... void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) { - *if (skipUIUpdate) { - return; - }* + *if (n2e_skipUIUpdate) { + return; + }* ... void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { - *if (skipUIUpdate) { - return; - }* + *if (n2e_skipUIUpdate) { + return; + }* ... void Editor::InvalidateCaret() { - *if (skipUIUpdate) { - return; - }* + *if (n2e_skipUIUpdate) { + return; + }* ... void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { - *if (skipUIUpdate) { - return; - }* + *if (n2e_skipUIUpdate) { + return; + }* ... Replace the code in Editor::WndProc() for case SCI_REPLACESEL: - SetEmptySelection(sel.MainCaret() + lengthInserted); - EnsureCaretVisible(); + SetEmptySelection(sel.MainCaret() + lengthInserted); + EnsureCaretVisible(); with - *if (!skipUIUpdate) { - SetEmptySelection(sel.MainCaret() + lengthInserted); - EnsureCaretVisible(); - }* + *if (!n2e_skipUIUpdate) { + SetEmptySelection(sel.MainCaret() + lengthInserted); + EnsureCaretVisible(); + }* ... Add next handler to Editor::WndProc(): - case SCI_SETSKIPUIUPDATE: - skipUIUpdate = (wParam != 0); - if (!skipUIUpdate) { - InvalidateWholeSelection(); - Redraw(); - } - return skipUIUpdate; + case SCI_N2E_SETSKIPUIUPDATE: + n2e_skipUIUpdate = (wParam != 0); + if (!n2e_skipUIUpdate) { + InvalidateWholeSelection(); + Redraw(); + } + return n2e_skipUIUpdate; [/scintilla/src/Editor.cxx] [/**Increasingly slow to hex/base64/qp #142**] [**DPI awareness #154**] -Add new message SCI_SETDPI: +Add new message SCI_N2E_SETDPI: [scintilla/include/Scintilla.h] -#define SCI_SETDPI 9001 +#define SCI_N2E_SETDPI 9001 [/scintilla/include/Scintilla.h] Add message handler and replace some code: [scintilla/win32/ScintillaWin.cxx] - drtp.dpiX = 96.0; - drtp.dpiY = 96.0; + drtp.dpiX = 96.0; + drtp.dpiY = 96.0; >> - drtp.dpiX = GetDpiX(); - drtp.dpiY = GetDpiY(); + drtp.dpiX = n2e_GetDpiX(); + drtp.dpiY = n2e_GetDpiY(); ... - 96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), + 96.0f, 96.0f, D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), >> - GetDpiSystemScaleFactorX(), GetDpiSystemScaleFactorY(), D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), + GetDpiSystemScaleFactorX(), GetDpiSystemScaleFactorY(), D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), ... - case SCI_SETDPI: - SetDPI(LOWORD(wParam), - HIWORD(wParam), - MulDiv(DEFAULT_FONT_DPI, DEFAULT_SCREEN_DPI, GetDpiY())); - InvalidateStyleData(); - RefreshStyleData(); - return 0; + case SCI_N2E_SETDPI: + n2e_SetDPI(LOWORD(wParam), + HIWORD(wParam), + MulDiv(N2E_DEFAULT_FONT_DPI, N2E_DEFAULT_SCREEN_DPI, n2e_GetDpiY())); + InvalidateStyleData(); + RefreshStyleData(); + return 0; ... - drtp.dpiX = 96.0; - drtp.dpiY = 96.0; + drtp.dpiX = 96.0; + drtp.dpiY = 96.0; >> - drtp.dpiX = GetDpiX(); - drtp.dpiY = GetDpiY(); + drtp.dpiX = n2e_GetDpiX(); + drtp.dpiY = n2e_GetDpiY(); [/scintilla/win32/ScintillaWin.cxx] Add required subroutines: [scintilla/win32/PlatWin.h] -#define DEFAULT_SCREEN_DPI 96 -#define DEFAULT_FONT_DPI 72 +#define N2E_DEFAULT_SCREEN_DPI 96 +#define N2E_DEFAULT_FONT_DPI 72 -void SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont); -float GetDpiX(); -float GetDpiY(); -int GetDpiFont(); +void n2e_SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont); +float n2e_GetDpiX(); +float n2e_GetDpiY(); +int n2e_GetDpiFont(); [/scintilla/win32/PlatWin.h] [scintilla/win32/PlatWin.cxx] -static float dpiX = DEFAULT_SCREEN_DPI; -static float dpiY = DEFAULT_SCREEN_DPI; -static int dpiFont = DEFAULT_FONT_DPI; +static float n2e_dpiX = N2E_DEFAULT_SCREEN_DPI; +static float n2e_dpiY = N2E_DEFAULT_SCREEN_DPI; +static int n2e_dpiFont = N2E_DEFAULT_FONT_DPI; -void SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont) +void n2e_SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont) { - dpiX = _dpiX; - dpiY = _dpiY; - dpiFont = _dpiFont; + n2e_dpiX = _dpiX; + n2e_dpiY = _dpiY; + n2e_dpiFont = _dpiFont; } -float GetDpiX() +float n2e_GetDpiX() { - return dpiX; + return n2e_dpiX; } -float GetDpiY() +float n2e_GetDpiY() { - return dpiY; + return n2e_dpiY; } -int GetDpiFont() +int n2e_GetDpiFont() { - return dpiFont; + return n2e_dpiFont; } ... +In SurfaceD2D::SurfaceD2D() replace +logPixelsY = 72; +with +logPixelsY = N2E_DEFAULT_FONT_DPI; + int SurfaceGDI::LogPixelsY() { - return GetDpiY(); + return n2e_GetDpiY(); } int SurfaceGDI::DeviceHeightFont(int points) { - return ::MulDiv(points, LogPixelsY(), DEFAULT_FONT_DPI); + return ::MulDiv(points, LogPixelsY(), N2E_DEFAULT_FONT_DPI); } void SurfaceD2D::SetScale() { - HDC hdcMeasure = ::CreateCompatibleDC(NULL); - logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY); - dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / GetDpiX(); - dpiScaleY = logPixelsY / GetDpiY(); - ::DeleteDC(hdcMeasure); + HDC hdcMeasure = ::CreateCompatibleDC(NULL); + logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY); + dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / n2e_GetDpiX(); + dpiScaleY = logPixelsY / n2e_GetDpiY(); + ::DeleteDC(hdcMeasure); } int SurfaceD2D::DeviceHeightFont(int points) { - return ::MulDiv(points, LogPixelsY(), GetDpiFont()); + return ::MulDiv(points, LogPixelsY(), n2e_GetDpiFont()); } [/scintilla/win32/PlatWin.cxx] -[/**DPI awareness #154**] \ No newline at end of file +[/**DPI awareness #154**] + +[**EscapeHTML**] +Remove const from lpstrText. + +[scintilla/include/scintilla.h] +struct Sci_TextToFind { + struct Sci_CharacterRange chrg; + char *lpstrText; + struct Sci_CharacterRange chrgText; +}; +[/scintilla/include/scintilla.h] +[/**EscapeHTML**] + +[**repaint issue when using Ctrl+Shift+Backspace/Del #116**] +[scintilla/src/Editor.cxx] +Replace + + if (currentLine >= wrapPending.start) + WrapLines(wsAll); + +with + + if (currentLine >= wrapPending.start) { + if (WrapLines(wsAll)) { + Redraw(); + } + } +[/scintilla/src/Editor.cxx] +[/**repaint issue when using Ctrl+Shift+Backspace/Del #116**] + +[**#145 Allow NULL character substitution when using regexp-replace (\x00)**] +[scintilla/src/UniConversion.cxx] +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) { +>> +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL) { + +... + +for (unsigned int i = 0; i < tlen && uptr[i];) { +>> +for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { + +... + +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) { +>> +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL) { + +... + +for (unsigned int i = 0; i < tlen && uptr[i];) { +>> +for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { + +[/scintilla/src/UniConversion.cxx] + +[scintilla/src/UniConversion.h] +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen); +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len); +>> +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL = false); +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL = false); +[/scintilla/src/UniConversion.h] diff --git a/lexlink.js b/lexlink.js index 56edf14e4..40a96fd45 100644 --- a/lexlink.js +++ b/lexlink.js @@ -21,7 +21,14 @@ "lmSQL", "lmVB", "lmVBScript", - "lmXML" + "lmXML", + "lmAsn1", /* [n2e] */ + "lmBash", /* [n2e] */ + "lmCaml", /* [n2e] */ + "lmCoffeeScript", /* [n2e] */ + "lmD", /* [n2e] */ + "lmLISP", /* [n2e] */ + "lmTeX" /* [n2e] */ ); var fso = new ActiveXObject("Scripting.FileSystemObject"); diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index 55cfece6a..9074a6d81 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.h @@ -133,7 +133,7 @@ #define SCLEX_IHEX 118 #define SCLEX_TEHEX 119 #define SCLEX_JSON 120 -#define SCLEX_AHK 200 +#define SCLEX_AHK 200 // [n2e]: add AHK lexer #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -1525,6 +1525,7 @@ #define SCE_TXT2TAGS_OPTION 23 #define SCE_TXT2TAGS_PREPROC 24 #define SCE_TXT2TAGS_POSTPROC 25 +// [n2e]: add AHK lexer #define SCE_AHK_DEFAULT 0 #define SCE_AHK_COMMENTLINE 1 #define SCE_AHK_COMMENTBLOCK 2 @@ -1546,6 +1547,7 @@ #define SCE_AHK_WORD_UD 18 #define SCE_AHK_VARREFKW 19 #define SCE_AHK_ERROR 20 +// [/n2e] #define SCE_A68K_DEFAULT 0 #define SCE_A68K_COMMENT 1 #define SCE_A68K_NUMBER_DEC 2 diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h index c59cd7698..757fc3257 100644 --- a/scintilla/include/Scintilla.h +++ b/scintilla/include/Scintilla.h @@ -13,8 +13,10 @@ #include "Sci_Position.h" -typedef void ( * wheel_action ) ( int ); -typedef int ( * key_action ) ( int , int ); +// [n2e]: Implement wheel_action/proc_action +typedef void (*wheel_action) (int); +typedef int (*key_action)(int , int); +// [/n2e]: Implement wheel_action/proc_action #ifdef __cplusplus extern "C" { #endif @@ -25,8 +27,10 @@ int Scintilla_RegisterClasses(void *hInstance); int Scintilla_ReleaseResources(void); #endif int Scintilla_LinkLexers(void); +// [n2e]: Implement wheel_action/proc_action extern wheel_action n2e_wheel_action; extern key_action n2e_proc_action; +// [/n2e]: Implement wheel_action/proc_action #ifdef __cplusplus } @@ -663,7 +667,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SEARCHANCHOR 2366 #define SCI_SEARCHNEXT 2367 #define SCI_SEARCHPREV 2368 -#define SCI_MOVECARETONRCLICK 2369 +#define SCI_N2E_MOVECARETONRCLICK 2369 // [n2e]: Implement Notepad's right click behavior #54 #define SCI_LINESONSCREEN 2370 #define SCI_USEPOPUP 2371 #define SCI_SELECTIONISRECTANGLE 2372 @@ -673,7 +677,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_ADDREFDOCUMENT 2376 #define SCI_RELEASEDOCUMENT 2377 #define SCI_GETMODEVENTMASK 2378 -#define SCI_SETWORDNAVIGATIONMODE 2379 +#define SCI_N2E_SETWORDNAVIGATIONMODE 2379 // [n2e]: ctrl+arrow behavior toggle #89 #define SCI_SETFOCUS 2380 #define SCI_GETFOCUS 2381 #define SC_STATUS_OK 0 @@ -984,8 +988,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETIDENTIFIERS 4024 #define SCI_DISTANCETOSECONDARYSTYLES 4025 #define SCI_GETSUBSTYLEBASES 4026 -#define SCI_SETSKIPUIUPDATE 9000 -#define SCI_SETDPI 9001 +#define SCI_N2E_SETSKIPUIUPDATE 9000 // [n2e]: Increasingly slow to hex/base64/qp #142 +#define SCI_N2E_SETDPI 9001 // [n2e]: DPI awareness #154 #define SC_MOD_INSERTTEXT 0x1 #define SC_MOD_DELETETEXT 0x2 #define SC_MOD_CHANGESTYLE 0x4 @@ -1077,8 +1081,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCN_FOCUSIN 2028 #define SCN_FOCUSOUT 2029 #define SCN_AUTOCCOMPLETED 2030 -#define SCN_CARETMOVED 2031 -#define SCN_LINECOUNTCHANGED 2032 +#define SCN_N2E_CARETMOVED 2031 // [n2e]: "Scroll margin"-feature +#define SCN_N2E_LINECOUNTCHANGED 2032 // [n2e]: "Update gutter width"-feature /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ /* These structures are defined to be exactly the same shape as the Win32 @@ -1101,7 +1105,7 @@ struct Sci_TextRange { struct Sci_TextToFind { struct Sci_CharacterRange chrg; - char *lpstrText; + char *lpstrText; // [n2e]: EscapeHTML struct Sci_CharacterRange chrgText; }; diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx index ed525f31a..b998b1dae 100644 --- a/scintilla/src/Catalogue.cxx +++ b/scintilla/src/Catalogue.cxx @@ -78,123 +78,123 @@ int Scintilla_LinkLexers() { //++Autogenerated -- run scripts/LexGen.py to regenerate //**\(\tLINK_LEXER(\*);\n\) //LINK_LEXER(lmA68k); - //LINK_LEXER(lmAbaqus); - //LINK_LEXER(lmAda); - //LINK_LEXER(lmAHK); - //LINK_LEXER(lmAPDL); - //LINK_LEXER(lmAs); - LINK_LEXER(lmAsm); - LINK_LEXER(lmAsn1); - //LINK_LEXER(lmASY); - LINK_LEXER(lmAU3); - //LINK_LEXER(lmAVE); - LINK_LEXER(lmAVS); - //LINK_LEXER(lmBaan); - LINK_LEXER(lmBash); - LINK_LEXER(lmBatch); - //LINK_LEXER(lmBibTeX); - //LINK_LEXER(lmBlitzBasic); - //LINK_LEXER(lmBullant); - LINK_LEXER(lmCaml); - //LINK_LEXER(lmClw); - //LINK_LEXER(lmClwNoCase); - LINK_LEXER(lmCmake); - //LINK_LEXER(lmCOBOL); - LINK_LEXER(lmCoffeeScript); - LINK_LEXER(lmConf); - LINK_LEXER(lmCPP); - LINK_LEXER(lmCPPNoCase); - //LINK_LEXER(lmCsound); - LINK_LEXER(lmCss); - LINK_LEXER(lmD); - LINK_LEXER(lmDiff); - //LINK_LEXER(lmDMAP); - //LINK_LEXER(lmDMIS); - //LINK_LEXER(lmECL); - //LINK_LEXER(lmEiffel); - //LINK_LEXER(lmEiffelkw); - //LINK_LEXER(lmErlang); - //LINK_LEXER(lmErrorList); - //LINK_LEXER(lmESCRIPT); - //LINK_LEXER(lmF77); - //LINK_LEXER(lmFlagShip); - //LINK_LEXER(lmForth); - //LINK_LEXER(lmFortran); - //LINK_LEXER(lmFreeBasic); - //LINK_LEXER(lmGAP); - //LINK_LEXER(lmGui4Cli); - //LINK_LEXER(lmHaskell); - LINK_LEXER(lmHTML); - //LINK_LEXER(lmIHex); - LINK_LEXER(lmInno); - //LINK_LEXER(lmJSON); - //LINK_LEXER(lmKix); - //LINK_LEXER(lmKVIrc); - LINK_LEXER(lmLatex); - LINK_LEXER(lmLISP); - //LINK_LEXER(lmLiterateHaskell); - //LINK_LEXER(lmLot); - //LINK_LEXER(lmLout); - LINK_LEXER(lmLua); - //LINK_LEXER(lmMagikSF); - LINK_LEXER(lmMake); - LINK_LEXER(lmMarkdown); - //LINK_LEXER(lmMatlab); - //LINK_LEXER(lmMETAPOST); - //LINK_LEXER(lmMMIXAL); - //LINK_LEXER(lmModula); - //LINK_LEXER(lmMSSQL); - //LINK_LEXER(lmMySQL); - //LINK_LEXER(lmNimrod); - //LINK_LEXER(lmNncrontab); - LINK_LEXER(lmNsis); - LINK_LEXER(lmNull); - //LINK_LEXER(lmOctave); - //LINK_LEXER(lmOpal); - //LINK_LEXER(lmOScript); - LINK_LEXER(lmPascal); - //LINK_LEXER(lmPB); - LINK_LEXER(lmPerl); - //LINK_LEXER(lmPHPSCRIPT); - //LINK_LEXER(lmPLM); - //LINK_LEXER(lmPO); - //LINK_LEXER(lmPOV); - //LINK_LEXER(lmPowerPro); - LINK_LEXER(lmPowerShell); - //LINK_LEXER(lmProgress); - LINK_LEXER(lmProps); - //LINK_LEXER(lmPS); - //LINK_LEXER(lmPureBasic); - LINK_LEXER(lmPython); - //LINK_LEXER(lmR); - //LINK_LEXER(lmREBOL); - //LINK_LEXER(lmRegistry); - LINK_LEXER(lmRuby); - LINK_LEXER(lmRust); - //LINK_LEXER(lmScriptol); - //LINK_LEXER(lmSmalltalk); - //LINK_LEXER(lmSML); - //LINK_LEXER(lmSorc); - //LINK_LEXER(lmSpecman); - //LINK_LEXER(lmSpice); - LINK_LEXER(lmSQL); - //LINK_LEXER(lmSrec); - //LINK_LEXER(lmSTTXT); - //LINK_LEXER(lmTACL); - //LINK_LEXER(lmTADS3); - //LINK_LEXER(lmTAL); - LINK_LEXER(lmTCL); - //LINK_LEXER(lmTCMD); - //LINK_LEXER(lmTEHex); - LINK_LEXER(lmTeX); - //LINK_LEXER(lmTxt2tags); - LINK_LEXER(lmVB); - LINK_LEXER(lmVBScript); - //LINK_LEXER(lmVerilog); - //LINK_LEXER(lmVHDL); - //LINK_LEXER(lmVisualProlog); - LINK_LEXER(lmXML); - LINK_LEXER(lmYAML); + //LINK_LEXER(lmAbaqus); + //LINK_LEXER(lmAda); + //LINK_LEXER(lmAHK); + //LINK_LEXER(lmAPDL); + //LINK_LEXER(lmAs); + LINK_LEXER(lmAsm); + LINK_LEXER(lmAsn1); + //LINK_LEXER(lmASY); + LINK_LEXER(lmAU3); + //LINK_LEXER(lmAVE); + LINK_LEXER(lmAVS); + //LINK_LEXER(lmBaan); + LINK_LEXER(lmBash); + LINK_LEXER(lmBatch); + //LINK_LEXER(lmBibTeX); + //LINK_LEXER(lmBlitzBasic); + //LINK_LEXER(lmBullant); + LINK_LEXER(lmCaml); + //LINK_LEXER(lmClw); + //LINK_LEXER(lmClwNoCase); + LINK_LEXER(lmCmake); + //LINK_LEXER(lmCOBOL); + LINK_LEXER(lmCoffeeScript); + LINK_LEXER(lmConf); + LINK_LEXER(lmCPP); + LINK_LEXER(lmCPPNoCase); + //LINK_LEXER(lmCsound); + LINK_LEXER(lmCss); + LINK_LEXER(lmD); + LINK_LEXER(lmDiff); + //LINK_LEXER(lmDMAP); + //LINK_LEXER(lmDMIS); + //LINK_LEXER(lmECL); + //LINK_LEXER(lmEiffel); + //LINK_LEXER(lmEiffelkw); + //LINK_LEXER(lmErlang); + //LINK_LEXER(lmErrorList); + //LINK_LEXER(lmESCRIPT); + //LINK_LEXER(lmF77); + //LINK_LEXER(lmFlagShip); + //LINK_LEXER(lmForth); + //LINK_LEXER(lmFortran); + //LINK_LEXER(lmFreeBasic); + //LINK_LEXER(lmGAP); + //LINK_LEXER(lmGui4Cli); + //LINK_LEXER(lmHaskell); + LINK_LEXER(lmHTML); + //LINK_LEXER(lmIHex); + LINK_LEXER(lmInno); + //LINK_LEXER(lmJSON); + //LINK_LEXER(lmKix); + //LINK_LEXER(lmKVIrc); + LINK_LEXER(lmLatex); + LINK_LEXER(lmLISP); + //LINK_LEXER(lmLiterateHaskell); + //LINK_LEXER(lmLot); + //LINK_LEXER(lmLout); + LINK_LEXER(lmLua); + //LINK_LEXER(lmMagikSF); + LINK_LEXER(lmMake); + LINK_LEXER(lmMarkdown); + //LINK_LEXER(lmMatlab); + //LINK_LEXER(lmMETAPOST); + //LINK_LEXER(lmMMIXAL); + //LINK_LEXER(lmModula); + //LINK_LEXER(lmMSSQL); + //LINK_LEXER(lmMySQL); + //LINK_LEXER(lmNimrod); + //LINK_LEXER(lmNncrontab); + LINK_LEXER(lmNsis); + LINK_LEXER(lmNull); + //LINK_LEXER(lmOctave); + //LINK_LEXER(lmOpal); + //LINK_LEXER(lmOScript); + LINK_LEXER(lmPascal); + //LINK_LEXER(lmPB); + LINK_LEXER(lmPerl); + //LINK_LEXER(lmPHPSCRIPT); + //LINK_LEXER(lmPLM); + //LINK_LEXER(lmPO); + //LINK_LEXER(lmPOV); + //LINK_LEXER(lmPowerPro); + LINK_LEXER(lmPowerShell); + //LINK_LEXER(lmProgress); + LINK_LEXER(lmProps); + //LINK_LEXER(lmPS); + //LINK_LEXER(lmPureBasic); + LINK_LEXER(lmPython); + //LINK_LEXER(lmR); + //LINK_LEXER(lmREBOL); + //LINK_LEXER(lmRegistry); + LINK_LEXER(lmRuby); + LINK_LEXER(lmRust); + //LINK_LEXER(lmScriptol); + //LINK_LEXER(lmSmalltalk); + //LINK_LEXER(lmSML); + //LINK_LEXER(lmSorc); + //LINK_LEXER(lmSpecman); + //LINK_LEXER(lmSpice); + LINK_LEXER(lmSQL); + //LINK_LEXER(lmSrec); + //LINK_LEXER(lmSTTXT); + //LINK_LEXER(lmTACL); + //LINK_LEXER(lmTADS3); + //LINK_LEXER(lmTAL); + LINK_LEXER(lmTCL); + //LINK_LEXER(lmTCMD); + //LINK_LEXER(lmTEHex); + LINK_LEXER(lmTeX); + //LINK_LEXER(lmTxt2tags); + LINK_LEXER(lmVB); + LINK_LEXER(lmVBScript); + //LINK_LEXER(lmVerilog); + //LINK_LEXER(lmVHDL); + //LINK_LEXER(lmVisualProlog); + LINK_LEXER(lmXML); + LINK_LEXER(lmYAML); //--Autogenerated -- end of automatically generated section diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx index 71fdbfcad..c8d30332d 100644 --- a/scintilla/src/Document.cxx +++ b/scintilla/src/Document.cxx @@ -110,8 +110,7 @@ Document::Document() { tabIndents = true; backspaceUnindents = false; durationStyleOneLine = 0.00001; - // [2e]: ctrl+arrow behavior toggle #89 - wordNavigationMode = 0; + wordNavigationMode = 0; // [n2e]: ctrl+arrow behavior toggle #89 matchesValid = false; regex = 0; @@ -1522,7 +1521,7 @@ int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) { */ int Document::NextWordStart(int pos, int delta) { if (delta < 0) { - // [2e]: ctrl+arrow behavior toggle #89 + // [n2e]: ctrl+arrow behavior toggle #89 switch (wordNavigationMode) { case 0: @@ -1537,7 +1536,6 @@ int Document::NextWordStart(int pos, int delta) { } break; case 1: - // [2e]: ctrl+arrow behavior toggle #89 // accelerated navigation { if (pos > 0) @@ -1569,14 +1567,12 @@ int Document::NextWordStart(int pos, int delta) { } } break; - // [/2e] default: // not implemented PLATFORM_ASSERT(false); break; } } else { - // [2e]: ctrl+arrow behavior toggle #89 switch (wordNavigationMode) { case 0: @@ -1590,7 +1586,6 @@ int Document::NextWordStart(int pos, int delta) { } break; case 1: - // [2e]: ctrl+arrow behavior toggle #89 // accelerated navigation { bool stopAtCurrentNewLine = false; @@ -1622,6 +1617,7 @@ int Document::NextWordStart(int pos, int delta) { PLATFORM_ASSERT(false); break; } + // [/n2e] } return pos; } @@ -2328,12 +2324,12 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) { return - 1; } -// [2e]: ctrl+arrow behavior toggle #89 +// [n2e]: ctrl+arrow behavior toggle #89 void Document::SetWordNavigationMode(const int iMode) { wordNavigationMode = iMode; } -// [/2e] +// [/n2e] /** * Implementation of RegexSearchBase for the default built-in regular expression engine @@ -2357,6 +2353,7 @@ class BuiltinRegex : public RegexSearchBase { }; namespace { +// [n2e]: Regexp: confine to single line #90: moved RESearchRange to Document.h // Define a way for the Regular Expression code to access the document class DocumentIndexer : public CharacterIndexer { diff --git a/scintilla/src/Document.h b/scintilla/src/Document.h index eb3d7cf58..31f6938d1 100644 --- a/scintilla/src/Document.h +++ b/scintilla/src/Document.h @@ -251,8 +251,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { bool tabIndents; bool backspaceUnindents; double durationStyleOneLine; - // [2e]: ctrl+arrow behavior toggle #89 - int wordNavigationMode; + int wordNavigationMode; // [n2e]: ctrl+arrow behavior toggle #89 DecorationList decorations; @@ -449,8 +448,7 @@ class Document : PerLine, public IDocumentWithLineEnd, public ILoader { int ParaDown(int pos) const; int IndentSize() const { return actualIndentInChars; } int BraceMatch(int position, int maxReStyle); - // [2e]: ctrl+arrow behavior toggle #89 - void SetWordNavigationMode(const int iMode); + void SetWordNavigationMode(const int iMode); // [n2e]: ctrl+arrow behavior toggle #89 private: void NotifyModifyAttempt(); @@ -540,6 +538,7 @@ class DocWatcher { virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0; }; +// [n2e]: Regexp: confine to single line #90: RESearchRange moved from Document.cpp /** * RESearchRange keeps track of search range. */ @@ -592,6 +591,7 @@ class RESearchRange { return range; } }; +// [/n2e] #ifdef SCI_NAMESPACE } diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index 963e8bc95..448dd808b 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -184,7 +184,7 @@ Editor::Editor() { foldAutomatic = 0; convertPastes = true; - skipUIUpdate = false; + n2e_skipUIUpdate = false; // [n2e]: Increasingly slow to hex/base64/qp #142 SetRepresentations(); } @@ -450,9 +450,11 @@ bool Editor::AbandonPaint() { void Editor::RedrawRect(PRectangle rc) { //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom); - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } + // [/n2e] // Clip the redraw rectangle into the client area PRectangle rcClient = GetClientRectangle(); @@ -476,9 +478,11 @@ void Editor::DiscardOverdraw() { void Editor::Redraw() { //Platform::DebugPrintf("Redraw all\n"); - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } + // [/n2e] PRectangle rcClient = GetClientRectangle(); wMain.InvalidateRectangle(rcClient); @@ -604,9 +608,11 @@ void Editor::ThinRectangularRange() { } void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) { - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } + // [/n2e] if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) { invalidateWholeSelection = true; @@ -826,11 +832,13 @@ void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, const int currentLine = pdoc->LineFromPosition(newPos.Position()); if (ensureVisible) { // In case in need of wrapping to ensure DisplayFromDoc works. + // [n2e]: repaint issue when using Ctrl+Shift+Backspace/Del #116 if (currentLine >= wrapPending.start) { - if (WrapLines(wsAll)) { - Redraw(); - } - } + if (WrapLines(wsAll)) { + Redraw(); + } + } + // [/n2e] XYScrollPosition newXY = XYScrollToMakeVisible( SelectionRange(posDrag.IsValid() ? posDrag : newPos), xysDefault); if (previousPos.IsValid() && (newXY.xOffset == xOffset)) { @@ -1396,9 +1404,11 @@ void Editor::ScrollRange(SelectionRange range) { } void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } + // [/n2e] SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), static_cast((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0)))); @@ -1447,10 +1457,11 @@ void Editor::CaretSetPeriod(int period) { } void Editor::InvalidateCaret() { - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } - + // [/n2e] if (posDrag.IsValid()) { InvalidateRange(posDrag.Position(), posDrag.Position() + 1); } else { @@ -1710,10 +1721,11 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { } void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { - if (skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (n2e_skipUIUpdate) { return; } - + // [/n2e] //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); AllocateGraphics(); @@ -2510,21 +2522,25 @@ void Editor::NotifyZoom() { NotifyParent(scn); } -void Editor::NotifyCaretMoved() +// [n2e]: "Scroll margin"-feature +void Editor::n2e_NotifyCaretMoved() { - // Send notification - SCNotification scn = { 0 }; - scn.nmhdr.code = SCN_CARETMOVED; - NotifyParent(scn); + // Send notification + SCNotification scn = { 0 }; + scn.nmhdr.code = SCN_N2E_CARETMOVED; + NotifyParent(scn); } +// [/n2e] -void Editor::NotifyLineCountChanged() +// [n2e]: "Update gutter width"-feature +void Editor::n2e_NotifyLineCountChanged() { - // Send notification - SCNotification scn = { 0 }; - scn.nmhdr.code = SCN_LINECOUNTCHANGED; - NotifyParent(scn); + // Send notification + SCNotification scn = { 0 }; + scn.nmhdr.code = SCN_N2E_LINECOUNTCHANGED; + NotifyParent(scn); } +// [/n2e] // Notifications from document void Editor::NotifyModifyAttempt(Document *, void *) { @@ -3608,11 +3624,11 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_PARADOWN: ParaUpOrDown(1, Selection::noSel); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PARADOWNEXTEND: ParaUpOrDown(1, Selection::selStream); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_LINESCROLLDOWN: ScrollTo(topLine + 1); @@ -3629,11 +3645,11 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_PARAUP: ParaUpOrDown(-1, Selection::noSel); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PARAUPEXTEND: ParaUpOrDown(-1, Selection::selStream); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_LINESCROLLUP: ScrollTo(topLine - 1); @@ -3711,27 +3727,27 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_PAGEUP: PageMove(-1); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PAGEUPEXTEND: PageMove(-1, Selection::selStream); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PAGEUPRECTEXTEND: PageMove(-1, Selection::selRectangle); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PAGEDOWN: PageMove(1); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PAGEDOWNEXTEND: PageMove(1, Selection::selStream); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_PAGEDOWNRECTEXTEND: PageMove(1, Selection::selRectangle); - NotifyCaretMoved(); + n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature break; case SCI_EDITTOGGLEOVERTYPE: inOverstrike = !inOverstrike; @@ -3780,7 +3796,7 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_NEWLINE: NewLine(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_FORMFEED: AddChar('\f'); @@ -3829,7 +3845,7 @@ int Editor::KeyCommand(unsigned int iMessage) { int start = pdoc->LineStart(line); int end = pdoc->LineStart(line + 1); pdoc->DeleteChars(start, end - start); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature } break; case SCI_LINETRANSPOSE: @@ -3912,6 +3928,7 @@ void Editor::Indent(bool forwards) { } } } else { + // [n2e]: Unindent and tabs #128 if (pdoc->tabIndents) { SelectionPosition posCaret(sel.Range(r).caret.Position()); SelectionPosition posAnchor(sel.Range(r).anchor.Position()); @@ -3938,6 +3955,7 @@ void Editor::Indent(bool forwards) { posAnchor.Add(-indentationStep); sel.Range(r) = SelectionRange(posCaret, posAnchor); } + // [/n2e] } else { int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) * pdoc->tabInChars; @@ -4509,7 +4527,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie selectionType = selWord; doubleClick = true; } else if (selectionType == selWord) { - // do nothing on *triple* click + // [n2e]: "No line selection on active selection"-feature: do nothing on *triple* click } else { selectionType = selChar; originalAnchorPos = sel.MainCaret(); @@ -5791,7 +5809,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_CUT: Cut(); SetLastXChosen(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_COPY: @@ -5828,20 +5846,20 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { SetLastXChosen(); } EnsureCaretVisible(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_CLEAR: Clear(); SetLastXChosen(); EnsureCaretVisible(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_UNDO: Undo(); SetLastXChosen(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_CANUNDO: @@ -5945,10 +5963,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { char *replacement = CharPtrFromSPtr(lParam); const int lengthInserted = pdoc->InsertString( sel.MainCaret(), replacement, istrlen(replacement)); - if (!skipUIUpdate) { - SetEmptySelection(sel.MainCaret() + lengthInserted); - EnsureCaretVisible(); + // [n2e]: Increasingly slow to hex/base64/qp #142 + if (!n2e_skipUIUpdate) { + SetEmptySelection(sel.MainCaret() + lengthInserted); + EnsureCaretVisible(); } + // [/n2e] } break; @@ -6307,7 +6327,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_REDO: Redo(); - NotifyLineCountChanged(); + n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature break; case SCI_SELECTALL: @@ -8133,13 +8153,15 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_COUNTCHARACTERS: return pdoc->CountCharacters(static_cast(wParam), static_cast(lParam)); - case SCI_SETSKIPUIUPDATE: - skipUIUpdate = (wParam != 0); - if (!skipUIUpdate) { + // [n2e]: Increasingly slow to hex/base64/qp #142 + case SCI_N2E_SETSKIPUIUPDATE: + n2e_skipUIUpdate = (wParam != 0); + if (!n2e_skipUIUpdate) { InvalidateWholeSelection(); Redraw(); } - return skipUIUpdate; + return n2e_skipUIUpdate; + // /n2e default: return DefWndProc(iMessage, wParam, lParam); diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index 4e1f83ab2..27a23f647 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -258,7 +258,7 @@ class Editor : public EditModel, public DocWatcher { WrapPending wrapPending; bool convertPastes; - bool skipUIUpdate; + bool n2e_skipUIUpdate; // [n2e]: Increasingly slow to hex/base64/qp #142 Editor(); virtual ~Editor(); @@ -441,8 +441,8 @@ class Editor : public EditModel, public DocWatcher { void NotifyNeedShown(int pos, int len); void NotifyDwelling(Point pt, bool state); void NotifyZoom(); - void NotifyCaretMoved(); - void NotifyLineCountChanged(); + void n2e_NotifyCaretMoved(); // [n2e]: "Scroll margin"-feature + void n2e_NotifyLineCountChanged(); // [n2e]: "Update gutter width"-feature void NotifyModifyAttempt(Document *document, void *userData); void NotifySavePoint(Document *document, void *userData, bool atSavePoint); diff --git a/scintilla/src/ScintillaBase.cxx b/scintilla/src/ScintillaBase.cxx index 2ab995607..ed25898c2 100644 --- a/scintilla/src/ScintillaBase.cxx +++ b/scintilla/src/ScintillaBase.cxx @@ -64,7 +64,7 @@ using namespace Scintilla; #endif ScintillaBase::ScintillaBase() { - moveCaretOnRClick = true; + n2e_moveCaretOnRClick = true; // [n2e]: Implement Notepad's right click behavior #54 displayPopupMenu = true; listType = 0; maxListWidth = 0; @@ -970,15 +970,17 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara InvalidateStyleRedraw(); break; - case SCI_MOVECARETONRCLICK: - moveCaretOnRClick = wParam != 0; + // [n2e]: Implement Notepad's right click behavior #54 + case SCI_N2E_MOVECARETONRCLICK: + n2e_moveCaretOnRClick = wParam != 0; break; + // [/n2e] - // [2e]: ctrl+arrow behavior toggle #89 - case SCI_SETWORDNAVIGATIONMODE: + // [n2e]: ctrl+arrow behavior toggle #89 + case SCI_N2E_SETWORDNAVIGATIONMODE: pdoc->SetWordNavigationMode((int)wParam); break; - // [/2e] + // [/n2e] case SCI_USEPOPUP: displayPopupMenu = wParam != 0; diff --git a/scintilla/src/ScintillaBase.h b/scintilla/src/ScintillaBase.h index 05cec7a50..edf063d09 100644 --- a/scintilla/src/ScintillaBase.h +++ b/scintilla/src/ScintillaBase.h @@ -40,7 +40,7 @@ class ScintillaBase : public Editor { enum { maxLenInputIME = 200 }; - bool moveCaretOnRClick; + bool n2e_moveCaretOnRClick; // [n2e]: Implement Notepad's right click behavior #54 bool displayPopupMenu; Menu popup; AutoComplete ac; diff --git a/scintilla/src/UniConversion.cxx b/scintilla/src/UniConversion.cxx index d821d1904..99ef4b16b 100644 --- a/scintilla/src/UniConversion.cxx +++ b/scintilla/src/UniConversion.cxx @@ -19,9 +19,9 @@ using namespace Scintilla; namespace Scintilla { #endif -unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL) { +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL) { // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) unsigned int len = 0; - for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { + for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) unsigned int uch = uptr[i]; if (uch < 0x80) { len++; @@ -39,9 +39,9 @@ unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool proce return len; } -void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL) { +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL) { // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) unsigned int k = 0; - for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { + for (unsigned int i = 0; i < tlen && (uptr[i] || processNULL);) { // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) unsigned int uch = uptr[i]; if (uch < 0x80) { putf[k++] = static_cast(uch); diff --git a/scintilla/src/UniConversion.h b/scintilla/src/UniConversion.h index f727bd3bf..595381246 100644 --- a/scintilla/src/UniConversion.h +++ b/scintilla/src/UniConversion.h @@ -16,8 +16,8 @@ const int UTF8MaxBytes = 4; const int unicodeReplacementChar = 0xFFFD; -unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL = false); -void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL = false); +unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen, const bool processNULL = false); // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) +void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len, const bool processNULL = false); // [n2e]: #145 Allow NULL character substitution when using regexp-replace (\x00) unsigned int UTF8CharLength(unsigned char ch); size_t UTF16Length(const char *s, size_t len); size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen); diff --git a/scintilla/win32/PlatWin.cxx b/scintilla/win32/PlatWin.cxx index 26448e0bf..15cbdc641 100644 --- a/scintilla/win32/PlatWin.cxx +++ b/scintilla/win32/PlatWin.cxx @@ -37,7 +37,7 @@ #endif #include "Platform.h" -#include "PlatWin.h" +#include "PlatWin.h" // [n2e]: DPI awareness #154 #include "StringCopy.h" #include "XPM.h" #include "UniConversion.h" @@ -51,31 +51,33 @@ #define SPI_GETFONTSMOOTHINGCONTRAST 0x200C #endif -static float dpiX = DEFAULT_SCREEN_DPI; -static float dpiY = DEFAULT_SCREEN_DPI; -static int dpiFont = DEFAULT_FONT_DPI; +// [n2e]: DPI awareness #154 +static float n2e_dpiX = N2E_DEFAULT_SCREEN_DPI; +static float n2e_dpiY = N2E_DEFAULT_SCREEN_DPI; +static int n2e_dpiFont = N2E_DEFAULT_FONT_DPI; -void SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont) +void n2e_SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont) { - dpiX = _dpiX; - dpiY = _dpiY; - dpiFont = _dpiFont; + n2e_dpiX = _dpiX; + n2e_dpiY = _dpiY; + n2e_dpiFont = _dpiFont; } -float GetDpiX() +float n2e_GetDpiX() { - return dpiX; + return n2e_dpiX; } -float GetDpiY() +float n2e_GetDpiY() { - return dpiY; + return n2e_dpiY; } -int GetDpiFont() +int n2e_GetDpiFont() { - return dpiFont; + return n2e_dpiFont; } +// [/n2e] static void *PointerFromWindow(HWND hWnd) { return reinterpret_cast(::GetWindowLongPtr(hWnd, 0)); @@ -714,7 +716,7 @@ int SurfaceGDI::LogPixelsY() { } int SurfaceGDI::DeviceHeightFont(int points) { - return ::MulDiv(points, LogPixelsY(), DEFAULT_FONT_DPI); + return ::MulDiv(points, LogPixelsY(), N2E_DEFAULT_FONT_DPI); // [n2e]: DPI awareness #154 } void SurfaceGDI::MoveTo(int x_, int y_) { @@ -1182,7 +1184,7 @@ SurfaceD2D::SurfaceD2D() : pBrush = NULL; - logPixelsY = DEFAULT_FONT_DPI; + logPixelsY = N2E_DEFAULT_FONT_DPI; // [n2e]: DPI awareness #154 dpiScaleX = 1.0; dpiScaleY = 1.0; } @@ -1211,8 +1213,8 @@ void SurfaceD2D::Release() { void SurfaceD2D::SetScale() { HDC hdcMeasure = ::CreateCompatibleDC(NULL); logPixelsY = ::GetDeviceCaps(hdcMeasure, LOGPIXELSY); - dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / GetDpiX(); - dpiScaleY = logPixelsY / GetDpiY(); + dpiScaleX = ::GetDeviceCaps(hdcMeasure, LOGPIXELSX) / n2e_GetDpiX(); // [n2e]: DPI awareness #154 + dpiScaleY = logPixelsY / n2e_GetDpiY(); // [n2e]: DPI awareness #154 ::DeleteDC(hdcMeasure); } @@ -1311,7 +1313,7 @@ int SurfaceD2D::LogPixelsY() { } int SurfaceD2D::DeviceHeightFont(int points) { - return ::MulDiv(points, LogPixelsY(), GetDpiFont()); + return ::MulDiv(points, LogPixelsY(), n2e_GetDpiFont()); // [n2e]: DPI awareness #154 } void SurfaceD2D::MoveTo(int x_, int y_) { diff --git a/scintilla/win32/PlatWin.h b/scintilla/win32/PlatWin.h index cafba9abf..36510d012 100644 --- a/scintilla/win32/PlatWin.h +++ b/scintilla/win32/PlatWin.h @@ -12,13 +12,16 @@ namespace Scintilla { #endif -#define DEFAULT_SCREEN_DPI 96 -#define DEFAULT_FONT_DPI 72 -void SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont); -float GetDpiX(); -float GetDpiY(); -int GetDpiFont(); +// [n2e]: DPI awareness #154 +#define N2E_DEFAULT_SCREEN_DPI 96 +#define N2E_DEFAULT_FONT_DPI 72 + +void n2e_SetDPI(const float _dpiX, const float _dpiY, const int _dpiFont); +float n2e_GetDpiX(); +float n2e_GetDpiY(); +int n2e_GetDpiFont(); +// [/n2e] extern void Platform_Initialise(void *hInstance); extern void Platform_Finalise(bool fromDllMain); diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx index d55f70e78..5f9b553c7 100644 --- a/scintilla/win32/ScintillaWin.cxx +++ b/scintilla/win32/ScintillaWin.cxx @@ -2,8 +2,8 @@ /** @file ScintillaWin.cxx ** Windows specific subclass of ScintillaBase. **/ - // Copyright 1998-2003 by Neil Hodgson - // The License.txt file describes the conditions under which this software may be distributed. +// Copyright 1998-2003 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. #include #include @@ -125,11 +125,13 @@ #define SCS_SETRECONVERTSTRING 0x00010000 #endif -typedef BOOL(WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT); +typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT); +// [n2e]: Implement wheel_action/proc_action wheel_action n2e_wheel_action = 0; key_action n2e_proc_action = 0; -typedef UINT_PTR(WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent, - UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay); +// [/n2e] +typedef UINT_PTR (WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent, + UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay); // GCC has trouble with the standard COM ABI so do it the old C way with explicit vtables. @@ -139,24 +141,20 @@ const TCHAR callClassName[] = TEXT("CallTip"); using namespace Scintilla; #endif -static void *PointerFromWindow(HWND hWnd) -{ - return reinterpret_cast(::GetWindowLongPtr(hWnd, 0)); +static void *PointerFromWindow(HWND hWnd) { + return reinterpret_cast(::GetWindowLongPtr(hWnd, 0)); } -static void SetWindowPointer(HWND hWnd, void *ptr) -{ - ::SetWindowLongPtr(hWnd, 0, reinterpret_cast(ptr)); +static void SetWindowPointer(HWND hWnd, void *ptr) { + ::SetWindowLongPtr(hWnd, 0, reinterpret_cast(ptr)); } -static void SetWindowID(HWND hWnd, int identifier) -{ - ::SetWindowLongPtr(hWnd, GWLP_ID, identifier); +static void SetWindowID(HWND hWnd, int identifier) { + ::SetWindowLongPtr(hWnd, GWLP_ID, identifier); } -static Point PointFromPOINT(POINT pt) -{ - return Point::FromInts(pt.x, pt.y); +static Point PointFromPOINT(POINT pt) { + return Point::FromInts(pt.x, pt.y); } class ScintillaWin; // Forward declaration for COM interface subobjects @@ -167,84 +165,73 @@ static HMODULE commctrl32 = 0; /** */ -class FormatEnumerator -{ +class FormatEnumerator { public: - VFunction **vtbl; - int ref; - unsigned int pos; - std::vector formats; - FormatEnumerator(int pos_, CLIPFORMAT formats_[], size_t formatsLen_); + VFunction **vtbl; + int ref; + unsigned int pos; + std::vector formats; + FormatEnumerator(int pos_, CLIPFORMAT formats_[], size_t formatsLen_); }; /** */ -class DropSource -{ +class DropSource { public: - VFunction **vtbl; - ScintillaWin *sci; - DropSource(); + VFunction **vtbl; + ScintillaWin *sci; + DropSource(); }; /** */ -class DataObject -{ +class DataObject { public: - VFunction **vtbl; - ScintillaWin *sci; - DataObject(); + VFunction **vtbl; + ScintillaWin *sci; + DataObject(); }; /** */ -class DropTarget -{ +class DropTarget { public: - VFunction **vtbl; - ScintillaWin *sci; - DropTarget(); + VFunction **vtbl; + ScintillaWin *sci; + DropTarget(); }; -namespace -{ +namespace { -class IMContext -{ - HWND hwnd; +class IMContext { + HWND hwnd; public: - HIMC hIMC; - IMContext(HWND hwnd_) : - hwnd(hwnd_), hIMC(::ImmGetContext(hwnd_)) - { - } - ~IMContext() - { - if (hIMC) - ::ImmReleaseContext(hwnd, hIMC); - } - - unsigned int GetImeCaretPos() - { - return ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0); - } - - std::vector GetImeAttributes() - { - int attrLen = ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0); - std::vector attr(attrLen, 0); - ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, &attr[0], static_cast(attr.size())); - return attr; - } - - std::wstring GetCompositionString(DWORD dwIndex) - { - const LONG byteLen = ::ImmGetCompositionStringW(hIMC, dwIndex, NULL, 0); - std::wstring wcs(byteLen / 2, 0); - ::ImmGetCompositionStringW(hIMC, dwIndex, &wcs[0], byteLen); - return wcs; - } + HIMC hIMC; + IMContext(HWND hwnd_) : + hwnd(hwnd_), hIMC(::ImmGetContext(hwnd_)) { + } + ~IMContext() { + if (hIMC) + ::ImmReleaseContext(hwnd, hIMC); + } + + unsigned int GetImeCaretPos() { + return ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0); + } + + std::vector GetImeAttributes() { + int attrLen = ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0); + std::vector attr(attrLen, 0); + ::ImmGetCompositionStringW(hIMC, GCS_COMPATTR, &attr[0], static_cast(attr.size())); + return attr; + } + + std::wstring GetCompositionString(DWORD dwIndex) { + const LONG byteLen = ::ImmGetCompositionStringW(hIMC, dwIndex, NULL, 0); + std::wstring wcs(byteLen / 2, 0); + ::ImmGetCompositionStringW(hIMC, dwIndex, &wcs[0], byteLen); + return wcs; + } }; } @@ -252,3708 +239,3187 @@ class IMContext /** */ class ScintillaWin : - public ScintillaBase -{ + public ScintillaBase { - bool lastKeyDownConsumed; - wchar_t lastHighSurrogateChar; + bool lastKeyDownConsumed; + wchar_t lastHighSurrogateChar; - bool capturedMouse; - bool trackedMouseLeave; - TrackMouseEventSig TrackMouseEventFn; - SetCoalescableTimerSig SetCoalescableTimerFn; + bool capturedMouse; + bool trackedMouseLeave; + TrackMouseEventSig TrackMouseEventFn; + SetCoalescableTimerSig SetCoalescableTimerFn; - unsigned int linesPerScroll; ///< Intellimouse support - int wheelDelta; ///< Wheel delta from roll + unsigned int linesPerScroll; ///< Intellimouse support + int wheelDelta; ///< Wheel delta from roll - HRGN hRgnUpdate; + HRGN hRgnUpdate; - bool hasOKText; + bool hasOKText; - CLIPFORMAT cfColumnSelect; - CLIPFORMAT cfBorlandIDEBlockType; - CLIPFORMAT cfLineSelect; - CLIPFORMAT cfVSLineTag; + CLIPFORMAT cfColumnSelect; + CLIPFORMAT cfBorlandIDEBlockType; + CLIPFORMAT cfLineSelect; + CLIPFORMAT cfVSLineTag; - HRESULT hrOle; - DropSource ds; - DataObject dob; - DropTarget dt; + HRESULT hrOle; + DropSource ds; + DataObject dob; + DropTarget dt; - static HINSTANCE hInstance; - static ATOM scintillaClassAtom; - static ATOM callClassAtom; + static HINSTANCE hInstance; + static ATOM scintillaClassAtom; + static ATOM callClassAtom; #if defined(USE_D2D) - ID2D1RenderTarget *pRenderTarget; - bool renderTargetValid; + ID2D1RenderTarget *pRenderTarget; + bool renderTargetValid; #endif - explicit ScintillaWin(HWND hwnd); - ScintillaWin(const ScintillaWin &); - virtual ~ScintillaWin(); - ScintillaWin &operator=(const ScintillaWin &); + explicit ScintillaWin(HWND hwnd); + ScintillaWin(const ScintillaWin &); + virtual ~ScintillaWin(); + ScintillaWin &operator=(const ScintillaWin &); - virtual void Initialise(); - virtual void Finalise(); + virtual void Initialise(); + virtual void Finalise(); #if defined(USE_D2D) - void EnsureRenderTarget(HDC hdc); - void DropRenderTarget(); + void EnsureRenderTarget(HDC hdc); + void DropRenderTarget(); #endif - HWND MainHWND(); - - static sptr_t DirectFunction( - sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam); - static LRESULT PASCAL SWndProc( - HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); - static LRESULT PASCAL CTWndProc( - HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); - - enum { invalidTimerID, standardTimerID, idleTimerID, fineTimerStart }; - - virtual bool DragThreshold(Point ptStart, Point ptNow); - virtual void StartDrag(); - int TargetAsUTF8(char *text); - void AddCharUTF16(wchar_t const *wcs, unsigned int wclen); - int EncodedFromUTF8(char *utf8, char *encoded) const; - sptr_t WndPaint(uptr_t wParam); - - sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam); - sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam); - static bool KoreanIME(); - void MoveImeCarets(int offset); - void DrawImeIndicator(int indicator, int len); - void SetCandidateWindowPos(); - void SelectionToHangul(); - void EscapeHanja(); - void ToggleHanja(); - void AddWString(std::wstring wcs); - - UINT CodePageOfDocument() const; - virtual bool ValidCodePage(int codePage) const; - virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - virtual bool SetIdle(bool on); - UINT_PTR timers[tickDwell + 1]; - virtual bool FineTickerAvailable(); - virtual bool FineTickerRunning(TickReason reason); - virtual void FineTickerStart(TickReason reason, int millis, int tolerance); - virtual void FineTickerCancel(TickReason reason); - virtual void SetMouseCapture(bool on); - virtual bool HaveMouseCapture(); - virtual void SetTrackMouseLeaveEvent(bool on); - virtual bool PaintContains(PRectangle rc); - virtual void ScrollText(int linesToMove); - virtual void NotifyCaretMove(); - virtual void UpdateSystemCaret(); - virtual void SetVerticalScrollPos(); - virtual void SetHorizontalScrollPos(); - virtual bool ModifyScrollBars(int nMax, int nPage); - virtual void NotifyChange(); - virtual void NotifyFocus(bool focus); - virtual void SetCtrlID(int identifier); - virtual int GetCtrlID(); - virtual void NotifyParent(SCNotification scn); - virtual void NotifyDoubleClick(Point pt, int modifiers); - virtual CaseFolder *CaseFolderForEncoding(); - virtual std::string CaseMapString(const std::string &s, int caseMapping); - virtual void Copy(); - virtual void CopyAllowLine(); - virtual bool CanPaste(); - virtual void Paste(); - virtual void CreateCallTipWindow(PRectangle rc); - virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); - virtual void ClaimSelection(); - - // DBCS - void ImeStartComposition(); - void ImeEndComposition(); - LRESULT ImeOnReconvert(LPARAM lParam); - - void GetIntelliMouseParameters(); - virtual void CopyToClipboard(const SelectionText &selectedText); - void ScrollMessage(WPARAM wParam); - void HorizontalScrollMessage(WPARAM wParam); - void FullPaint(); - void FullPaintDC(HDC dc); - bool IsCompatibleDC(HDC dc); - DWORD EffectFromState(DWORD grfKeyState) const; - - virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw); - virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi); - void ChangeScrollPos(int barType, int pos); - sptr_t GetTextLength(); - sptr_t GetText(uptr_t wParam, sptr_t lParam); + HWND MainHWND(); + + static sptr_t DirectFunction( + sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam); + static LRESULT PASCAL SWndProc( + HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); + static LRESULT PASCAL CTWndProc( + HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam); + + enum { invalidTimerID, standardTimerID, idleTimerID, fineTimerStart }; + + virtual bool DragThreshold(Point ptStart, Point ptNow); + virtual void StartDrag(); + int TargetAsUTF8(char *text); + void AddCharUTF16(wchar_t const *wcs, unsigned int wclen); + int EncodedFromUTF8(char *utf8, char *encoded) const; + sptr_t WndPaint(uptr_t wParam); + + sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam); + sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam); + static bool KoreanIME(); + void MoveImeCarets(int offset); + void DrawImeIndicator(int indicator, int len); + void SetCandidateWindowPos(); + void SelectionToHangul(); + void EscapeHanja(); + void ToggleHanja(); + void AddWString(std::wstring wcs); + + UINT CodePageOfDocument() const; + virtual bool ValidCodePage(int codePage) const; + virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + virtual bool SetIdle(bool on); + UINT_PTR timers[tickDwell+1]; + virtual bool FineTickerAvailable(); + virtual bool FineTickerRunning(TickReason reason); + virtual void FineTickerStart(TickReason reason, int millis, int tolerance); + virtual void FineTickerCancel(TickReason reason); + virtual void SetMouseCapture(bool on); + virtual bool HaveMouseCapture(); + virtual void SetTrackMouseLeaveEvent(bool on); + virtual bool PaintContains(PRectangle rc); + virtual void ScrollText(int linesToMove); + virtual void NotifyCaretMove(); + virtual void UpdateSystemCaret(); + virtual void SetVerticalScrollPos(); + virtual void SetHorizontalScrollPos(); + virtual bool ModifyScrollBars(int nMax, int nPage); + virtual void NotifyChange(); + virtual void NotifyFocus(bool focus); + virtual void SetCtrlID(int identifier); + virtual int GetCtrlID(); + virtual void NotifyParent(SCNotification scn); + virtual void NotifyDoubleClick(Point pt, int modifiers); + virtual CaseFolder *CaseFolderForEncoding(); + virtual std::string CaseMapString(const std::string &s, int caseMapping); + virtual void Copy(); + virtual void CopyAllowLine(); + virtual bool CanPaste(); + virtual void Paste(); + virtual void CreateCallTipWindow(PRectangle rc); + virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true); + virtual void ClaimSelection(); + + // DBCS + void ImeStartComposition(); + void ImeEndComposition(); + LRESULT ImeOnReconvert(LPARAM lParam); + + void GetIntelliMouseParameters(); + virtual void CopyToClipboard(const SelectionText &selectedText); + void ScrollMessage(WPARAM wParam); + void HorizontalScrollMessage(WPARAM wParam); + void FullPaint(); + void FullPaintDC(HDC dc); + bool IsCompatibleDC(HDC dc); + DWORD EffectFromState(DWORD grfKeyState) const; + + virtual int SetScrollInfo(int nBar, LPCSCROLLINFO lpsi, BOOL bRedraw); + virtual bool GetScrollInfo(int nBar, LPSCROLLINFO lpsi); + void ChangeScrollPos(int barType, int pos); + sptr_t GetTextLength(); + sptr_t GetText(uptr_t wParam, sptr_t lParam); public: - // Public for benefit of Scintilla_DirectFunction - virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); - - /// Implement IUnknown - STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv); - STDMETHODIMP_(ULONG)AddRef(); - STDMETHODIMP_(ULONG)Release(); - - /// Implement IDropTarget - STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, - POINTL pt, PDWORD pdwEffect); - STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect); - STDMETHODIMP DragLeave(); - STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, - POINTL pt, PDWORD pdwEffect); - - /// Implement important part of IDataObject - STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM); - - static bool Register(HINSTANCE hInstance_); - static bool Unregister(); - - friend class DropSource; - friend class DataObject; - friend class DropTarget; - bool DragIsRectangularOK(CLIPFORMAT fmt) const - { - return drag.rectangular && (fmt == cfColumnSelect); - } + // Public for benefit of Scintilla_DirectFunction + virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + + /// Implement IUnknown + STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv); + STDMETHODIMP_(ULONG)AddRef(); + STDMETHODIMP_(ULONG)Release(); + + /// Implement IDropTarget + STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, + POINTL pt, PDWORD pdwEffect); + STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect); + STDMETHODIMP DragLeave(); + STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, + POINTL pt, PDWORD pdwEffect); + + /// Implement important part of IDataObject + STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM); + + static bool Register(HINSTANCE hInstance_); + static bool Unregister(); + + friend class DropSource; + friend class DataObject; + friend class DropTarget; + bool DragIsRectangularOK(CLIPFORMAT fmt) const { + return drag.rectangular && (fmt == cfColumnSelect); + } private: - // For use in creating a system caret - bool HasCaretSizeChanged() const; - BOOL CreateSystemCaret(); - BOOL DestroySystemCaret(); - HBITMAP sysCaretBitmap; - int sysCaretWidth; - int sysCaretHeight; + // For use in creating a system caret + bool HasCaretSizeChanged() const; + BOOL CreateSystemCaret(); + BOOL DestroySystemCaret(); + HBITMAP sysCaretBitmap; + int sysCaretWidth; + int sysCaretHeight; }; HINSTANCE ScintillaWin::hInstance = 0; ATOM ScintillaWin::scintillaClassAtom = 0; ATOM ScintillaWin::callClassAtom = 0; -ScintillaWin::ScintillaWin(HWND hwnd) -{ +ScintillaWin::ScintillaWin(HWND hwnd) { - lastKeyDownConsumed = false; - lastHighSurrogateChar = 0; + lastKeyDownConsumed = false; + lastHighSurrogateChar = 0; - capturedMouse = false; - trackedMouseLeave = false; - TrackMouseEventFn = 0; - SetCoalescableTimerFn = 0; + capturedMouse = false; + trackedMouseLeave = false; + TrackMouseEventFn = 0; + SetCoalescableTimerFn = 0; - linesPerScroll = 0; - wheelDelta = 0; // Wheel delta from roll + linesPerScroll = 0; + wheelDelta = 0; // Wheel delta from roll - hRgnUpdate = 0; + hRgnUpdate = 0; - hasOKText = false; + hasOKText = false; - // There does not seem to be a real standard for indicating that the clipboard - // contains a rectangular selection, so copy Developer Studio and Borland Delphi. - cfColumnSelect = static_cast( - ::RegisterClipboardFormat(TEXT("MSDEVColumnSelect"))); - cfBorlandIDEBlockType = static_cast( - ::RegisterClipboardFormat(TEXT("Borland IDE Block Type"))); + // There does not seem to be a real standard for indicating that the clipboard + // contains a rectangular selection, so copy Developer Studio and Borland Delphi. + cfColumnSelect = static_cast( + ::RegisterClipboardFormat(TEXT("MSDEVColumnSelect"))); + cfBorlandIDEBlockType = static_cast( + ::RegisterClipboardFormat(TEXT("Borland IDE Block Type"))); - // Likewise for line-copy (copies a full line when no text is selected) - cfLineSelect = static_cast( - ::RegisterClipboardFormat(TEXT("MSDEVLineSelect"))); - cfVSLineTag = static_cast( - ::RegisterClipboardFormat(TEXT("VisualStudioEditorOperationsLineCutCopyClipboardTag"))); - hrOle = E_FAIL; + // Likewise for line-copy (copies a full line when no text is selected) + cfLineSelect = static_cast( + ::RegisterClipboardFormat(TEXT("MSDEVLineSelect"))); + cfVSLineTag = static_cast( + ::RegisterClipboardFormat(TEXT("VisualStudioEditorOperationsLineCutCopyClipboardTag"))); + hrOle = E_FAIL; - wMain = hwnd; + wMain = hwnd; - dob.sci = this; - ds.sci = this; - dt.sci = this; + dob.sci = this; + ds.sci = this; + dt.sci = this; - sysCaretBitmap = 0; - sysCaretWidth = 0; - sysCaretHeight = 0; + sysCaretBitmap = 0; + sysCaretWidth = 0; + sysCaretHeight = 0; #if defined(USE_D2D) - pRenderTarget = 0; - renderTargetValid = true; + pRenderTarget = 0; + renderTargetValid = true; #endif - caret.period = ::GetCaretBlinkTime(); - if (caret.period < 0) - caret.period = 0; + caret.period = ::GetCaretBlinkTime(); + if (caret.period < 0) + caret.period = 0; - Initialise(); + Initialise(); } ScintillaWin::~ScintillaWin() {} -void ScintillaWin::Initialise() -{ - // Initialize COM. If the app has already done this it will have - // no effect. If the app hasn't, we really shouldn't ask them to call - // it just so this internal feature works. - hrOle = ::OleInitialize(NULL); - - // Find TrackMouseEvent which is available on Windows > 95 - HMODULE user32 = ::GetModuleHandle(TEXT("user32.dll")); - if (user32) - { - TrackMouseEventFn = (TrackMouseEventSig)::GetProcAddress(user32, "TrackMouseEvent"); - SetCoalescableTimerFn = (SetCoalescableTimerSig)::GetProcAddress(user32, "SetCoalescableTimer"); - } - if (TrackMouseEventFn == NULL) - { - // Windows 95 has an emulation in comctl32.dll:_TrackMouseEvent - if (!commctrl32) - commctrl32 = ::LoadLibrary(TEXT("comctl32.dll")); - if (commctrl32 != NULL) - { - TrackMouseEventFn = (TrackMouseEventSig) - ::GetProcAddress(commctrl32, "_TrackMouseEvent"); - } - } - for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast(tr + 1)) - { - timers[tr] = 0; - } - vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff)); - vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff)); - vs.indicators[SC_INDICATOR_CONVERTED] = Indicator(INDIC_COMPOSITIONTHICK, ColourDesired(0, 0, 0xff)); - vs.indicators[SC_INDICATOR_TARGET] = Indicator(INDIC_STRAIGHTBOX, ColourDesired(0, 0, 0xff)); -} - -void ScintillaWin::Finalise() -{ - ScintillaBase::Finalise(); - for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast(tr + 1)) - { - FineTickerCancel(tr); - } - SetIdle(false); +void ScintillaWin::Initialise() { + // Initialize COM. If the app has already done this it will have + // no effect. If the app hasn't, we really shouldn't ask them to call + // it just so this internal feature works. + hrOle = ::OleInitialize(NULL); + + // Find TrackMouseEvent which is available on Windows > 95 + HMODULE user32 = ::GetModuleHandle(TEXT("user32.dll")); + if (user32) { + TrackMouseEventFn = (TrackMouseEventSig)::GetProcAddress(user32, "TrackMouseEvent"); + SetCoalescableTimerFn = (SetCoalescableTimerSig)::GetProcAddress(user32, "SetCoalescableTimer"); + } + if (TrackMouseEventFn == NULL) { + // Windows 95 has an emulation in comctl32.dll:_TrackMouseEvent + if (!commctrl32) + commctrl32 = ::LoadLibrary(TEXT("comctl32.dll")); + if (commctrl32 != NULL) { + TrackMouseEventFn = (TrackMouseEventSig) + ::GetProcAddress(commctrl32, "_TrackMouseEvent"); + } + } + for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast(tr + 1)) { + timers[tr] = 0; + } + vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff)); + vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff)); + vs.indicators[SC_INDICATOR_CONVERTED] = Indicator(INDIC_COMPOSITIONTHICK, ColourDesired(0, 0, 0xff)); + vs.indicators[SC_INDICATOR_TARGET] = Indicator(INDIC_STRAIGHTBOX, ColourDesired(0, 0, 0xff)); +} + +void ScintillaWin::Finalise() { + ScintillaBase::Finalise(); + for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast(tr + 1)) { + FineTickerCancel(tr); + } + SetIdle(false); #if defined(USE_D2D) - DropRenderTarget(); + DropRenderTarget(); #endif - ::RevokeDragDrop(MainHWND()); - if (SUCCEEDED(hrOle)) - { - ::OleUninitialize(); - } + ::RevokeDragDrop(MainHWND()); + if (SUCCEEDED(hrOle)) { + ::OleUninitialize(); + } } #if defined(USE_D2D) -void ScintillaWin::EnsureRenderTarget(HDC hdc) -{ - if (!renderTargetValid) - { - DropRenderTarget(); - renderTargetValid = true; - } - if (pD2DFactory && !pRenderTarget) - { - RECT rc; - HWND hw = MainHWND(); - GetClientRect(hw, &rc); - - D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); - - // Create a Direct2D render target. +void ScintillaWin::EnsureRenderTarget(HDC hdc) { + if (!renderTargetValid) { + DropRenderTarget(); + renderTargetValid = true; + } + if (pD2DFactory && !pRenderTarget) { + RECT rc; + HWND hw = MainHWND(); + GetClientRect(hw, &rc); + + D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); + + // Create a Direct2D render target. #if 1 - D2D1_RENDER_TARGET_PROPERTIES drtp; - drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; - drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN; - drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN; - drtp.dpiX = GetDpiX(); - drtp.dpiY = GetDpiY(); - drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE; - drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; - - if (technology == SC_TECHNOLOGY_DIRECTWRITEDC) - { - // Explicit pixel format needed. - drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, - D2D1_ALPHA_MODE_IGNORE); - - ID2D1DCRenderTarget *pDCRT = NULL; - HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pDCRT); - if (SUCCEEDED(hr)) - { - pRenderTarget = pDCRT; - } - else - { - Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%x\n", hr); - pRenderTarget = NULL; - } - - } - else - { - D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp; - dhrtp.hwnd = hw; - dhrtp.pixelSize = size; - dhrtp.presentOptions = (technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ? - D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE; - - ID2D1HwndRenderTarget *pHwndRenderTarget = NULL; - HRESULT hr = pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pHwndRenderTarget); - if (SUCCEEDED(hr)) - { - pRenderTarget = pHwndRenderTarget; - } - else - { - Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%x\n", hr); - pRenderTarget = NULL; - } - } + D2D1_RENDER_TARGET_PROPERTIES drtp; + drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; + drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN; + drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN; + drtp.dpiX = n2e_GetDpiX(); // [n2e]: DPI awareness #154 + drtp.dpiY = n2e_GetDpiY(); // [n2e]: DPI awareness #154 + drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE; + drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; + + if (technology == SC_TECHNOLOGY_DIRECTWRITEDC) { + // Explicit pixel format needed. + drtp.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, + D2D1_ALPHA_MODE_IGNORE); + + ID2D1DCRenderTarget *pDCRT = NULL; + HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pDCRT); + if (SUCCEEDED(hr)) { + pRenderTarget = pDCRT; + } else { + Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%x\n", hr); + pRenderTarget = NULL; + } + + } else { + D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp; + dhrtp.hwnd = hw; + dhrtp.pixelSize = size; + dhrtp.presentOptions = (technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ? + D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE; + + ID2D1HwndRenderTarget *pHwndRenderTarget = NULL; + HRESULT hr = pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pHwndRenderTarget); + if (SUCCEEDED(hr)) { + pRenderTarget = pHwndRenderTarget; + } else { + Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%x\n", hr); + pRenderTarget = NULL; + } + } #else - pD2DFactory->CreateHwndRenderTarget( - D2D1::RenderTargetProperties( - D2D1_RENDER_TARGET_TYPE_DEFAULT, - D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), - GetDpiSystemScaleFactorX(), GetDpiSystemScaleFactorY(), D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), - D2D1::HwndRenderTargetProperties(hw, size), - &pRenderTarget); + pD2DFactory->CreateHwndRenderTarget( + D2D1::RenderTargetProperties( + D2D1_RENDER_TARGET_TYPE_DEFAULT , + D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), + GetDpiSystemScaleFactorX(), GetDpiSystemScaleFactorY(), D2D1_RENDER_TARGET_USAGE_NONE, D2D1_FEATURE_LEVEL_DEFAULT), // [n2e]: DPI awareness #154 + D2D1::HwndRenderTargetProperties(hw, size), + &pRenderTarget); #endif - // Pixmaps were created to be compatible with previous render target so - // need to be recreated. - DropGraphics(false); - } - - if ((technology == SC_TECHNOLOGY_DIRECTWRITEDC) && pRenderTarget) - { - RECT rcWindow; - GetClientRect(MainHWND(), &rcWindow); - HRESULT hr = static_cast(pRenderTarget)->BindDC(hdc, &rcWindow); - if (FAILED(hr)) - { - Platform::DebugPrintf("BindDC failed 0x%x\n", hr); - DropRenderTarget(); - } - } - } - -void ScintillaWin::DropRenderTarget() -{ - if (pRenderTarget) - { - pRenderTarget->Release(); - pRenderTarget = 0; - } + // Pixmaps were created to be compatible with previous render target so + // need to be recreated. + DropGraphics(false); + } + + if ((technology == SC_TECHNOLOGY_DIRECTWRITEDC) && pRenderTarget) { + RECT rcWindow; + GetClientRect(MainHWND(), &rcWindow); + HRESULT hr = static_cast(pRenderTarget)->BindDC(hdc, &rcWindow); + if (FAILED(hr)) { + Platform::DebugPrintf("BindDC failed 0x%x\n", hr); + DropRenderTarget(); + } + } +} + +void ScintillaWin::DropRenderTarget() { + if (pRenderTarget) { + pRenderTarget->Release(); + pRenderTarget = 0; + } } #endif -HWND ScintillaWin::MainHWND() -{ - return static_cast(wMain.GetID()); -} - -bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) -{ - int xMove = static_cast(std::abs(ptStart.x - ptNow.x)); - int yMove = static_cast(std::abs(ptStart.y - ptNow.y)); - return (xMove > ::GetSystemMetrics(SM_CXDRAG)) || - (yMove > ::GetSystemMetrics(SM_CYDRAG)); -} - -void ScintillaWin::StartDrag() -{ - inDragDrop = ddDragging; - DWORD dwEffect = 0; - dropWentOutside = true; - IDataObject *pDataObject = reinterpret_cast(&dob); - IDropSource *pDropSource = reinterpret_cast(&ds); - //Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource); - HRESULT hr = ::DoDragDrop( - pDataObject, - pDropSource, - DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect); - //Platform::DebugPrintf("DoDragDrop = %x\n", hr); - if (SUCCEEDED(hr)) - { - if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) - { - // Remove dragged out text - ClearSelection(); - } - } - inDragDrop = ddNone; - SetDragPosition(SelectionPosition(invalidPosition)); +HWND ScintillaWin::MainHWND() { + return static_cast(wMain.GetID()); +} + +bool ScintillaWin::DragThreshold(Point ptStart, Point ptNow) { + int xMove = static_cast(std::abs(ptStart.x - ptNow.x)); + int yMove = static_cast(std::abs(ptStart.y - ptNow.y)); + return (xMove > ::GetSystemMetrics(SM_CXDRAG)) || + (yMove > ::GetSystemMetrics(SM_CYDRAG)); +} + +void ScintillaWin::StartDrag() { + inDragDrop = ddDragging; + DWORD dwEffect = 0; + dropWentOutside = true; + IDataObject *pDataObject = reinterpret_cast(&dob); + IDropSource *pDropSource = reinterpret_cast(&ds); + //Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource); + HRESULT hr = ::DoDragDrop( + pDataObject, + pDropSource, + DROPEFFECT_COPY | DROPEFFECT_MOVE, &dwEffect); + //Platform::DebugPrintf("DoDragDrop = %x\n", hr); + if (SUCCEEDED(hr)) { + if ((hr == DRAGDROP_S_DROP) && (dwEffect == DROPEFFECT_MOVE) && dropWentOutside) { + // Remove dragged out text + ClearSelection(); + } + } + inDragDrop = ddNone; + SetDragPosition(SelectionPosition(invalidPosition)); } // Avoid warnings everywhere for old style casts by concentrating them here -static WORD LoWord(uptr_t l) -{ - return LOWORD(l); +static WORD LoWord(uptr_t l) { + return LOWORD(l); } -static WORD HiWord(uptr_t l) -{ - return HIWORD(l); +static WORD HiWord(uptr_t l) { + return HIWORD(l); } -static int InputCodePage() -{ - HKL inputLocale = ::GetKeyboardLayout(0); - LANGID inputLang = LOWORD(inputLocale); - char sCodePage[10]; - int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT), - LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage)); - if (!res) - return 0; - return atoi(sCodePage); +static int InputCodePage() { + HKL inputLocale = ::GetKeyboardLayout(0); + LANGID inputLang = LOWORD(inputLocale); + char sCodePage[10]; + int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT), + LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage)); + if (!res) + return 0; + return atoi(sCodePage); } /** Map the key codes to their equivalent SCK_ form. */ -static int KeyTranslate(int keyIn) -{ - //PLATFORM_ASSERT(!keyIn); - switch (keyIn) - { - case VK_DOWN: return SCK_DOWN; - case VK_UP: return SCK_UP; - case VK_LEFT: return SCK_LEFT; - case VK_RIGHT: return SCK_RIGHT; - case VK_HOME: return SCK_HOME; - case VK_END: return SCK_END; - case VK_PRIOR: return SCK_PRIOR; - case VK_NEXT: return SCK_NEXT; - case VK_DELETE: return SCK_DELETE; - case VK_INSERT: return SCK_INSERT; - case VK_ESCAPE: return SCK_ESCAPE; - case VK_BACK: return SCK_BACK; - case VK_TAB: return SCK_TAB; - case VK_RETURN: return SCK_RETURN; - case VK_ADD: return SCK_ADD; - case VK_SUBTRACT: return SCK_SUBTRACT; - case VK_DIVIDE: return SCK_DIVIDE; - case VK_LWIN: return SCK_WIN; - case VK_RWIN: return SCK_RWIN; - case VK_APPS: return SCK_MENU; - case VK_OEM_2: return '/'; - case VK_OEM_3: return '`'; - case VK_OEM_4: return '['; - case VK_OEM_5: return '\\'; - case VK_OEM_6: return ']'; - default: return keyIn; - } -} - -static bool BoundsContains(PRectangle rcBounds, HRGN hRgnBounds, PRectangle rcCheck) -{ - bool contains = true; - if (!rcCheck.Empty()) - { - if (!rcBounds.Contains(rcCheck)) - { - contains = false; - } - else if (hRgnBounds) - { - // In bounding rectangle so check more accurately using region - HRGN hRgnCheck = ::CreateRectRgn(static_cast(rcCheck.left), static_cast(rcCheck.top), - static_cast(rcCheck.right), static_cast(rcCheck.bottom)); - if (hRgnCheck) - { - HRGN hRgnDifference = ::CreateRectRgn(0, 0, 0, 0); - if (hRgnDifference) - { - int combination = ::CombineRgn(hRgnDifference, hRgnCheck, hRgnBounds, RGN_DIFF); - if (combination != NULLREGION) - { - contains = false; - } - ::DeleteRgn(hRgnDifference); - } - ::DeleteRgn(hRgnCheck); - } - } - } - return contains; +static int KeyTranslate(int keyIn) { +//PLATFORM_ASSERT(!keyIn); + switch (keyIn) { + case VK_DOWN: return SCK_DOWN; + case VK_UP: return SCK_UP; + case VK_LEFT: return SCK_LEFT; + case VK_RIGHT: return SCK_RIGHT; + case VK_HOME: return SCK_HOME; + case VK_END: return SCK_END; + case VK_PRIOR: return SCK_PRIOR; + case VK_NEXT: return SCK_NEXT; + case VK_DELETE: return SCK_DELETE; + case VK_INSERT: return SCK_INSERT; + case VK_ESCAPE: return SCK_ESCAPE; + case VK_BACK: return SCK_BACK; + case VK_TAB: return SCK_TAB; + case VK_RETURN: return SCK_RETURN; + case VK_ADD: return SCK_ADD; + case VK_SUBTRACT: return SCK_SUBTRACT; + case VK_DIVIDE: return SCK_DIVIDE; + case VK_LWIN: return SCK_WIN; + case VK_RWIN: return SCK_RWIN; + case VK_APPS: return SCK_MENU; + case VK_OEM_2: return '/'; + case VK_OEM_3: return '`'; + case VK_OEM_4: return '['; + case VK_OEM_5: return '\\'; + case VK_OEM_6: return ']'; + default: return keyIn; + } +} + +static bool BoundsContains(PRectangle rcBounds, HRGN hRgnBounds, PRectangle rcCheck) { + bool contains = true; + if (!rcCheck.Empty()) { + if (!rcBounds.Contains(rcCheck)) { + contains = false; + } else if (hRgnBounds) { + // In bounding rectangle so check more accurately using region + HRGN hRgnCheck = ::CreateRectRgn(static_cast(rcCheck.left), static_cast(rcCheck.top), + static_cast(rcCheck.right), static_cast(rcCheck.bottom)); + if (hRgnCheck) { + HRGN hRgnDifference = ::CreateRectRgn(0, 0, 0, 0); + if (hRgnDifference) { + int combination = ::CombineRgn(hRgnDifference, hRgnCheck, hRgnBounds, RGN_DIFF); + if (combination != NULLREGION) { + contains = false; + } + ::DeleteRgn(hRgnDifference); + } + ::DeleteRgn(hRgnCheck); + } + } + } + return contains; } // Returns the target converted to UTF8. // Return the length in bytes. -int ScintillaWin::TargetAsUTF8(char *text) -{ - int targetLength = targetEnd - targetStart; - if (IsUnicodeMode()) - { - if (text) - { - pdoc->GetCharRange(text, targetStart, targetLength); - } - } - else - { - // Need to convert - std::string s = RangeText(targetStart, targetEnd); - int charsLen = ::MultiByteToWideChar(CodePageOfDocument(), 0, &s[0], targetLength, NULL, 0); - std::wstring characters(charsLen, '\0'); - ::MultiByteToWideChar(CodePageOfDocument(), 0, &s[0], targetLength, &characters[0], charsLen); - - int utf8Len = ::WideCharToMultiByte(CP_UTF8, 0, &characters[0], charsLen, NULL, 0, 0, 0); - if (text) - { - ::WideCharToMultiByte(CP_UTF8, 0, &characters[0], charsLen, text, utf8Len, 0, 0); - text[utf8Len] = '\0'; - } - return utf8Len; - } - return targetLength; +int ScintillaWin::TargetAsUTF8(char *text) { + int targetLength = targetEnd - targetStart; + if (IsUnicodeMode()) { + if (text) { + pdoc->GetCharRange(text, targetStart, targetLength); + } + } else { + // Need to convert + std::string s = RangeText(targetStart, targetEnd); + int charsLen = ::MultiByteToWideChar(CodePageOfDocument(), 0, &s[0], targetLength, NULL, 0); + std::wstring characters(charsLen, '\0'); + ::MultiByteToWideChar(CodePageOfDocument(), 0, &s[0], targetLength, &characters[0], charsLen); + + int utf8Len = ::WideCharToMultiByte(CP_UTF8, 0, &characters[0], charsLen, NULL, 0, 0, 0); + if (text) { + ::WideCharToMultiByte(CP_UTF8, 0, &characters[0], charsLen, text, utf8Len, 0, 0); + text[utf8Len] = '\0'; + } + return utf8Len; + } + return targetLength; } // Translates a nul terminated UTF8 string into the document encoding. // Return the length of the result in bytes. -int ScintillaWin::EncodedFromUTF8(char *utf8, char *encoded) const -{ - int inputLength = (lengthForEncode >= 0) ? lengthForEncode : static_cast(strlen(utf8)); - if (IsUnicodeMode()) - { - if (encoded) - { - memcpy(encoded, utf8, inputLength); - } - return inputLength; - } - else - { - // Need to convert - int charsLen = ::MultiByteToWideChar(CP_UTF8, 0, utf8, inputLength, NULL, 0); - std::wstring characters(charsLen, '\0'); - ::MultiByteToWideChar(CP_UTF8, 0, utf8, inputLength, &characters[0], charsLen); - - int encodedLen = ::WideCharToMultiByte(CodePageOfDocument(), - 0, &characters[0], charsLen, NULL, 0, 0, 0); - if (encoded) - { - ::WideCharToMultiByte(CodePageOfDocument(), 0, &characters[0], charsLen, encoded, encodedLen, 0, 0); - encoded[encodedLen] = '\0'; - } - return encodedLen; - } +int ScintillaWin::EncodedFromUTF8(char *utf8, char *encoded) const { + int inputLength = (lengthForEncode >= 0) ? lengthForEncode : static_cast(strlen(utf8)); + if (IsUnicodeMode()) { + if (encoded) { + memcpy(encoded, utf8, inputLength); + } + return inputLength; + } else { + // Need to convert + int charsLen = ::MultiByteToWideChar(CP_UTF8, 0, utf8, inputLength, NULL, 0); + std::wstring characters(charsLen, '\0'); + ::MultiByteToWideChar(CP_UTF8, 0, utf8, inputLength, &characters[0], charsLen); + + int encodedLen = ::WideCharToMultiByte(CodePageOfDocument(), + 0, &characters[0], charsLen, NULL, 0, 0, 0); + if (encoded) { + ::WideCharToMultiByte(CodePageOfDocument(), 0, &characters[0], charsLen, encoded, encodedLen, 0, 0); + encoded[encodedLen] = '\0'; + } + return encodedLen; + } } // Add one character from a UTF-16 string, by converting to either UTF-8 or // the current codepage. Code is similar to HandleCompositionWindowed(). -void ScintillaWin::AddCharUTF16(wchar_t const *wcs, unsigned int wclen) -{ - if (IsUnicodeMode()) - { - char utfval[maxLenInputIME * 3]; - unsigned int len = UTF8Length(wcs, wclen); - UTF8FromUTF16(wcs, wclen, utfval, len); - utfval[len] = '\0'; - AddCharUTF(utfval, len); - } - else - { - UINT cpDest = CodePageOfDocument(); - char inBufferCP[maxLenInputIME * 2]; - int size = ::WideCharToMultiByte(cpDest, - 0, wcs, wclen, inBufferCP, sizeof(inBufferCP) - 1, 0, 0); - for (int i = 0; i < size; i++) - { - AddChar(inBufferCP[i]); - } - } -} - -sptr_t ScintillaWin::WndPaint(uptr_t wParam) -{ - //ElapsedTime et; - - // Redirect assertions to debug output and save current state - bool assertsPopup = Platform::ShowAssertionPopUps(false); - paintState = painting; - PAINTSTRUCT ps; - PAINTSTRUCT *pps; - - bool IsOcxCtrl = (wParam != 0); // if wParam != 0, it contains - // a PAINSTRUCT* from the OCX - // Removed since this interferes with reporting other assertions as it occurs repeatedly - //PLATFORM_ASSERT(hRgnUpdate == NULL); - hRgnUpdate = ::CreateRectRgn(0, 0, 0, 0); - if (IsOcxCtrl) - { - pps = reinterpret_cast(wParam); - } - else - { - ::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE); - pps = &ps; - ::BeginPaint(MainHWND(), pps); - } - rcPaint = PRectangle::FromInts(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); - PRectangle rcClient = GetClientRectangle(); - paintingAllText = BoundsContains(rcPaint, hRgnUpdate, rcClient); - if (technology == SC_TECHNOLOGY_DEFAULT) - { - AutoSurface surfaceWindow(pps->hdc, this); - if (surfaceWindow) - { - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - } - } - else - { +void ScintillaWin::AddCharUTF16(wchar_t const *wcs, unsigned int wclen) { + if (IsUnicodeMode()) { + char utfval[maxLenInputIME * 3]; + unsigned int len = UTF8Length(wcs, wclen); + UTF8FromUTF16(wcs, wclen, utfval, len); + utfval[len] = '\0'; + AddCharUTF(utfval, len); + } else { + UINT cpDest = CodePageOfDocument(); + char inBufferCP[maxLenInputIME * 2]; + int size = ::WideCharToMultiByte(cpDest, + 0, wcs, wclen, inBufferCP, sizeof(inBufferCP) - 1, 0, 0); + for (int i=0; i(wParam); + } else { + ::GetUpdateRgn(MainHWND(), hRgnUpdate, FALSE); + pps = &ps; + ::BeginPaint(MainHWND(), pps); + } + rcPaint = PRectangle::FromInts(pps->rcPaint.left, pps->rcPaint.top, pps->rcPaint.right, pps->rcPaint.bottom); + PRectangle rcClient = GetClientRectangle(); + paintingAllText = BoundsContains(rcPaint, hRgnUpdate, rcClient); + if (technology == SC_TECHNOLOGY_DEFAULT) { + AutoSurface surfaceWindow(pps->hdc, this); + if (surfaceWindow) { + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + } + } else { #if defined(USE_D2D) - EnsureRenderTarget(pps->hdc); - AutoSurface surfaceWindow(pRenderTarget, this); - if (surfaceWindow) - { - pRenderTarget->BeginDraw(); - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - HRESULT hr = pRenderTarget->EndDraw(); - if (hr == D2DERR_RECREATE_TARGET) - { - DropRenderTarget(); - paintState = paintAbandoned; - } - } + EnsureRenderTarget(pps->hdc); + AutoSurface surfaceWindow(pRenderTarget, this); + if (surfaceWindow) { + pRenderTarget->BeginDraw(); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + HRESULT hr = pRenderTarget->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) { + DropRenderTarget(); + paintState = paintAbandoned; + } + } #endif - } - if (hRgnUpdate) - { - ::DeleteRgn(hRgnUpdate); - hRgnUpdate = 0; - } - - if (!IsOcxCtrl) - ::EndPaint(MainHWND(), pps); - if (paintState == paintAbandoned) - { - // Painting area was insufficient to cover new styling or brace highlight positions - if (IsOcxCtrl) - { - FullPaintDC(pps->hdc); - } - else - { - FullPaint(); - } - } - paintState = notPainting; - - // Restore debug output state - Platform::ShowAssertionPopUps(assertsPopup); - - //Platform::DebugPrintf("Paint took %g\n", et.Duration()); - return 0l; -} - -sptr_t ScintillaWin::HandleCompositionWindowed(uptr_t wParam, sptr_t lParam) -{ - if (lParam & GCS_RESULTSTR) - { - IMContext imc(MainHWND()); - if (imc.hIMC) - { - AddWString(imc.GetCompositionString(GCS_RESULTSTR)); - - // Set new position after converted - Point pos = PointMainCaret(); - COMPOSITIONFORM CompForm; - CompForm.dwStyle = CFS_POINT; - CompForm.ptCurrentPos.x = static_cast(pos.x); - CompForm.ptCurrentPos.y = static_cast(pos.y); - ::ImmSetCompositionWindow(imc.hIMC, &CompForm); - } - return 0; - } - return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam); -} - -bool ScintillaWin::KoreanIME() -{ - const int codePage = InputCodePage(); - return codePage == 949 || codePage == 1361; -} - -void ScintillaWin::MoveImeCarets(int offset) -{ - // Move carets relatively by bytes. - for (size_t r = 0; r < sel.Count(); r++) - { - int positionInsert = sel.Range(r).Start().Position(); - sel.Range(r).caret.SetPosition(positionInsert + offset); - sel.Range(r).anchor.SetPosition(positionInsert + offset); - } -} - -void ScintillaWin::DrawImeIndicator(int indicator, int len) -{ - // Emulate the visual style of IME characters with indicators. - // Draw an indicator on the character before caret by the character bytes of len - // so it should be called after addCharUTF(). - // It does not affect caret positions. - if (indicator < 8 || indicator > INDIC_MAX) - { - return; - } - pdoc->decorations.SetCurrentIndicator(indicator); - for (size_t r = 0; r < sel.Count(); r++) - { - int positionInsert = sel.Range(r).Start().Position(); - pdoc->DecorationFillRange(positionInsert - len, 1, len); - } -} - -void ScintillaWin::SetCandidateWindowPos() -{ - IMContext imc(MainHWND()); - if (imc.hIMC) - { - Point pos = PointMainCaret(); - CANDIDATEFORM CandForm; - CandForm.dwIndex = 0; - CandForm.dwStyle = CFS_CANDIDATEPOS; - CandForm.ptCurrentPos.x = static_cast(pos.x); - CandForm.ptCurrentPos.y = static_cast(pos.y + vs.lineHeight); - ::ImmSetCandidateWindow(imc.hIMC, &CandForm); - } -} - -static std::string StringEncode(std::wstring s, int codePage) -{ - if (s.length()) - { - int cchMulti = ::WideCharToMultiByte(codePage, 0, s.c_str(), static_cast(s.length()), NULL, 0, NULL, NULL); - std::string sMulti(cchMulti, 0); - ::WideCharToMultiByte(codePage, 0, s.c_str(), static_cast(s.size()), &sMulti[0], cchMulti, NULL, NULL); - return sMulti; - } - else - { - return std::string(); - } -} - -static std::wstring StringDecode(std::string s, int codePage) -{ - if (s.length()) - { - int cchWide = ::MultiByteToWideChar(codePage, 0, s.c_str(), static_cast(s.length()), NULL, 0); - std::wstring sWide(cchWide, 0); - ::MultiByteToWideChar(codePage, 0, s.c_str(), static_cast(s.length()), &sWide[0], cchWide); - return sWide; - } - else - { - return std::wstring(); - } -} - -void ScintillaWin::SelectionToHangul() -{ - // Convert every hanja to hangul within the main range. - const int selStart = sel.RangeMain().Start().Position(); - const int documentStrLen = sel.RangeMain().Length(); - const int selEnd = selStart + documentStrLen; - const int utf16Len = pdoc->CountUTF16(selStart, selEnd); - - if (utf16Len > 0) - { - std::string documentStr(documentStrLen, '\0'); - pdoc->GetCharRange(&documentStr[0], selStart, documentStrLen); - - std::wstring uniStr = StringDecode(documentStr, CodePageOfDocument()); - int converted = HanjaDict::GetHangulOfHanja(&uniStr[0]); - documentStr = StringEncode(uniStr, CodePageOfDocument()); - - if (converted > 0) - { - pdoc->BeginUndoAction(); - ClearSelection(); - InsertPaste(&documentStr[0], static_cast(documentStr.size())); - pdoc->EndUndoAction(); - } - } -} - -void ScintillaWin::EscapeHanja() -{ - // The candidate box pops up to user to select a hanja. - // It comes into WM_IME_COMPOSITION with GCS_RESULTSTR. - // The existing hangul or hanja is replaced with it. - if (sel.Count() > 1) - { - return; // Do not allow multi carets. - } - int currentPos = CurrentPosition(); - int oneCharLen = pdoc->LenChar(currentPos); - - if (oneCharLen < 2) - { - return; // No need to handle SBCS. - } - - // ImmEscapeW() may overwrite uniChar[] with a null terminated string. - // So enlarge it enough to Maximum 4 as in UTF-8. - unsigned int const safeLength = UTF8MaxBytes + 1; - std::string oneChar(safeLength, '\0'); - pdoc->GetCharRange(&oneChar[0], currentPos, oneCharLen); - - std::wstring uniChar = StringDecode(oneChar, CodePageOfDocument()); - - IMContext imc(MainHWND()); - if (imc.hIMC) - { - // Set the candidate box position since IME may show it. - SetCandidateWindowPos(); - // IME_ESC_HANJA_MODE appears to receive the first character only. - if (ImmEscapeW(GetKeyboardLayout(0), imc.hIMC, IME_ESC_HANJA_MODE, &uniChar[0])) - { - SetSelection(currentPos, currentPos + oneCharLen); - } - } -} - -void ScintillaWin::ToggleHanja() -{ - // If selection, convert every hanja to hangul within the main range. - // If no selection, commit to IME. - if (sel.Count() > 1) - { - return; // Do not allow multi carets. - } - - if (sel.Empty()) - { - EscapeHanja(); - } - else - { - SelectionToHangul(); - } -} - -namespace -{ - -std::vector MapImeIndicators(std::vector inputStyle) -{ - std::vector imeIndicator(inputStyle.size(), SC_INDICATOR_UNKNOWN); - for (size_t i = 0; i < inputStyle.size(); i++) - { - switch (static_cast(inputStyle.at(i))) - { - case ATTR_INPUT: - imeIndicator[i] = SC_INDICATOR_INPUT; - break; - case ATTR_TARGET_NOTCONVERTED: - case ATTR_TARGET_CONVERTED: - imeIndicator[i] = SC_INDICATOR_TARGET; - break; - case ATTR_CONVERTED: - imeIndicator[i] = SC_INDICATOR_CONVERTED; - break; - default: - imeIndicator[i] = SC_INDICATOR_UNKNOWN; - break; - } - } - return imeIndicator; -} - -} - -void ScintillaWin::AddWString(std::wstring wcs) -{ - if (wcs.empty()) - return; - - int codePage = CodePageOfDocument(); - for (size_t i = 0; i < wcs.size(); ) - { - const size_t ucWidth = UTF16CharLength(wcs[i]); - const std::wstring uniChar(wcs, i, ucWidth); - std::string docChar = StringEncode(uniChar, codePage); - - AddCharUTF(docChar.c_str(), static_cast(docChar.size())); - i += ucWidth; - } -} - -sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) -{ - // Copy & paste by johnsonj with a lot of helps of Neil. - // Great thanks for my foreruners, jiniya and BLUEnLIVE. - - IMContext imc(MainHWND()); - if (!imc.hIMC) - return 0; - if (pdoc->IsReadOnly() || SelectionContainsProtected()) - { - ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); - return 0; - } - - if (pdoc->TentativeActive()) - { - pdoc->TentativeUndo(); - } - else - { - // No tentative undo means start of this composition so - // fill in any virtual spaces. - ClearBeforeTentativeStart(); - } - - view.imeCaretBlockOverride = false; - - if (lParam & GCS_COMPSTR) - { - const std::wstring wcs = imc.GetCompositionString(GCS_COMPSTR); - if ((wcs.size() == 0) || (wcs.size() >= maxLenInputIME)) - { - ShowCaretAtCurrentPosition(); - return 0; - } - - pdoc->TentativeStart(); // TentativeActive from now on. - - std::vector imeIndicator = MapImeIndicators(imc.GetImeAttributes()); - - bool tmpRecordingMacro = recordingMacro; - recordingMacro = false; - int codePage = CodePageOfDocument(); - for (size_t i = 0; i < wcs.size(); ) - { - const size_t ucWidth = UTF16CharLength(wcs[i]); - const std::wstring uniChar(wcs, i, ucWidth); - std::string docChar = StringEncode(uniChar, codePage); - - AddCharUTF(docChar.c_str(), static_cast(docChar.size())); - - DrawImeIndicator(imeIndicator[i], static_cast(docChar.size())); - i += ucWidth; - } - recordingMacro = tmpRecordingMacro; - - // Move IME caret from current last position to imeCaretPos. - int imeEndToImeCaretU16 = imc.GetImeCaretPos() - static_cast(wcs.size()); - int imeCaretPosDoc = pdoc->GetRelativePositionUTF16(CurrentPosition(), imeEndToImeCaretU16); - - MoveImeCarets(-CurrentPosition() + imeCaretPosDoc); - - if (KoreanIME()) - { - view.imeCaretBlockOverride = true; - } - } - else if (lParam & GCS_RESULTSTR) - { - AddWString(imc.GetCompositionString(GCS_RESULTSTR)); - } - EnsureCaretVisible(); - SetCandidateWindowPos(); - ShowCaretAtCurrentPosition(); - return 0; + } + if (hRgnUpdate) { + ::DeleteRgn(hRgnUpdate); + hRgnUpdate = 0; + } + + if (!IsOcxCtrl) + ::EndPaint(MainHWND(), pps); + if (paintState == paintAbandoned) { + // Painting area was insufficient to cover new styling or brace highlight positions + if (IsOcxCtrl) { + FullPaintDC(pps->hdc); + } else { + FullPaint(); + } + } + paintState = notPainting; + + // Restore debug output state + Platform::ShowAssertionPopUps(assertsPopup); + + //Platform::DebugPrintf("Paint took %g\n", et.Duration()); + return 0l; +} + +sptr_t ScintillaWin::HandleCompositionWindowed(uptr_t wParam, sptr_t lParam) { + if (lParam & GCS_RESULTSTR) { + IMContext imc(MainHWND()); + if (imc.hIMC) { + AddWString(imc.GetCompositionString(GCS_RESULTSTR)); + + // Set new position after converted + Point pos = PointMainCaret(); + COMPOSITIONFORM CompForm; + CompForm.dwStyle = CFS_POINT; + CompForm.ptCurrentPos.x = static_cast(pos.x); + CompForm.ptCurrentPos.y = static_cast(pos.y); + ::ImmSetCompositionWindow(imc.hIMC, &CompForm); + } + return 0; + } + return ::DefWindowProc(MainHWND(), WM_IME_COMPOSITION, wParam, lParam); +} + +bool ScintillaWin::KoreanIME() { + const int codePage = InputCodePage(); + return codePage == 949 || codePage == 1361; +} + +void ScintillaWin::MoveImeCarets(int offset) { + // Move carets relatively by bytes. + for (size_t r=0; r INDIC_MAX) { + return; + } + pdoc->decorations.SetCurrentIndicator(indicator); + for (size_t r=0; rDecorationFillRange(positionInsert - len, 1, len); + } +} + +void ScintillaWin::SetCandidateWindowPos() { + IMContext imc(MainHWND()); + if (imc.hIMC) { + Point pos = PointMainCaret(); + CANDIDATEFORM CandForm; + CandForm.dwIndex = 0; + CandForm.dwStyle = CFS_CANDIDATEPOS; + CandForm.ptCurrentPos.x = static_cast(pos.x); + CandForm.ptCurrentPos.y = static_cast(pos.y + vs.lineHeight); + ::ImmSetCandidateWindow(imc.hIMC, &CandForm); + } +} + +static std::string StringEncode(std::wstring s, int codePage) { + if (s.length()) { + int cchMulti = ::WideCharToMultiByte(codePage, 0, s.c_str(), static_cast(s.length()), NULL, 0, NULL, NULL); + std::string sMulti(cchMulti, 0); + ::WideCharToMultiByte(codePage, 0, s.c_str(), static_cast(s.size()), &sMulti[0], cchMulti, NULL, NULL); + return sMulti; + } else { + return std::string(); + } +} + +static std::wstring StringDecode(std::string s, int codePage) { + if (s.length()) { + int cchWide = ::MultiByteToWideChar(codePage, 0, s.c_str(), static_cast(s.length()), NULL, 0); + std::wstring sWide(cchWide, 0); + ::MultiByteToWideChar(codePage, 0, s.c_str(), static_cast(s.length()), &sWide[0], cchWide); + return sWide; + } else { + return std::wstring(); + } +} + +void ScintillaWin::SelectionToHangul() { + // Convert every hanja to hangul within the main range. + const int selStart = sel.RangeMain().Start().Position(); + const int documentStrLen = sel.RangeMain().Length(); + const int selEnd = selStart + documentStrLen; + const int utf16Len = pdoc->CountUTF16(selStart, selEnd); + + if (utf16Len > 0) { + std::string documentStr(documentStrLen, '\0'); + pdoc->GetCharRange(&documentStr[0], selStart, documentStrLen); + + std::wstring uniStr = StringDecode(documentStr, CodePageOfDocument()); + int converted = HanjaDict::GetHangulOfHanja(&uniStr[0]); + documentStr = StringEncode(uniStr, CodePageOfDocument()); + + if (converted > 0) { + pdoc->BeginUndoAction(); + ClearSelection(); + InsertPaste(&documentStr[0], static_cast(documentStr.size())); + pdoc->EndUndoAction(); + } + } +} + +void ScintillaWin::EscapeHanja() { + // The candidate box pops up to user to select a hanja. + // It comes into WM_IME_COMPOSITION with GCS_RESULTSTR. + // The existing hangul or hanja is replaced with it. + if (sel.Count() > 1) { + return; // Do not allow multi carets. + } + int currentPos = CurrentPosition(); + int oneCharLen = pdoc->LenChar(currentPos); + + if (oneCharLen < 2) { + return; // No need to handle SBCS. + } + + // ImmEscapeW() may overwrite uniChar[] with a null terminated string. + // So enlarge it enough to Maximum 4 as in UTF-8. + unsigned int const safeLength = UTF8MaxBytes+1; + std::string oneChar(safeLength, '\0'); + pdoc->GetCharRange(&oneChar[0], currentPos, oneCharLen); + + std::wstring uniChar = StringDecode(oneChar, CodePageOfDocument()); + + IMContext imc(MainHWND()); + if (imc.hIMC) { + // Set the candidate box position since IME may show it. + SetCandidateWindowPos(); + // IME_ESC_HANJA_MODE appears to receive the first character only. + if (ImmEscapeW(GetKeyboardLayout(0), imc.hIMC, IME_ESC_HANJA_MODE, &uniChar[0])) { + SetSelection(currentPos, currentPos + oneCharLen); + } + } +} + +void ScintillaWin::ToggleHanja() { + // If selection, convert every hanja to hangul within the main range. + // If no selection, commit to IME. + if (sel.Count() > 1) { + return; // Do not allow multi carets. + } + + if (sel.Empty()) { + EscapeHanja(); + } else { + SelectionToHangul(); + } +} + +namespace { + +std::vector MapImeIndicators(std::vector inputStyle) { + std::vector imeIndicator(inputStyle.size(), SC_INDICATOR_UNKNOWN); + for (size_t i = 0; i < inputStyle.size(); i++) { + switch (static_cast(inputStyle.at(i))) { + case ATTR_INPUT: + imeIndicator[i] = SC_INDICATOR_INPUT; + break; + case ATTR_TARGET_NOTCONVERTED: + case ATTR_TARGET_CONVERTED: + imeIndicator[i] = SC_INDICATOR_TARGET; + break; + case ATTR_CONVERTED: + imeIndicator[i] = SC_INDICATOR_CONVERTED; + break; + default: + imeIndicator[i] = SC_INDICATOR_UNKNOWN; + break; + } + } + return imeIndicator; +} + +} + +void ScintillaWin::AddWString(std::wstring wcs) { + if (wcs.empty()) + return; + + int codePage = CodePageOfDocument(); + for (size_t i = 0; i < wcs.size(); ) { + const size_t ucWidth = UTF16CharLength(wcs[i]); + const std::wstring uniChar(wcs, i, ucWidth); + std::string docChar = StringEncode(uniChar, codePage); + + AddCharUTF(docChar.c_str(), static_cast(docChar.size())); + i += ucWidth; + } +} + +sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) { + // Copy & paste by johnsonj with a lot of helps of Neil. + // Great thanks for my foreruners, jiniya and BLUEnLIVE. + + IMContext imc(MainHWND()); + if (!imc.hIMC) + return 0; + if (pdoc->IsReadOnly() || SelectionContainsProtected()) { + ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); + return 0; + } + + if (pdoc->TentativeActive()) { + pdoc->TentativeUndo(); + } else { + // No tentative undo means start of this composition so + // fill in any virtual spaces. + ClearBeforeTentativeStart(); + } + + view.imeCaretBlockOverride = false; + + if (lParam & GCS_COMPSTR) { + const std::wstring wcs = imc.GetCompositionString(GCS_COMPSTR); + if ((wcs.size() == 0) || (wcs.size() >= maxLenInputIME)) { + ShowCaretAtCurrentPosition(); + return 0; + } + + pdoc->TentativeStart(); // TentativeActive from now on. + + std::vector imeIndicator = MapImeIndicators(imc.GetImeAttributes()); + + bool tmpRecordingMacro = recordingMacro; + recordingMacro = false; + int codePage = CodePageOfDocument(); + for (size_t i = 0; i < wcs.size(); ) { + const size_t ucWidth = UTF16CharLength(wcs[i]); + const std::wstring uniChar(wcs, i, ucWidth); + std::string docChar = StringEncode(uniChar, codePage); + + AddCharUTF(docChar.c_str(), static_cast(docChar.size())); + + DrawImeIndicator(imeIndicator[i], static_cast(docChar.size())); + i += ucWidth; + } + recordingMacro = tmpRecordingMacro; + + // Move IME caret from current last position to imeCaretPos. + int imeEndToImeCaretU16 = imc.GetImeCaretPos() - static_cast(wcs.size()); + int imeCaretPosDoc = pdoc->GetRelativePositionUTF16(CurrentPosition(), imeEndToImeCaretU16); + + MoveImeCarets(- CurrentPosition() + imeCaretPosDoc); + + if (KoreanIME()) { + view.imeCaretBlockOverride = true; + } + } else if (lParam & GCS_RESULTSTR) { + AddWString(imc.GetCompositionString(GCS_RESULTSTR)); + } + EnsureCaretVisible(); + SetCandidateWindowPos(); + ShowCaretAtCurrentPosition(); + return 0; } // Translate message IDs from WM_* and EM_* to SCI_* so can partly emulate Windows Edit control -static unsigned int SciMessageFromEM(unsigned int iMessage) -{ - switch (iMessage) - { - case EM_CANPASTE: return SCI_CANPASTE; - case EM_CANUNDO: return SCI_CANUNDO; - case EM_EMPTYUNDOBUFFER: return SCI_EMPTYUNDOBUFFER; - case EM_FINDTEXTEX: return SCI_FINDTEXT; - case EM_FORMATRANGE: return SCI_FORMATRANGE; - case EM_GETFIRSTVISIBLELINE: return SCI_GETFIRSTVISIBLELINE; - case EM_GETLINECOUNT: return SCI_GETLINECOUNT; - case EM_GETSELTEXT: return SCI_GETSELTEXT; - case EM_GETTEXTRANGE: return SCI_GETTEXTRANGE; - case EM_HIDESELECTION: return SCI_HIDESELECTION; - case EM_LINEINDEX: return SCI_POSITIONFROMLINE; - case EM_LINESCROLL: return SCI_LINESCROLL; - case EM_REPLACESEL: return SCI_REPLACESEL; - case EM_SCROLLCARET: return SCI_SCROLLCARET; - case EM_SETREADONLY: return SCI_SETREADONLY; - case WM_CLEAR: return SCI_CLEAR; - case WM_COPY: return SCI_COPY; - case WM_CUT: return SCI_CUT; - case WM_SETTEXT: return SCI_SETTEXT; - case WM_PASTE: return SCI_PASTE; - case WM_UNDO: return SCI_UNDO; - } - return iMessage; -} - -UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) -{ - if (documentCodePage == SC_CP_UTF8) - { - return SC_CP_UTF8; - } - switch (characterSet) - { - case SC_CHARSET_ANSI: return 1252; - case SC_CHARSET_DEFAULT: return documentCodePage; - case SC_CHARSET_BALTIC: return 1257; - case SC_CHARSET_CHINESEBIG5: return 950; - case SC_CHARSET_EASTEUROPE: return 1250; - case SC_CHARSET_GB2312: return 936; - case SC_CHARSET_GREEK: return 1253; - case SC_CHARSET_HANGUL: return 949; - case SC_CHARSET_MAC: return 10000; - case SC_CHARSET_OEM: return 437; - case SC_CHARSET_RUSSIAN: return 1251; - case SC_CHARSET_SHIFTJIS: return 932; - case SC_CHARSET_TURKISH: return 1254; - case SC_CHARSET_JOHAB: return 1361; - case SC_CHARSET_HEBREW: return 1255; - case SC_CHARSET_ARABIC: return 1256; - case SC_CHARSET_VIETNAMESE: return 1258; - case SC_CHARSET_THAI: return 874; - case SC_CHARSET_8859_15: return 28605; - // Not supported - case SC_CHARSET_CYRILLIC: return documentCodePage; - case SC_CHARSET_SYMBOL: return documentCodePage; - } - return documentCodePage; -} - -UINT ScintillaWin::CodePageOfDocument() const -{ - return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); -} - -sptr_t ScintillaWin::GetTextLength() -{ - if (pdoc->Length() == 0) - return 0; - std::vector docBytes(pdoc->Length(), '\0'); - pdoc->GetCharRange(&docBytes[0], 0, pdoc->Length()); - if (IsUnicodeMode()) - { - return UTF16Length(&docBytes[0], static_cast(docBytes.size())); - } - else - { - return ::MultiByteToWideChar(CodePageOfDocument(), 0, &docBytes[0], - static_cast(docBytes.size()), NULL, 0); - } -} - -sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) -{ - wchar_t *ptr = reinterpret_cast(lParam); - if (pdoc->Length() == 0) - { - *ptr = L'\0'; - return 0; - } - std::vector docBytes(pdoc->Length(), '\0'); - pdoc->GetCharRange(&docBytes[0], 0, pdoc->Length()); - if (IsUnicodeMode()) - { - size_t lengthUTF16 = UTF16Length(&docBytes[0], static_cast(docBytes.size())); - if (lParam == 0) - return lengthUTF16; - if (wParam == 0) - return 0; - size_t uLen = UTF16FromUTF8(&docBytes[0], docBytes.size(), - ptr, static_cast(wParam) - 1); - ptr[uLen] = L'\0'; - return uLen; - } - else - { - // Not Unicode mode - // Convert to Unicode using the current Scintilla code page - const UINT cpSrc = CodePageOfDocument(); - int lengthUTF16 = ::MultiByteToWideChar(cpSrc, 0, &docBytes[0], - static_cast(docBytes.size()), NULL, 0); - if (lengthUTF16 >= static_cast(wParam)) - lengthUTF16 = static_cast(wParam) - 1; - ::MultiByteToWideChar(cpSrc, 0, &docBytes[0], - static_cast(docBytes.size()), - ptr, lengthUTF16); - ptr[lengthUTF16] = L'\0'; - return lengthUTF16; - } -} - -sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) -{ - try - { - //Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam); - iMessage = SciMessageFromEM(iMessage); - switch (iMessage) - { - - case WM_CREATE: - ctrlID = ::GetDlgCtrlID(static_cast(wMain.GetID())); - // Get Intellimouse scroll line parameters - GetIntelliMouseParameters(); - ::RegisterDragDrop(MainHWND(), reinterpret_cast(&dt)); - break; - - case WM_COMMAND: - Command(LoWord(wParam)); - break; - - case WM_PAINT: - return WndPaint(wParam); - - case WM_PRINTCLIENT: { - HDC hdc = reinterpret_cast(wParam); - if (!IsCompatibleDC(hdc)) - { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - FullPaintDC(hdc); - } - break; - - case WM_VSCROLL: - ScrollMessage(wParam); - break; - - case WM_HSCROLL: - HorizontalScrollMessage(wParam); - break; - - case WM_SIZE: { +static unsigned int SciMessageFromEM(unsigned int iMessage) { + switch (iMessage) { + case EM_CANPASTE: return SCI_CANPASTE; + case EM_CANUNDO: return SCI_CANUNDO; + case EM_EMPTYUNDOBUFFER: return SCI_EMPTYUNDOBUFFER; + case EM_FINDTEXTEX: return SCI_FINDTEXT; + case EM_FORMATRANGE: return SCI_FORMATRANGE; + case EM_GETFIRSTVISIBLELINE: return SCI_GETFIRSTVISIBLELINE; + case EM_GETLINECOUNT: return SCI_GETLINECOUNT; + case EM_GETSELTEXT: return SCI_GETSELTEXT; + case EM_GETTEXTRANGE: return SCI_GETTEXTRANGE; + case EM_HIDESELECTION: return SCI_HIDESELECTION; + case EM_LINEINDEX: return SCI_POSITIONFROMLINE; + case EM_LINESCROLL: return SCI_LINESCROLL; + case EM_REPLACESEL: return SCI_REPLACESEL; + case EM_SCROLLCARET: return SCI_SCROLLCARET; + case EM_SETREADONLY: return SCI_SETREADONLY; + case WM_CLEAR: return SCI_CLEAR; + case WM_COPY: return SCI_COPY; + case WM_CUT: return SCI_CUT; + case WM_SETTEXT: return SCI_SETTEXT; + case WM_PASTE: return SCI_PASTE; + case WM_UNDO: return SCI_UNDO; + } + return iMessage; +} + +UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) { + if (documentCodePage == SC_CP_UTF8) { + return SC_CP_UTF8; + } + switch (characterSet) { + case SC_CHARSET_ANSI: return 1252; + case SC_CHARSET_DEFAULT: return documentCodePage; + case SC_CHARSET_BALTIC: return 1257; + case SC_CHARSET_CHINESEBIG5: return 950; + case SC_CHARSET_EASTEUROPE: return 1250; + case SC_CHARSET_GB2312: return 936; + case SC_CHARSET_GREEK: return 1253; + case SC_CHARSET_HANGUL: return 949; + case SC_CHARSET_MAC: return 10000; + case SC_CHARSET_OEM: return 437; + case SC_CHARSET_RUSSIAN: return 1251; + case SC_CHARSET_SHIFTJIS: return 932; + case SC_CHARSET_TURKISH: return 1254; + case SC_CHARSET_JOHAB: return 1361; + case SC_CHARSET_HEBREW: return 1255; + case SC_CHARSET_ARABIC: return 1256; + case SC_CHARSET_VIETNAMESE: return 1258; + case SC_CHARSET_THAI: return 874; + case SC_CHARSET_8859_15: return 28605; + // Not supported + case SC_CHARSET_CYRILLIC: return documentCodePage; + case SC_CHARSET_SYMBOL: return documentCodePage; + } + return documentCodePage; +} + +UINT ScintillaWin::CodePageOfDocument() const { + return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); +} + +sptr_t ScintillaWin::GetTextLength() { + if (pdoc->Length() == 0) + return 0; + std::vector docBytes(pdoc->Length(), '\0'); + pdoc->GetCharRange(&docBytes[0], 0, pdoc->Length()); + if (IsUnicodeMode()) { + return UTF16Length(&docBytes[0], static_cast(docBytes.size())); + } else { + return ::MultiByteToWideChar(CodePageOfDocument(), 0, &docBytes[0], + static_cast(docBytes.size()), NULL, 0); + } +} + +sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) { + wchar_t *ptr = reinterpret_cast(lParam); + if (pdoc->Length() == 0) { + *ptr = L'\0'; + return 0; + } + std::vector docBytes(pdoc->Length(), '\0'); + pdoc->GetCharRange(&docBytes[0], 0, pdoc->Length()); + if (IsUnicodeMode()) { + size_t lengthUTF16 = UTF16Length(&docBytes[0], static_cast(docBytes.size())); + if (lParam == 0) + return lengthUTF16; + if (wParam == 0) + return 0; + size_t uLen = UTF16FromUTF8(&docBytes[0], docBytes.size(), + ptr, static_cast(wParam) - 1); + ptr[uLen] = L'\0'; + return uLen; + } else { + // Not Unicode mode + // Convert to Unicode using the current Scintilla code page + const UINT cpSrc = CodePageOfDocument(); + int lengthUTF16 = ::MultiByteToWideChar(cpSrc, 0, &docBytes[0], + static_cast(docBytes.size()), NULL, 0); + if (lengthUTF16 >= static_cast(wParam)) + lengthUTF16 = static_cast(wParam)-1; + ::MultiByteToWideChar(cpSrc, 0, &docBytes[0], + static_cast(docBytes.size()), + ptr, lengthUTF16); + ptr[lengthUTF16] = L'\0'; + return lengthUTF16; + } +} + +sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + try { + //Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam); + iMessage = SciMessageFromEM(iMessage); + switch (iMessage) { + + case WM_CREATE: + ctrlID = ::GetDlgCtrlID(static_cast(wMain.GetID())); + // Get Intellimouse scroll line parameters + GetIntelliMouseParameters(); + ::RegisterDragDrop(MainHWND(), reinterpret_cast(&dt)); + break; + + case WM_COMMAND: + Command(LoWord(wParam)); + break; + + case WM_PAINT: + return WndPaint(wParam); + + case WM_PRINTCLIENT: { + HDC hdc = reinterpret_cast(wParam); + if (!IsCompatibleDC(hdc)) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + FullPaintDC(hdc); + } + break; + + case WM_VSCROLL: + ScrollMessage(wParam); + break; + + case WM_HSCROLL: + HorizontalScrollMessage(wParam); + break; + + case WM_SIZE: { #if defined(USE_D2D) - if (paintState == notPainting) - { - DropRenderTarget(); - } - else - { - renderTargetValid = false; - } + if (paintState == notPainting) { + DropRenderTarget(); + } else { + renderTargetValid = false; + } #endif - //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam)); - ChangeSize(); - } - break; - - case WM_MOUSEWHEEL: - // if autocomplete list active then send mousewheel message to it - if (ac.Active()) - { - HWND hWnd = static_cast(ac.lb->GetID()); - ::SendMessage(hWnd, iMessage, wParam, lParam); - break; - } - - // Don't handle datazoom. - // (A good idea for datazoom would be to "fold" or "unfold" details. - // i.e. if datazoomed out only class structures are visible, when datazooming in the control - // structures appear, then eventually the individual statements...) - if (wParam & MK_SHIFT) - { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - // Either SCROLL or ZOOM. We handle the wheel steppings calculation - wheelDelta -= static_cast(HiWord(wParam)); - if (abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) - { - int linesToScroll = linesPerScroll; - if (linesPerScroll == WHEEL_PAGESCROLL) - linesToScroll = LinesOnScreen() - 1; - if (linesToScroll == 0) - { - linesToScroll = 1; - } - linesToScroll *= (wheelDelta / WHEEL_DELTA); - if (wheelDelta >= 0) - wheelDelta = wheelDelta % WHEEL_DELTA; - else - wheelDelta = -(-wheelDelta % WHEEL_DELTA); - - if (wParam & MK_CONTROL) - { - // Zoom! We play with the font sizes in the styles. - // Number of steps/line is ignored, we just care if sizing up or down - if ( n2e_wheel_action ) { - n2e_wheel_action ( linesToScroll ); - } else { - if ( linesToScroll < 0 ) { - KeyCommand ( SCI_ZOOMIN ); - } else { - KeyCommand ( SCI_ZOOMOUT ); - } - } - } - else - { - // Scroll - ScrollTo(topLine + linesToScroll); - } - } - return 0; - - case WM_TIMER: - if (wParam == idleTimerID && idler.state) - { - SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1); - } - else - { - TickFor(static_cast(wParam - fineTimerStart)); - } - break; - - case SC_WIN_IDLE: - // wParam=dwTickCountInitial, or 0 to initialize. lParam=bSkipUserInputTest - if (idler.state) - { - if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, 0, 0, 0, QS_INPUT | QS_HOTKEY))) - { - if (Idle()) - { - // User input was given priority above, but all events do get a turn. Other - // messages, notifications, etc. will get interleaved with the idle messages. - - // However, some things like WM_PAINT are a lower priority, and will not fire - // when there's a message posted. So, several times a second, we stop and let - // the low priority events have a turn (after which the timer will fire again). - - DWORD dwCurrent = GetTickCount(); - DWORD dwStart = wParam ? static_cast(wParam) : dwCurrent; - const DWORD maxWorkTime = 50; - - if (dwCurrent >= dwStart && dwCurrent > maxWorkTime && dwCurrent - maxWorkTime < dwStart) - PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0); - } - else - { - SetIdle(false); - } - } - } - break; - - case WM_GETMINMAXINFO: - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_LBUTTONDOWN: { - // For IME, set the composition string as the result string. - IMContext imc(MainHWND()); - ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); - // - //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam, - // Platform::IsKeyDown(VK_SHIFT), - // Platform::IsKeyDown(VK_CONTROL), - // Platform::IsKeyDown(VK_MENU)); - ::SetFocus(MainHWND()); - ButtonDown(Point::FromLong(static_cast(lParam)), ::GetMessageTime(), - (wParam & MK_SHIFT) != 0, - (wParam & MK_CONTROL) != 0, - Platform::IsKeyDown(VK_MENU)); - } - break; - - case WM_MOUSEMOVE: { - const Point pt = Point::FromLong(static_cast(lParam)); - - // Windows might send WM_MOUSEMOVE even though the mouse has not been moved: - // http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx - if (ptMouseLast.x != pt.x || ptMouseLast.y != pt.y) - { - SetTrackMouseLeaveEvent(true); - ButtonMoveWithModifiers(pt, - ((wParam & MK_SHIFT) != 0 ? SCI_SHIFT : 0) | - ((wParam & MK_CONTROL) != 0 ? SCI_CTRL : 0) | - (Platform::IsKeyDown(VK_MENU) ? SCI_ALT : 0)); - } - } - break; - - case WM_MOUSELEAVE: - SetTrackMouseLeaveEvent(false); - MouseLeave(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_LBUTTONUP: - ButtonUp(Point::FromLong(static_cast(lParam)), - ::GetMessageTime(), - (wParam & MK_CONTROL) != 0); - break; - - case WM_RBUTTONDOWN: - ::SetFocus(MainHWND()); - if (moveCaretOnRClick && !PointInSelection(Point::FromLong(static_cast(lParam)))) - { - CancelModes(); - SetEmptySelection(PositionFromLocation(Point::FromLong(static_cast(lParam)))); - } - break; - - case WM_SETCURSOR: - if (LoWord(lParam) == HTCLIENT) - { - if (inDragDrop == ddDragging) - { - DisplayCursor(Window::cursorUp); - } - else - { - // Display regular (drag) cursor over selection - POINT pt; - if (0 != ::GetCursorPos(&pt)) - { - ::ScreenToClient(MainHWND(), &pt); - if (PointInSelMargin(PointFromPOINT(pt))) - { - DisplayCursor(GetMarginCursor(PointFromPOINT(pt))); - } - else if (PointInSelection(PointFromPOINT(pt)) && !SelectionEmpty()) - { - DisplayCursor(Window::cursorArrow); - } - else if (PointIsHotspot(PointFromPOINT(pt))) - { - DisplayCursor(Window::cursorHand); - } - else - { - DisplayCursor(Window::cursorText); - } - } - } - return TRUE; - } - else - { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_CHAR: - if (n2e_proc_action) - { - int ret = n2e_proc_action(wParam, WM_CHAR); - if (ret >= 0) - { - return ret; - } - } - if (((wParam >= 128) || !iscntrl(static_cast(wParam))) || !lastKeyDownConsumed) - { - wchar_t wcs[3] = { static_cast(wParam), 0 }; - unsigned int wclen = 1; - if (IS_HIGH_SURROGATE(wcs[0])) - { - // If this is a high surrogate character, we need a second one - lastHighSurrogateChar = wcs[0]; - return 0; - } - else if (IS_LOW_SURROGATE(wcs[0])) - { - wcs[1] = wcs[0]; - wcs[0] = lastHighSurrogateChar; - lastHighSurrogateChar = 0; - wclen = 2; - } - AddCharUTF16(wcs, wclen); - } - return 0; - - case WM_UNICHAR: - if (wParam == UNICODE_NOCHAR) - { - return TRUE; - } - else if (lastKeyDownConsumed) - { - return 1; - } - else - { - wchar_t wcs[3] = { 0 }; - unsigned int wclen = UTF16FromUTF32Character(static_cast(wParam), wcs); - AddCharUTF16(wcs, wclen); - return FALSE; - } - - case WM_SYSKEYDOWN: - case WM_KEYDOWN: { - //Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL)); - if (n2e_proc_action) - { - int ret = n2e_proc_action(wParam, WM_KEYDOWN); - if (ret >= 0) - { - return ret; - } - } - lastKeyDownConsumed = false; - int ret = KeyDown(KeyTranslate(static_cast(wParam)), - Platform::IsKeyDown(VK_SHIFT), - Platform::IsKeyDown(VK_CONTROL), - Platform::IsKeyDown(VK_MENU), - &lastKeyDownConsumed); - if (!ret && !lastKeyDownConsumed) - { - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - break; - } - - case WM_IME_KEYDOWN: { - if (wParam == VK_HANJA) - { - ToggleHanja(); - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_IME_REQUEST: { - if (wParam == IMR_RECONVERTSTRING) - { - return ImeOnReconvert(lParam); - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_KEYUP: - //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_SETTINGCHANGE: - //Platform::DebugPrintf("Setting Changed\n"); - InvalidateStyleData(); - // Get Intellimouse scroll line parameters - GetIntelliMouseParameters(); - break; - - case WM_GETDLGCODE: - return DLGC_HASSETSEL | DLGC_WANTALLKEYS; - - case WM_KILLFOCUS: { - HWND wOther = reinterpret_cast(wParam); - HWND wThis = MainHWND(); - HWND wCT = static_cast(ct.wCallTip.GetID()); - if (!wParam || - !(::IsChild(wThis, wOther) || (wOther == wCT))) - { - SetFocusState(false); - DestroySystemCaret(); - } - // Explicitly complete any IME composition - IMContext imc(MainHWND()); - if (imc.hIMC) - { - ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); - } - } - break; - - case WM_SETFOCUS: - SetFocusState(true); - DestroySystemCaret(); - CreateSystemCaret(); - break; - - case WM_SYSCOLORCHANGE: - //Platform::DebugPrintf("Setting Changed\n"); - InvalidateStyleData(); - break; - - case WM_IME_STARTCOMPOSITION: // dbcs - if (KoreanIME() || imeInteraction == imeInline) - { - return 0; - } - else - { - ImeStartComposition(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - } - - case WM_IME_ENDCOMPOSITION: // dbcs - ImeEndComposition(); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_IME_COMPOSITION: - if (KoreanIME() || imeInteraction == imeInline) - { - return HandleCompositionInline(wParam, lParam); - } - else - { - return HandleCompositionWindowed(wParam, lParam); - } - - case WM_CONTEXTMENU: - if (displayPopupMenu) - { - Point pt = Point::FromLong(static_cast(lParam)); - if ((pt.x == -1) && (pt.y == -1)) - { - // Caused by keyboard so display menu near caret - pt = PointMainCaret(); - POINT spt = { static_cast(pt.x), static_cast(pt.y) }; - ::ClientToScreen(MainHWND(), &spt); - pt = PointFromPOINT(spt); - } - ContextMenu(pt); - return 0; - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_INPUTLANGCHANGE: - //::SetThreadLocale(LOWORD(lParam)); - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_INPUTLANGCHANGEREQUEST: - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_ERASEBKGND: - return 1; // Avoid any background erasure as whole window painted. - - case WM_CAPTURECHANGED: - capturedMouse = false; - return 0; - - case WM_IME_SETCONTEXT: - if (KoreanIME() || imeInteraction == imeInline) - { - if (wParam) - { - LPARAM NoImeWin = lParam; - NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW); - return ::DefWindowProc(MainHWND(), iMessage, wParam, NoImeWin); - } - } - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - // These are not handled in Scintilla and its faster to dispatch them here. - // Also moves time out to here so profile doesn't count lots of empty message calls. - - case WM_MOVE: - case WM_MOUSEACTIVATE: - case WM_NCHITTEST: - case WM_NCCALCSIZE: - case WM_NCPAINT: - case WM_NCMOUSEMOVE: - case WM_NCLBUTTONDOWN: - case WM_IME_NOTIFY: - case WM_SYSCOMMAND: - case WM_WINDOWPOSCHANGING: - case WM_WINDOWPOSCHANGED: - return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); - - case WM_GETTEXTLENGTH: - return GetTextLength(); - - case WM_GETTEXT: - return GetText(wParam, lParam); - - case EM_LINEFROMCHAR: - if (static_cast(wParam) < 0) - { - wParam = SelectionStart().Position(); - } - return pdoc->LineFromPosition(static_cast(wParam)); - - case EM_EXLINEFROMCHAR: - return pdoc->LineFromPosition(static_cast(lParam)); - - case EM_GETSEL: - if (wParam) - { - *reinterpret_cast(wParam) = SelectionStart().Position(); - } - if (lParam) - { - *reinterpret_cast(lParam) = SelectionEnd().Position(); - } - return MAKELONG(SelectionStart().Position(), SelectionEnd().Position()); - - case EM_EXGETSEL: { - if (lParam == 0) - { - return 0; - } - Sci_CharacterRange *pCR = reinterpret_cast(lParam); - pCR->cpMin = SelectionStart().Position(); - pCR->cpMax = SelectionEnd().Position(); - } - break; - - case EM_SETSEL: { - int nStart = static_cast(wParam); - int nEnd = static_cast(lParam); - if (nStart == 0 && nEnd == -1) - { - nEnd = pdoc->Length(); - } - if (nStart == -1) - { - nStart = nEnd; // Remove selection - } - if (nStart > nEnd) - { - SetSelection(nEnd, nStart); - } - else - { - SetSelection(nStart, nEnd); - } - EnsureCaretVisible(); - } - break; - - case EM_EXSETSEL: { - if (lParam == 0) - { - return 0; - } - Sci_CharacterRange *pCR = reinterpret_cast(lParam); - sel.selType = Selection::selStream; - if (pCR->cpMin == 0 && pCR->cpMax == -1) - { - SetSelection(pCR->cpMin, pdoc->Length()); - } - else - { - SetSelection(pCR->cpMin, pCR->cpMax); - } - EnsureCaretVisible(); - return pdoc->LineFromPosition(SelectionStart().Position()); - } - - case SCI_GETDIRECTFUNCTION: - return reinterpret_cast(DirectFunction); - - case SCI_GETDIRECTPOINTER: - return reinterpret_cast(this); - - case SCI_GRABFOCUS: - ::SetFocus(MainHWND()); - break; + //Platform::DebugPrintf("Scintilla WM_SIZE %d %d\n", LoWord(lParam), HiWord(lParam)); + ChangeSize(); + } + break; + + case WM_MOUSEWHEEL: + // if autocomplete list active then send mousewheel message to it + if (ac.Active()) { + HWND hWnd = static_cast(ac.lb->GetID()); + ::SendMessage(hWnd, iMessage, wParam, lParam); + break; + } + + // Don't handle datazoom. + // (A good idea for datazoom would be to "fold" or "unfold" details. + // i.e. if datazoomed out only class structures are visible, when datazooming in the control + // structures appear, then eventually the individual statements...) + if (wParam & MK_SHIFT) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + // Either SCROLL or ZOOM. We handle the wheel steppings calculation + wheelDelta -= static_cast(HiWord(wParam)); + if (abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) { + int linesToScroll = linesPerScroll; + if (linesPerScroll == WHEEL_PAGESCROLL) + linesToScroll = LinesOnScreen() - 1; + if (linesToScroll == 0) { + linesToScroll = 1; + } + linesToScroll *= (wheelDelta / WHEEL_DELTA); + if (wheelDelta >= 0) + wheelDelta = wheelDelta % WHEEL_DELTA; + else + wheelDelta = - (-wheelDelta % WHEEL_DELTA); + + if (wParam & MK_CONTROL) { + // Zoom! We play with the font sizes in the styles. + // Number of steps/line is ignored, we just care if sizing up or down + // [n2e]: Implement wheel_action/proc_action + if (n2e_wheel_action) { + n2e_wheel_action(linesToScroll); + } else { + if (linesToScroll < 0) { + KeyCommand(SCI_ZOOMIN); + } else { + KeyCommand(SCI_ZOOMOUT); + } + } + // [/n2e] + } else { + // Scroll + ScrollTo(topLine + linesToScroll); + } + } + return 0; + + case WM_TIMER: + if (wParam == idleTimerID && idler.state) { + SendMessage(MainHWND(), SC_WIN_IDLE, 0, 1); + } else { + TickFor(static_cast(wParam - fineTimerStart)); + } + break; + + case SC_WIN_IDLE: + // wParam=dwTickCountInitial, or 0 to initialize. lParam=bSkipUserInputTest + if (idler.state) { + if (lParam || (WAIT_TIMEOUT == MsgWaitForMultipleObjects(0, 0, 0, 0, QS_INPUT|QS_HOTKEY))) { + if (Idle()) { + // User input was given priority above, but all events do get a turn. Other + // messages, notifications, etc. will get interleaved with the idle messages. + + // However, some things like WM_PAINT are a lower priority, and will not fire + // when there's a message posted. So, several times a second, we stop and let + // the low priority events have a turn (after which the timer will fire again). + + DWORD dwCurrent = GetTickCount(); + DWORD dwStart = wParam ? static_cast(wParam) : dwCurrent; + const DWORD maxWorkTime = 50; + + if (dwCurrent >= dwStart && dwCurrent > maxWorkTime && dwCurrent - maxWorkTime < dwStart) + PostMessage(MainHWND(), SC_WIN_IDLE, dwStart, 0); + } else { + SetIdle(false); + } + } + } + break; + + case WM_GETMINMAXINFO: + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_LBUTTONDOWN: { + // For IME, set the composition string as the result string. + IMContext imc(MainHWND()); + ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); + // + //Platform::DebugPrintf("Buttdown %d %x %x %x %x %x\n",iMessage, wParam, lParam, + // Platform::IsKeyDown(VK_SHIFT), + // Platform::IsKeyDown(VK_CONTROL), + // Platform::IsKeyDown(VK_MENU)); + ::SetFocus(MainHWND()); + ButtonDown(Point::FromLong(static_cast(lParam)), ::GetMessageTime(), + (wParam & MK_SHIFT) != 0, + (wParam & MK_CONTROL) != 0, + Platform::IsKeyDown(VK_MENU)); + } + break; + + case WM_MOUSEMOVE: { + const Point pt = Point::FromLong(static_cast(lParam)); + + // Windows might send WM_MOUSEMOVE even though the mouse has not been moved: + // http://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx + if (ptMouseLast.x != pt.x || ptMouseLast.y != pt.y) { + SetTrackMouseLeaveEvent(true); + ButtonMoveWithModifiers(pt, + ((wParam & MK_SHIFT) != 0 ? SCI_SHIFT : 0) | + ((wParam & MK_CONTROL) != 0 ? SCI_CTRL : 0) | + (Platform::IsKeyDown(VK_MENU) ? SCI_ALT : 0)); + } + } + break; + + case WM_MOUSELEAVE: + SetTrackMouseLeaveEvent(false); + MouseLeave(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_LBUTTONUP: + ButtonUp(Point::FromLong(static_cast(lParam)), + ::GetMessageTime(), + (wParam & MK_CONTROL) != 0); + break; + + case WM_RBUTTONDOWN: + ::SetFocus(MainHWND()); + if (n2e_moveCaretOnRClick && !PointInSelection(Point::FromLong(static_cast(lParam)))) { // [n2e]: Implement Notepad's right click behavior #54 + CancelModes(); + SetEmptySelection(PositionFromLocation(Point::FromLong(static_cast(lParam)))); + } + break; + + case WM_SETCURSOR: + if (LoWord(lParam) == HTCLIENT) { + if (inDragDrop == ddDragging) { + DisplayCursor(Window::cursorUp); + } else { + // Display regular (drag) cursor over selection + POINT pt; + if (0 != ::GetCursorPos(&pt)) { + ::ScreenToClient(MainHWND(), &pt); + if (PointInSelMargin(PointFromPOINT(pt))) { + DisplayCursor(GetMarginCursor(PointFromPOINT(pt))); + } else if (PointInSelection(PointFromPOINT(pt)) && !SelectionEmpty()) { + DisplayCursor(Window::cursorArrow); + } else if (PointIsHotspot(PointFromPOINT(pt))) { + DisplayCursor(Window::cursorHand); + } else { + DisplayCursor(Window::cursorText); + } + } + } + return TRUE; + } else { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_CHAR: + // [n2e]: Implement wheel_action/proc_action + if (n2e_proc_action) { + int ret = n2e_proc_action(wParam, WM_CHAR); + if (ret >= 0) { + return ret; + } + } + // [/n2e] + if (((wParam >= 128) || !iscntrl(static_cast(wParam))) || !lastKeyDownConsumed) { + wchar_t wcs[3] = {static_cast(wParam), 0}; + unsigned int wclen = 1; + if (IS_HIGH_SURROGATE(wcs[0])) { + // If this is a high surrogate character, we need a second one + lastHighSurrogateChar = wcs[0]; + return 0; + } else if (IS_LOW_SURROGATE(wcs[0])) { + wcs[1] = wcs[0]; + wcs[0] = lastHighSurrogateChar; + lastHighSurrogateChar = 0; + wclen = 2; + } + AddCharUTF16(wcs, wclen); + } + return 0; + + case WM_UNICHAR: + if (wParam == UNICODE_NOCHAR) { + return TRUE; + } else if (lastKeyDownConsumed) { + return 1; + } else { + wchar_t wcs[3] = {0}; + unsigned int wclen = UTF16FromUTF32Character(static_cast(wParam), wcs); + AddCharUTF16(wcs, wclen); + return FALSE; + } + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + //Platform::DebugPrintf("S keydown %d %x %x %x %x\n",iMessage, wParam, lParam, ::IsKeyDown(VK_SHIFT), ::IsKeyDown(VK_CONTROL)); + // [n2e]: Implement wheel_action/proc_action + if (n2e_proc_action) { + int ret = n2e_proc_action(wParam, WM_KEYDOWN); + if (ret >= 0) { + + return ret; + } + } + // [/n2e] + lastKeyDownConsumed = false; + int ret = KeyDown(KeyTranslate(static_cast(wParam)), + Platform::IsKeyDown(VK_SHIFT), + Platform::IsKeyDown(VK_CONTROL), + Platform::IsKeyDown(VK_MENU), + &lastKeyDownConsumed); + if (!ret && !lastKeyDownConsumed) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + break; + } + + case WM_IME_KEYDOWN: { + if (wParam == VK_HANJA) { + ToggleHanja(); + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_IME_REQUEST: { + if (wParam == IMR_RECONVERTSTRING) { + return ImeOnReconvert(lParam); + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_KEYUP: + //Platform::DebugPrintf("S keyup %d %x %x\n",iMessage, wParam, lParam); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_SETTINGCHANGE: + //Platform::DebugPrintf("Setting Changed\n"); + InvalidateStyleData(); + // Get Intellimouse scroll line parameters + GetIntelliMouseParameters(); + break; + + case WM_GETDLGCODE: + return DLGC_HASSETSEL | DLGC_WANTALLKEYS; + + case WM_KILLFOCUS: { + HWND wOther = reinterpret_cast(wParam); + HWND wThis = MainHWND(); + HWND wCT = static_cast(ct.wCallTip.GetID()); + if (!wParam || + !(::IsChild(wThis, wOther) || (wOther == wCT))) { + SetFocusState(false); + DestroySystemCaret(); + } + // Explicitly complete any IME composition + IMContext imc(MainHWND()); + if (imc.hIMC) { + ::ImmNotifyIME(imc.hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); + } + } + break; + + case WM_SETFOCUS: + SetFocusState(true); + DestroySystemCaret(); + CreateSystemCaret(); + break; + + case WM_SYSCOLORCHANGE: + //Platform::DebugPrintf("Setting Changed\n"); + InvalidateStyleData(); + break; + + case WM_IME_STARTCOMPOSITION: // dbcs + if (KoreanIME() || imeInteraction == imeInline) { + return 0; + } else { + ImeStartComposition(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + } + + case WM_IME_ENDCOMPOSITION: // dbcs + ImeEndComposition(); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_IME_COMPOSITION: + if (KoreanIME() || imeInteraction == imeInline) { + return HandleCompositionInline(wParam, lParam); + } else { + return HandleCompositionWindowed(wParam, lParam); + } + + case WM_CONTEXTMENU: + if (displayPopupMenu) { + Point pt = Point::FromLong(static_cast(lParam)); + if ((pt.x == -1) && (pt.y == -1)) { + // Caused by keyboard so display menu near caret + pt = PointMainCaret(); + POINT spt = {static_cast(pt.x), static_cast(pt.y)}; + ::ClientToScreen(MainHWND(), &spt); + pt = PointFromPOINT(spt); + } + ContextMenu(pt); + return 0; + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_INPUTLANGCHANGE: + //::SetThreadLocale(LOWORD(lParam)); + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_INPUTLANGCHANGEREQUEST: + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_ERASEBKGND: + return 1; // Avoid any background erasure as whole window painted. + + case WM_CAPTURECHANGED: + capturedMouse = false; + return 0; + + case WM_IME_SETCONTEXT: + if (KoreanIME() || imeInteraction == imeInline) { + if (wParam) { + LPARAM NoImeWin = lParam; + NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW); + return ::DefWindowProc(MainHWND(), iMessage, wParam, NoImeWin); + } + } + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + // These are not handled in Scintilla and its faster to dispatch them here. + // Also moves time out to here so profile doesn't count lots of empty message calls. + + case WM_MOVE: + case WM_MOUSEACTIVATE: + case WM_NCHITTEST: + case WM_NCCALCSIZE: + case WM_NCPAINT: + case WM_NCMOUSEMOVE: + case WM_NCLBUTTONDOWN: + case WM_IME_NOTIFY: + case WM_SYSCOMMAND: + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); + + case WM_GETTEXTLENGTH: + return GetTextLength(); + + case WM_GETTEXT: + return GetText(wParam, lParam); + + case EM_LINEFROMCHAR: + if (static_cast(wParam) < 0) { + wParam = SelectionStart().Position(); + } + return pdoc->LineFromPosition(static_cast(wParam)); + + case EM_EXLINEFROMCHAR: + return pdoc->LineFromPosition(static_cast(lParam)); + + case EM_GETSEL: + if (wParam) { + *reinterpret_cast(wParam) = SelectionStart().Position(); + } + if (lParam) { + *reinterpret_cast(lParam) = SelectionEnd().Position(); + } + return MAKELONG(SelectionStart().Position(), SelectionEnd().Position()); + + case EM_EXGETSEL: { + if (lParam == 0) { + return 0; + } + Sci_CharacterRange *pCR = reinterpret_cast(lParam); + pCR->cpMin = SelectionStart().Position(); + pCR->cpMax = SelectionEnd().Position(); + } + break; + + case EM_SETSEL: { + int nStart = static_cast(wParam); + int nEnd = static_cast(lParam); + if (nStart == 0 && nEnd == -1) { + nEnd = pdoc->Length(); + } + if (nStart == -1) { + nStart = nEnd; // Remove selection + } + if (nStart > nEnd) { + SetSelection(nEnd, nStart); + } else { + SetSelection(nStart, nEnd); + } + EnsureCaretVisible(); + } + break; + + case EM_EXSETSEL: { + if (lParam == 0) { + return 0; + } + Sci_CharacterRange *pCR = reinterpret_cast(lParam); + sel.selType = Selection::selStream; + if (pCR->cpMin == 0 && pCR->cpMax == -1) { + SetSelection(pCR->cpMin, pdoc->Length()); + } else { + SetSelection(pCR->cpMin, pCR->cpMax); + } + EnsureCaretVisible(); + return pdoc->LineFromPosition(SelectionStart().Position()); + } + + case SCI_GETDIRECTFUNCTION: + return reinterpret_cast(DirectFunction); + + case SCI_GETDIRECTPOINTER: + return reinterpret_cast(this); + + case SCI_GRABFOCUS: + ::SetFocus(MainHWND()); + break; #ifdef INCLUDE_DEPRECATED_FEATURES - case SCI_SETKEYSUNICODE: - break; + case SCI_SETKEYSUNICODE: + break; - case SCI_GETKEYSUNICODE: - return true; + case SCI_GETKEYSUNICODE: + return true; #endif - case SCI_SETTECHNOLOGY: - if ((wParam == SC_TECHNOLOGY_DEFAULT) || - (wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) || - (wParam == SC_TECHNOLOGY_DIRECTWRITEDC) || - (wParam == SC_TECHNOLOGY_DIRECTWRITE)) - { - if (technology != static_cast(wParam)) - { - if (static_cast(wParam) > SC_TECHNOLOGY_DEFAULT) - { + case SCI_SETTECHNOLOGY: + if ((wParam == SC_TECHNOLOGY_DEFAULT) || + (wParam == SC_TECHNOLOGY_DIRECTWRITERETAIN) || + (wParam == SC_TECHNOLOGY_DIRECTWRITEDC) || + (wParam == SC_TECHNOLOGY_DIRECTWRITE)) { + if (technology != static_cast(wParam)) { + if (static_cast(wParam) > SC_TECHNOLOGY_DEFAULT) { #if defined(USE_D2D) - if (!LoadD2D()) - // Failed to load Direct2D or DirectWrite so no effect - return 0; + if (!LoadD2D()) + // Failed to load Direct2D or DirectWrite so no effect + return 0; #else - return 0; + return 0; #endif - } + } #if defined(USE_D2D) - DropRenderTarget(); + DropRenderTarget(); #endif - technology = static_cast(wParam); - // Invalidate all cached information including layout. - DropGraphics(true); - InvalidateStyleRedraw(); - } - } - break; + technology = static_cast(wParam); + // Invalidate all cached information including layout. + DropGraphics(true); + InvalidateStyleRedraw(); + } + } + break; #ifdef SCI_LEXER - case SCI_LOADLEXERLIBRARY: - LexerManager::GetInstance()->Load(reinterpret_cast(lParam)); - break; + case SCI_LOADLEXERLIBRARY: + LexerManager::GetInstance()->Load(reinterpret_cast(lParam)); + break; #endif - case SCI_TARGETASUTF8: - return TargetAsUTF8(reinterpret_cast(lParam)); + case SCI_TARGETASUTF8: + return TargetAsUTF8(reinterpret_cast(lParam)); - case SCI_ENCODEDFROMUTF8: - return EncodedFromUTF8(reinterpret_cast(wParam), - reinterpret_cast(lParam)); + case SCI_ENCODEDFROMUTF8: + return EncodedFromUTF8(reinterpret_cast(wParam), + reinterpret_cast(lParam)); - case SCI_SETDPI: - SetDPI(LOWORD(wParam), - HIWORD(wParam), - MulDiv(DEFAULT_FONT_DPI, DEFAULT_SCREEN_DPI, GetDpiY())); - InvalidateStyleData(); - RefreshStyleData(); - return 0; + // [n2e]: DPI awareness #154 + case SCI_N2E_SETDPI: + n2e_SetDPI(LOWORD(wParam), + HIWORD(wParam), + MulDiv(N2E_DEFAULT_FONT_DPI, N2E_DEFAULT_SCREEN_DPI, n2e_GetDpiY())); + InvalidateStyleData(); + RefreshStyleData(); + return 0; + // [/n2e] - default: - return ScintillaBase::WndProc(iMessage, wParam, lParam); - } - } - catch (std::bad_alloc &) - { - errorStatus = SC_STATUS_BADALLOC; - } - catch (...) - { - errorStatus = SC_STATUS_FAILURE; - } - return 0l; + default: + return ScintillaBase::WndProc(iMessage, wParam, lParam); + } + } catch (std::bad_alloc &) { + errorStatus = SC_STATUS_BADALLOC; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + 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; +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); +sptr_t ScintillaWin::DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { + return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); } /** * Report that this Editor subclass has a working implementation of FineTickerStart. */ -bool ScintillaWin::FineTickerAvailable() -{ - return true; -} - -bool ScintillaWin::FineTickerRunning(TickReason reason) -{ - return timers[reason] != 0; -} - -void ScintillaWin::FineTickerStart(TickReason reason, int millis, int tolerance) -{ - FineTickerCancel(reason); - if (SetCoalescableTimerFn && tolerance) - { - timers[reason] = SetCoalescableTimerFn(MainHWND(), fineTimerStart + reason, millis, NULL, tolerance); - } - else - { - timers[reason] = ::SetTimer(MainHWND(), fineTimerStart + reason, millis, NULL); - } -} - -void ScintillaWin::FineTickerCancel(TickReason reason) -{ - if (timers[reason]) - { - ::KillTimer(MainHWND(), timers[reason]); - timers[reason] = 0; - } -} - - -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(idleTimerID) : 0; - } - else - { - ::KillTimer(MainHWND(), reinterpret_cast(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()); -} - -void ScintillaWin::SetTrackMouseLeaveEvent(bool on) -{ - if (on && TrackMouseEventFn && !trackedMouseLeave) - { - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(tme); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = MainHWND(); - tme.dwHoverTime = HOVER_DEFAULT; // Unused but triggers Dr. Memory if not initialized - TrackMouseEventFn(&tme); - } - trackedMouseLeave = on; -} - -bool ScintillaWin::PaintContains(PRectangle rc) -{ - if (paintState == painting) - { - return BoundsContains(rcPaint, hRgnUpdate, rc); - } - return true; -} - -void ScintillaWin::ScrollText(int /* linesToMove */) -{ - //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove); - //::ScrollWindow(MainHWND(), 0, - // vs.lineHeight * linesToMove, 0, 0); - //::UpdateWindow(MainHWND()); - Redraw(); - UpdateSystemCaret(); -} - -void ScintillaWin::NotifyCaretMove() -{ - NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, MainHWND(), OBJID_CARET, CHILDID_SELF); -} - -void ScintillaWin::UpdateSystemCaret() -{ - if (hasFocus) - { - if (HasCaretSizeChanged()) - { - DestroySystemCaret(); - CreateSystemCaret(); - } - Point pos = PointMainCaret(); - ::SetCaretPos(static_cast(pos.x), static_cast(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; +bool ScintillaWin::FineTickerAvailable() { + return true; +} + +bool ScintillaWin::FineTickerRunning(TickReason reason) { + return timers[reason] != 0; +} + +void ScintillaWin::FineTickerStart(TickReason reason, int millis, int tolerance) { + FineTickerCancel(reason); + if (SetCoalescableTimerFn && tolerance) { + timers[reason] = SetCoalescableTimerFn(MainHWND(), fineTimerStart + reason, millis, NULL, tolerance); + } else { + timers[reason] = ::SetTimer(MainHWND(), fineTimerStart + reason, millis, NULL); + } +} + +void ScintillaWin::FineTickerCancel(TickReason reason) { + if (timers[reason]) { + ::KillTimer(MainHWND(), timers[reason]); + timers[reason] = 0; + } +} + + +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(idleTimerID) : 0; + } else { + ::KillTimer(MainHWND(), reinterpret_cast(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()); +} + +void ScintillaWin::SetTrackMouseLeaveEvent(bool on) { + if (on && TrackMouseEventFn && !trackedMouseLeave) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = MainHWND(); + tme.dwHoverTime = HOVER_DEFAULT; // Unused but triggers Dr. Memory if not initialized + TrackMouseEventFn(&tme); + } + trackedMouseLeave = on; +} + +bool ScintillaWin::PaintContains(PRectangle rc) { + if (paintState == painting) { + return BoundsContains(rcPaint, hRgnUpdate, rc); + } + return true; +} + +void ScintillaWin::ScrollText(int /* linesToMove */) { + //Platform::DebugPrintf("ScintillaWin::ScrollText %d\n", linesToMove); + //::ScrollWindow(MainHWND(), 0, + // vs.lineHeight * linesToMove, 0, 0); + //::UpdateWindow(MainHWND()); + Redraw(); + UpdateSystemCaret(); +} + +void ScintillaWin::NotifyCaretMove() { + NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, MainHWND(), OBJID_CARET, CHILDID_SELF); +} + +void ScintillaWin::UpdateSystemCaret() { + if (hasFocus) { + if (HasCaretSizeChanged()) { + DestroySystemCaret(); + CreateSystemCaret(); + } + Point pos = PointMainCaret(); + ::SetCaretPos(static_cast(pos.x), static_cast(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) - nPage = vertEndPreferred + 1; - if ((sci.nMin != 0) || - (sci.nMax != vertEndPreferred) || - (sci.nPage != static_cast(nPage)) || - (sci.nPos != 0)) - { - 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; - unsigned int pageWidth = static_cast(rcText.Width()); - if (!horizontalScrollBarVisible || Wrapping()) - pageWidth = horizEndPreferred + 1; - 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(pageWidth)) - { - HorizontalScrollTo(0); - } - } - return modified; -} - -void ScintillaWin::NotifyChange() -{ - ::SendMessage(::GetParent(MainHWND()), WM_COMMAND, - MAKELONG(GetCtrlID(), SCEN_CHANGE), - reinterpret_cast(MainHWND())); -} - -void ScintillaWin::NotifyFocus(bool focus) -{ - ::SendMessage(::GetParent(MainHWND()), WM_COMMAND, - MAKELONG(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), - reinterpret_cast(MainHWND())); - Editor::NotifyFocus(focus); -} - -void ScintillaWin::SetCtrlID(int identifier) -{ - ::SetWindowID(static_cast(wMain.GetID()), identifier); -} - -int ScintillaWin::GetCtrlID() -{ - return ::GetDlgCtrlID(static_cast(wMain.GetID())); -} - -void ScintillaWin::NotifyParent(SCNotification scn) -{ - scn.nmhdr.hwndFrom = MainHWND(); - scn.nmhdr.idFrom = GetCtrlID(); - ::SendMessage(::GetParent(MainHWND()), WM_NOTIFY, - GetCtrlID(), reinterpret_cast(&scn)); -} - -void ScintillaWin::NotifyDoubleClick(Point pt, int modifiers) -{ - //Platform::DebugPrintf("ScintillaWin Double click 0\n"); - ScintillaBase::NotifyDoubleClick(pt, modifiers); - // Send myself a WM_LBUTTONDBLCLK, so the container can handle it too. - ::SendMessage(MainHWND(), - WM_LBUTTONDBLCLK, - (modifiers & SCI_SHIFT) ? MK_SHIFT : 0, - MAKELPARAM(pt.x, pt.y)); -} - -class CaseFolderDBCS : public CaseFolderTable -{ - // Allocate the expandable storage here so that it does not need to be reallocated - // for each call to Fold. - std::vector utf16Mixed; - std::vector utf16Folded; - UINT cp; +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) + nPage = vertEndPreferred + 1; + if ((sci.nMin != 0) || + (sci.nMax != vertEndPreferred) || + (sci.nPage != static_cast(nPage)) || + (sci.nPos != 0)) { + 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; + unsigned int pageWidth = static_cast(rcText.Width()); + if (!horizontalScrollBarVisible || Wrapping()) + pageWidth = horizEndPreferred + 1; + 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(pageWidth)) { + HorizontalScrollTo(0); + } + } + return modified; +} + +void ScintillaWin::NotifyChange() { + ::SendMessage(::GetParent(MainHWND()), WM_COMMAND, + MAKELONG(GetCtrlID(), SCEN_CHANGE), + reinterpret_cast(MainHWND())); +} + +void ScintillaWin::NotifyFocus(bool focus) { + ::SendMessage(::GetParent(MainHWND()), WM_COMMAND, + MAKELONG(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS), + reinterpret_cast(MainHWND())); + Editor::NotifyFocus(focus); +} + +void ScintillaWin::SetCtrlID(int identifier) { + ::SetWindowID(static_cast(wMain.GetID()), identifier); +} + +int ScintillaWin::GetCtrlID() { + return ::GetDlgCtrlID(static_cast(wMain.GetID())); +} + +void ScintillaWin::NotifyParent(SCNotification scn) { + scn.nmhdr.hwndFrom = MainHWND(); + scn.nmhdr.idFrom = GetCtrlID(); + ::SendMessage(::GetParent(MainHWND()), WM_NOTIFY, + GetCtrlID(), reinterpret_cast(&scn)); +} + +void ScintillaWin::NotifyDoubleClick(Point pt, int modifiers) { + //Platform::DebugPrintf("ScintillaWin Double click 0\n"); + ScintillaBase::NotifyDoubleClick(pt, modifiers); + // Send myself a WM_LBUTTONDBLCLK, so the container can handle it too. + ::SendMessage(MainHWND(), + WM_LBUTTONDBLCLK, + (modifiers & SCI_SHIFT) ? MK_SHIFT : 0, + MAKELPARAM(pt.x, pt.y)); +} + +class CaseFolderDBCS : public CaseFolderTable { + // Allocate the expandable storage here so that it does not need to be reallocated + // for each call to Fold. + std::vector utf16Mixed; + std::vector utf16Folded; + UINT cp; public: - explicit CaseFolderDBCS(UINT cp_) : cp(cp_) - { - StandardASCII(); - } - virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) - { - if ((lenMixed == 1) && (sizeFolded > 0)) - { - folded[0] = mapping[static_cast(mixed[0])]; - return 1; - } - else - { - if (lenMixed > utf16Mixed.size()) - { - utf16Mixed.resize(lenMixed + 8); - } - size_t nUtf16Mixed = ::MultiByteToWideChar(cp, 0, mixed, - static_cast(lenMixed), - &utf16Mixed[0], - static_cast(utf16Mixed.size())); - - if (nUtf16Mixed == 0) - { - // Failed to convert -> bad input - folded[0] = '\0'; - return 1; - } - - unsigned int lenFlat = 0; - for (size_t mixIndex = 0; mixIndex < nUtf16Mixed; mixIndex++) - { - if ((lenFlat + 20) > utf16Folded.size()) - utf16Folded.resize(lenFlat + 60); - const char *foldedUTF8 = CaseConvert(utf16Mixed[mixIndex], CaseConversionFold); - if (foldedUTF8) - { - // Maximum length of a case conversion is 6 bytes, 3 characters - wchar_t wFolded[20]; - size_t charsConverted = UTF16FromUTF8(foldedUTF8, - strlen(foldedUTF8), - wFolded, ELEMENTS(wFolded)); - for (size_t j = 0; j < charsConverted; j++) - utf16Folded[lenFlat++] = wFolded[j]; - } - else - { - utf16Folded[lenFlat++] = utf16Mixed[mixIndex]; - } - } - - size_t lenOut = ::WideCharToMultiByte(cp, 0, - &utf16Folded[0], lenFlat, - NULL, 0, NULL, 0); - - if (lenOut < sizeFolded) - { - ::WideCharToMultiByte(cp, 0, - &utf16Folded[0], lenFlat, - folded, static_cast(lenOut), NULL, 0); - return lenOut; - } - else - { - return 0; - } - } - } + explicit CaseFolderDBCS(UINT cp_) : cp(cp_) { + StandardASCII(); + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if ((lenMixed == 1) && (sizeFolded > 0)) { + folded[0] = mapping[static_cast(mixed[0])]; + return 1; + } else { + if (lenMixed > utf16Mixed.size()) { + utf16Mixed.resize(lenMixed + 8); + } + size_t nUtf16Mixed = ::MultiByteToWideChar(cp, 0, mixed, + static_cast(lenMixed), + &utf16Mixed[0], + static_cast(utf16Mixed.size())); + + if (nUtf16Mixed == 0) { + // Failed to convert -> bad input + folded[0] = '\0'; + return 1; + } + + unsigned int lenFlat = 0; + for (size_t mixIndex=0; mixIndex < nUtf16Mixed; mixIndex++) { + if ((lenFlat + 20) > utf16Folded.size()) + utf16Folded.resize(lenFlat + 60); + const char *foldedUTF8 = CaseConvert(utf16Mixed[mixIndex], CaseConversionFold); + if (foldedUTF8) { + // Maximum length of a case conversion is 6 bytes, 3 characters + wchar_t wFolded[20]; + size_t charsConverted = UTF16FromUTF8(foldedUTF8, + strlen(foldedUTF8), + wFolded, ELEMENTS(wFolded)); + for (size_t j=0; j(lenOut), NULL, 0); + return lenOut; + } else { + return 0; + } + } + } }; -CaseFolder *ScintillaWin::CaseFolderForEncoding() -{ - UINT cpDest = CodePageOfDocument(); - if (cpDest == SC_CP_UTF8) - { - return new CaseFolderUnicode(); - } - else - { - if (pdoc->dbcsCodePage == 0) - { - CaseFolderTable *pcf = new CaseFolderTable(); - pcf->StandardASCII(); - // Only for single byte encodings - UINT cpDoc = CodePageOfDocument(); - for (int i = 0x80; i < 0x100; i++) - { - char sCharacter[2] = "A"; - sCharacter[0] = static_cast(i); - wchar_t wCharacter[20]; - unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, sCharacter, 1, - wCharacter, ELEMENTS(wCharacter)); - if (lengthUTF16 == 1) - { - const char *caseFolded = CaseConvert(wCharacter[0], CaseConversionFold); - if (caseFolded) - { - wchar_t wLower[20]; - size_t charsConverted = UTF16FromUTF8(caseFolded, - strlen(caseFolded), - wLower, ELEMENTS(wLower)); - if (charsConverted == 1) - { - char sCharacterLowered[20]; - unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, - wLower, static_cast(charsConverted), - sCharacterLowered, ELEMENTS(sCharacterLowered), NULL, 0); - if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) - { - pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]); - } - } - } - } - } - return pcf; - } - else - { - return new CaseFolderDBCS(cpDest); - } - } -} - -std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) -{ - if ((s.size() == 0) || (caseMapping == cmSame)) - return s; - - UINT cpDoc = CodePageOfDocument(); - if (cpDoc == SC_CP_UTF8) - { - std::string retMapped(s.length() * maxExpansionCaseConversion, 0); - size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(), - (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower); - retMapped.resize(lenMapped); - return retMapped; - } - - unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(), - static_cast(s.size()), NULL, 0); - if (lengthUTF16 == 0) // Failed to convert - return s; - - DWORD mapFlags = LCMAP_LINGUISTIC_CASING | - ((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE); - - // Change text to UTF-16 - std::vector vwcText(lengthUTF16); - ::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast(s.size()), &vwcText[0], lengthUTF16); - - // Change case - int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, - &vwcText[0], lengthUTF16, NULL, 0); - std::vector vwcConverted(charsConverted); - ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, - &vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted); - - // Change back to document encoding - unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, - &vwcConverted[0], static_cast(vwcConverted.size()), - NULL, 0, NULL, 0); - std::vector vcConverted(lengthConverted); - ::WideCharToMultiByte(cpDoc, 0, - &vwcConverted[0], static_cast(vwcConverted.size()), - &vcConverted[0], static_cast(vcConverted.size()), NULL, 0); - - return std::string(&vcConverted[0], vcConverted.size()); -} - -void ScintillaWin::Copy() -{ - //Platform::DebugPrintf("Copy\n"); - if (!sel.Empty()) - { - SelectionText selectedText; - CopySelectionRange(&selectedText); - CopyToClipboard(selectedText); - } -} - -void ScintillaWin::CopyAllowLine() -{ - SelectionText selectedText; - CopySelectionRange(&selectedText, true); - 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; -} - -class GlobalMemory -{ - HGLOBAL hand; +CaseFolder *ScintillaWin::CaseFolderForEncoding() { + UINT cpDest = CodePageOfDocument(); + if (cpDest == SC_CP_UTF8) { + return new CaseFolderUnicode(); + } else { + if (pdoc->dbcsCodePage == 0) { + CaseFolderTable *pcf = new CaseFolderTable(); + pcf->StandardASCII(); + // Only for single byte encodings + UINT cpDoc = CodePageOfDocument(); + for (int i=0x80; i<0x100; i++) { + char sCharacter[2] = "A"; + sCharacter[0] = static_cast(i); + wchar_t wCharacter[20]; + unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, sCharacter, 1, + wCharacter, ELEMENTS(wCharacter)); + if (lengthUTF16 == 1) { + const char *caseFolded = CaseConvert(wCharacter[0], CaseConversionFold); + if (caseFolded) { + wchar_t wLower[20]; + size_t charsConverted = UTF16FromUTF8(caseFolded, + strlen(caseFolded), + wLower, ELEMENTS(wLower)); + if (charsConverted == 1) { + char sCharacterLowered[20]; + unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, + wLower, static_cast(charsConverted), + sCharacterLowered, ELEMENTS(sCharacterLowered), NULL, 0); + if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) { + pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]); + } + } + } + } + } + return pcf; + } else { + return new CaseFolderDBCS(cpDest); + } + } +} + +std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) { + if ((s.size() == 0) || (caseMapping == cmSame)) + return s; + + UINT cpDoc = CodePageOfDocument(); + if (cpDoc == SC_CP_UTF8) { + std::string retMapped(s.length() * maxExpansionCaseConversion, 0); + size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(), + (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower); + retMapped.resize(lenMapped); + return retMapped; + } + + unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(), + static_cast(s.size()), NULL, 0); + if (lengthUTF16 == 0) // Failed to convert + return s; + + DWORD mapFlags = LCMAP_LINGUISTIC_CASING | + ((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE); + + // Change text to UTF-16 + std::vector vwcText(lengthUTF16); + ::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast(s.size()), &vwcText[0], lengthUTF16); + + // Change case + int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, + &vwcText[0], lengthUTF16, NULL, 0); + std::vector vwcConverted(charsConverted); + ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, + &vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted); + + // Change back to document encoding + unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, + &vwcConverted[0], static_cast(vwcConverted.size()), + NULL, 0, NULL, 0); + std::vector vcConverted(lengthConverted); + ::WideCharToMultiByte(cpDoc, 0, + &vwcConverted[0], static_cast(vwcConverted.size()), + &vcConverted[0], static_cast(vcConverted.size()), NULL, 0); + + return std::string(&vcConverted[0], vcConverted.size()); +} + +void ScintillaWin::Copy() { + //Platform::DebugPrintf("Copy\n"); + if (!sel.Empty()) { + SelectionText selectedText; + CopySelectionRange(&selectedText); + CopyToClipboard(selectedText); + } +} + +void ScintillaWin::CopyAllowLine() { + SelectionText selectedText; + CopySelectionRange(&selectedText, true); + 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; +} + +class GlobalMemory { + HGLOBAL hand; public: - void *ptr; - GlobalMemory() : hand(0), ptr(0) - { - } - explicit GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) - { - if (hand) - { - ptr = ::GlobalLock(hand); - } - } - ~GlobalMemory() - { - PLATFORM_ASSERT(!ptr); - assert(!hand); - } - void Allocate(size_t bytes) - { - assert(!hand); - 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() const - { - return ptr != 0; - } - SIZE_T Size() - { - return ::GlobalSize(hand); - } + void *ptr; + GlobalMemory() : hand(0), ptr(0) { + } + explicit GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) { + if (hand) { + ptr = ::GlobalLock(hand); + } + } + ~GlobalMemory() { + PLATFORM_ASSERT(!ptr); + assert(!hand); + } + void Allocate(size_t bytes) { + assert(!hand); + 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() const { + return ptr != 0; + } + SIZE_T Size() { + return ::GlobalSize(hand); + } }; // OpenClipboard may fail if another application has opened the clipboard. // Try up to 8 times, with an initial delay of 1 ms and an exponential back off // for a maximum total delay of 127 ms (1+2+4+8+16+32+64). -static bool OpenClipboardRetry(HWND hwnd) -{ - for (int attempt = 0; attempt < 8; attempt++) - { - if (attempt > 0) - { - ::Sleep(1 << (attempt - 1)); - } - if (::OpenClipboard(hwnd)) - { - return true; - } - } - return false; -} - -void ScintillaWin::Paste() -{ - if (!::OpenClipboardRetry(MainHWND())) - { - return; - } - UndoGroup ug(pdoc); - const bool isLine = SelectionEmpty() && - (::IsClipboardFormatAvailable(cfLineSelect) || ::IsClipboardFormatAvailable(cfVSLineTag)); - ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH); - bool isRectangular = (::IsClipboardFormatAvailable(cfColumnSelect) != 0); - - if (!isRectangular) - { - // Evaluate "Borland IDE Block Type" explicitly - GlobalMemory memBorlandSelection(::GetClipboardData(cfBorlandIDEBlockType)); - if (memBorlandSelection) - { - isRectangular = (memBorlandSelection.Size() == 1) && (static_cast(memBorlandSelection.ptr)[0] == 0x02); - memBorlandSelection.Unlock(); - } - } - const PasteShape pasteShape = isRectangular ? pasteRectangular : (isLine ? pasteLine : pasteStream); - - // Always use CF_UNICODETEXT if available - GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT)); - if (memUSelection) - { - wchar_t *uptr = static_cast(memUSelection.ptr); - if (uptr) - { - unsigned int len; - std::vector putf; - // Default Scintilla behaviour in Unicode mode - if (IsUnicodeMode()) - { - unsigned int bytes = static_cast(memUSelection.Size()); - len = UTF8Length(uptr, bytes / 2); - putf.resize(len + 1); - UTF8FromUTF16(uptr, bytes / 2, &putf[0], len); - } - else - { - // CF_UNICODETEXT available, but not in Unicode mode - // Convert from Unicode to current Scintilla code page - UINT cpDest = CodePageOfDocument(); - len = ::WideCharToMultiByte(cpDest, 0, uptr, -1, - NULL, 0, NULL, NULL) - 1; // subtract 0 terminator - putf.resize(len + 1); - ::WideCharToMultiByte(cpDest, 0, uptr, -1, - &putf[0], len + 1, NULL, NULL); - } - - InsertPasteShape(&putf[0], len, pasteShape); - } - memUSelection.Unlock(); - } - else - { - // CF_UNICODETEXT not available, paste ANSI text - GlobalMemory memSelection(::GetClipboardData(CF_TEXT)); - if (memSelection) - { - char *ptr = static_cast(memSelection.ptr); - if (ptr) - { - unsigned int bytes = static_cast(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()) - { - std::vector uptr(len + 1); - - unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0, - ptr, len, &uptr[0], len + 1); - - unsigned int mlen = UTF8Length(&uptr[0], ulen); - std::vector putf(mlen + 1); - UTF8FromUTF16(&uptr[0], ulen, &putf[0], mlen); - - InsertPasteShape(&putf[0], mlen, pasteShape); - } - else - { - InsertPasteShape(ptr, len, pasteShape); - } - } - memSelection.Unlock(); - } - } - ::CloseClipboard(); - Redraw(); -} - -void ScintillaWin::CreateCallTipWindow(PRectangle) -{ - 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; - } -} - -void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) -{ - HMENU hmenuPopup = static_cast(popup.GetID()); - if (!label[0]) - ::AppendMenuA(hmenuPopup, MF_SEPARATOR, 0, ""); - else if (enabled) - ::AppendMenuA(hmenuPopup, MF_STRING, cmd, label); - else - ::AppendMenuA(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label); -} - -void ScintillaWin::ClaimSelection() -{ - // Windows does not have a primary selection +static bool OpenClipboardRetry(HWND hwnd) { + for (int attempt=0; attempt<8; attempt++) { + if (attempt > 0) { + ::Sleep(1 << (attempt-1)); + } + if (::OpenClipboard(hwnd)) { + return true; + } + } + return false; +} + +void ScintillaWin::Paste() { + if (!::OpenClipboardRetry(MainHWND())) { + return; + } + UndoGroup ug(pdoc); + const bool isLine = SelectionEmpty() && + (::IsClipboardFormatAvailable(cfLineSelect) || ::IsClipboardFormatAvailable(cfVSLineTag)); + ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH); + bool isRectangular = (::IsClipboardFormatAvailable(cfColumnSelect) != 0); + + if (!isRectangular) { + // Evaluate "Borland IDE Block Type" explicitly + GlobalMemory memBorlandSelection(::GetClipboardData(cfBorlandIDEBlockType)); + if (memBorlandSelection) { + isRectangular = (memBorlandSelection.Size() == 1) && (static_cast(memBorlandSelection.ptr)[0] == 0x02); + memBorlandSelection.Unlock(); + } + } + const PasteShape pasteShape = isRectangular ? pasteRectangular : (isLine ? pasteLine : pasteStream); + + // Always use CF_UNICODETEXT if available + GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT)); + if (memUSelection) { + wchar_t *uptr = static_cast(memUSelection.ptr); + if (uptr) { + unsigned int len; + std::vector putf; + // Default Scintilla behaviour in Unicode mode + if (IsUnicodeMode()) { + unsigned int bytes = static_cast(memUSelection.Size()); + len = UTF8Length(uptr, bytes / 2); + putf.resize(len + 1); + UTF8FromUTF16(uptr, bytes / 2, &putf[0], len); + } else { + // CF_UNICODETEXT available, but not in Unicode mode + // Convert from Unicode to current Scintilla code page + UINT cpDest = CodePageOfDocument(); + len = ::WideCharToMultiByte(cpDest, 0, uptr, -1, + NULL, 0, NULL, NULL) - 1; // subtract 0 terminator + putf.resize(len + 1); + ::WideCharToMultiByte(cpDest, 0, uptr, -1, + &putf[0], len + 1, NULL, NULL); + } + + InsertPasteShape(&putf[0], len, pasteShape); + } + memUSelection.Unlock(); + } else { + // CF_UNICODETEXT not available, paste ANSI text + GlobalMemory memSelection(::GetClipboardData(CF_TEXT)); + if (memSelection) { + char *ptr = static_cast(memSelection.ptr); + if (ptr) { + unsigned int bytes = static_cast(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()) { + std::vector uptr(len+1); + + unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0, + ptr, len, &uptr[0], len+1); + + unsigned int mlen = UTF8Length(&uptr[0], ulen); + std::vector putf(mlen+1); + UTF8FromUTF16(&uptr[0], ulen, &putf[0], mlen); + + InsertPasteShape(&putf[0], mlen, pasteShape); + } else { + InsertPasteShape(ptr, len, pasteShape); + } + } + memSelection.Unlock(); + } + } + ::CloseClipboard(); + Redraw(); +} + +void ScintillaWin::CreateCallTipWindow(PRectangle) { + 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; + } +} + +void ScintillaWin::AddToPopUp(const char *label, int cmd, bool enabled) { + HMENU hmenuPopup = static_cast(popup.GetID()); + if (!label[0]) + ::AppendMenuA(hmenuPopup, MF_SEPARATOR, 0, ""); + else if (enabled) + ::AppendMenuA(hmenuPopup, MF_STRING, cmd, label); + else + ::AppendMenuA(hmenuPopup, MF_STRING | MF_DISABLED | MF_GRAYED, cmd, label); +} + +void ScintillaWin::ClaimSelection() { + // Windows does not have a primary selection } /// 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(fe); - if (riid == IID_IEnumFORMATETC) - *ppv = reinterpret_cast(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; +STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) { + //Platform::DebugPrintf("EFE QI"); + *ppv = NULL; + if (riid == IID_IUnknown) + *ppv = reinterpret_cast(fe); + if (riid == IID_IEnumFORMATETC) + *ppv = reinterpret_cast(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) -{ - if (rgelt == NULL) return E_POINTER; - unsigned int putPos = 0; - while ((fe->pos < fe->formats.size()) && (putPos < celt)) - { - rgelt->cfFormat = fe->formats[fe->pos]; - rgelt->ptd = 0; - rgelt->dwAspect = DVASPECT_CONTENT; - rgelt->lindex = -1; - rgelt->tymed = TYMED_HGLOBAL; - rgelt++; - 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; - try - { - pfe = new FormatEnumerator(fe->pos, &fe->formats[0], fe->formats.size()); - } - catch (...) - { - return E_OUTOFMEMORY; - } - return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, - reinterpret_cast(ppenum)); +STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) { + if (rgelt == NULL) return E_POINTER; + unsigned int putPos = 0; + while ((fe->pos < fe->formats.size()) && (putPos < celt)) { + rgelt->cfFormat = fe->formats[fe->pos]; + rgelt->ptd = 0; + rgelt->dwAspect = DVASPECT_CONTENT; + rgelt->lindex = -1; + rgelt->tymed = TYMED_HGLOBAL; + rgelt++; + 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; + try { + pfe = new FormatEnumerator(fe->pos, &fe->formats[0], fe->formats.size()); + } catch (...) { + return E_OUTOFMEMORY; + } + return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, + reinterpret_cast(ppenum)); } static VFunction *vtFormatEnumerator[] = { - (VFunction *)(FormatEnumerator_QueryInterface), - (VFunction *)(FormatEnumerator_AddRef), - (VFunction *)(FormatEnumerator_Release), - (VFunction *)(FormatEnumerator_Next), - (VFunction *)(FormatEnumerator_Skip), - (VFunction *)(FormatEnumerator_Reset), - (VFunction *)(FormatEnumerator_Clone) + (VFunction *)(FormatEnumerator_QueryInterface), + (VFunction *)(FormatEnumerator_AddRef), + (VFunction *)(FormatEnumerator_Release), + (VFunction *)(FormatEnumerator_Next), + (VFunction *)(FormatEnumerator_Skip), + (VFunction *)(FormatEnumerator_Reset), + (VFunction *)(FormatEnumerator_Clone) }; -FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], size_t formatsLen_) -{ - vtbl = vtFormatEnumerator; - ref = 0; // First QI adds first reference... - pos = pos_; - formats.insert(formats.begin(), formats_, formats_ + formatsLen_); +FormatEnumerator::FormatEnumerator(int pos_, CLIPFORMAT formats_[], size_t formatsLen_) { + vtbl = vtFormatEnumerator; + ref = 0; // First QI adds first reference... + pos = pos_; + formats.insert(formats.begin(), formats_, formats_+formatsLen_); } /// Implement IUnknown -STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) -{ - return ds->sci->QueryInterface(riid, ppv); +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_AddRef(DropSource *ds) { + return ds->sci->AddRef(); } -STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) -{ - return ds->sci->Release(); +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_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; +STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) { + return DRAGDROP_S_USEDEFAULTCURSORS; } static VFunction *vtDropSource[] = { - (VFunction *)(DropSource_QueryInterface), - (VFunction *)(DropSource_AddRef), - (VFunction *)(DropSource_Release), - (VFunction *)(DropSource_QueryContinueDrag), - (VFunction *)(DropSource_GiveFeedback) + (VFunction *)(DropSource_QueryInterface), + (VFunction *)(DropSource_AddRef), + (VFunction *)(DropSource_Release), + (VFunction *)(DropSource_QueryContinueDrag), + (VFunction *)(DropSource_GiveFeedback) }; -DropSource::DropSource() -{ - vtbl = vtDropSource; - sci = 0; +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 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_AddRef(DataObject *pd) { + return pd->sci->AddRef(); } -STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) -{ - return pd->sci->Release(); +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()); - 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) -{ - try - { - //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, ELEMENTS(formats)); - } - else - { - CLIPFORMAT formats[] = { CF_TEXT }; - pfe = new FormatEnumerator(0, formats, ELEMENTS(formats)); - } - return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, - reinterpret_cast(ppEnum)); - } - catch (std::bad_alloc &) - { - pd->sci->errorStatus = SC_STATUS_BADALLOC; - return E_OUTOFMEMORY; - } - catch (...) - { - pd->sci->errorStatus = SC_STATUS_FAILURE; - return E_FAIL; - } -} - -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; +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()); + 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) { + try { + //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, ELEMENTS(formats)); + } else { + CLIPFORMAT formats[] = {CF_TEXT}; + pfe = new FormatEnumerator(0, formats, ELEMENTS(formats)); + } + return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, + reinterpret_cast(ppEnum)); + } catch (std::bad_alloc &) { + pd->sci->errorStatus = SC_STATUS_BADALLOC; + return E_OUTOFMEMORY; + } catch (...) { + pd->sci->errorStatus = SC_STATUS_FAILURE; + return E_FAIL; + } +} + +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 VFunction *vtDataObject[] = { - (VFunction *)(DataObject_QueryInterface), - (VFunction *)(DataObject_AddRef), - (VFunction *)(DataObject_Release), - (VFunction *)(DataObject_GetData), - (VFunction *)(DataObject_GetDataHere), - (VFunction *)(DataObject_QueryGetData), - (VFunction *)(DataObject_GetCanonicalFormatEtc), - (VFunction *)(DataObject_SetData), - (VFunction *)(DataObject_EnumFormatEtc), - (VFunction *)(DataObject_DAdvise), - (VFunction *)(DataObject_DUnadvise), - (VFunction *)(DataObject_EnumDAdvise) + (VFunction *)(DataObject_QueryInterface), + (VFunction *)(DataObject_AddRef), + (VFunction *)(DataObject_Release), + (VFunction *)(DataObject_GetData), + (VFunction *)(DataObject_GetDataHere), + (VFunction *)(DataObject_QueryGetData), + (VFunction *)(DataObject_GetCanonicalFormatEtc), + (VFunction *)(DataObject_SetData), + (VFunction *)(DataObject_EnumFormatEtc), + (VFunction *)(DataObject_DAdvise), + (VFunction *)(DataObject_DUnadvise), + (VFunction *)(DataObject_EnumDAdvise) }; -DataObject::DataObject() -{ - vtbl = vtDataObject; - sci = 0; +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 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_AddRef(DropTarget *dt) { + return dt->sci->AddRef(); } -STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) -{ - return dt->sci->Release(); +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) -{ - try - { - return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect); - } - catch (...) - { - dt->sci->errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; -} -STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) -{ - try - { - return dt->sci->DragOver(grfKeyState, pt, pdwEffect); - } - catch (...) - { - dt->sci->errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; -} -STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) -{ - try - { - return dt->sci->DragLeave(); - } - catch (...) - { - dt->sci->errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; + POINTL pt, PDWORD pdwEffect) { + try { + return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect); + } catch (...) { + dt->sci->errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; +} +STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) { + try { + return dt->sci->DragOver(grfKeyState, pt, pdwEffect); + } catch (...) { + dt->sci->errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; +} +STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) { + try { + return dt->sci->DragLeave(); + } catch (...) { + dt->sci->errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; } STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState, - POINTL pt, PDWORD pdwEffect) -{ - try - { - return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect); - } - catch (...) - { - dt->sci->errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; + POINTL pt, PDWORD pdwEffect) { + try { + return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect); + } catch (...) { + dt->sci->errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; } static VFunction *vtDropTarget[] = { - (VFunction *)(DropTarget_QueryInterface), - (VFunction *)(DropTarget_AddRef), - (VFunction *)(DropTarget_Release), - (VFunction *)(DropTarget_DragEnter), - (VFunction *)(DropTarget_DragOver), - (VFunction *)(DropTarget_DragLeave), - (VFunction *)(DropTarget_Drop) + (VFunction *)(DropTarget_QueryInterface), + (VFunction *)(DropTarget_AddRef), + (VFunction *)(DropTarget_Release), + (VFunction *)(DropTarget_DragEnter), + (VFunction *)(DropTarget_DragOver), + (VFunction *)(DropTarget_DragLeave), + (VFunction *)(DropTarget_Drop) }; -DropTarget::DropTarget() -{ - vtbl = vtDropTarget; - sci = 0; +DropTarget::DropTarget() { + vtbl = vtDropTarget; + sci = 0; } /** * DBCS: support Input Method Editor (IME). * Called when IME Window opened. */ -void ScintillaWin::ImeStartComposition() -{ - if (caret.active) - { - // Move IME Window to current caret position - IMContext imc(MainHWND()); - Point pos = PointMainCaret(); - COMPOSITIONFORM CompForm; - CompForm.dwStyle = CFS_POINT; - CompForm.ptCurrentPos.x = static_cast(pos.x); - CompForm.ptCurrentPos.y = static_cast(pos.y); - - ::ImmSetCompositionWindow(imc.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. - const int styleHere = pdoc->StyleIndexAt(sel.MainCaret()); - LOGFONTW lf = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"" }; - int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER; - if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 - sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; - AutoSurface surface(this); - int deviceHeight = sizeZoomed; - if (surface) - { - deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72; - } - // The negative is to allow for leading - lf.lfHeight = -(abs(deviceHeight / SC_FONT_SIZE_MULTIPLIER)); - lf.lfWeight = vs.styles[styleHere].weight; - lf.lfItalic = static_cast(vs.styles[styleHere].italic ? 1 : 0); - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfFaceName[0] = L'\0'; - if (vs.styles[styleHere].fontName) - { - const char* fontName = vs.styles[styleHere].fontName; - UTF16FromUTF8(fontName, strlen(fontName) + 1, lf.lfFaceName, LF_FACESIZE); - } - - ::ImmSetCompositionFontW(imc.hIMC, &lf); - } - // Caret is displayed in IME window. So, caret in Scintilla is useless. - DropCaret(); - } +void ScintillaWin::ImeStartComposition() { + if (caret.active) { + // Move IME Window to current caret position + IMContext imc(MainHWND()); + Point pos = PointMainCaret(); + COMPOSITIONFORM CompForm; + CompForm.dwStyle = CFS_POINT; + CompForm.ptCurrentPos.x = static_cast(pos.x); + CompForm.ptCurrentPos.y = static_cast(pos.y); + + ::ImmSetCompositionWindow(imc.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. + const int styleHere = pdoc->StyleIndexAt(sel.MainCaret()); + LOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L""}; + int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER; + if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 + sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; + AutoSurface surface(this); + int deviceHeight = sizeZoomed; + if (surface) { + deviceHeight = (sizeZoomed * surface->LogPixelsY()) / 72; + } + // The negative is to allow for leading + lf.lfHeight = -(abs(deviceHeight / SC_FONT_SIZE_MULTIPLIER)); + lf.lfWeight = vs.styles[styleHere].weight; + lf.lfItalic = static_cast(vs.styles[styleHere].italic ? 1 : 0); + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfFaceName[0] = L'\0'; + if (vs.styles[styleHere].fontName) { + const char* fontName = vs.styles[styleHere].fontName; + UTF16FromUTF8(fontName, strlen(fontName)+1, lf.lfFaceName, LF_FACESIZE); + } + + ::ImmSetCompositionFontW(imc.hIMC, &lf); + } + // Caret is displayed in IME window. So, caret in Scintilla is useless. + DropCaret(); + } } /** Called when IME Window closed. */ -void ScintillaWin::ImeEndComposition() -{ - ShowCaretAtCurrentPosition(); -} - -LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) -{ - // Reconversion on windows limits within one line without eol. - // Look around: baseStart <-- (|mainStart| -- mainEnd) --> baseEnd. - const int mainStart = sel.RangeMain().Start().Position(); - const int mainEnd = sel.RangeMain().End().Position(); - const int curLine = pdoc->LineFromPosition(mainStart); - if (curLine != pdoc->LineFromPosition(mainEnd)) - return 0; - const int baseStart = pdoc->LineStart(curLine); - const int baseEnd = pdoc->LineEnd(curLine); - if ((baseStart == baseEnd) || (mainEnd > baseEnd)) - return 0; - - const int codePage = CodePageOfDocument(); - const std::wstring rcFeed = StringDecode(RangeText(baseStart, baseEnd), codePage); - const int rcFeedLen = static_cast(rcFeed.length()) * sizeof(wchar_t); - const int rcSize = sizeof(RECONVERTSTRING) + rcFeedLen + sizeof(wchar_t); - - RECONVERTSTRING *rc = (RECONVERTSTRING *)lParam; - if (!rc) - return rcSize; // Immediately be back with rcSize of memory block. - - wchar_t *rcFeedStart = (wchar_t*)(rc + 1); - memcpy(rcFeedStart, &rcFeed[0], rcFeedLen); - - std::string rcCompString = RangeText(mainStart, mainEnd); - std::wstring rcCompWstring = StringDecode(rcCompString, codePage); - std::string rcCompStart = RangeText(baseStart, mainStart); - std::wstring rcCompWstart = StringDecode(rcCompStart, codePage); - - // Map selection to dwCompStr. - // No selection assumes current caret as rcCompString without length. - rc->dwVersion = 0; // It should be absolutely 0. - rc->dwStrLen = (DWORD)static_cast(rcFeed.length()); - rc->dwStrOffset = sizeof(RECONVERTSTRING); - rc->dwCompStrLen = (DWORD)static_cast(rcCompWstring.length()); - rc->dwCompStrOffset = (DWORD)static_cast(rcCompWstart.length()) * sizeof(wchar_t); - rc->dwTargetStrLen = rc->dwCompStrLen; - rc->dwTargetStrOffset = rc->dwCompStrOffset; - - IMContext imc(MainHWND()); - if (!imc.hIMC) - return 0; - - if (!::ImmSetCompositionStringW(imc.hIMC, SCS_QUERYRECONVERTSTRING, rc, rcSize, NULL, 0)) - return 0; - - // No selection asks IME to fill target fields with its own value. - int tgWlen = rc->dwTargetStrLen; - int tgWstart = rc->dwTargetStrOffset / sizeof(wchar_t); - - std::string tgCompStart = StringEncode(rcFeed.substr(0, tgWstart), codePage); - std::string tgComp = StringEncode(rcFeed.substr(tgWstart, tgWlen), codePage); - - // No selection needs to adjust reconvert start position for IME set. - int adjust = static_cast(tgCompStart.length() - rcCompStart.length()); - int docCompLen = static_cast(tgComp.length()); - - // Make place for next composition string to sit in. - for (size_t r = 0; r < sel.Count(); r++) - { - int rBase = sel.Range(r).Start().Position(); - int docCompStart = rBase + adjust; - - if (inOverstrike) - { // the docCompLen of bytes will be overstriked. - sel.Range(r).caret.SetPosition(docCompStart); - sel.Range(r).anchor.SetPosition(docCompStart); - } - else - { - // Ensure docCompStart+docCompLen be not beyond lineEnd. - // since docCompLen by byte might break eol. - int lineEnd = pdoc->LineEnd(pdoc->LineFromPosition(rBase)); - int overflow = (docCompStart + docCompLen) - lineEnd; - if (overflow > 0) - { - pdoc->DeleteChars(docCompStart, docCompLen - overflow); - } - else - { - pdoc->DeleteChars(docCompStart, docCompLen); - } - } - } - // Immediately Target Input or candidate box choice with GCS_COMPSTR. - return rcSize; -} - -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) -{ - if (!::OpenClipboardRetry(MainHWND())) - { - return; - } - ::EmptyClipboard(); - - GlobalMemory uniText; - - // Default Scintilla behaviour in Unicode mode - if (IsUnicodeMode()) - { - size_t uchars = UTF16Length(selectedText.Data(), - static_cast(selectedText.LengthWithTerminator())); - uniText.Allocate(2 * uchars); - if (uniText) - { - UTF16FromUTF8(selectedText.Data(), selectedText.LengthWithTerminator(), - static_cast(uniText.ptr), uchars); - } - } - else - { - // Not Unicode mode - // Convert to Unicode using the current Scintilla code page - UINT cpSrc = CodePageFromCharSet( - selectedText.characterSet, selectedText.codePage); - int uLen = ::MultiByteToWideChar(cpSrc, 0, selectedText.Data(), - static_cast(selectedText.LengthWithTerminator()), 0, 0); - uniText.Allocate(2 * uLen); - if (uniText) - { - ::MultiByteToWideChar(cpSrc, 0, selectedText.Data(), - static_cast(selectedText.LengthWithTerminator()), - static_cast(uniText.ptr), uLen); - } - } - - if (uniText) - { - uniText.SetClip(CF_UNICODETEXT); - } - else - { - // There was a failure - try to copy at least ANSI text - GlobalMemory ansiText; - ansiText.Allocate(selectedText.LengthWithTerminator()); - if (ansiText) - { - memcpy(static_cast(ansiText.ptr), selectedText.Data(), selectedText.LengthWithTerminator()); - ansiText.SetClip(CF_TEXT); - } - } - - if (selectedText.rectangular) - { - ::SetClipboardData(cfColumnSelect, 0); - - GlobalMemory borlandSelection; - borlandSelection.Allocate(1); - if (borlandSelection) - { - static_cast(borlandSelection.ptr)[0] = 0x02; - borlandSelection.SetClip(cfBorlandIDEBlockType); - } - } - - if (selectedText.lineCopy) - { - ::SetClipboardData(cfLineSelect, 0); - ::SetClipboardData(cfVSLineTag, 0); - } - - ::CloseClipboard(); -} - -void ScintillaWin::ScrollMessage(WPARAM wParam) -{ - //DWORD dwStart = timeGetTime(); - //Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam); - - SCROLLINFO 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 = static_cast(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 - static_cast(rcText.Width()); - } - break; - case SB_TOP: - xPos = 0; - break; - case SB_BOTTOM: - xPos = scrollWidth; - break; - case SB_THUMBPOSITION: - case SB_THUMBTRACK: { - // Do NOT use wParam, its 16 bit and not enough for very long lines. Its still possible to overflow the 32 bit but you have to try harder =] - SCROLLINFO si; - si.cbSize = sizeof(si); - si.fMask = SIF_TRACKPOS; - if (GetScrollInfo(SB_HORZ, &si)) - { - xPos = si.nTrackPos; - } - } - break; - } - HorizontalScrollTo(xPos); +void ScintillaWin::ImeEndComposition() { + ShowCaretAtCurrentPosition(); +} + +LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) { + // Reconversion on windows limits within one line without eol. + // Look around: baseStart <-- (|mainStart| -- mainEnd) --> baseEnd. + const int mainStart = sel.RangeMain().Start().Position(); + const int mainEnd = sel.RangeMain().End().Position(); + const int curLine = pdoc->LineFromPosition(mainStart); + if (curLine != pdoc->LineFromPosition(mainEnd)) + return 0; + const int baseStart = pdoc->LineStart(curLine); + const int baseEnd = pdoc->LineEnd(curLine); + if ((baseStart == baseEnd) || (mainEnd > baseEnd)) + return 0; + + const int codePage = CodePageOfDocument(); + const std::wstring rcFeed = StringDecode(RangeText(baseStart, baseEnd), codePage); + const int rcFeedLen = static_cast(rcFeed.length()) * sizeof(wchar_t); + const int rcSize = sizeof(RECONVERTSTRING) + rcFeedLen + sizeof(wchar_t); + + RECONVERTSTRING *rc = (RECONVERTSTRING *)lParam; + if (!rc) + return rcSize; // Immediately be back with rcSize of memory block. + + wchar_t *rcFeedStart = (wchar_t*)(rc + 1); + memcpy(rcFeedStart, &rcFeed[0], rcFeedLen); + + std::string rcCompString = RangeText(mainStart, mainEnd); + std::wstring rcCompWstring = StringDecode(rcCompString, codePage); + std::string rcCompStart = RangeText(baseStart, mainStart); + std::wstring rcCompWstart = StringDecode(rcCompStart, codePage); + + // Map selection to dwCompStr. + // No selection assumes current caret as rcCompString without length. + rc->dwVersion = 0; // It should be absolutely 0. + rc->dwStrLen = (DWORD)static_cast(rcFeed.length()); + rc->dwStrOffset = sizeof(RECONVERTSTRING); + rc->dwCompStrLen = (DWORD)static_cast(rcCompWstring.length()); + rc->dwCompStrOffset = (DWORD)static_cast(rcCompWstart.length()) * sizeof(wchar_t); + rc->dwTargetStrLen = rc->dwCompStrLen; + rc->dwTargetStrOffset =rc->dwCompStrOffset; + + IMContext imc(MainHWND()); + if (!imc.hIMC) + return 0; + + if (!::ImmSetCompositionStringW(imc.hIMC, SCS_QUERYRECONVERTSTRING, rc, rcSize, NULL, 0)) + return 0; + + // No selection asks IME to fill target fields with its own value. + int tgWlen = rc->dwTargetStrLen; + int tgWstart = rc->dwTargetStrOffset / sizeof(wchar_t); + + std::string tgCompStart = StringEncode(rcFeed.substr(0, tgWstart), codePage); + std::string tgComp = StringEncode(rcFeed.substr(tgWstart, tgWlen), codePage); + + // No selection needs to adjust reconvert start position for IME set. + int adjust = static_cast(tgCompStart.length() - rcCompStart.length()); + int docCompLen = static_cast(tgComp.length()); + + // Make place for next composition string to sit in. + for (size_t r=0; rLineEnd(pdoc->LineFromPosition(rBase)); + int overflow = (docCompStart + docCompLen) - lineEnd; + if (overflow > 0) { + pdoc->DeleteChars(docCompStart, docCompLen - overflow); + } else { + pdoc->DeleteChars(docCompStart, docCompLen); + } + } + } + // Immediately Target Input or candidate box choice with GCS_COMPSTR. + return rcSize; +} + +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) { + if (!::OpenClipboardRetry(MainHWND())) { + return; + } + ::EmptyClipboard(); + + GlobalMemory uniText; + + // Default Scintilla behaviour in Unicode mode + if (IsUnicodeMode()) { + size_t uchars = UTF16Length(selectedText.Data(), + static_cast(selectedText.LengthWithTerminator())); + uniText.Allocate(2 * uchars); + if (uniText) { + UTF16FromUTF8(selectedText.Data(), selectedText.LengthWithTerminator(), + static_cast(uniText.ptr), uchars); + } + } else { + // Not Unicode mode + // Convert to Unicode using the current Scintilla code page + UINT cpSrc = CodePageFromCharSet( + selectedText.characterSet, selectedText.codePage); + int uLen = ::MultiByteToWideChar(cpSrc, 0, selectedText.Data(), + static_cast(selectedText.LengthWithTerminator()), 0, 0); + uniText.Allocate(2 * uLen); + if (uniText) { + ::MultiByteToWideChar(cpSrc, 0, selectedText.Data(), + static_cast(selectedText.LengthWithTerminator()), + static_cast(uniText.ptr), uLen); + } + } + + if (uniText) { + uniText.SetClip(CF_UNICODETEXT); + } else { + // There was a failure - try to copy at least ANSI text + GlobalMemory ansiText; + ansiText.Allocate(selectedText.LengthWithTerminator()); + if (ansiText) { + memcpy(static_cast(ansiText.ptr), selectedText.Data(), selectedText.LengthWithTerminator()); + ansiText.SetClip(CF_TEXT); + } + } + + if (selectedText.rectangular) { + ::SetClipboardData(cfColumnSelect, 0); + + GlobalMemory borlandSelection; + borlandSelection.Allocate(1); + if (borlandSelection) { + static_cast(borlandSelection.ptr)[0] = 0x02; + borlandSelection.SetClip(cfBorlandIDEBlockType); + } + } + + if (selectedText.lineCopy) { + ::SetClipboardData(cfLineSelect, 0); + ::SetClipboardData(cfVSLineTag, 0); + } + + ::CloseClipboard(); +} + +void ScintillaWin::ScrollMessage(WPARAM wParam) { + //DWORD dwStart = timeGetTime(); + //Platform::DebugPrintf("Scroll %x %d\n", wParam, lParam); + + SCROLLINFO 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 = static_cast(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 - static_cast(rcText.Width()); + } + break; + case SB_TOP: + xPos = 0; + break; + case SB_BOTTOM: + xPos = scrollWidth; + break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: { + // Do NOT use wParam, its 16 bit and not enough for very long lines. Its still possible to overflow the 32 bit but you have to try harder =] + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_TRACKPOS; + if (GetScrollInfo(SB_HORZ, &si)) { + xPos = si.nTrackPos; + } + } + break; + } + HorizontalScrollTo(xPos); } /** * Redraw all of text area. * This paint will not be abandoned. */ -void ScintillaWin::FullPaint() -{ - if ((technology == SC_TECHNOLOGY_DEFAULT) || (technology == SC_TECHNOLOGY_DIRECTWRITEDC)) - { - HDC hdc = ::GetDC(MainHWND()); - FullPaintDC(hdc); - ::ReleaseDC(MainHWND(), hdc); - } - else - { - FullPaintDC(0); - } +void ScintillaWin::FullPaint() { + if ((technology == SC_TECHNOLOGY_DEFAULT) || (technology == SC_TECHNOLOGY_DIRECTWRITEDC)) { + HDC hdc = ::GetDC(MainHWND()); + FullPaintDC(hdc); + ::ReleaseDC(MainHWND(), hdc); + } else { + FullPaintDC(0); + } } /** * 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; - if (technology == SC_TECHNOLOGY_DEFAULT) - { - AutoSurface surfaceWindow(hdc, this); - if (surfaceWindow) - { - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - } - } - else - { +void ScintillaWin::FullPaintDC(HDC hdc) { + paintState = painting; + rcPaint = GetClientRectangle(); + paintingAllText = true; + if (technology == SC_TECHNOLOGY_DEFAULT) { + AutoSurface surfaceWindow(hdc, this); + if (surfaceWindow) { + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + } + } else { #if defined(USE_D2D) - EnsureRenderTarget(hdc); - AutoSurface surfaceWindow(pRenderTarget, this); - if (surfaceWindow) - { - pRenderTarget->BeginDraw(); - Paint(surfaceWindow, rcPaint); - surfaceWindow->Release(); - HRESULT hr = pRenderTarget->EndDraw(); - if (hr == D2DERR_RECREATE_TARGET) - { - DropRenderTarget(); - } - } + EnsureRenderTarget(hdc); + AutoSurface surfaceWindow(pRenderTarget, this); + if (surfaceWindow) { + pRenderTarget->BeginDraw(); + Paint(surfaceWindow, rcPaint); + surfaceWindow->Release(); + HRESULT hr = pRenderTarget->EndDraw(); + if (hr == D2DERR_RECREATE_TARGET) { + DropRenderTarget(); + } + } #endif - } - 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; -} - -DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) const -{ - // These are the Wordpad semantics. - DWORD dwEffect; - if (inDragDrop == ddDragging) // Internal defaults to move - dwEffect = DROPEFFECT_MOVE; - else - dwEffect = DROPEFFECT_COPY; - if (grfKeyState & MK_ALT) - dwEffect = DROPEFFECT_MOVE; - if (grfKeyState & MK_CONTROL) - dwEffect = DROPEFFECT_COPY; - return dwEffect; + } + 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; +} + +DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) const { + // These are the Wordpad semantics. + DWORD dwEffect; + if (inDragDrop == ddDragging) // Internal defaults to move + dwEffect = DROPEFFECT_MOVE; + else + dwEffect = DROPEFFECT_COPY; + if (grfKeyState & MK_ALT) + dwEffect = DROPEFFECT_MOVE; + if (grfKeyState & MK_CONTROL) + dwEffect = DROPEFFECT_COPY; + return dwEffect; } /// Implement IUnknown -STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) -{ - *ppv = NULL; - if (riid == IID_IUnknown) - *ppv = reinterpret_cast(&dt); - if (riid == IID_IDropSource) - *ppv = reinterpret_cast(&ds); - if (riid == IID_IDropTarget) - *ppv = reinterpret_cast(&dt); - if (riid == IID_IDataObject) - *ppv = reinterpret_cast(&dob); - if (!*ppv) - return E_NOINTERFACE; - return S_OK; +STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) { + *ppv = NULL; + if (riid == IID_IUnknown) + *ppv = reinterpret_cast(&dt); + if (riid == IID_IDropSource) + *ppv = reinterpret_cast(&ds); + if (riid == IID_IDropTarget) + *ppv = reinterpret_cast(&dt); + if (riid == IID_IDataObject) + *ppv = reinterpret_cast(&dob); + if (!*ppv) + return E_NOINTERFACE; + return S_OK; } -STDMETHODIMP_(ULONG) ScintillaWin::AddRef() -{ - return 1; +STDMETHODIMP_(ULONG) ScintillaWin::AddRef() { + return 1; } -STDMETHODIMP_(ULONG) ScintillaWin::Release() -{ - 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; - 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; - } - - *pdwEffect = EffectFromState(grfKeyState); - return S_OK; -} - -STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) -{ - try - { - if (!hasOKText || pdoc->IsReadOnly()) - { - *pdwEffect = DROPEFFECT_NONE; - return S_OK; - } - - *pdwEffect = EffectFromState(grfKeyState); - - // Update the cursor. - POINT rpt = { pt.x, pt.y }; - ::ScreenToClient(MainHWND(), &rpt); - SetDragPosition(SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace())); - - return S_OK; - } - catch (...) - { - errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; -} - -STDMETHODIMP ScintillaWin::DragLeave() -{ - try - { - SetDragPosition(SelectionPosition(invalidPosition)); - return S_OK; - } - catch (...) - { - errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; + POINTL, PDWORD pdwEffect) { + if (pIDataSource == NULL) + return E_POINTER; + 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; + } + + *pdwEffect = EffectFromState(grfKeyState); + return S_OK; +} + +STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) { + try { + if (!hasOKText || pdoc->IsReadOnly()) { + *pdwEffect = DROPEFFECT_NONE; + return S_OK; + } + + *pdwEffect = EffectFromState(grfKeyState); + + // Update the cursor. + POINT rpt = {pt.x, pt.y}; + ::ScreenToClient(MainHWND(), &rpt); + SetDragPosition(SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace())); + + return S_OK; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; +} + +STDMETHODIMP ScintillaWin::DragLeave() { + try { + SetDragPosition(SelectionPosition(invalidPosition)); + return S_OK; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; } STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, - POINTL pt, PDWORD pdwEffect) -{ - try - { - *pdwEffect = EffectFromState(grfKeyState); - - if (pIDataSource == NULL) - return E_POINTER; - - SetDragPosition(SelectionPosition(invalidPosition)); - - STGMEDIUM medium = { 0, {0}, 0 }; - - std::vector data; // Includes terminating NUL - - FORMATETC fmtu = { CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - HRESULT hr = pIDataSource->GetData(&fmtu, &medium); - if (SUCCEEDED(hr) && medium.hGlobal) - { - GlobalMemory memUDrop(medium.hGlobal); - wchar_t *udata = static_cast(memUDrop.ptr); - if (udata) - { - if (IsUnicodeMode()) - { - int tlen = static_cast(memUDrop.Size()); - // Convert UTF-16 to UTF-8 - int dataLen = UTF8Length(udata, tlen / 2); - data.resize(dataLen + 1); - UTF8FromUTF16(udata, tlen / 2, &data[0], dataLen); - } - else - { - // Convert UTF-16 to ANSI - // - // Default Scintilla behavior in Unicode mode - // CF_UNICODETEXT available, but not in Unicode mode - // Convert from Unicode to current Scintilla code page - UINT cpDest = CodePageOfDocument(); - int tlen = ::WideCharToMultiByte(cpDest, 0, udata, -1, - NULL, 0, NULL, NULL) - 1; // subtract 0 terminator - data.resize(tlen + 1); - ::WideCharToMultiByte(cpDest, 0, udata, -1, - &data[0], tlen + 1, NULL, NULL); - } - } - memUDrop.Unlock(); - } - else - { - FORMATETC fmte = { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - hr = pIDataSource->GetData(&fmte, &medium); - if (SUCCEEDED(hr) && medium.hGlobal) - { - GlobalMemory memDrop(medium.hGlobal); - const char *cdata = static_cast(memDrop.ptr); - if (cdata) - data.assign(cdata, cdata + strlen(cdata) + 1); - memDrop.Unlock(); - } - } - - if (!SUCCEEDED(hr) || data.empty()) - { - //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); - SelectionPosition movePos = SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace()); - const bool bIsTrailingLineEnd = (data.size() >= 3) && (data[data.size() - 3] == '\r') && (data[data.size() - 2] == '\n'); - const bool bAddNewLine = (inDragDrop != ddDragging) && (!bIsTrailingLineEnd && pdoc->IsLineStartPosition(movePos.Position()) && pdoc->IsLineEndPosition(movePos.Position())); - if (bAddNewLine) - { - data.insert(data.end() - 1, '\r'); - data.insert(data.end() - 1, '\n'); - } - DropAt(movePos, &data[0], data.size() - 1, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK); - if (bAddNewLine) - { - KeyCommand(SCI_CHARRIGHT); - } - - // Free data - if (medium.pUnkForRelease != NULL) - medium.pUnkForRelease->Release(); - else - ::GlobalFree(medium.hGlobal); - - return S_OK; - } - catch (...) - { - errorStatus = SC_STATUS_FAILURE; - } - return E_FAIL; + POINTL pt, PDWORD pdwEffect) { + try { + *pdwEffect = EffectFromState(grfKeyState); + + if (pIDataSource == NULL) + return E_POINTER; + + SetDragPosition(SelectionPosition(invalidPosition)); + + STGMEDIUM medium = {0, {0}, 0}; + + std::vector data; // Includes terminating NUL + + FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + HRESULT hr = pIDataSource->GetData(&fmtu, &medium); + if (SUCCEEDED(hr) && medium.hGlobal) { + GlobalMemory memUDrop(medium.hGlobal); + wchar_t *udata = static_cast(memUDrop.ptr); + if (udata) { + if (IsUnicodeMode()) { + int tlen = static_cast(memUDrop.Size()); + // Convert UTF-16 to UTF-8 + int dataLen = UTF8Length(udata, tlen/2); + data.resize(dataLen+1); + UTF8FromUTF16(udata, tlen/2, &data[0], dataLen); + } else { + // Convert UTF-16 to ANSI + // + // Default Scintilla behavior in Unicode mode + // CF_UNICODETEXT available, but not in Unicode mode + // Convert from Unicode to current Scintilla code page + UINT cpDest = CodePageOfDocument(); + int tlen = ::WideCharToMultiByte(cpDest, 0, udata, -1, + NULL, 0, NULL, NULL) - 1; // subtract 0 terminator + data.resize(tlen + 1); + ::WideCharToMultiByte(cpDest, 0, udata, -1, + &data[0], tlen + 1, NULL, NULL); + } + } + memUDrop.Unlock(); + } else { + FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + hr = pIDataSource->GetData(&fmte, &medium); + if (SUCCEEDED(hr) && medium.hGlobal) { + GlobalMemory memDrop(medium.hGlobal); + const char *cdata = static_cast(memDrop.ptr); + if (cdata) + data.assign(cdata, cdata+strlen(cdata)+1); + memDrop.Unlock(); + } + } + + if (!SUCCEEDED(hr) || data.empty()) { + //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); + SelectionPosition movePos = SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace()); + // [n2e]: Drag & drop improvement #63 + const bool bIsTrailingLineEnd = (data.size() >= 3) && (data[data.size() - 3] == '\r') && (data[data.size() - 2] == '\n'); + const bool bAddNewLine = (inDragDrop != ddDragging) && (!bIsTrailingLineEnd && pdoc->IsLineStartPosition(movePos.Position()) && pdoc->IsLineEndPosition(movePos.Position())); + if (bAddNewLine) + { + data.insert(data.end() - 1, '\r'); + data.insert(data.end() - 1, '\n'); + } + DropAt(movePos, &data[0], data.size() - 1, *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK); + if (bAddNewLine) { + KeyCommand(SCI_CHARRIGHT); + } + // [/n2e] + + // Free data + if (medium.pUnkForRelease != NULL) + medium.pUnkForRelease->Release(); + else + ::GlobalFree(medium.hGlobal); + + return S_OK; + } catch (...) { + errorStatus = SC_STATUS_FAILURE; + } + return E_FAIL; } /// 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) - { - size_t uchars = UTF16Length(drag.Data(), static_cast(drag.LengthWithTerminator())); - text.Allocate(2 * uchars); - if (text) - { - UTF16FromUTF8(drag.Data(), drag.LengthWithTerminator(), - static_cast(text.ptr), uchars); - } - } - else - { - text.Allocate(drag.LengthWithTerminator()); - if (text) - { - memcpy(static_cast(text.ptr), drag.Data(), drag.LengthWithTerminator()); - } - } - pSTM->hGlobal = text ? text.Unlock() : 0; - pSTM->pUnkForRelease = 0; - return S_OK; -} - -bool ScintillaWin::Register(HINSTANCE hInstance_) -{ - - hInstance = hInstance_; - bool result; - - // Register the Scintilla class - // 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; - scintillaClassAtom = ::RegisterClassExW(&wndclass); - result = 0 != scintillaClassAtom; - - 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; - - callClassAtom = ::RegisterClassEx(&wndclassc); - result = 0 != callClassAtom; - } - - return result; -} - -bool ScintillaWin::Unregister() -{ - bool result = true; - if (0 != scintillaClassAtom) - { - if (::UnregisterClass(MAKEINTATOM(scintillaClassAtom), hInstance) == 0) - { - result = false; - } - scintillaClassAtom = 0; - } - if (0 != callClassAtom) - { - if (::UnregisterClass(MAKEINTATOM(callClassAtom), hInstance) == 0) - { - result = false; - } - callClassAtom = 0; - } - return result; -} - -bool ScintillaWin::HasCaretSizeChanged() const -{ - 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; - std::vector bits(bitmapSize); - sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1, - 1, reinterpret_cast(&bits[0])); - BOOL retval = ::CreateCaret( - MainHWND(), sysCaretBitmap, - sysCaretWidth, sysCaretHeight); - if (technology == SC_TECHNOLOGY_DEFAULT) - { - // System caret interferes with Direct2D drawing so only show it for GDI. - ::ShowCaret(MainHWND()); - } - return retval; -} - -BOOL ScintillaWin::DestroySystemCaret() -{ - ::HideCaret(MainHWND()); - BOOL retval = ::DestroyCaret(); - if (sysCaretBitmap) - { - ::DeleteObject(sysCaretBitmap); - sysCaretBitmap = 0; - } - return retval; +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) { + size_t uchars = UTF16Length(drag.Data(), static_cast(drag.LengthWithTerminator())); + text.Allocate(2 * uchars); + if (text) { + UTF16FromUTF8(drag.Data(), drag.LengthWithTerminator(), + static_cast(text.ptr), uchars); + } + } else { + text.Allocate(drag.LengthWithTerminator()); + if (text) { + memcpy(static_cast(text.ptr), drag.Data(), drag.LengthWithTerminator()); + } + } + pSTM->hGlobal = text ? text.Unlock() : 0; + pSTM->pUnkForRelease = 0; + return S_OK; +} + +bool ScintillaWin::Register(HINSTANCE hInstance_) { + + hInstance = hInstance_; + bool result; + + // Register the Scintilla class + // 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; + scintillaClassAtom = ::RegisterClassExW(&wndclass); + result = 0 != scintillaClassAtom; + + 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; + + callClassAtom = ::RegisterClassEx(&wndclassc); + result = 0 != callClassAtom; + } + + return result; +} + +bool ScintillaWin::Unregister() { + bool result = true; + if (0 != scintillaClassAtom) { + if (::UnregisterClass(MAKEINTATOM(scintillaClassAtom), hInstance) == 0) { + result = false; + } + scintillaClassAtom = 0; + } + if (0 != callClassAtom) { + if (::UnregisterClass(MAKEINTATOM(callClassAtom), hInstance) == 0) { + result = false; + } + callClassAtom = 0; + } + return result; +} + +bool ScintillaWin::HasCaretSizeChanged() const { + 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; + std::vector bits(bitmapSize); + sysCaretBitmap = ::CreateBitmap(sysCaretWidth, sysCaretHeight, 1, + 1, reinterpret_cast(&bits[0])); + BOOL retval = ::CreateCaret( + MainHWND(), sysCaretBitmap, + sysCaretWidth, sysCaretHeight); + if (technology == SC_TECHNOLOGY_DEFAULT) { + // System caret interferes with Direct2D drawing so only show it for GDI. + ::ShowCaret(MainHWND()); + } + return retval; +} + +BOOL ScintillaWin::DestroySystemCaret() { + ::HideCaret(MainHWND()); + BOOL retval = ::DestroyCaret(); + if (sysCaretBitmap) { + ::DeleteObject(sysCaretBitmap); + sysCaretBitmap = 0; + } + return retval; } LRESULT PASCAL ScintillaWin::CTWndProc( - HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) -{ - // Find C++ object associated with window. - ScintillaWin *sciThis = static_cast(PointerFromWindow(hWnd)); - try - { - // ctp will be zero if WM_CREATE not seen yet - if (sciThis == 0) - { - if (iMessage == WM_CREATE) - { - // Associate CallTip object with window - CREATESTRUCT *pCreate = reinterpret_cast(lParam); - SetWindowPointer(hWnd, pCreate->lpCreateParams); - return 0; - } - else - { - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); - } - } - else - { - if (iMessage == WM_NCDESTROY) - { - ::SetWindowLong(hWnd, 0, 0); - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); - } - else if (iMessage == WM_PAINT) - { - PAINTSTRUCT ps; - ::BeginPaint(hWnd, &ps); - Surface *surfaceWindow = Surface::Allocate(sciThis->technology); - if (surfaceWindow) - { + HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { + // Find C++ object associated with window. + ScintillaWin *sciThis = static_cast(PointerFromWindow(hWnd)); + try { + // ctp will be zero if WM_CREATE not seen yet + if (sciThis == 0) { + if (iMessage == WM_CREATE) { + // Associate CallTip object with window + CREATESTRUCT *pCreate = reinterpret_cast(lParam); + SetWindowPointer(hWnd, pCreate->lpCreateParams); + return 0; + } else { + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } + } else { + if (iMessage == WM_NCDESTROY) { + ::SetWindowLong(hWnd, 0, 0); + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } else if (iMessage == WM_PAINT) { + PAINTSTRUCT ps; + ::BeginPaint(hWnd, &ps); + Surface *surfaceWindow = Surface::Allocate(sciThis->technology); + if (surfaceWindow) { #if defined(USE_D2D) - ID2D1HwndRenderTarget *pCTRenderTarget = 0; + ID2D1HwndRenderTarget *pCTRenderTarget = 0; #endif - RECT rc; - GetClientRect(hWnd, &rc); - // Create a Direct2D render target. - if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) - { - surfaceWindow->Init(ps.hdc, hWnd); - } - else - { + RECT rc; + GetClientRect(hWnd, &rc); + // Create a Direct2D render target. + if (sciThis->technology == SC_TECHNOLOGY_DEFAULT) { + surfaceWindow->Init(ps.hdc, hWnd); + } else { #if defined(USE_D2D) - D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp; - dhrtp.hwnd = hWnd; - dhrtp.pixelSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); - dhrtp.presentOptions = (sciThis->technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ? - D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE; - - D2D1_RENDER_TARGET_PROPERTIES drtp; - drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; - drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN; - drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN; - drtp.dpiX = GetDpiX(); - drtp.dpiY = GetDpiY(); - drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE; - drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; - - if (!SUCCEEDED(pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pCTRenderTarget))) - { - surfaceWindow->Release(); - delete surfaceWindow; - ::EndPaint(hWnd, &ps); - return 0; - } - surfaceWindow->Init(pCTRenderTarget, hWnd); - pCTRenderTarget->BeginDraw(); + D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp; + dhrtp.hwnd = hWnd; + dhrtp.pixelSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top); + dhrtp.presentOptions = (sciThis->technology == SC_TECHNOLOGY_DIRECTWRITERETAIN) ? + D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS : D2D1_PRESENT_OPTIONS_NONE; + + D2D1_RENDER_TARGET_PROPERTIES drtp; + drtp.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; + drtp.pixelFormat.format = DXGI_FORMAT_UNKNOWN; + drtp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN; + drtp.dpiX = n2e_GetDpiX(); // [n2e]: DPI awareness #154 + drtp.dpiY = n2e_GetDpiY(); // [n2e]: DPI awareness #154 + drtp.usage = D2D1_RENDER_TARGET_USAGE_NONE; + drtp.minLevel = D2D1_FEATURE_LEVEL_DEFAULT; + + if (!SUCCEEDED(pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pCTRenderTarget))) { + surfaceWindow->Release(); + delete surfaceWindow; + ::EndPaint(hWnd, &ps); + return 0; + } + surfaceWindow->Init(pCTRenderTarget, hWnd); + pCTRenderTarget->BeginDraw(); #endif - } - surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage); - surfaceWindow->SetDBCSMode(sciThis->ct.codePage); - sciThis->ct.PaintCT(surfaceWindow); + } + surfaceWindow->SetUnicodeMode(SC_CP_UTF8 == sciThis->ct.codePage); + surfaceWindow->SetDBCSMode(sciThis->ct.codePage); + sciThis->ct.PaintCT(surfaceWindow); #if defined(USE_D2D) - if (pCTRenderTarget) - pCTRenderTarget->EndDraw(); + if (pCTRenderTarget) + pCTRenderTarget->EndDraw(); #endif - surfaceWindow->Release(); - delete surfaceWindow; + surfaceWindow->Release(); + delete surfaceWindow; #if defined(USE_D2D) - if (pCTRenderTarget) - pCTRenderTarget->Release(); + if (pCTRenderTarget) + pCTRenderTarget->Release(); #endif - } - ::EndPaint(hWnd, &ps); - return 0; - } - else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) - { - POINT pt; - pt.x = static_cast(LOWORD(lParam)); - pt.y = static_cast(HIWORD(lParam)); - ScreenToClient(hWnd, &pt); - sciThis->ct.MouseClick(PointFromPOINT(pt)); - sciThis->CallTipClick(); - return 0; - } - else if (iMessage == WM_LBUTTONDOWN) - { - // This does not fire due to the hit test code - sciThis->ct.MouseClick(Point::FromLong(static_cast(lParam))); - sciThis->CallTipClick(); - return 0; - } - else if (iMessage == WM_SETCURSOR) - { - ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); - return 0; - } - else if (iMessage == WM_NCHITTEST) - { - return HTCAPTION; - } - else - { - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); - } - } - } - catch (...) - { - sciThis->errorStatus = SC_STATUS_FAILURE; - } - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } + ::EndPaint(hWnd, &ps); + return 0; + } else if ((iMessage == WM_NCLBUTTONDOWN) || (iMessage == WM_NCLBUTTONDBLCLK)) { + POINT pt; + pt.x = static_cast(LOWORD(lParam)); + pt.y = static_cast(HIWORD(lParam)); + ScreenToClient(hWnd, &pt); + sciThis->ct.MouseClick(PointFromPOINT(pt)); + sciThis->CallTipClick(); + return 0; + } else if (iMessage == WM_LBUTTONDOWN) { + // This does not fire due to the hit test code + sciThis->ct.MouseClick(Point::FromLong(static_cast(lParam))); + sciThis->CallTipClick(); + return 0; + } else if (iMessage == WM_SETCURSOR) { + ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); + return 0; + } else if (iMessage == WM_NCHITTEST) { + return HTCAPTION; + } else { + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } + } + } catch (...) { + sciThis->errorStatus = SC_STATUS_FAILURE; + } + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); } sptr_t ScintillaWin::DirectFunction( - sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam) -{ - PLATFORM_ASSERT(::GetCurrentThreadId() == ::GetWindowThreadProcessId(reinterpret_cast(ptr)->MainHWND(), NULL)); - return reinterpret_cast(ptr)->WndProc(iMessage, wParam, lParam); + sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam) { + PLATFORM_ASSERT(::GetCurrentThreadId() == ::GetWindowThreadProcessId(reinterpret_cast(ptr)->MainHWND(), NULL)); + return reinterpret_cast(ptr)->WndProc(iMessage, wParam, lParam); } extern "C" @@ -3961,104 +3427,80 @@ extern "C" __declspec(dllexport) #endif sptr_t __stdcall Scintilla_DirectFunction( - ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) -{ - return sci->WndProc(iMessage, wParam, lParam); + ScintillaWin *sci, UINT iMessage, uptr_t wParam, sptr_t lParam) { + return sci->WndProc(iMessage, wParam, lParam); } LRESULT PASCAL ScintillaWin::SWndProc( - HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) -{ - //Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam); - - // Find C++ object associated with window. - ScintillaWin *sci = static_cast(PointerFromWindow(hWnd)); - // sci will be zero if WM_CREATE not seen yet - if (sci == 0) - { - try - { - if (iMessage == WM_CREATE) - { - // Create C++ object associated with window - sci = new ScintillaWin(hWnd); - SetWindowPointer(hWnd, sci); - return sci->WndProc(iMessage, wParam, lParam); - } - } - catch (...) - { - } - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); - } - else - { - if (iMessage == WM_NCDESTROY) - { - try - { - sci->Finalise(); - delete sci; - } - catch (...) - { - } - ::SetWindowLong(hWnd, 0, 0); - return ::DefWindowProc(hWnd, iMessage, wParam, lParam); - } - else - { - return sci->WndProc(iMessage, wParam, lParam); - } - } + HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { + //Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam); + + // Find C++ object associated with window. + ScintillaWin *sci = static_cast(PointerFromWindow(hWnd)); + // sci will be zero if WM_CREATE not seen yet + if (sci == 0) { + try { + if (iMessage == WM_CREATE) { + // Create C++ object associated with window + sci = new ScintillaWin(hWnd); + SetWindowPointer(hWnd, sci); + return sci->WndProc(iMessage, wParam, lParam); + } + } catch (...) { + } + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } else { + if (iMessage == WM_NCDESTROY) { + try { + sci->Finalise(); + delete sci; + } catch (...) { + } + ::SetWindowLong(hWnd, 0, 0); + return ::DefWindowProc(hWnd, iMessage, wParam, lParam); + } else { + return sci->WndProc(iMessage, wParam, lParam); + } + } } // This function is externally visible so it can be called from container when building statically. // Must be called once only. -int Scintilla_RegisterClasses(void *hInstance) -{ - Platform_Initialise(hInstance); - bool result = ScintillaWin::Register(static_cast(hInstance)); +int Scintilla_RegisterClasses(void *hInstance) { + Platform_Initialise(hInstance); + bool result = ScintillaWin::Register(static_cast(hInstance)); #ifdef SCI_LEXER - Scintilla_LinkLexers(); + Scintilla_LinkLexers(); #endif - return result; + return result; } -static int ResourcesRelease(bool fromDllMain) -{ - bool result = ScintillaWin::Unregister(); - if (commctrl32) - { - FreeLibrary(commctrl32); - commctrl32 = NULL; - } - Platform_Finalise(fromDllMain); - return result; +static int ResourcesRelease(bool fromDllMain) { + bool result = ScintillaWin::Unregister(); + if (commctrl32) { + FreeLibrary(commctrl32); + commctrl32 = NULL; + } + Platform_Finalise(fromDllMain); + return result; } // This function is externally visible so it can be called from container when building statically. -int Scintilla_ReleaseResources() -{ - return ResourcesRelease(false); +int Scintilla_ReleaseResources() { + return ResourcesRelease(false); } #ifndef STATIC_BUILD -extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) -{ - //Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason); - if (dwReason == DLL_PROCESS_ATTACH) - { - if (!Scintilla_RegisterClasses(hInstance)) - return FALSE; - } - else if (dwReason == DLL_PROCESS_DETACH) - { - if (lpvReserved == NULL) - { - ResourcesRelease(true); - } - } - return TRUE; +extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) { + //Platform::DebugPrintf("Scintilla::DllMain %d %d\n", hInstance, dwReason); + if (dwReason == DLL_PROCESS_ATTACH) { + if (!Scintilla_RegisterClasses(hInstance)) + return FALSE; + } else if (dwReason == DLL_PROCESS_DETACH) { + if (lpvReserved == NULL) { + ResourcesRelease(true); + } + } + return TRUE; } #endif diff --git a/src/Extension/ExtSelection.c b/src/Extension/ExtSelection.c index 238e8823a..195698744 100644 --- a/src/Extension/ExtSelection.c +++ b/src/Extension/ExtSelection.c @@ -108,7 +108,7 @@ void n2e_EditSelectionInit(LPCWSTR lpSection, const int iDefaultSection, const i void n2e_EditInit() { SendMessage(hwndEdit, SCI_SETCARETLINEVISIBLEALWAYS, bHighlightLineIfWindowInactive, 0); - SendMessage(hwndEdit, SCI_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); + SendMessage(hwndEdit, SCI_N2E_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); #define DEFAULT_SECTION 6 #define EXTENDED_SECTION 7 diff --git a/src/Extension/SciCall.h b/src/Extension/SciCall.h index 5a34a92ef..14db36270 100644 --- a/src/Extension/SciCall.h +++ b/src/Extension/SciCall.h @@ -93,7 +93,7 @@ DeclareSciCallR2(GetTextRange, GETTEXTRANGE, int, int, unused, struct Sci_TextRa DeclareSciCallV0(BeginUndoAction, BEGINUNDOACTION); DeclareSciCallV0(EndUndoAction, ENDUNDOACTION); -DeclareSciCallV1(SetSkipUIUpdate, SETSKIPUIUPDATE, int, skipUIUpdate); +DeclareSciCallV1(SetSkipUIUpdate, N2E_SETSKIPUIUPDATE, int, skipUIUpdate); //============================================================================= // @@ -153,4 +153,4 @@ DeclareSciCallV1(EnsureVisible, ENSUREVISIBLE, int, line); // // DeclareSciCallV2(SetProperty, SETPROPERTY, const char *, key, const char *, value); -DeclareSciCallV1(SetDPI, SETDPI, DWORD, dpi); +DeclareSciCallV1(SetDPI, N2E_SETDPI, DWORD, dpi); diff --git a/src/Notepad2.c b/src/Notepad2.c index 1826a4a92..807d28c45 100644 --- a/src/Notepad2.c +++ b/src/Notepad2.c @@ -1464,7 +1464,7 @@ void _MsgCreate() // Nonprinting characters SendMessage(hwndEdit, SCI_SETVIEWWS, bViewWhiteSpace ? SCWS_VISIBLEALWAYS : SCWS_INVISIBLE, 0); SendMessage(hwndEdit, SCI_SETVIEWEOL, bViewEOLs, 0); - SendMessage(hwndEdit, SCI_MOVECARETONRCLICK, bMoveCaretOnRightClick, 0); + SendMessage(hwndEdit, SCI_N2E_MOVECARETONRCLICK, bMoveCaretOnRightClick, 0); } // [/2e] @@ -4294,7 +4294,7 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) // [2e]: Implement Notepad's right click behavior #54 case ID_SETTINGS_MOVE_CARET_ON_RCLICK: bMoveCaretOnRightClick = !bMoveCaretOnRightClick; - SendMessage(hwndEdit, SCI_MOVECARETONRCLICK, bMoveCaretOnRightClick, 0); + SendMessage(hwndEdit, SCI_N2E_MOVECARETONRCLICK, bMoveCaretOnRightClick, 0); break; // [/2e] @@ -4322,12 +4322,12 @@ LRESULT MsgCommand(HWND hwnd, WPARAM wParam, LPARAM lParam) // [2e]: ctrl + arrow behavior toggle #89 case ID_SETTINGS_WORD_NAVIGATION_STANDARD: iWordNavigationMode = WNM_STANDARD; - SendMessage(hwndEdit, SCI_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); + SendMessage(hwndEdit, SCI_N2E_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); break; case ID_SETTINGS_WORD_NAVIGATION_ACCELERATED: iWordNavigationMode = WNM_ACCELERATED; - SendMessage(hwndEdit, SCI_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); + SendMessage(hwndEdit, SCI_N2E_SETWORDNAVIGATIONMODE, iWordNavigationMode, 0); break; // [/2e] @@ -5334,7 +5334,7 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) break; // [2e]: "Scroll margin"-feature - case SCN_CARETMOVED: + case SCN_N2E_CARETMOVED: { const int iSelPos = SendMessage(hwndEdit, SCI_GETCURRENTPOS, 0, 0); const int iSelAnchor = SendMessage(hwndEdit, SCI_GETANCHOR, 0, 0); @@ -5344,7 +5344,7 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) // [/2e] // [2e]: "Update gutter width"-feature - case SCN_LINECOUNTCHANGED: + case SCN_N2E_LINECOUNTCHANGED: UpdateLineNumberWidth(); break; // [/2e]