Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => CodeCompletion redesign => Topic started by: blueshake on March 08, 2010, 08:47:42 am

Title: hook "tab" key
Post by: blueshake on March 08, 2010, 08:47:42 am
dear all:


mybe you have the function of eclipse,in eclipse editor,when you type "tab",and if the next char is one of ")]}",it will skip it. see the screen shot.so if we want to implement this function,we need to hook getkey donw message,in codelite, it just simple handle it in this way.see the quote.

and in codeblock ,I can not figure out how to do this.can somebode tell me how to do this in codeblock,thanks.
Quote
BEGIN_EVENT_TABLE(LEditor, wxScintilla)

    EVT_SCI_CHARADDED              (wxID_ANY, LEditor::OnCharAdded)
    EVT_SCI_MARGINCLICK            (wxID_ANY, LEditor::OnMarginClick)
    EVT_SCI_CALLTIP_CLICK          (wxID_ANY, LEditor::OnCallTipClick)
    EVT_SCI_DWELLEND               (wxID_ANY, LEditor::OnDwellEnd)
    EVT_SCI_UPDATEUI               (wxID_ANY, LEditor::OnSciUpdateUI)
    EVT_SCI_SAVEPOINTREACHED       (wxID_ANY, LEditor::OnSavePoint)
    EVT_SCI_SAVEPOINTLEFT          (wxID_ANY, LEditor::OnSavePoint)
    EVT_SCI_MODIFIED               (wxID_ANY, LEditor::OnChange)
    EVT_CONTEXT_MENU               (LEditor::OnContextMenu)
    EVT_KEY_DOWN                   (LEditor::OnKeyDown)
    EVT_LEFT_DOWN                  (LEditor::OnLeftDown)
    EVT_MIDDLE_DOWN                (LEditor::OnMiddleDown)
    EVT_MIDDLE_UP                  (LEditor::OnMiddleUp)
    EVT_LEFT_UP                    (LEditor::OnLeftUp)
    EVT_LEAVE_WINDOW               (LEditor::OnLeaveWindow)
    EVT_KILL_FOCUS                 (LEditor::OnFocusLost)
    EVT_SCI_DOUBLECLICK            (wxID_ANY, LEditor::OnLeftDClick)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_FIND_NEXT, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_REPLACE, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_REPLACEALL, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_BOOKMARKALL, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_CLOSE, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_FRD_CLEARBOOKMARKS, LEditor::OnFindDialog)
    EVT_COMMAND                    (wxID_ANY, wxEVT_CMD_JOB_STATUS_VOID_PTR, LEditor::OnHighlightThread)
    EVT_COMMAND                    (wxID_ANY, wxCMD_EVENT_REMOVE_MATCH_INDICATOR, LEditor::OnRemoveMatchInidicator)
END_EVENT_TABLE()

[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: ollydbg on March 08, 2010, 09:17:47 am
I have tried, but failed. :(

In the codelite editor, say LEditor class, it is just derived from wxScintilla class, so it can hook the EVT_KEY_DOWN message.

But in Codeblocks, cbEditor class use wxScintilla as its member, I don't know how to hook the Key_down event.

By the way, if we can handle the message SCI_TAB from scintilla (see: http://www.scintilla.org/ScintillaDoc.html#KeyboardCommands), we can do the same thing.

hope some one can help you.
Title: Re: hook "tab" key
Post by: MortenMacFly on March 08, 2010, 11:44:07 am
and in codeblock ,I can not figure out how to do this.can somebode tell me how to do this in codeblock,thanks.
Look into:
Code
void cbEditor::OnScintillaEvent(wxScintillaEvent& event)

Notice that you should do any listening via an (the) editor hook. It can even be implemented as plugin btw!
Title: Re: hook "tab" key
Post by: blueshake on March 08, 2010, 01:41:40 pm
@morten

thanks for your answer.I will check into it. :D
Title: Re: hook "tab" key
Post by: ollydbg on March 09, 2010, 03:30:37 am
I don't know we can do it in the OnScintillaEvent(), because we don't have a  wxEVT_SCI_TAB defined in wxscintilla.h

See the code snippet :

Code
cbStyledTextCtrl* cbEditor::CreateEditor()
{
    m_ID = wxNewId();

    // avoid gtk-critical because of sizes less than -1 (can happen with wxAuiNotebook/cbAuiNotebook)
    wxSize size = m_pControl ? wxDefaultSize : GetSize();
    size.x = std::max(size.x, -1);
    size.y = std::max(size.y, -1);

    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, size);
    control->UsePopUp(false);

    wxString enc_name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/default_encoding"), wxEmptyString);
    m_pData->m_encoding = wxFontMapper::GetEncodingFromName(enc_name);

    // dynamic events
    Connect( m_ID,  -1, wxEVT_SCI_MARGINCLICK,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnMarginClick );
    Connect( m_ID,  -1, wxEVT_SCI_UPDATEUI,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorUpdateUI );
    Connect( m_ID,  -1, wxEVT_SCI_CHANGE,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorChange );
    Connect( m_ID,  -1, wxEVT_SCI_CHARADDED,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorCharAdded );
    Connect( m_ID,  -1, wxEVT_SCI_DWELLSTART,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorDwellStart );
    Connect( m_ID,  -1, wxEVT_SCI_DWELLEND,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorDwellEnd );
    Connect( m_ID,  -1, wxEVT_SCI_USERLISTSELECTION,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnUserListSelection );
    Connect( m_ID,  -1, wxEVT_SCI_MODIFIED,
                  (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                  &cbEditor::OnEditorModified );

    // Now bind all *other* scintilla events to a common function so that editor hooks
    // can be informed for them too.
    // If you implement one of these events using a different function, do the following:
    //  * comment it out here,
    //  * "connect" it in the above block
    //  * and make sure you call OnScintillaEvent() from your new handler function
    // This will make sure that all editor hooks will be called when needed.
    int scintilla_events[] =
    {
//        wxEVT_SCI_CHANGE,
        wxEVT_SCI_STYLENEEDED,
//        wxEVT_SCI_CHARADDED,
        wxEVT_SCI_SAVEPOINTREACHED,
        wxEVT_SCI_SAVEPOINTLEFT,
        wxEVT_SCI_ROMODIFYATTEMPT,
        wxEVT_SCI_KEY,
        wxEVT_SCI_DOUBLECLICK,
//        wxEVT_SCI_UPDATEUI,
//        wxEVT_SCI_MODIFIED,
        wxEVT_SCI_MACRORECORD,
//        wxEVT_SCI_MARGINCLICK,
        wxEVT_SCI_NEEDSHOWN,
        wxEVT_SCI_PAINTED,
//        wxEVT_SCI_USERLISTSELECTION,
        wxEVT_SCI_URIDROPPED,
//        wxEVT_SCI_DWELLSTART,
//        wxEVT_SCI_DWELLEND,
        wxEVT_SCI_START_DRAG,
        wxEVT_SCI_DRAG_OVER,
        wxEVT_SCI_DO_DROP,
        wxEVT_SCI_ZOOM,
        wxEVT_SCI_HOTSPOT_CLICK,
        wxEVT_SCI_HOTSPOT_DCLICK,
        wxEVT_SCI_CALLTIP_CLICK,
        wxEVT_SCI_AUTOCOMP_SELECTION,
//        wxEVT_SCI_INDICATOR_CLICK,
//        wxEVT_SCI_INDICATOR_RELEASE,

        -1 // to help enumeration of this array
    };
    int i = 0;
    while (scintilla_events[i] != -1)
    {
        Connect( m_ID,  -1, scintilla_events[i],
                      (wxObjectEventFunction) (wxEventFunction) (wxScintillaEventFunction)
                      &cbEditor::OnScintillaEvent );
        ++i;
    }

    return control;
}


We can only handle all the events in the scintilla_events array, either commented events or uncommented events. But the "tab" event will never carried in the wxEVT_SCI_KEY, because from the docs:

http://www.scintilla.org/ScintillaDoc.html#SCN_KEY

Quote
SCN_KEY
Reports all keys pressed but not consumed by Scintilla.

Since I think the "tab" event is already consumed by Scintilla internally, the only chance we can hook the tab event is the "SCI_TAB" stated in the
http://www.scintilla.org/ScintillaDoc.html#KeyboardCommands

which is not implemented in wxScintilla.

I'm not sure all my comments is right. :D
Title: Re: hook "tab" key
Post by: Loaden on March 24, 2010, 02:12:05 pm
I solved this problem.

Code
cbStyledTextCtrl* cbEditor::CreateEditor()
{
    m_ID = wxNewId();

    // avoid gtk-critical because of sizes less than -1 (can happen with wxAuiNotebook/cbAuiNotebook)
    wxSize size = m_pControl ? wxDefaultSize : GetSize();
    size.x = std::max(size.x, -1);
    size.y = std::max(size.y, -1);

    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, size);
    control->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(cbEditor::OnKeyDown));

Notice:
    control->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(cbEditor::OnKeyDown));
Title: Re: hook "tab" key
Post by: Loaden on March 25, 2010, 05:18:13 pm
I make a patch for this, welcome to test.


[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: ollydbg on March 26, 2010, 01:59:31 am
I make a patch for this, welcome to test.


I found a bug:

When I enter this:
Code
void f(
Then, I will get the close parenthesis auto added.
Code
void f(|)
But at this moment, I press backspace key, then the opening parenthesis was deleted but the close parenthesis still there.
Code
void f)

Except this bug, all the other functions works really nice!!! Thanks for the contribution.
Title: Re: hook "tab" key
Post by: Loaden on March 26, 2010, 04:29:42 am
I make a patch for this, welcome to test.


I found a bug:

When I enter this:
Code
void f(
Then, I will get the close parenthesis auto added.
Code
void f(|)
But at this moment, I press backspace key, then the opening parenthesis was deleted but the close parenthesis still there.
Code
void f)

Except this bug, all the other functions works really nice!!! Thanks for the contribution.
Fix now.


[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: MortenMacFly on March 26, 2010, 07:24:48 am
Fix now.
Some remarks concerning this patch:
1.) Methods should not start like "No", "Dont", "Not". This is hard to read. Instead always call a method like e.g. "AllowTabSmartJump" and change the break statement to "if (!AllowTabSmartJump()) break;"
2.) The trial for AllowTabSmartJump() should be the first statement in the method, like:
Code
if (!AllowTabSmartJump())
{
    event.Skip();
    return;
}
3.) These statements look weird to me:
Code
        case _T('\''):
        case 57:    // (
        case 0x91:  // {
You are using character comparison, then integer and finally hex. Why? Couldn't this be consistent, readable like e.g. all of type char?
4.) It does not use our code style (indention of 4 spaces)

...if you keep that in mind then it easier for us to integrate with the C::B sources.

...sorry for nut-picking. Take it as a hint for future work.
Title: Re: hook "tab" key
Post by: Loaden on March 26, 2010, 08:21:30 am
Hi, morten, thanks for your tips.
The following patch should solve your related issues.

Code
Index: src/include/cbstyledtextctrl.h
===================================================================
--- src/include/cbstyledtextctrl.h (revision 6196)
+++ src/include/cbstyledtextctrl.h (working copy)
@@ -24,9 +24,13 @@
         void OnKillFocus(wxFocusEvent& event);
         void OnGetFocus(wxFocusEvent& event);
         void OnGPM(wxMouseEvent& event);
+        void OnKeyDown(wxKeyEvent& event);
+        void OnKeyUp(wxKeyEvent& event);
+        bool AllowTabSmartJump();
 
         wxWindow* m_pParent;
         wxLongLong m_lastFocusTime;
+        bool m_tabSmartJump;
 
         DECLARE_EVENT_TABLE()
 };
Index: src/sdk/cbstyledtextctrl.cpp
===================================================================
--- src/sdk/cbstyledtextctrl.cpp (revision 6196)
+++ src/sdk/cbstyledtextctrl.cpp (working copy)
@@ -18,17 +18,23 @@
 #include "editorbase.h" // DisplayContextMenu
 #include "prep.h" // platform::gtk
 
+static const wxString s_leftBrace(_T("([{'\""));
+static const wxString s_rightBrace(_T(")]}'\""));
+
 BEGIN_EVENT_TABLE(cbStyledTextCtrl, wxScintilla)
     EVT_CONTEXT_MENU(cbStyledTextCtrl::OnContextMenu)
     EVT_KILL_FOCUS(cbStyledTextCtrl::OnKillFocus)
     EVT_MIDDLE_DOWN(cbStyledTextCtrl::OnGPM)
     EVT_SET_FOCUS(cbStyledTextCtrl::OnGetFocus)
+    EVT_KEY_DOWN(cbStyledTextCtrl::OnKeyDown)
+    EVT_KEY_UP(cbStyledTextCtrl::OnKeyUp)
 END_EVENT_TABLE()
 
 cbStyledTextCtrl::cbStyledTextCtrl(wxWindow* pParent, int id, const wxPoint& pos, const wxSize& size, long style)
     : wxScintilla(pParent, id, pos, size, style),
     m_pParent(pParent),
-    m_lastFocusTime(0L)
+    m_lastFocusTime(0L),
+    m_tabSmartJump(false)
 {
     //ctor
 }
@@ -103,3 +109,125 @@
         SetSelectionVoid(start, end);
     }
 } // end of OnGPM
+
+void cbStyledTextCtrl::OnKeyDown(wxKeyEvent& event)
+{
+    int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case WXK_TAB:
+        {
+            if (m_tabSmartJump)
+            {
+                if (s_rightBrace.Find(GetCharAt(GetCurrentPos())) == wxNOT_FOUND)
+                {
+                    m_tabSmartJump = false;
+                }
+                else
+                {
+                    CharRight();
+                    return;
+                }
+            }
+        }
+        break;
+
+        case WXK_BACK:
+        {
+            if (m_tabSmartJump)
+            {
+                const int pos = GetCurrentPos();
+                const int index = s_leftBrace.Find(GetCharAt(pos - 1));
+                if (index != wxNOT_FOUND && GetCharAt(pos) == s_rightBrace.GetChar(index))
+                {
+                    CharRight();
+                    DeleteBack();
+                }
+            }
+        }
+        break;
+
+        case WXK_ESCAPE:
+        {
+            if (m_tabSmartJump)
+            {
+                m_tabSmartJump = false;
+                CharLeft();
+                Tab();
+                return;
+            }
+        }
+        break;
+
+        case WXK_RETURN:
+        {
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+void cbStyledTextCtrl::OnKeyUp(wxKeyEvent& event)
+{
+    const int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case _T('['):   // [ {
+        case _T('\''):  // ' "
+        case _T('9'):   // (
+        {
+            if (!AllowTabSmartJump()) break;
+
+            wxChar ch = keyCode;
+            if (event.ShiftDown())
+            {
+                if (keyCode == _T('\'')) ch = _T('"');
+                else if (keyCode == _T('9')) ch = _T('(');
+                else if (keyCode == _T('[')) ch = _T('{');
+            }
+
+            int index = s_leftBrace.Find(ch);
+            if (index != wxNOT_FOUND && GetCharAt(GetCurrentPos()) == s_rightBrace.GetChar(index))
+                m_tabSmartJump = true;
+            else if (keyCode == _T('\'')) // ' "
+                m_tabSmartJump = false;
+        }
+        break;
+
+        case _T(']'):   // ] }
+        case _T('0'):   // )
+        {
+            if (!AllowTabSmartJump()) break;
+            if (keyCode == _T('0') && !event.ShiftDown()) break;
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+bool cbStyledTextCtrl::AllowTabSmartJump()
+{
+    int style = GetStyleAt(GetCurrentPos() - 2);
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}

[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: Loaden on March 26, 2010, 08:25:01 am
But now I encountered difficulties: I do not know how to draw the lines for tips?
Moreover, whether it is necessary for drawing the root tips of the lines that do?
Everyone's opinion?
Title: Re: hook "tab" key
Post by: Loaden on March 26, 2010, 08:36:00 am
2.) The trial for AllowTabSmartJump() should be the first statement in the method, like:
Code
if (!AllowTabSmartJump())
{
    event.Skip();
    return;
}
Here, I do not quite understand: Why did not directly break it, because at the end of the function, there implementation: 'event.Skip ();' ?
Title: Re: hook "tab" key
Post by: MortenMacFly on March 26, 2010, 08:39:09 pm
Here, I do not quite understand: Why did not directly break it, because at the end of the function, there implementation: 'event.Skip ();' ?
Yes, but there are computations in between which can be avoided. Namely event.GetKeyCode(); and the switch computation.
Title: Re: hook "tab" key
Post by: MortenMacFly on March 26, 2010, 08:43:22 pm
Hehe... now after the modifications, isn't this:
Code
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+            else
+                return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}
The same like this:
Code
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+        }
+    }
+    return false;
+}
???
:lol: :lol: :lol:
Title: Re: hook "tab" key
Post by: Loaden on March 27, 2010, 12:19:28 am
The same like this:
Code
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            if (style != wxSCI_C_STRING && style != wxSCI_C_CHARACTER)
+                return true;
+        }
+        case wxSCI_LEX_D:
+        {
+            if (style != wxSCI_D_STRING && style != wxSCI_D_CHARACTER)
+                return true;
+        }
+    }
+    return false;
+}
???
:lol: :lol: :lol:
Haha, you're right! Thank you. :P
Title: Re: hook "tab" key
Post by: Jenna on March 27, 2010, 12:36:04 am
Why not this (and get rid of the if-statements) :

Code
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}
?
Title: Re: hook "tab" key
Post by: Loaden on March 27, 2010, 12:43:27 am
Here, I do not quite understand: Why did not directly break it, because at the end of the function, there implementation: 'event.Skip ();' ?
Yes, but there are computations in between which can be avoided. Namely event.GetKeyCode(); and the switch computation.
Sorry, I still do not quite understand.
If change the code like this:
Code
void cbStyledTextCtrl::OnKeyUp(wxKeyEvent& event)
{
    if (!AllowTabSmartJump())
    {
        event.Skip();
        return;
    }
    const int keyCode = event.GetKeyCode();
    switch (keyCode)
    {
...
    }

    event.Skip();
}

We do not have access to ‘event.GetKeyCode()’ value and 'switch’ calculation, BUT, we need call 'AllowTabSmartJump' each time.
Here, the time occupied may be greater.
Title: Re: hook "tab" key
Post by: Loaden on March 27, 2010, 12:45:36 am
Why not this (and get rid of the if-statements) :

Code
Index: src/include/cbstyledtextctrl.h
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+        {
+            return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        }
+        case wxSCI_LEX_D:
+        {
+            return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+        }
+    }
+    return false;
+}
?
cool! :D
Title: Re: hook "tab" key
Post by: Loaden on March 27, 2010, 01:04:01 am
Add an interface for external use :
Code
+        void SetTabSmartJump(bool enable = true) { m_tabSmartJump = enable; }
+

And according to everyone's tips for perfect 'AllowTabSmartJump' function.
Code
Index: src/include/cbstyledtextctrl.h
===================================================================
--- src/include/cbstyledtextctrl.h (revision 6196)
+++ src/include/cbstyledtextctrl.h (working copy)
@@ -19,14 +19,20 @@
         cbStyledTextCtrl(wxWindow* pParent, int id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0);
         virtual ~cbStyledTextCtrl();
         wxDateTime GetLastFocusTime() const {return m_lastFocusTime;}
+        void SetTabSmartJump(bool enable = true) { m_tabSmartJump = enable; }
+
     private:
         void OnContextMenu(wxContextMenuEvent& event);
         void OnKillFocus(wxFocusEvent& event);
         void OnGetFocus(wxFocusEvent& event);
         void OnGPM(wxMouseEvent& event);
+        void OnKeyDown(wxKeyEvent& event);
+        void OnKeyUp(wxKeyEvent& event);
+        bool AllowTabSmartJump();
 
         wxWindow* m_pParent;
         wxLongLong m_lastFocusTime;
+        bool m_tabSmartJump;
 
         DECLARE_EVENT_TABLE()
 };
Index: src/sdk/cbstyledtextctrl.cpp
===================================================================
--- src/sdk/cbstyledtextctrl.cpp (revision 6196)
+++ src/sdk/cbstyledtextctrl.cpp (working copy)
@@ -18,17 +18,23 @@
 #include "editorbase.h" // DisplayContextMenu
 #include "prep.h" // platform::gtk
 
+static const wxString s_leftBrace(_T("([{'\""));
+static const wxString s_rightBrace(_T(")]}'\""));
+
 BEGIN_EVENT_TABLE(cbStyledTextCtrl, wxScintilla)
     EVT_CONTEXT_MENU(cbStyledTextCtrl::OnContextMenu)
     EVT_KILL_FOCUS(cbStyledTextCtrl::OnKillFocus)
     EVT_MIDDLE_DOWN(cbStyledTextCtrl::OnGPM)
     EVT_SET_FOCUS(cbStyledTextCtrl::OnGetFocus)
+    EVT_KEY_DOWN(cbStyledTextCtrl::OnKeyDown)
+    EVT_KEY_UP(cbStyledTextCtrl::OnKeyUp)
 END_EVENT_TABLE()
 
 cbStyledTextCtrl::cbStyledTextCtrl(wxWindow* pParent, int id, const wxPoint& pos, const wxSize& size, long style)
     : wxScintilla(pParent, id, pos, size, style),
     m_pParent(pParent),
-    m_lastFocusTime(0L)
+    m_lastFocusTime(0L),
+    m_tabSmartJump(false)
 {
     //ctor
 }
@@ -103,3 +109,115 @@
         SetSelectionVoid(start, end);
     }
 } // end of OnGPM
+
+void cbStyledTextCtrl::OnKeyDown(wxKeyEvent& event)
+{
+    int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case WXK_TAB:
+        {
+            if (m_tabSmartJump)
+            {
+                if (s_rightBrace.Find(GetCharAt(GetCurrentPos())) == wxNOT_FOUND)
+                {
+                    m_tabSmartJump = false;
+                }
+                else
+                {
+                    CharRight();
+                    return;
+                }
+            }
+        }
+        break;
+
+        case WXK_BACK:
+        {
+            if (m_tabSmartJump)
+            {
+                const int pos = GetCurrentPos();
+                const int index = s_leftBrace.Find(GetCharAt(pos - 1));
+                if (index != wxNOT_FOUND && GetCharAt(pos) == s_rightBrace.GetChar(index))
+                {
+                    CharRight();
+                    DeleteBack();
+                }
+            }
+        }
+        break;
+
+        case WXK_ESCAPE:
+        {
+            if (m_tabSmartJump)
+            {
+                m_tabSmartJump = false;
+                CharLeft();
+                Tab();
+                return;
+            }
+        }
+        break;
+
+        case WXK_RETURN:
+        {
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+void cbStyledTextCtrl::OnKeyUp(wxKeyEvent& event)
+{
+    const int keyCode = event.GetKeyCode();
+    switch (keyCode)
+    {
+        case _T('['):   // [ {
+        case _T('\''):  // ' "
+        case _T('9'):   // (
+        {
+            if (!AllowTabSmartJump()) break;
+
+            wxChar ch = keyCode;
+            if (event.ShiftDown())
+            {
+                if (keyCode == _T('\'')) ch = _T('"');
+                else if (keyCode == _T('9')) ch = _T('(');
+                else if (keyCode == _T('[')) ch = _T('{');
+            }
+
+            int index = s_leftBrace.Find(ch);
+            if (index != wxNOT_FOUND && GetCharAt(GetCurrentPos()) == s_rightBrace.GetChar(index))
+                m_tabSmartJump = true;
+            else if (keyCode == _T('\'')) // ' "
+                m_tabSmartJump = false;
+        }
+        break;
+
+        case _T(']'):   // ] }
+        case _T('0'):   // )
+        {
+            if (!AllowTabSmartJump()) break;
+            if (keyCode == _T('0') && !event.ShiftDown()) break;
+            m_tabSmartJump = false;
+        }
+        break;
+    }
+
+    event.Skip();
+}
+
+bool cbStyledTextCtrl::AllowTabSmartJump()
+{
+    int style = GetStyleAt(GetCurrentPos() - 2);
+    switch (GetLexer())
+    {
+        case wxSCI_LEX_CPP:
+            return !(style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER);
+        case wxSCI_LEX_D:
+            return !(style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER);
+    }
+    return false;
+}

[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: MortenMacFly on March 28, 2010, 03:43:52 pm
We do not have access to ‘event.GetKeyCode()’ value and 'switch’ calculation, BUT, we need call 'AllowTabSmartJump' each time.
Yes, but in the other case you do call AllowTabSmartJump() all the time, too - right?! You do it in every case statement.

So - I am not sure what causes more CPU time, really. However, I believe it makes the code easier to understand. But I guess this discussion is based on personal habits - so I accept your decision however it is.
Title: Re: hook "tab" key
Post by: Loaden on April 07, 2010, 11:16:45 am
Auto delete ')', when press backspace.
Code
Index: src/plugins/codecompletion/codecompletion.cpp

===================================================================

--- src/plugins/codecompletion/codecompletion.cpp (revision 6202)

+++ src/plugins/codecompletion/codecompletion.cpp (working copy)

@@ -2014,6 +2014,7 @@

             control->SetTargetStart(start);
             control->SetTargetEnd(pos);
             control->ReplaceTarget(itemText+_T("()"));
+            control->SetTabSmartJump();
             pos = control->GetCurrentPos();
             control->GotoPos(pos + itemText.size()+2);
             if ((*it).second != 0)

test code:
Code
#include <stdio.h>

class A
{
public:
    void test()
    {
       
    }
};

int main(int argc, char* argv[])
{
    A a;
    a.test(|) // HERE, when backspace, it's can delete '(', also ')'.
    return 0;
}
Title: Re: hook "tab" key
Post by: Loaden on April 20, 2010, 07:29:24 pm
Rewrote this, it's support jump tip now.

EDIT: fix a bug. Welcome for test!

[attachment deleted by admin]
Title: Re: hook "tab" key
Post by: killerbot on August 20, 2010, 01:25:00 pm
wake up call ;-)
What's the state on this patch, any issues still open, or could we try to apply it ?
Is the patch attached here the same as the one in the berlios tracker, or are they out of sync ?
Title: Re: hook "tab" key
Post by: Loaden on August 20, 2010, 03:33:10 pm
Hi, killerbot, The patch is applied in cc branch now.
And looks works well.
Title: Re: hook "tab" key
Post by: killerbot on August 20, 2010, 03:36:57 pm
ok, then I won't apply it on trunk and wait till cc gets merged towards trunk :-)
Title: Re: hook "tab" key
Post by: Loaden on August 20, 2010, 03:47:48 pm
ok, then I won't apply it on trunk and wait till cc gets merged towards trunk :-)
Yeah, and i hope the merge will be soon, we just need more test.