//////////////////////////////////////////////////////////////////////////// // Name: stc.cpp // Purpose: A wxWidgets implementation of Scintilla. This class is the // one meant to be used directly by wx applications. It does not // derive directly from the Scintilla classes, but instead // delegates most things to the real Scintilla class. // This allows the use of Scintilla without polluting the // namespace with all the classes and identifiers from Scintilla. // // Author: Robin Dunn // // Created: 13-Jan-2000 // RCS-ID: $Id$ // Copyright: (c) 2000 by Total Control Software // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// /* IMPORTANT: src/stc/stc.cpp is generated by src/stc/gen_iface.py from src/stc/stc.cpp.in, don't edit stc.cpp file as your changes will be lost after the next regeneration, edit stc.cpp.in and rerun the gen_iface.py script instead! Parts of this file generated by the script are found in between the special "{{{" and "}}}" markers, the rest of it is copied verbatim from src.h.in. */ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #if wxUSE_STC #include "wx/stc/stc.h" #include "wx/stc/private.h" #ifndef WX_PRECOMP #include "wx/wx.h" #endif // WX_PRECOMP #include #include "wx/tokenzr.h" #include "wx/mstream.h" #include "wx/image.h" #include "wx/file.h" #include "ScintillaWX.h" //---------------------------------------------------------------------- const wxChar* wxSTCNameStr = wxT("stcwindow"); #ifdef MAKELONG #undef MAKELONG #endif #define MAKELONG(a, b) ((a) | ((b) << 16)) static long wxColourAsLong(const wxColour& co) { return (((long)co.Blue() << 16) | ((long)co.Green() << 8) | ((long)co.Red())); } static wxColour wxColourFromLong(long c) { wxColour clr; clr.Set((unsigned char)(c & 0xff), (unsigned char)((c >> 8) & 0xff), (unsigned char)((c >> 16) & 0xff)); return clr; } static wxColour wxColourFromSpec(const wxString& spec) { // spec should be a colour name or "#RRGGBB" if (spec.GetChar(0) == wxT('#')) { long red, green, blue; red = green = blue = 0; spec.Mid(1,2).ToLong(&red, 16); spec.Mid(3,2).ToLong(&green, 16); spec.Mid(5,2).ToLong(&blue, 16); return wxColour((unsigned char)red, (unsigned char)green, (unsigned char)blue); } else return wxColour(spec); } //---------------------------------------------------------------------- DEFINE_EVENT_TYPE( wxEVT_STC_CHANGE ) DEFINE_EVENT_TYPE( wxEVT_STC_STYLENEEDED ) DEFINE_EVENT_TYPE( wxEVT_STC_CHARADDED ) DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTREACHED ) DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTLEFT ) DEFINE_EVENT_TYPE( wxEVT_STC_ROMODIFYATTEMPT ) DEFINE_EVENT_TYPE( wxEVT_STC_KEY ) DEFINE_EVENT_TYPE( wxEVT_STC_DOUBLECLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_UPDATEUI ) DEFINE_EVENT_TYPE( wxEVT_STC_MODIFIED ) DEFINE_EVENT_TYPE( wxEVT_STC_MACRORECORD ) DEFINE_EVENT_TYPE( wxEVT_STC_MARGINCLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_NEEDSHOWN ) DEFINE_EVENT_TYPE( wxEVT_STC_PAINTED ) DEFINE_EVENT_TYPE( wxEVT_STC_USERLISTSELECTION ) DEFINE_EVENT_TYPE( wxEVT_STC_URIDROPPED ) DEFINE_EVENT_TYPE( wxEVT_STC_DWELLSTART ) DEFINE_EVENT_TYPE( wxEVT_STC_DWELLEND ) DEFINE_EVENT_TYPE( wxEVT_STC_START_DRAG ) DEFINE_EVENT_TYPE( wxEVT_STC_DRAG_OVER ) DEFINE_EVENT_TYPE( wxEVT_STC_DO_DROP ) DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM ) DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION ) DEFINE_EVENT_TYPE( wxEVT_STC_INDICATOR_CLICK ) DEFINE_EVENT_TYPE( wxEVT_STC_INDICATOR_RELEASE ) BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl) EVT_PAINT (wxStyledTextCtrl::OnPaint) EVT_SCROLLWIN (wxStyledTextCtrl::OnScrollWin) EVT_SCROLL (wxStyledTextCtrl::OnScroll) EVT_SIZE (wxStyledTextCtrl::OnSize) EVT_LEFT_DOWN (wxStyledTextCtrl::OnMouseLeftDown) // Let Scintilla see the double click as a second click EVT_LEFT_DCLICK (wxStyledTextCtrl::OnMouseLeftDown) EVT_MOTION (wxStyledTextCtrl::OnMouseMove) EVT_LEFT_UP (wxStyledTextCtrl::OnMouseLeftUp) #if defined(__WXGTK__) || defined(__WXMAC__) EVT_RIGHT_UP (wxStyledTextCtrl::OnMouseRightUp) #else EVT_CONTEXT_MENU (wxStyledTextCtrl::OnContextMenu) #endif EVT_MOUSEWHEEL (wxStyledTextCtrl::OnMouseWheel) EVT_MIDDLE_UP (wxStyledTextCtrl::OnMouseMiddleUp) EVT_CHAR (wxStyledTextCtrl::OnChar) EVT_KEY_DOWN (wxStyledTextCtrl::OnKeyDown) EVT_KILL_FOCUS (wxStyledTextCtrl::OnLoseFocus) EVT_SET_FOCUS (wxStyledTextCtrl::OnGainFocus) EVT_SYS_COLOUR_CHANGED (wxStyledTextCtrl::OnSysColourChanged) EVT_ERASE_BACKGROUND (wxStyledTextCtrl::OnEraseBackground) EVT_MENU_RANGE (10, 16, wxStyledTextCtrl::OnMenu) EVT_LISTBOX_DCLICK (wxID_ANY, wxStyledTextCtrl::OnListBox) END_EVENT_TABLE() IMPLEMENT_CLASS(wxStyledTextCtrl, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxStyledTextEvent, wxCommandEvent) #ifdef LINK_LEXERS // forces the linking of the lexer modules int Scintilla_LinkLexers(); #endif //---------------------------------------------------------------------- // Constructor and Destructor wxStyledTextCtrl::wxStyledTextCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { m_swx = NULL; Create(parent, id, pos, size, style, name); } bool wxStyledTextCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { style |= wxVSCROLL | wxHSCROLL; if (!wxControl::Create(parent, id, pos, size, style | wxWANTS_CHARS | wxCLIP_CHILDREN, wxDefaultValidator, name)) return false; #ifdef LINK_LEXERS Scintilla_LinkLexers(); #endif m_swx = new ScintillaWX(this); m_stopWatch.Start(); m_lastKeyDownConsumed = false; m_lastWheelTimestamp = 0; m_vScrollBar = NULL; m_hScrollBar = NULL; #if wxUSE_UNICODE // Put Scintilla into unicode (UTF-8) mode SetCodePage(wxSTC_CP_UTF8); #endif SetInitialSize(size); // Reduces flicker on GTK+/X11 SetBackgroundStyle(wxBG_STYLE_CUSTOM); // Make sure it can take the focus SetCanFocus(true); return true; } wxStyledTextCtrl::~wxStyledTextCtrl() { delete m_swx; } //---------------------------------------------------------------------- wxIntPtr wxStyledTextCtrl::SendMsg(int msg, wxUIntPtr wp, wxIntPtr lp) const { return m_swx->WndProc(msg, wp, lp); } //---------------------------------------------------------------------- // Set the vertical scrollbar to use instead of the ont that's built-in. void wxStyledTextCtrl::SetVScrollBar(wxScrollBar* bar) { m_vScrollBar = bar; if (bar != NULL) { // ensure that the built-in scrollbar is not visible SetScrollbar(wxVERTICAL, 0, 0, 0); } } // Set the horizontal scrollbar to use instead of the ont that's built-in. void wxStyledTextCtrl::SetHScrollBar(wxScrollBar* bar) { m_hScrollBar = bar; if (bar != NULL) { // ensure that the built-in scrollbar is not visible SetScrollbar(wxHORIZONTAL, 0, 0, 0); } } //---------------------------------------------------------------------- // Generated methods implementation section {{{ %(METHOD_IMPS)s //}}} //---------------------------------------------------------------------- // Returns the line number of the line with the caret. int wxStyledTextCtrl::GetCurrentLine() { int line = LineFromPosition(GetCurrentPos()); return line; } // Extract style settings from a spec-string which is composed of one or // more of the following comma separated elements: // // bold turns on bold // italic turns on italics // fore:[name or #RRGGBB] sets the foreground colour // back:[name or #RRGGBB] sets the background colour // face:[facename] sets the font face name to use // size:[num] sets the font size in points // eol turns on eol filling // underline turns on underlining // void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) { wxStringTokenizer tkz(spec, wxT(",")); while (tkz.HasMoreTokens()) { wxString token = tkz.GetNextToken(); wxString option = token.BeforeFirst(':'); wxString val = token.AfterFirst(':'); if (option == wxT("bold")) StyleSetBold(styleNum, true); else if (option == wxT("italic")) StyleSetItalic(styleNum, true); else if (option == wxT("underline")) StyleSetUnderline(styleNum, true); else if (option == wxT("eol")) StyleSetEOLFilled(styleNum, true); else if (option == wxT("size")) { long points; if (val.ToLong(&points)) StyleSetSize(styleNum, points); } else if (option == wxT("face")) StyleSetFaceName(styleNum, val); else if (option == wxT("fore")) StyleSetForeground(styleNum, wxColourFromSpec(val)); else if (option == wxT("back")) StyleSetBackground(styleNum, wxColourFromSpec(val)); } } // Get the font of a style wxFont wxStyledTextCtrl::StyleGetFont(int style) { wxFont font; font.SetPointSize(StyleGetSize(style)); font.SetFaceName(StyleGetFaceName(style)); if( StyleGetBold(style) ) font.SetWeight(wxFONTWEIGHT_BOLD); else font.SetWeight(wxFONTWEIGHT_NORMAL); if( StyleGetItalic(style) ) font.SetStyle(wxFONTSTYLE_ITALIC); else font.SetStyle(wxFONTSTYLE_NORMAL); return font; } // Set style size, face, bold, italic, and underline attributes from // a wxFont's attributes. void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) { #ifdef __WXGTK__ // Ensure that the native font is initialized int x, y; GetTextExtent(wxT("X"), &x, &y, NULL, NULL, &font); #endif int size = font.GetPointSize(); wxString faceName = font.GetFaceName(); bool bold = font.GetWeight() == wxBOLD; bool italic = font.GetStyle() != wxNORMAL; bool under = font.GetUnderlined(); wxFontEncoding encoding = font.GetEncoding(); StyleSetFontAttr(styleNum, size, faceName, bold, italic, under, encoding); } // Set all font style attributes at once. void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size, const wxString& faceName, bool bold, bool italic, bool underline, wxFontEncoding encoding) { StyleSetSize(styleNum, size); StyleSetFaceName(styleNum, faceName); StyleSetBold(styleNum, bold); StyleSetItalic(styleNum, italic); StyleSetUnderline(styleNum, underline); StyleSetFontEncoding(styleNum, encoding); } // Set the character set of the font in a style. Converts the Scintilla // character set values to a wxFontEncoding. void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet) { wxFontEncoding encoding; // Translate the Scintilla characterSet to a wxFontEncoding switch (characterSet) { default: case wxSTC_CHARSET_ANSI: case wxSTC_CHARSET_DEFAULT: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_BALTIC: encoding = wxFONTENCODING_ISO8859_13; break; case wxSTC_CHARSET_CHINESEBIG5: encoding = wxFONTENCODING_CP950; break; case wxSTC_CHARSET_EASTEUROPE: encoding = wxFONTENCODING_ISO8859_2; break; case wxSTC_CHARSET_GB2312: encoding = wxFONTENCODING_CP936; break; case wxSTC_CHARSET_GREEK: encoding = wxFONTENCODING_ISO8859_7; break; case wxSTC_CHARSET_HANGUL: encoding = wxFONTENCODING_CP949; break; case wxSTC_CHARSET_MAC: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_OEM: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_RUSSIAN: encoding = wxFONTENCODING_KOI8; break; case wxSTC_CHARSET_SHIFTJIS: encoding = wxFONTENCODING_CP932; break; case wxSTC_CHARSET_SYMBOL: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_TURKISH: encoding = wxFONTENCODING_ISO8859_9; break; case wxSTC_CHARSET_JOHAB: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_HEBREW: encoding = wxFONTENCODING_ISO8859_8; break; case wxSTC_CHARSET_ARABIC: encoding = wxFONTENCODING_ISO8859_6; break; case wxSTC_CHARSET_VIETNAMESE: encoding = wxFONTENCODING_DEFAULT; break; case wxSTC_CHARSET_THAI: encoding = wxFONTENCODING_ISO8859_11; break; case wxSTC_CHARSET_CYRILLIC: encoding = wxFONTENCODING_ISO8859_5; break; case wxSTC_CHARSET_8859_15: encoding = wxFONTENCODING_ISO8859_15;; break; } // We just have Scintilla track the wxFontEncoding for us. It gets used // in Font::Create in PlatWX.cpp. We add one to the value so that the // effective wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT and so when // Scintilla internally uses SC_CHARSET_DEFAULT we will translate it back // to wxFONENCODING_DEFAULT in Font::Create. SendMsg(SCI_STYLESETCHARACTERSET, style, encoding+1); } // Set the font encoding to be used by a style. void wxStyledTextCtrl::StyleSetFontEncoding(int style, wxFontEncoding encoding) { SendMsg(SCI_STYLESETCHARACTERSET, style, encoding+1); } // Perform one of the operations defined by the wxSTC_CMD_* constants. void wxStyledTextCtrl::CmdKeyExecute(int cmd) { SendMsg(cmd); } // Set the left and right margin in the edit area, measured in pixels. void wxStyledTextCtrl::SetMargins(int left, int right) { SetMarginLeft(left); SetMarginRight(right); } // Retrieve the start and end positions of the current selection. void wxStyledTextCtrl::GetSelection(int* startPos, int* endPos) { if (startPos != NULL) *startPos = SendMsg(SCI_GETSELECTIONSTART); if (endPos != NULL) *endPos = SendMsg(SCI_GETSELECTIONEND); } // Retrieve the point in the window where a position is displayed. wxPoint wxStyledTextCtrl::PointFromPosition(int pos) { int x = SendMsg(SCI_POINTXFROMPOSITION, 0, pos); int y = SendMsg(SCI_POINTYFROMPOSITION, 0, pos); return wxPoint(x, y); } // Scroll enough to make the given line visible void wxStyledTextCtrl::ScrollToLine(int line) { m_swx->DoScrollToLine(line); } // Scroll enough to make the given column visible void wxStyledTextCtrl::ScrollToColumn(int column) { m_swx->DoScrollToColumn(column); } #if wxUSE_TEXTCTRL bool wxStyledTextCtrl::DoSaveFile(const wxString& filename, int WXUNUSED(fileType)) #else bool wxStyledTextCtrl::SaveFile(const wxString& filename) #endif { wxFile file(filename, wxFile::write); if (!file.IsOpened()) return false; bool success = file.Write(GetText(), *wxConvCurrent); if (success) SetSavePoint(); return success; } #if wxUSE_TEXTCTRL bool wxStyledTextCtrl::DoLoadFile(const wxString& filename, int WXUNUSED(fileType)) #else bool wxStyledTextCtrl::LoadFile(const wxString& filename) #endif { bool success = false; wxFile file(filename, wxFile::read); if (file.IsOpened()) { wxString contents; // get the file size (assume it is not huge file...) ssize_t len = (ssize_t)file.Length(); if (len > 0) { #if wxUSE_UNICODE wxMemoryBuffer buffer(len+1); success = (file.Read(buffer.GetData(), len) == len); if (success) { ((char*)buffer.GetData())[len] = 0; contents = wxString(buffer, *wxConvCurrent, len); } #else wxString buffer; success = (file.Read(wxStringBuffer(buffer, len), len) == len); contents = buffer; #endif } else { if (len == 0) success = true; // empty file is ok else success = false; // len == wxInvalidOffset } if (success) { SetText(contents); EmptyUndoBuffer(); SetSavePoint(); } } return success; } #if wxUSE_DRAG_AND_DROP wxDragResult wxStyledTextCtrl::DoDragOver(wxCoord x, wxCoord y, wxDragResult def) { return m_swx->DoDragOver(x, y, def); } bool wxStyledTextCtrl::DoDropText(long x, long y, const wxString& data) { return m_swx->DoDropText(x, y, data); } #endif void wxStyledTextCtrl::SetUseAntiAliasing(bool useAA) { m_swx->SetUseAntiAliasing(useAA); } bool wxStyledTextCtrl::GetUseAntiAliasing() { return m_swx->GetUseAntiAliasing(); } void wxStyledTextCtrl::AddTextRaw(const char* text) { SendMsg(SCI_ADDTEXT, strlen(text), (sptr_t)text); } void wxStyledTextCtrl::InsertTextRaw(int pos, const char* text) { SendMsg(SCI_INSERTTEXT, pos, (sptr_t)text); } wxCharBuffer wxStyledTextCtrl::GetCurLineRaw(int* linePos) { int len = LineLength(GetCurrentLine()); if (!len) { if (linePos) *linePos = 0; wxCharBuffer empty; return empty; } wxCharBuffer buf(len); int pos = SendMsg(SCI_GETCURLINE, len, (sptr_t)buf.data()); if (linePos) *linePos = pos; return buf; } wxCharBuffer wxStyledTextCtrl::GetLineRaw(int line) { int len = LineLength(line); if (!len) { wxCharBuffer empty; return empty; } wxCharBuffer buf(len); SendMsg(SCI_GETLINE, line, (sptr_t)buf.data()); return buf; } wxCharBuffer wxStyledTextCtrl::GetSelectedTextRaw() { int start; int end; GetSelection(&start, &end); int len = end - start; if (!len) { wxCharBuffer empty; return empty; } wxCharBuffer buf(len); SendMsg(SCI_GETSELTEXT, 0, (sptr_t)buf.data()); return buf; } wxCharBuffer wxStyledTextCtrl::GetTextRangeRaw(int startPos, int endPos) { if (endPos < startPos) { int temp = startPos; startPos = endPos; endPos = temp; } int len = endPos - startPos; if (!len) { wxCharBuffer empty; return empty; } wxCharBuffer buf(len); TextRange tr; tr.lpstrText = buf.data(); tr.chrg.cpMin = startPos; tr.chrg.cpMax = endPos; SendMsg(SCI_GETTEXTRANGE, 0, (sptr_t)&tr); return buf; } void wxStyledTextCtrl::SetTextRaw(const char* text) { SendMsg(SCI_SETTEXT, 0, (sptr_t)text); } wxCharBuffer wxStyledTextCtrl::GetTextRaw() { int len = GetTextLength(); wxCharBuffer buf(len); // adds 1 for NUL automatically SendMsg(SCI_GETTEXT, len + 1, (sptr_t)buf.data()); return buf; } void wxStyledTextCtrl::AppendTextRaw(const char* text) { SendMsg(SCI_APPENDTEXT, strlen(text), (sptr_t)text); } //---------------------------------------------------------------------- // Event handlers void wxStyledTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(evt)) { wxPaintDC dc(this); m_swx->DoPaint(&dc, GetUpdateRegion().GetBox()); } void wxStyledTextCtrl::OnScrollWin(wxScrollWinEvent& evt) { if (evt.GetOrientation() == wxHORIZONTAL) m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition()); else m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition()); } void wxStyledTextCtrl::OnScroll(wxScrollEvent& evt) { wxScrollBar* sb = wxDynamicCast(evt.GetEventObject(), wxScrollBar); if (sb) { if (sb->IsVertical()) m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition()); else m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition()); } } void wxStyledTextCtrl::OnSize(wxSizeEvent& WXUNUSED(evt)) { if (m_swx) { wxSize sz = GetClientSize(); m_swx->DoSize(sz.x, sz.y); } } void wxStyledTextCtrl::OnMouseLeftDown(wxMouseEvent& evt) { SetFocus(); wxPoint pt = evt.GetPosition(); m_swx->DoLeftButtonDown(Point(pt.x, pt.y), m_stopWatch.Time(), evt.ShiftDown(), evt.ControlDown(), evt.AltDown()); } void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) { wxPoint pt = evt.GetPosition(); m_swx->DoLeftButtonMove(Point(pt.x, pt.y)); } void wxStyledTextCtrl::OnMouseLeftUp(wxMouseEvent& evt) { wxPoint pt = evt.GetPosition(); m_swx->DoLeftButtonUp(Point(pt.x, pt.y), m_stopWatch.Time(), evt.ControlDown()); } void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) { wxPoint pt = evt.GetPosition(); m_swx->DoContextMenu(Point(pt.x, pt.y)); } void wxStyledTextCtrl::OnMouseMiddleUp(wxMouseEvent& evt) { wxPoint pt = evt.GetPosition(); m_swx->DoMiddleButtonUp(Point(pt.x, pt.y)); } void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) { wxPoint pt = evt.GetPosition(); ScreenToClient(&pt.x, &pt.y); /* Show context menu at event point if it's within the window, or at caret location if not */ wxHitTest ht = this->HitTest(pt); if (ht != wxHT_WINDOW_INSIDE) { pt = this->PointFromPosition(this->GetCurrentPos()); } m_swx->DoContextMenu(Point(pt.x, pt.y)); } void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt) { // prevent having an event queue with wheel events that cannot be processed // reasonably fast (see ticket #9057) if ( m_lastWheelTimestamp <= evt.GetTimestamp() ) { m_lastWheelTimestamp = m_stopWatch.Time(); m_swx->DoMouseWheel(evt.GetWheelRotation(), evt.GetWheelDelta(), evt.GetLinesPerAction(), evt.ControlDown(), evt.IsPageScroll()); m_lastWheelTimestamp = m_stopWatch.Time() - m_lastWheelTimestamp; m_lastWheelTimestamp += evt.GetTimestamp(); } } void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) { // On (some?) non-US PC keyboards the AltGr key is required to enter some // common characters. It comes to us as both Alt and Ctrl down so we need // to let the char through in that case, otherwise if only ctrl or only // alt let's skip it. bool ctrl = evt.ControlDown(); #ifdef __WXMAC__ // On the Mac the Alt key is just a modifier key (like Shift) so we need // to allow the char events to be processed when Alt is pressed. // TODO: Should we check MetaDown instead in this case? bool alt = false; #else bool alt = evt.AltDown(); #endif bool skip = ((ctrl || alt) && ! (ctrl && alt)); #if wxUSE_UNICODE // apparently if we don't do this, Unicode keys pressed after non-char // ASCII ones (e.g. Enter, Tab) are not taken into account (patch 1615989) if (m_lastKeyDownConsumed && evt.GetUnicodeKey() > 255) m_lastKeyDownConsumed = false; #endif if (!m_lastKeyDownConsumed && !skip) { #if wxUSE_UNICODE int key = evt.GetUnicodeKey(); bool keyOk = true; // if the unicode key code is not really a unicode character (it may // be a function key or etc., the platforms appear to always give us a // small value in this case) then fallback to the ascii key code but // don't do anything for function keys or etc. if (key <= 127) { key = evt.GetKeyCode(); keyOk = (key <= 127); } if (keyOk) { m_swx->DoAddChar(key); return; } #else int key = evt.GetKeyCode(); if (key <= WXK_START || key > WXK_COMMAND) { m_swx->DoAddChar(key); return; } #endif } evt.Skip(); } void wxStyledTextCtrl::OnKeyDown(wxKeyEvent& evt) { int processed = m_swx->DoKeyDown(evt, &m_lastKeyDownConsumed); if (!processed && !m_lastKeyDownConsumed) evt.Skip(); } void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) { m_swx->DoLoseFocus(); evt.Skip(); } void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) { m_swx->DoGainFocus(); evt.Skip(); } void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(evt)) { m_swx->DoSysColourChange(); } void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt)) { // do nothing to help avoid flashing } void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) { m_swx->DoCommand(evt.GetId()); } void wxStyledTextCtrl::OnListBox(wxCommandEvent& WXUNUSED(evt)) { m_swx->DoOnListBox(); } void wxStyledTextCtrl::OnIdle(wxIdleEvent& evt) { m_swx->DoOnIdle(evt); } wxSize wxStyledTextCtrl::DoGetBestSize() const { // What would be the best size for a wxSTC? // Just give a reasonable minimum until something else can be figured out. return wxSize(200,100); } //---------------------------------------------------------------------- // Turn notifications from Scintilla into events void wxStyledTextCtrl::NotifyChange() { wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId()); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); } static void SetEventText(wxStyledTextEvent& evt, const char* text, size_t length) { if(!text) return; evt.SetText(stc2wx(text, length)); } void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) { SCNotification& scn = *_scn; wxStyledTextEvent evt(0, GetId()); evt.SetEventObject(this); evt.SetPosition(scn.position); evt.SetKey(scn.ch); evt.SetModifiers(scn.modifiers); switch (scn.nmhdr.code) { case SCN_STYLENEEDED: evt.SetEventType(wxEVT_STC_STYLENEEDED); break; case SCN_CHARADDED: evt.SetEventType(wxEVT_STC_CHARADDED); break; case SCN_SAVEPOINTREACHED: evt.SetEventType(wxEVT_STC_SAVEPOINTREACHED); break; case SCN_SAVEPOINTLEFT: evt.SetEventType(wxEVT_STC_SAVEPOINTLEFT); break; case SCN_MODIFYATTEMPTRO: evt.SetEventType(wxEVT_STC_ROMODIFYATTEMPT); break; case SCN_KEY: evt.SetEventType(wxEVT_STC_KEY); break; case SCN_DOUBLECLICK: evt.SetEventType(wxEVT_STC_DOUBLECLICK); break; case SCN_UPDATEUI: evt.SetEventType(wxEVT_STC_UPDATEUI); break; case SCN_MODIFIED: evt.SetEventType(wxEVT_STC_MODIFIED); evt.SetModificationType(scn.modificationType); SetEventText(evt, scn.text, scn.length); evt.SetLength(scn.length); evt.SetLinesAdded(scn.linesAdded); evt.SetLine(scn.line); evt.SetFoldLevelNow(scn.foldLevelNow); evt.SetFoldLevelPrev(scn.foldLevelPrev); break; case SCN_MACRORECORD: evt.SetEventType(wxEVT_STC_MACRORECORD); evt.SetMessage(scn.message); evt.SetWParam(scn.wParam); evt.SetLParam(scn.lParam); break; case SCN_MARGINCLICK: evt.SetEventType(wxEVT_STC_MARGINCLICK); evt.SetMargin(scn.margin); break; case SCN_NEEDSHOWN: evt.SetEventType(wxEVT_STC_NEEDSHOWN); evt.SetLength(scn.length); break; case SCN_PAINTED: evt.SetEventType(wxEVT_STC_PAINTED); break; case SCN_AUTOCSELECTION: evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION); evt.SetListType(scn.listType); SetEventText(evt, scn.text, strlen(scn.text)); evt.SetPosition(scn.lParam); break; case SCN_USERLISTSELECTION: evt.SetEventType(wxEVT_STC_USERLISTSELECTION); evt.SetListType(scn.listType); SetEventText(evt, scn.text, strlen(scn.text)); evt.SetPosition(scn.lParam); break; case SCN_URIDROPPED: evt.SetEventType(wxEVT_STC_URIDROPPED); SetEventText(evt, scn.text, strlen(scn.text)); break; case SCN_DWELLSTART: evt.SetEventType(wxEVT_STC_DWELLSTART); evt.SetX(scn.x); evt.SetY(scn.y); break; case SCN_DWELLEND: evt.SetEventType(wxEVT_STC_DWELLEND); evt.SetX(scn.x); evt.SetY(scn.y); break; case SCN_ZOOM: evt.SetEventType(wxEVT_STC_ZOOM); break; case SCN_HOTSPOTCLICK: evt.SetEventType(wxEVT_STC_HOTSPOT_CLICK); break; case SCN_HOTSPOTDOUBLECLICK: evt.SetEventType(wxEVT_STC_HOTSPOT_DCLICK); break; case SCN_CALLTIPCLICK: evt.SetEventType(wxEVT_STC_CALLTIP_CLICK); break; case SCN_INDICATORCLICK: evt.SetEventType(wxEVT_STC_INDICATOR_CLICK); break; case SCN_INDICATORRELEASE: evt.SetEventType(wxEVT_STC_INDICATOR_RELEASE); break; default: return; } GetEventHandler()->ProcessEvent(evt); } //---------------------------------------------------------------------- //---------------------------------------------------------------------- //---------------------------------------------------------------------- wxStyledTextEvent::wxStyledTextEvent(wxEventType commandType, int id) : wxCommandEvent(commandType, id) { m_position = 0; m_key = 0; m_modifiers = 0; m_modificationType = 0; m_length = 0; m_linesAdded = 0; m_line = 0; m_foldLevelNow = 0; m_foldLevelPrev = 0; m_margin = 0; m_message = 0; m_wParam = 0; m_lParam = 0; m_listType = 0; m_x = 0; m_y = 0; m_dragAllowMove = false; #if wxUSE_DRAG_AND_DROP m_dragResult = wxDragNone; #endif } bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; } bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; } bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; } wxStyledTextEvent::wxStyledTextEvent(const wxStyledTextEvent& event): wxCommandEvent(event) { m_position = event.m_position; m_key = event.m_key; m_modifiers = event.m_modifiers; m_modificationType = event.m_modificationType; m_text = event.m_text; m_length = event.m_length; m_linesAdded = event.m_linesAdded; m_line = event.m_line; m_foldLevelNow = event.m_foldLevelNow; m_foldLevelPrev = event.m_foldLevelPrev; m_margin = event.m_margin; m_message = event.m_message; m_wParam = event.m_wParam; m_lParam = event.m_lParam; m_listType = event.m_listType; m_x = event.m_x; m_y = event.m_y; m_dragText = event.m_dragText; m_dragAllowMove =event.m_dragAllowMove; #if wxUSE_DRAG_AND_DROP m_dragResult = event.m_dragResult; #endif } //---------------------------------------------------------------------- //---------------------------------------------------------------------- #endif // wxUSE_STC