Author Topic: question on how to trigger evt(cbEVT_COMPLETE_CODE)  (Read 67154 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
question on how to trigger evt(cbEVT_COMPLETE_CODE)
« on: August 17, 2017, 04:16:27 pm »
Code
            // auto suggest list can be triggered either:
            // 1, some number of chars are entered
            // 2, an interested char belong to alChars is entered
            int autolaunchCt = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/auto_launch_count"), 3);
            if (   (pos - wordStartPos >= autolaunchCt && !stc->AutoCompActive())
                || pos - wordStartPos == autolaunchCt + 4 )
            {
                CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
                Manager::Get()->ProcessEvent(evt);
            }
            else if (alChars->second.find(ch) != alChars->second.end())
            {
                m_AutoLaunchTimer.Start(10, wxTIMER_ONE_SHOT);
                m_AutocompPosition = pos;
            }


This is some code snippet in the ccmanager.cpp, you see there is a condition
Code
pos - wordStartPos == autolaunchCt + 4

I think this condition should be removed, this cause extra refresh of the suggestion list

For example, when I hit a dot, I get some suggestion list like "Method1", then I continue to type the "M", "e", "t"... When I hit "d", the whole code suggestion list will get refreshed. (In my case, autolaunchCt is 2), I think it just waste a lot of time, right?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #1 on: August 17, 2017, 09:05:18 pm »
I don't understand what is your problem. Can you try to describe it?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #2 on: August 18, 2017, 01:10:29 am »
My original reason was that a CC plugin might return a massive amount of results, especially if CC is initiated with no (or only one letter) context.  This allows the CC plugin to return only the most likely results, then later expand to all matching results once the context is more exact.

When using this with clang, I cache the symbol dump for the refine step (or if a user requests CC again in the same spot).  Although, I do not know what the current state of that is; I have not followed its development.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #3 on: August 18, 2017, 02:15:48 am »
I don't understand. What is supposed to happen?
Should the auto completion auto reload when the user types 4 character or the completion word becomes 4 characters long?
I see the former behaviour. It looks rather strange.

Why don't we update the list on every keystroke? Why don't we update the list on every backspace or delete character.
You can try sublime text 3 for a good implementation of this.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #4 on: August 18, 2017, 03:23:17 am »
I don't understand what is your problem. Can you try to describe it?
OK, let me explain it in more details.
Suppose you have a class:
Code
class AAA
{
public:
void Method1();
void Method2();
void Method3();
void Method4();
void Method5();
void Method6();
int aaa;
int bbb;
int ccc;
...
};

AAA obj;
obj.

Now, when you hit the ".", the suggestion list will show all the member functions and member variables. This is because "." is an interesting character. This is how the "else if" clause in my first post describes.  "else if (alChars->second.find(ch) != alChars->second.end())", this trigger a timer, and further trigger a evt(cbEVT_COMPLETE_CODE).

Now, you continue typing type "M", "e", .... The suggestion list get reduced, such as the member variables are removed from the suggestion list.
But when you get a condition that "pos - wordStartPos == autolaunchCt + 4", you trigger a evt(cbEVT_COMPLETE_CODE) again. I think the second evt(cbEVT_COMPLETE_CODE) is not necessary, because all the suggestion list is already generated, when you enter more characters, you are just reduce the suggestion list my prefix match. I think all the suggestion list items are already cached in the suggestion list.

Note: a evt(cbEVT_COMPLETE_CODE) normally ask the plugin to do a expression solving of the current statement, which is not a simple task, at least in our buildin CC plugin.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #5 on: August 18, 2017, 09:05:47 am »
I don't see this behaviour. For me the list of entries is not shrunk or trimmed at every character typed.
When I type a character I see that just the selection changes. And at one particular character the list is regenerated/reopened.

I'm surprised that you're describing different behaviour.

p.s. Our CC plugin will stay in the history just after I finish my editor experiments...
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #6 on: August 18, 2017, 10:08:30 am »
I don't see this behaviour. For me the list of entries is not shrunk or trimmed at every character typed.
When I type a character I see that just the selection changes. And at one particular character the list is regenerated/reopened.

I'm surprised that you're describing different behaviour.

You are right, the list never get shrunked when I enter "M", just the selection was changed.
My main question is about the "regenerated/reopened" behavior, which cause some extra CC, see my attachment gif file. (I have enabled the debuglog of the CC, so you see when I get the ".", we get 9 items, after I have entered 6 chars, that's 2+4, the evt(cbEVT_COMPLETE_CODE) is fired again, and you get 6 items). I mean the next run of the "statement solving inside CC" is not necessary, we have already generate 9 items, then we can shrunk directly on the previous results.

Here is the test code:
Code
class AAA
{
public:
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    void Method5();
    void Method6();
    int aaa;
    int bbb;
    int ccc;
    int aaa1;
    int bbb1;
    int ccc1;
    int aaa2;
    int bbb2;
    int ccc2;
};
AAA obj;
obj.M


Quote
p.s. Our CC plugin will stay in the history just after I finish my editor experiments...
You plan to remove the CC plugin, and implement the Clang CC plugin? Or some other ideas?

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #7 on: August 18, 2017, 07:23:53 pm »
You are right, the list never get shrunked when I enter "M", just the selection was changed.
... I mean the next run of the "statement solving inside CC" is not necessary, we have already generate 9 items, then we can shrunk directly on the previous results.
I think this is a limitation of the scintilla apis. We should just ask the cc plugin for a list of completions and then use it for our list control.
I don't know why this is done this way, but I guess I'll find out when I try to implement the auto-completion in multiple-selections.

You plan to remove the CC plugin, and implement the Clang CC plugin? Or some other ideas?
I plan to implement a client for http://langserver.org/
For me this is the only feasible option for an IDE with the size of CB.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #8 on: August 19, 2017, 01:53:09 am »
You plan to remove the CC plugin, and implement the Clang CC plugin? Or some other ideas?
I plan to implement a client for http://langserver.org/
For me this is the only feasible option for an IDE with the size of CB.
Sounds like langserver for C++ are maintained by LLVM, so it's still clang. But currently it's status is "in progress", and I see only a VS client is in the code repository. It sounds like all the communication is through IPC or socket(see here:sourcegraph/javascript-typescript-langserver: JavaScript and TypeScript code intelligence through the Language Server Protocol)
Code
# run over STDIO
node lib/language-server-stdio
# or run over TCP
node lib/language-server
Hope the speed is still good enough. ;)

BTW: About our current status in buildin CC, it needs some asynchronous mechanisms to avoid a lot of lockers to protect the tokentree or other resource.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #9 on: August 19, 2017, 09:14:27 am »
Guys, I found another bug under C::B build against wx3.1, that is "press shift + key" cancel the auto completion window under Windows. I test it again, and this does not happens under Nightly build version. I'm on Win7.

Test code is in the post: Re: question on how to trigger evt(cbEVT_COMPLETE_CODE), the step to reproduce is quite simple:

1, hit "." after the "obj", which shows the suggestion list.
2, hit "shift + m"
3, the expected behavior is the "Method.." item will be selected, but in my C::B build against wx3.1, the auto completion window is canceled.

Note that if in the step 2, I hit the "a", then the "a..." item is selected, and the auto completion window is still active.
Note that if in the step 2, I only hit the "shift" key, the auto completion window is still active.

Really strange, it looks like wx3.1 emit some extra event which cancel the active auto completion window when I hit "shift + key". Any one can reproduce?
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #10 on: August 26, 2017, 05:31:30 am »
Guys, I found another bug under C::B build against wx3.1, that is "press shift + key" cancel the auto completion window under Windows. I test it again, and this does not happens under Nightly build version. I'm on Win7.

Test code is in the post: Re: question on how to trigger evt(cbEVT_COMPLETE_CODE), the step to reproduce is quite simple:

1, hit "." after the "obj", which shows the suggestion list.
2, hit "shift + m"
3, the expected behavior is the "Method.." item will be selected, but in my C::B build against wx3.1, the auto completion window is canceled.

Note that if in the step 2, I hit the "a", then the "a..." item is selected, and the auto completion window is still active.
Note that if in the step 2, I only hit the "shift" key, the auto completion window is still active.

Really strange, it looks like wx3.1 emit some extra event which cancel the active auto completion window when I hit "shift + key". Any one can reproduce?

I found more annoying issue, sometimes, when I hit the "." key, the suggestion list won't happens, because a void CCManager::OnAutocompleteHide(wxShowEvent& event) event always happens after the hit, thus a user can't see the suggestion list.

@Alhpa, can you explain some logic about this piece of the code(how the suggestion list is shown, and how a non-focus window is shown, and how the doxygen html window is shown, in my test case, I don't have any doxygen style comments in the code), it is a bit hard to understand, thanks.

EDIT
Code
void CCManager::OnAutocompleteSelect(wxListEvent& event)
{
    event.Skip();
    m_AutocompSelectTimer.Start(AUTOCOMP_SELECT_DELAY, wxTIMER_ONE_SHOT);
    wxObject* evtObj = event.GetEventObject();
    if (!evtObj)
        return;
#ifdef __WXMSW__
    m_pAutocompPopup = static_cast<wxListView*>(evtObj);
#endif // __WXMSW__

    wxWindow* evtWin = static_cast<wxWindow*>(evtObj)->GetParent();
    if (!evtWin)
        return;
...
Why we have a special m_pAutocompPopup variable for Windows platform?
What is the window hireachy about those variables?(m_pAutocompPopup, m_pPopup, m_pHtml, and the native CClist)
« Last Edit: August 26, 2017, 10:15:50 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #11 on: August 26, 2017, 03:36:58 pm »
Under Windows, scroll events are always directed to the window in focus, making it difficult to scroll the autocomplete list and the doxygen popup with the mouse.  So, under Windows we catch scroll requests to the cbStyledTextCtrl, and run them through CCManager::OnPopupScroll().  This filters the event, and if the mouse is over the autocomplete list or the doxygen popup, the scroll event is instead sent there (and skipped for the editor window).

m_pAutocompPopup is a handle to the autocomplete list window created by (wx)scintilla, needed under Windows to determine its dimensions (so the scroll event can be sent to it, if relevant).
m_pPopup is the window for the doxygen popup, with properties so it is always on top, but cannot be focused.
m_pHtml is the rendered doxygen documentation to display in the popup.
By native CCList, I assume you are referring to m_AutocompTokens?  It is the data CCManager uses to populate the (wx)scintilla autocomplete list window.

(Also, self plug.  I cross linked our generated documentation, so wxWidgets classes link to their documentation.)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #12 on: August 26, 2017, 04:55:41 pm »
Under Windows, scroll events are always directed to the window in focus, making it difficult to scroll the autocomplete list and the doxygen popup with the mouse.  So, under Windows we catch scroll requests to the cbStyledTextCtrl, and run them through CCManager::OnPopupScroll().  This filters the event, and if the mouse is over the autocomplete list or the doxygen popup, the scroll event is instead sent there (and skipped for the editor window).

m_pAutocompPopup is a handle to the autocomplete list window created by (wx)scintilla, needed under Windows to determine its dimensions (so the scroll event can be sent to it, if relevant).
m_pPopup is the window for the doxygen popup, with properties so it is always on top, but cannot be focused.
m_pHtml is the rendered doxygen documentation to display in the popup.
By native CCList, I assume you are referring to m_AutocompTokens?  It is the data CCManager uses to populate the (wx)scintilla autocomplete list window.

(Also, self plug.  I cross linked our generated documentation, so wxWidgets classes link to their documentation.)

Thanks for the explanation.

Well, I debugged for several hours, and I still can't find where does the "wxEVT_SHOW" event comes, this event happens just after we set the event handler for this event.

Code
void CCManager::OnAutocompleteSelect(wxListEvent& event)
{
    event.Skip();
    m_AutocompSelectTimer.Start(AUTOCOMP_SELECT_DELAY, wxTIMER_ONE_SHOT);
    wxObject* evtObj = event.GetEventObject();
    if (!evtObj)
        return;
#ifdef __WXMSW__
    m_pAutocompPopup = static_cast<wxListView*>(evtObj);
#endif // __WXMSW__

    wxWindow* evtWin = static_cast<wxWindow*>(evtObj)->GetParent();
    if (!evtWin)
        return;

    m_DocPos = m_pPopup->GetParent()->ScreenToClient(evtWin->GetScreenPosition());
    m_DocPos.x += evtWin->GetSize().x;
    cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
    wxRect edRect = ed->GetRect();
    if (!m_pPopup->IsShown())
    {
        cbStyledTextCtrl* stc = ed->GetControl();
        int acMaxHeight = stc->AutoCompGetMaxHeight() + 1;
        int textHeight = stc->TextHeight(stc->GetCurrentLine());
        m_DocSize.x = edRect.width * 5 / 12;
        m_DocSize.y = acMaxHeight * textHeight;
        evtWin->Connect(wxEVT_SHOW, wxShowEventHandler(CCManager::OnAutocompleteHide), nullptr, this);
        Manager::Get()->GetLogManager()->DebugLog(F(_T("CCManager::OnAutocompleteSelect connet wxEVT_SHOW event")));
        const int idx = wxDisplay::GetFromWindow(evtWin);
        m_WindowBound = m_DocPos.x + m_DocSize.x;
        if (idx != wxNOT_FOUND)
        {
            const wxPoint& corner = m_pPopup->GetParent()->ScreenToClient(wxDisplay(idx).GetGeometry().GetBottomRight());
            m_DocSize.y = std::max(9 * textHeight,      std::min(m_DocSize.y, corner.y - m_DocPos.y - 2));
            m_DocSize.x = std::max(m_DocSize.y * 2 / 3, std::min(m_DocSize.x, corner.x - m_DocPos.x - 2));
            m_WindowBound = std::min(corner.x - 2, m_WindowBound);
        }
    }
    if ((m_DocPos.x + m_DocSize.x) > m_WindowBound)
        m_DocPos.x -= evtWin->GetSize().x + m_DocSize.x; // show to the left instead
    else
        m_DocSize.x = std::min(m_WindowBound - m_DocPos.x, edRect.width * 5 / 12);
}
The connection is here
Code
evtWin->Connect(wxEVT_SHOW, wxShowEventHandler(CCManager::OnAutocompleteHide), nullptr, this);
But after that, I see wxEVT_SHOW happens, then CCManager::OnAutocompleteHide just cancel the suggestion list.

Code
// Note: according to documentation, this event is only available under wxMSW, wxGTK, and wxOS2
void CCManager::OnAutocompleteHide(wxShowEvent& event)
{
    event.Skip();
    Manager::Get()->GetLogManager()->DebugLog(F(_T("OnAutocompleteHide show=%d"), event.IsShown()==true? 1:0));
    DoHidePopup();
    wxObject* evtObj = event.GetEventObject();
    if (evtObj)
    {
        static_cast<wxWindow*>(evtObj)->Disconnect(wxEVT_SHOW, wxShowEventHandler(CCManager::OnAutocompleteHide), nullptr, this);
        Manager::Get()->GetLogManager()->DebugLog(F(_T("disconnet wxEVT_SHOW event")));
    }

    if (m_CallTipActive != wxSCI_INVALID_POSITION && !m_AutoLaunchTimer.IsRunning())
        m_CallTipTimer.Start(CALLTIP_REFRESH_DELAY, wxTIMER_ONE_SHOT);
}

I have added some "DebugLog" to see what happens, but still don't know why wxEVT_SHOW comes when I just hit the "." after the "obj" in my test code.
Any hints?


If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #13 on: August 27, 2017, 09:43:27 am »
Code
CCManager::OnCompleteCode(): enter
CCManager::OnCompleteCode(): before calling stc->AutoCompShow()
CCManager::OnAutocompleteSelect(): connet wxEVT_SHOW event
CCManager::OnCompleteCode(): after calling stc->AutoCompShow()
CCManager::OnCompleteCode(): before calling stc->AutoCompSelect()
CCManager::OnAutocompleteHide(): wxShowEvent event received, IsShown=0
CCManager::OnAutocompleteSelect(): disconnet wxEVT_SHOW event handler
CCManager::OnCompleteCode(): after calling stc->AutoCompSelect()
CCManager::OnCompleteCode(): exit
I see some logs, it looks like the wxShowEvent happens inside the CCManager::OnCompleteCode() call, especially in the  stc->AutoCompSelect().

The bug can be reproduced by just press the menu item "Complete Code" after the "obj.".
« Last Edit: August 27, 2017, 11:28:12 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #14 on: August 27, 2017, 11:38:24 am »
Further debugged for a while, I found that:
Code
[debug]#0  AutoComplete::Cancel (this=0xac43850) at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:209
[debug]D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:209:5196:beg:0x1f20c37
[debug]>>>>>>cb_gdb:

At D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:209

[debug]> bt 30
[debug]#0  AutoComplete::Cancel (this=0xac43850) at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:209
[debug]#1  0x01f21018 in AutoComplete::Select (this=0xac43850, word=0xa835d30 "aaa1: int") at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:279
[debug]#2  0x01f19b7e in ScintillaBase::WndProc (this=0xac42ad8, iMessage=2108, wParam=0, lParam=176381232) at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\scintilla\src\ScintillaBase.cxx:806
[debug]#3  0x01e4e6aa in ScintillaWX::WndProc (this=0xac42ad8, iMessage=2108, wParam=0, lParam=176381232) at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\ScintillaWX.cpp:948
[debug]#4  0x01e37c31 in wxScintilla::SendMsg (this=0xac48380, msg=2108, wp=0, lp=176381232) at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\wxscintilla.cpp:280
[debug]#5  0x01e3a209 in wxScintilla::AutoCompSelect (this=0xac48380, text=L"aaa1: int") at D:\code\cb\cb_sf_git\trunk\src\sdk\wxscintilla\src\wxscintilla.cpp:1300
[debug]#6  0x01d5849c in CCManager::OnCompleteCode (this=0xabfb110, event=...) at D:\code\cb\cb_sf_git\trunk\src\sdk\ccmanager.cpp:582
[debug]#7  0x01f766c3 in cbEventFunctor<CCManager, CodeBlocksEvent>::Call (this=0xa76a440, event=...) at D:\code\cb\cb_sf_git\trunk\src\include\cbfunctor.h:49
[debug]#8  0x01dd15bd in Manager::ProcessEvent (this=0x57c0348, event=...) at D:\code\cb\cb_sf_git\trunk\src\sdk\manager.cpp:264
[debug]#9  0x004613fa in MainFrame::OnEditCompleteCode (this=0x76301a8, event=...) at D:\code\cb\cb_sf_git\trunk\src\src\main.cpp:3684
[debug]#10 0x68702eb2 in wxAppConsoleBase::HandleEvent(wxEvtHandler*, void (wxEvtHandler::*)(wxEvent&), wxEvent&) const () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#11 0x68703217 in wxAppConsoleBase::CallEventHandler(wxEvtHandler*, wxEventFunctor&, wxEvent&) const () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#12 0x6885bc80 in wxEvtHandler::ProcessEventIfMatchesId(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#13 0x6885bd6a in wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#14 0x6885c549 in wxEvtHandler::TryHereOnly(wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#15 0x6885bf0c in wxEvtHandler::DoTryChain(wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#16 0x6885c615 in wxEvtHandler::ProcessEvent(wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#17 0x68b24c8a in wxWindowBase::TryAfter(wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#18 0x6885dff2 in wxEvtHandler::SafelyProcessEvent(wxEvent&) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#19 0x68acb860 in wxMenuBase::DoProcessEvent(wxMenuBase*, wxEvent&, wxWindow*) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#20 0x68acb980 in wxMenuBase::SendEvent(int, int) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#21 0x68a72907 in wxFrameBase::ProcessCommand(wxMenuItem*) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#22 0x6898ceea in wxFrame::HandleCommand(unsigned short, unsigned short, HWND__*) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#23 0x6898e275 in wxFrame::MSWWindowProc(unsigned int, unsigned int, long) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#24 0x6893c8b3 in wxWndProc(HWND__*, unsigned int, unsigned int, long)@16 () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#25 0x765a62fa in gapfnScSendMessage () from C:\windows\syswow64\user32.dll
[debug]#26 0x00030570 in ?? ()
[debug]#27 0x765a6d3a in USER32!GetThreadDesktop () from C:\windows\syswow64\user32.dll
[debug]#28 0x6893c840 in wxWindow::SubclassWin(HWND__*) () from D:\code\wxWidgets-3.1.0\lib\gcc_dll\wxmsw310u_gcc_cb.dll
[debug]#29 0x765a77c4 in USER32!CharPrevW () from C:\windows\syswow64\user32.dll
[debug](More stack frames follow...)
[debug]>>>>>>cb_gdb:


Here, inside the function
Code
void AutoComplete::Select(const char *word) {
size_t lenWord = strlen(word);
int location = -1;
int start = 0; // lower bound of the api array block to search
int end = lb->Length() - 1; // upper bound of the api array block to search
while ((start <= end) && (location == -1)) { // Binary searching loop
int pivot = (start + end) / 2;
char item[maxItemLen];
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
int cond;
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
if (!cond) {
// Find first match
while (pivot > start) {
lb->GetValue(sortMatrix[pivot-1], item, maxItemLen);
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
if (0 != cond)
break;
--pivot;
}
location = pivot;
if (ignoreCase
&& ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) {
// Check for exact-case match
for (; pivot <= end; pivot++) {
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
if (!strncmp(word, item, lenWord)) {
location = pivot;
break;
}
if (CompareNCaseInsensitive(word, item, lenWord))
break;
}
}
} else if (cond < 0) {
end = pivot - 1;
} else if (cond > 0) {
start = pivot + 1;
}
}
if (location == -1) {
if (autoHide)
Cancel();
else
lb->Select(-1);
} else {
if (autoSort == SC_ORDER_CUSTOM) {
// Check for a logically earlier match
char item[maxItemLen];
for (int i = location + 1; i <= end; ++i) {
lb->GetValue(sortMatrix[i], item, maxItemLen);
if (CompareNCaseInsensitive(word, item, lenWord))
break;
if (sortMatrix[i] < sortMatrix[location] && !strncmp(word, item, lenWord))
location = i;
}
}
lb->Select(sortMatrix[location]);
}
}

Here, it goes to the "Cancel();“ call.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #15 on: August 31, 2017, 07:30:02 am »
It looks like there are some item sort issue.

I see the CC gives the suggestion list as:
Code
"
aaa(): int\n13\r
Bbb(): int\n13\r
Gethod6(): void\n13\r
Kethod1(): void\n13\r
Kethod2(): void\n13\r
Method3(): void\n13\r
method4(): void\n13\r
method5(): void\n13
"
Look, it is case insensitive, but I see in the function void AutoComplete::Select(const char *word), it use this
Code
				if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
cond = strncmp(word, item, lenWord);
The strncmp is used, so it cause errors, in this case, CompareNCaseInsensitive should be used.

In CC, we have a sorter:
Code
    bool isPureAlphabetical = true;
    TokenSorter sortFunctor(isPureAlphabetical);
    std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
But it looks like TokenSorter is always case insensitive.
Code
// priority, then alphabetical
struct TokenSorter
{
    bool& m_PureAlphabetical;

    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
    {
        m_PureAlphabetical = true;
    }

    bool operator()(const cbCodeCompletionPlugin::CCToken& a, const cbCodeCompletionPlugin::CCToken& b)
    {
        int diff = a.weight - b.weight;
        if (diff == 0)
        {
            // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
            diff = a.displayName.Upper().Cmp(b.displayName.Upper());
            if (diff == 0)
                diff = a.displayName.Cmp(b.displayName);
        }
        else
            m_PureAlphabetical = false;
        return diff < 0;
    }
};
So, we should set "case insensitive" in our CC option, otherwise, this bug happens.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #16 on: September 03, 2017, 12:05:39 am »
This bug also happens in wx 2.8.12 based CodeBlocks. The method to solve this is to sort the item list depending on the "case sensitive" option of the Editor dialog.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #17 on: September 03, 2017, 01:00:00 am »
Here are patches to fix this issue:
Code
@@ -461,26 +461,31 @@ bool CCManager::ProcessArrow(int key)
 }
 
 // priority, then alphabetical
 struct TokenSorter
 {
-    bool& m_PureAlphabetical;
+    bool& m_PureAlphabetical;  // modify the passed argument(set to false) if weight are different
+    bool m_CaseSensitive;
 
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
     {
         m_PureAlphabetical = true;
     }
 
     bool operator()(const cbCodeCompletionPlugin::CCToken& a, const cbCodeCompletionPlugin::CCToken& b)
     {
         int diff = a.weight - b.weight;
         if (diff == 0)
         {
-            // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
-            diff = a.displayName.Upper().Cmp(b.displayName.Upper());
-            if (diff == 0)
+            if (m_CaseSensitive)
                 diff = a.displayName.Cmp(b.displayName);
+            else
+            {   // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
+                diff = a.displayName.Upper().Cmp(b.displayName.Upper());
+                if (diff == 0)
+                    diff = a.displayName.Cmp(b.displayName);
+            }
         }
         else
             m_PureAlphabetical = false;
         return diff < 0;
     }
@@ -537,11 +542,12 @@ void CCManager::OnCompleteCode(CodeBlocksEvent& event)
 
         return;
     }
 
     bool isPureAlphabetical = true;
-    TokenSorter sortFunctor(isPureAlphabetical);
+    bool isCaseSensitive = cfg->ReadBool(wxT("/case_sensitive"), false);
+    TokenSorter sortFunctor(isPureAlphabetical, isCaseSensitive);
     std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
     if (isPureAlphabetical)
         stc->AutoCompSetOrder(wxSCI_ORDER_PRESORTED);
     else
         stc->AutoCompSetOrder(wxSCI_ORDER_CUSTOM);
@@ -559,11 +565,11 @@ void CCManager::OnCompleteCode(CodeBlocksEvent& event)
     items.RemoveLast();
 
     if (!stc->CallTipActive() && !stc->AutoCompActive())
         m_CallTipActive = wxSCI_INVALID_POSITION;
 
-    stc->AutoCompSetIgnoreCase(!cfg->ReadBool(wxT("/case_sensitive"), false));
+    stc->AutoCompSetIgnoreCase(!isCaseSensitive);
     stc->AutoCompSetMaxHeight(14);
     stc->AutoCompSetTypeSeparator(wxT('\n'));
     stc->AutoCompSetSeparator(wxT('\r'));
     Manager::Get()->GetLogManager()->DebugLog(F(_T("CCManager::OnCompleteCode(): before calling stc->AutoCompShow()")));
     stc->AutoCompShow(tknEnd - tknStart, items);


This obeys the "case_sensitive" option setting by the user.

One question: why the m_PureAlphabetical = false, when weights are different? I think is if this is false, we can't call the Select function later, as it is not purely sorted by alphabetical.

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #18 on: September 03, 2017, 06:24:50 pm »
Code
    bool isPureAlphabetical = true;
    TokenSorter sortFunctor(isPureAlphabetical);
    std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
    if (isPureAlphabetical)
        stc->AutoCompSetOrder(wxSCI_ORDER_PRESORTED);
    else
        stc->AutoCompSetOrder(wxSCI_ORDER_CUSTOM);
wxSCI_ORDER_CUSTOM tells scintilla to do some extra processing and maintain a search index internally so that we can supply an arbitrary order.  I suppose the cost for this extra sort is not very large compared to initially computing what tokens to even suggest, so maybe it makes sense to simplify and just always specify wxSCI_ORDER_CUSTOM.

Code
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
Probably pass caseSensitive by value.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #19 on: September 04, 2017, 01:30:23 am »
Code
-    TokenSorter(bool& alphabetical) : m_PureAlphabetical(alphabetical)
+    TokenSorter(bool& alphabetical, bool& caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
Probably pass caseSensitive by value.
Thanks, I committed in r11157.

Quote
wxSCI_ORDER_CUSTOM tells scintilla to do some extra processing and maintain a search index internally...
I may need some test later. Thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #20 on: September 05, 2017, 03:59:21 am »
(Also, self plug.  I cross linked our generated documentation, so wxWidgets classes link to their documentation.)
I never noticed this before, just found it now. :)
This is quite a nice feature, how do you achieve this? Thanks.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Alpha

  • Developer
  • Lives here!
  • *****
  • Posts: 1513
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #21 on: September 05, 2017, 07:24:09 pm »
I ran doxygen for wxWidgets with GENERATE_TAGFILE enabled.  Then set TAGFILES = wxTagFile.xml=http://docs.wxwidgets.org/3.0 when building our docs.  The tricky part was that in order to match up, the tag file for wxWidgets needed to be built via the same version of doxygen as the wxWidgets team uses.

If there is interest, I could share the tag file.

Offline yvesdm3000

  • Almost regular
  • **
  • Posts: 225
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #22 on: September 07, 2017, 03:51:36 pm »
Hi,

Has anything changed related to  evt(cbEVT_COMPLETE_CODE) with latest SVN version ? When I use ClangCC and send this event, the CC window opens and closes quickly again. This has always worked correctly in 16.01

Yves
Clang based code completion for Code::Blocks:   http://github.com/yvesdm3000/ClangLib

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6034
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: question on how to trigger evt(cbEVT_COMPLETE_CODE)
« Reply #23 on: September 07, 2017, 04:08:38 pm »
Hi,

Has anything changed related to  evt(cbEVT_COMPLETE_CODE) with latest SVN version ? When I use ClangCC and send this event, the CC window opens and closes quickly again. This has always worked correctly in 16.01

Yves
I have a commit to fix your described issue days before, discussions and analysis are put in this thread,  Strange it breaks something.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.