Debug C::B under C::B using gdb, then set a bp in the function: int CodeCompletion::CodeComplete() (around line 2061 of codecompletion.cpp), then run several steps (or step int some functions like MarkItemsByAI()), then continue running will cause the debugee C::B crash in the line
ed->GetControl()->AutoCompShow(pos - start, final);
I debugged some time, and find that the above line try to pop-up the autocompletion window. But when the debugee C::B stops at a bp which is before call the function AutoCompShow(), there will be a window switch. I mean, the debugee C::B will receive a KillFocus event.
What I see the crash backtrace is:
[debug]#0 0x61a08afa in wxSCIListBoxWin::GetLB (this=0x0) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\PlatWX.cpp:1043
[debug]#1 0x619eb809 in GETLB (win=0x0) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\PlatWX.cpp:1218
[debug]#2 0x618e2f70 in ListBoxImpl::Length (this=0x3dbf1d8) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\PlatWX.cpp:1414
[debug]#3 0x6198e9e8 in AutoComplete::Select (this=0x1c20fb0, word=0x3ea8d84 "ac") at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\scintilla\src\AutoComplete.cxx:148
[debug]#4 0x61978e76 in ScintillaBase::AutoCompleteMoveToCurrentWord (this=0x1c205c0) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\scintilla\src\ScintillaBase.cxx:300
[debug]#5 0x61978d14 in ScintillaBase::AutoCompleteStart (this=0x1c205c0, lenEntered=2, list=0x3ddd290 "accB?1\naccess(): int __cdecl?13\naccumulate?40\nacos(): double __cdecl?13\nacosf(): float __cdecl?13\nacosh(): double __cdecl?13\nacoshf(): float __cdecl?13\nacoshl(): long double __cdecl?13\nacosl(): long d"...) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\scintilla\src\ScintillaBase.cxx:277
[debug]#6 0x6197a491 in ScintillaBase::WndProc (this=0x1c205c0, iMessage=2100, wParam=2, lParam=64869008) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\scintilla\src\ScintillaBase.cxx:666
[debug]#7 0x618def3f in ScintillaWX::WndProc (this=0x1c205c0, iMessage=2100, wParam=2, lParam=64869008) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\ScintillaWX.cpp:883
[debug]#8 0x618d02b9 in wxScintilla::SendMsg (this=0x3d9ef40, msg=2100, wp=2, lp=64869008) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\wxscintilla.cpp:270
[debug]#9 0x618d21e3 in wxScintilla::AutoCompShow (this=0x3d9ef40, lenEntered=2, itemList="accB?1\naccess(): int __cdecl?13\naccumulate?40\nacos(): double __cdecl?13\nacosf(): float __cdecl?13\nacosh(): double __cdecl?13\nacoshf(): float __cdecl?13\nacoshl(): long double __cdecl?13\nacosl(): long d"...) at E:\code\cb\cleantrunk\src\sdk\wxscintilla\src\wxscintilla.cpp:1203
[debug]#10 0x65e8d7a7 in CodeCompletion::CodeComplete (this=0x39c6180) at E:\code\cb\cleantrunk\src\plugins\codecompletion\codecompletion.cpp:2240
[debug]#11 0x65e976b3 in CodeCompletion::DoCodeComplete (this=0x39c6180) at E:\code\cb\cleantrunk\src\plugins\codecompletion\codecompletion.cpp:4127
[debug]#12 0x65e910d5 in CodeCompletion::EditorEventHook (this=0x39c6180, editor=0x3c8f0a8, event=...) at E:\code\cb\cleantrunk\src\plugins\codecompletion\codecompletion.cpp:2947
[debug]#13 0x65f29c7d in EditorHooks::HookFunctor<CodeCompletion>::Call (this=0x3bf1540, editor=0x3c8f0a8, event=...) at E:\code\cb\cleantrunk\src\include\editor_hooks.h:49
[debug]#14 0x6189a021 in EditorHooks::CallHooks (editor=0x3c8f0a8, event=...) at E:\code\cb\cleantrunk\src\sdk\editor_hooks.cpp:69
[debug]#15 0x6183b03d in cbEditor::OnScintillaEvent (this=0x3c8f0a8, event=...) at E:\code\cb\cleantrunk\src\sdk\cbeditor.cpp:3280
[debug]#16 0x6183a335 in cbEditor::OnEditorCharAdded (this=0x3c8f0a8, event=...) at E:\code\cb\cleantrunk\src\sdk\cbeditor.cpp:3037
[debug]#17 0x00e7ff27 in wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from E:\code\cb\cleantrunk\src\devel\wxmsw28u_gcc_custom.dll
It crash at the function:
inline wxSCIListBoxWin* GETLBW(WindowID win) {
return ((wxSCIListBoxWin*)win);
}
inline wxListView* GETLB(WindowID win) {
return GETLBW(win)->GetLB();
}
.....
int ListBoxImpl::Length()
{
return GETLB(wid)->GetItemCount();
}
But the "wid" is currently 0. I found the reason is, when a KillFocus is received, it will finally let the auto-completion canceled. So
void Window::Destroy()
{
if (wid) {
Show(false);
GETWIN(wid)->Destroy();
}
wid = 0;
}
will be called.
The interesting thing is: If you set two bps in the switch statement below(one for each case), you will see firstly it entered a SCI_AUTOCSHOW, and later a SCI_AUTOCCANCEL.
sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
switch (iMessage) {
case SCI_AUTOCSHOW:
listType = 0;
AutoCompleteStart(wParam, reinterpret_cast<const char *>(lParam));
break;
case SCI_AUTOCCANCEL:
ac.Cancel();
break;
My question is: how to solve this issue? Thanks.
(Another question is: how to build C::B which can link to a debug version of wxWidgets library, so that I can see/track the messages more clearly, currently, gdb's bt command always stop at [debug]#17 0x00e7ff27 in wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from E:\code\cb\cleantrunk\src\devel\wxmsw28u_gcc_custom.dll)
@ollydbg:
Can you test this patch? Index: src/sdk/wxscintilla/src/PlatWX.cpp
===================================================================
--- src/sdk/wxscintilla/src/PlatWX.cpp (wersja 8739)
+++ src/sdk/wxscintilla/src/PlatWX.cpp (kopia robocza)
@@ -1286,7 +1286,21 @@
lineHeight = lineHeight_;
unicodeMode = unicodeMode_;
maxStrWidth = 0;
- wid = new wxSCIListBoxWin (GETWIN(parent.GetID()), ctrlID, location_);
+
+/* C::B begin */
+ if(wid == 0)
+ {
+ wid = new wxSCIListBoxWin (GETWIN(parent.GetID()), ctrlID, location_);
+ }
+ else if(GETLBW(wid)->GetParent() != GETWIN(parent.GetID()))
+ {
+ GETLBW(wid)->Reparent(GETWIN(parent.GetID()));
+ }
+ GETLBW(wid)->SetPosition(wxPoint(location_.x,location_.y));
+ GETLBW(wid)->SetId(ctrlID);
+ GETLB(wid)->SetId(ctrlID);
+/* C::B end */
+
if (imgList != NULL)
GETLB(wid)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
/* C::B begin */
Index: src/sdk/wxscintilla/src/scintilla/src/AutoComplete.cxx
===================================================================
--- src/sdk/wxscintilla/src/scintilla/src/AutoComplete.cxx (wersja 8739)
+++ src/sdk/wxscintilla/src/scintilla/src/AutoComplete.cxx (kopia robocza)
@@ -57,9 +57,11 @@
void AutoComplete::Start(Window &parent, int ctrlID,
int position, Point location, int startLen_,
int lineHeight, bool unicodeMode, int technology) {
- if (active) {
- Cancel();
- }
+/* C::B begin */
+// if (active) {
+// Cancel();
+// }
+/* C::B end */
lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology);
lb->Clear();
active = true;
@@ -124,7 +126,10 @@
void AutoComplete::Cancel() {
if (lb->Created()) {
lb->Clear();
- lb->Destroy();
+/* C::B begin */
+ //lb->Destroy();
+ lb->Show(false);
+/* C::B end */
active = false;
}
}
It hides autocomplete window instead of deleting it. It should improve performance. And with this patch applied dynamic filtering (http://forums.codeblocks.org/index.php/topic,16571.0.html) will be possible.
That said, the filtering is currently forced to re-build the box, so there are brief pauses when it disappears, then reappears.
With patch from my previous post autocomplete window is recreated only when its have to be shown in another window (i.e when user opens another file)
will launch the box, and typing auto-launch + 4 more:
That's true, but list will be refreshed only once, my proposition is:
Index: src/plugins/codecompletion/codecompletion.cpp
===================================================================
--- src/plugins/codecompletion/codecompletion.cpp (wersja 8739)
+++ src/plugins/codecompletion/codecompletion.cpp (kopia robocza)
@@ -1619,7 +1807,7 @@
}
// code completion
- else if ( (autoCC && !control->AutoCompActive()) // not already active autocompletion
+ else if ( (autoCC && (((pos - wordStartPos) % m_CCAutoLaunchChars) == 0)) // Refresh box every m_CCAutoLaunchChars letters
|| (prevChar == _T('"')) // #include "
|| (prevChar == _T('<')) // #include <
|| (ch == _T('.'))
@@ -1629,8 +1817,7 @@
|| ( (ch == _T(':')) // ::
&& (prevChar == _T(':')) )
|| ( control->AutoCompActive() // refine listing:
- && ( ch == _T('/') // for #include (reduce directories)
- || (pos - wordStartPos == m_CCAutoLaunchChars + 4)) ) // for more typed characters
+ && ( ch == _T('/') )) // for #include (reduce directories)
)
{
int style = control->GetStyleAt(pos);
This approach refreshes box every 'm_CCAutoLaunchChars' typed characters.
Where in this patch is the window finally being destroyed?
AutoComplete::~AutoComplete() calls Window::Destroy() - window is destroyed there (see code at first post).
Why not:
else if ( (autoCC && (((pos - wordStartPos) >= m_CCAutoLaunchChars))
The autocomplete window in Scintilla is created each time but not destroyed.
Sorry, but I can't argee with that.
Here's how ListBox is created:
void AutoComplete::Start(Window &parent, int ctrlID,
int position, Point location, int startLen_,
int lineHeight, bool unicodeMode, int technology) {
/* C::B begin */
// if (active) {
// Cancel();
// }
/* C::B end */
lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology);
lb->Clear();
"lb->clear" calls ListBoxImpl::Create, here is part of it's implementation:
/* C::B begin */
if (wid == 0)
wid = new wxSCIListBoxWin(GETWIN(parent.GetID()), ctrlID, location_);
else if (GETLBW(wid)->GetParent() != GETWIN(parent.GetID()))
GETLBW(wid)->Reparent(GETWIN(parent.GetID()));
GETLBW(wid)->SetPosition(wxPoint(location_.x,location_.y));
GETLBW(wid)->SetId(ctrlID);
GETLB(wid)->SetId(ctrlID);
/* C::B end */
If window wasn't destroyed it will be reused.
At first I thought "How could I make so horrible mistake", but I look deeper into code and it's not so bad :)
(Another question is: how to build C::B which can link to a debug version of wxWidgets library, so that I can see/track the messages more clearly, currently, gdb's bt command always stop at [debug]#17 0x00e7ff27 in wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () from E:\code\cb\cleantrunk\src\devel\wxmsw28u_gcc_custom.dll)
Build options->Custom variables and probably you should define some wxdebug macros...
Today, I build the C::B which link against wx2.8.12 debug library to hunt a bug in Re: The 22 March 2014 build (9744) is out. (http://forums.codeblocks.org/index.php/topic,19117.msg130969/topicseen.html#msg130969), here is the simple patch
src/CodeBlocks.cbp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/CodeBlocks.cbp b/src/CodeBlocks.cbp
index 07c384f..b456243 100644
--- a/src/CodeBlocks.cbp
+++ b/src/CodeBlocks.cbp
@@ -711,7 +711,7 @@
</Target>
<Environment>
<Variable name="WX_CFG" value="" />
- <Variable name="WX_SUFFIX" value="u" />
+ <Variable name="WX_SUFFIX" value="ud" />
<Variable name="WX_VERSION" value="28" />
</Environment>
</Build>
@@ -735,6 +735,7 @@
<Add option="-DCB_PRECOMP" />
<Add option="-DWX_PRECOMP" />
<Add option="-DwxUSE_UNICODE" />
+ <Add option="-D__WXDEBUG__" />
<Add directory="$(#WX.include)" />
<Add directory="$(#WX.lib)/gcc_dll$(WX_CFG)/msw$(WX_SUFFIX)" />
<Add directory="sdk/wxscintilla/include" />