Code::Blocks  SVN r11506
ccmanager.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11399 $
6  * $Id: ccmanager.cpp 11399 2018-05-08 21:54:03Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/ccmanager.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #include "ccmanager.h"
13 
14 #ifndef CB_PRECOMP
15  #include <algorithm>
16 
17  #include <wx/listctrl.h>
18  #include <wx/menu.h>
19 #if wxUSE_POPUPWIN
20  #include <wx/popupwin.h>
21 #endif
22  #include <wx/timer.h>
23 
24  #include "cbeditor.h"
25  #include "configmanager.h"
26  #include "editormanager.h"
27  #include "logmanager.h" // for F
28 #endif
29 
30 #include <wx/html/htmlwin.h>
31 #include <wx/display.h>
32 
33 #include "cbcolourmanager.h"
34 #include "cbstyledtextctrl.h"
35 #include "editor_hooks.h"
36 
37 namespace CCManagerHelper
38 {
39  // shift points if they are past the insertion/deletion point
40  inline void RipplePts(int& ptA, int& ptB, int len, int delta)
41  {
42  if (ptA > len - delta)
43  ptA += delta;
44  if (ptB > len - delta)
45  ptB += delta;
46  }
47 
48  // wxScintilla::FindColumn seems to be broken; re-implement:
49  // Find the position of a column on a line taking into account tabs and
50  // multi-byte characters. If beyond end of line, return line end position.
51  inline int FindColumn(int line, int column, wxScintilla* stc)
52  {
53  int lnEnd = stc->GetLineEndPosition(line);
54  for (int pos = stc->PositionFromLine(line); pos < lnEnd; ++pos)
55  {
56  if (stc->GetColumn(pos) == column)
57  return pos;
58  }
59  return lnEnd;
60  }
61 
62  // test if an editor position is displayed
63  inline bool IsPosVisible(int pos, wxScintilla* stc)
64  {
65  const int dist = stc->VisibleFromDocLine(stc->LineFromPosition(pos)) - stc->GetFirstVisibleLine();
66  return !(dist < 0 || dist > stc->LinesOnScreen()); // caret is off screen
67  }
68 
69  // return a hash of a calltip context (to avoid storing strings of each calltip)
70  // used in m_CallTipChoiceDict and m_CallTipFuzzyChoiceDict
71  static int CallTipToInt(const wxString& firstTip, int numPages)
72  {
73  int val = 33 * firstTip.Length() ^ numPages;
74  for (wxString::const_iterator itr = firstTip.begin();
75  itr != firstTip.end(); ++itr)
76  {
77  val = 33 * val ^ static_cast<int>(*itr);
78  }
79  return val;
80  }
81 
82  // (shamelessly stolen from mime handler plugin ;) )
83  // build all HTML font sizes (1..7) from the given base size
84  static void BuildFontSizes(int *sizes, int size)
85  {
86  // using a fixed factor (1.2, from CSS2) is a bad idea as explained at
87  // http://www.w3.org/TR/CSS21/fonts.html#font-size-props but this is by far
88  // simplest thing to do so still do it like this for now
89  sizes[0] = int(size * 0.75); // exception to 1.2 rule, otherwise too small
90  sizes[1] = int(size * 0.83);
91  sizes[2] = size;
92  sizes[3] = int(size * 1.2);
93  sizes[4] = int(size * 1.44);
94  sizes[5] = int(size * 1.73);
95  sizes[6] = int(size * 2);
96  }
97 
98  // (shamelessly stolen from mime handler plugin ;) )
100  {
101  // base the default font size on the size of the default system font but
102  // also ensure that we have a font of reasonable size, otherwise small HTML
103  // fonts are unreadable
104  int size = wxNORMAL_FONT->GetPointSize();
105  if ( size < 9 )
106  size = 9;
107  return size;
108  }
109 }
110 
111 template<> CCManager* Mgr<CCManager>::instance = nullptr;
112 template<> bool Mgr<CCManager>::isShutdown = false;
113 
114 const int idCallTipTimer = wxNewId();
115 const int idAutoLaunchTimer = wxNewId();
116 const int idAutocompSelectTimer = wxNewId();
117 const int idShowTooltip = wxNewId();
118 const int idCallTipNext = wxNewId();
120 
121 DEFINE_EVENT_TYPE(cbEVT_DEFERRED_CALLTIP_SHOW)
122 DEFINE_EVENT_TYPE(cbEVT_DEFERRED_CALLTIP_CANCEL)
123 
124 // milliseconds
125 #define CALLTIP_REFRESH_DELAY 90
126 #define AUTOCOMP_SELECT_DELAY 35
127 #define SCROLL_REFRESH_DELAY 500
128 
131 {
136 };
137 
146 #define FROM_TIMER 1
147 
149 {
152 };
153 
154 
155 //{ Unfocusable popup
156 
157 // imported with small changes from PlatWX.cpp
159 #if wxUSE_POPUPWIN
160  public wxPopupWindow
161 #else
162  public wxFrame
163 #endif // wxUSE_POPUPWIN
164 {
165 public:
166 #if wxUSE_POPUPWIN
168 
169  UnfocusablePopupWindow(wxWindow* parent, int style = wxBORDER_NONE) :
170  wxPopupWindow(parent, style)
171 #else
172  typedef wxFrame BaseClass;
173 
174  UnfocusablePopupWindow(wxWindow* parent, int style = 0) :
177 #ifdef __WXMAC__
179 #endif // __WXMAC__
180  )
181 #endif // wxUSE_POPUPWIN
182  {
183  Hide();
184  }
185 
186  bool Destroy() override;
187  void OnFocus(wxFocusEvent& event);
188  void ActivateParent();
189 
190  void DoSetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO) override;
191  bool Show(bool show = true) override;
192 
193 private:
194  DECLARE_EVENT_TABLE()
195 };
196 
197 // On OSX and (possibly others) there can still be pending
198 // messages/events for the list control when Scintilla wants to
199 // close it, so do a pending delete of it instead of destroying
200 // immediately.
202 {
203 #ifdef __WXMAC__
204  // The bottom edge of this window is not getting properly
205  // refreshed upon deletion, so help it out...
206  wxWindow* p = GetParent();
207  wxRect r(GetPosition(), GetSize());
208  r.SetHeight(r.GetHeight()+1);
209  p->Refresh(false, &r);
210 #endif
211  if ( !wxPendingDelete.Member(this) )
212  wxPendingDelete.Append(this);
213  return true;
214 }
215 
217 {
218  ActivateParent();
219  GetParent()->SetFocus();
220  event.Skip();
221 }
222 
224 {
225  // Although we're a frame, we always want the parent to be active, so
226  // raise it whenever we get shown, focused, etc.
228  wxGetTopLevelParent(GetParent()), wxTopLevelWindow);
229  if (frame)
230  frame->Raise();
231 }
232 
234  int width, int height,
235  int sizeFlags)
236 {
237  // convert coords to screen coords since we're a top-level window
238  if (x != wxDefaultCoord)
239  GetParent()->ClientToScreen(&x, NULL);
240 
241  if (y != wxDefaultCoord)
242  GetParent()->ClientToScreen(NULL, &y);
243 
244  BaseClass::DoSetSize(x, y, width, height, sizeFlags);
245 }
246 
248 {
249  bool rv = BaseClass::Show(show);
250  if (rv && show)
251  ActivateParent();
252 #ifdef __WXMAC__
253  GetParent()->Refresh(false);
254 #endif
255  return rv;
256 }
257 
259  EVT_SET_FOCUS(UnfocusablePopupWindow::OnFocus)
260 END_EVENT_TABLE()
261 
262 //} end Unfocusable popup
263 
264 
265 // class constructor
267  m_AutocompPosition(wxSCI_INVALID_POSITION),
268  m_CallTipActive(wxSCI_INVALID_POSITION),
269  m_LastAutocompIndex(wxNOT_FOUND),
270  m_LastTipPos(wxSCI_INVALID_POSITION),
271  m_WindowBound(0),
272  m_OwnsAutocomp(true),
273  m_CallTipTimer(this, idCallTipTimer),
274  m_AutoLaunchTimer(this, idAutoLaunchTimer),
275  m_AutocompSelectTimer(this, idAutocompSelectTimer),
276 #ifdef __WXMSW__
277  m_pAutocompPopup(nullptr),
278 #endif // __WXMSW__
279  m_pLastEditor(nullptr),
280  m_pLastCCPlugin(nullptr)
281 {
282  const wxString ctChars = wxT(",;\n()"); // default set
283  m_CallTipChars[nullptr] = std::set<wxChar>(ctChars.begin(), ctChars.end());
284  const wxString alChars = wxT(".:<>\"#/"); // default set
285  m_AutoLaunchChars[nullptr] = std::set<wxChar>(alChars.begin(), alChars.end());
286  m_LastACLaunchState[lsCaretStart] = wxSCI_INVALID_POSITION;
287 
288  // init documentation popup
289  m_pPopup = new UnfocusablePopupWindow(Manager::Get()->GetAppFrame());
290  m_pHtml = new wxHtmlWindow(m_pPopup, wxID_ANY, wxDefaultPosition,
292  int sizes[7] = {};
294  m_pHtml->SetFonts(wxEmptyString, wxEmptyString, &sizes[0]);
295  m_pHtml->Connect(wxEVT_COMMAND_HTML_LINK_CLICKED,
296  wxHtmlLinkEventHandler(CCManager::OnHtmlLink), nullptr, this);
297 
298  // register colours
300  cmgr->RegisterColour(_("Code completion"), _("Tooltip/Calltip background"), wxT("cc_tips_back"), *wxWHITE);
301  cmgr->RegisterColour(_("Code completion"), _("Tooltip/Calltip foreground"), wxT("cc_tips_fore"), wxColour(wxT("DIM GREY")));
302  cmgr->RegisterColour(_("Code completion"), _("Tooltip/Calltip highlight"), wxT("cc_tips_highlight"), wxColour(wxT("BLUE")));
303 
304  // connect menus
305  wxFrame* mainFrame = Manager::Get()->GetAppFrame();
306  wxMenuBar* menuBar = mainFrame->GetMenuBar();
307  if (menuBar)
308  {
309  int idx = menuBar->FindMenu(wxT("&Edit"));
310  wxMenu* edMenu = menuBar->GetMenu(idx < 0 ? 0 : idx);
311  const wxMenuItemList& itemsList = edMenu->GetMenuItems();
312  size_t insertPos = itemsList.GetCount();
313  for (size_t i = 0; i < insertPos; ++i)
314  {
315  if (itemsList[i]->GetItemLabel() == _("Complete code"))
316  {
317  insertPos = i + 1;
318  break;
319  }
320  }
321  // insert after Edit->Complete code
322  edMenu->Insert(insertPos, idShowTooltip, _("Show tooltip\tShift-Alt-Space"));
323  edMenu->Insert(insertPos + 1, idCallTipNext, _("Next call tip\tCtrl-N"));
324  edMenu->Insert(insertPos + 2, idCallTipPrevious, _("Previous call tip\tCtrl-P"));
325  }
326  mainFrame->Connect(idShowTooltip, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
327  mainFrame->Connect(idCallTipNext, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
328  mainFrame->Connect(idCallTipPrevious, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
329 
330  // connect events
340  Connect(idCallTipTimer, wxEVT_TIMER, wxTimerEventHandler(CCManager::OnTimer));
341  Connect(idAutoLaunchTimer, wxEVT_TIMER, wxTimerEventHandler(CCManager::OnTimer));
342  Connect(idAutocompSelectTimer, wxEVT_TIMER, wxTimerEventHandler(CCManager::OnTimer));
343  Connect(cbEVT_DEFERRED_CALLTIP_SHOW, wxCommandEventHandler(CCManager::OnDeferredCallTipShow));
344  Connect(cbEVT_DEFERRED_CALLTIP_CANCEL, wxCommandEventHandler(CCManager::OnDeferredCallTipCancel));
345 }
346 
347 // class destructor
349 {
350  m_pHtml->Disconnect(wxEVT_COMMAND_HTML_LINK_CLICKED,
351  wxHtmlLinkEventHandler(CCManager::OnHtmlLink), nullptr, this);
352  m_pHtml->Destroy();
353  m_pPopup->Destroy();
354  wxFrame* mainFrame = Manager::Get()->GetAppFrame();
355  mainFrame->Disconnect(idShowTooltip, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
356  mainFrame->Disconnect(idCallTipNext, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
357  mainFrame->Disconnect(idCallTipPrevious, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CCManager::OnMenuSelect), nullptr, this);
359  EditorHooks::UnregisterHook(m_EditorHookID, true);
360  Disconnect(idCallTipTimer);
361  Disconnect(idAutoLaunchTimer);
362  Disconnect(idAutocompSelectTimer);
363  Disconnect(cbEVT_DEFERRED_CALLTIP_SHOW);
364  Disconnect(cbEVT_DEFERRED_CALLTIP_CANCEL);
365 }
366 
368 {
369  if (!ed)
371  if (ed == m_pLastEditor)
372  return m_pLastCCPlugin; // use cached
373 
374  m_pLastEditor = ed;
375  m_pLastCCPlugin = nullptr;
376  m_LastACLaunchState[lsCaretStart] = wxSCI_INVALID_POSITION;
377  const PluginsArray& pa = Manager::Get()->GetPluginManager()->GetCodeCompletionOffers();
378  for (size_t i = 0; i < pa.GetCount(); ++i)
379  {
380  cbCodeCompletionPlugin::CCProviderStatus status = static_cast<cbCodeCompletionPlugin*>(pa[i])->GetProviderStatusFor(ed);
382  {
383  m_pLastCCPlugin = static_cast<cbCodeCompletionPlugin*>(pa[i]);
384  break;
385  }
386  else if (status == cbCodeCompletionPlugin::ccpsUniversal)
387  m_pLastCCPlugin = static_cast<cbCodeCompletionPlugin*>(pa[i]);
388  }
389  return m_pLastCCPlugin;
390 }
391 
393 {
394  if (registrant)
395  m_CallTipChars[registrant] = std::set<wxChar>(chars.begin(), chars.end());
396 }
397 
399 {
400  if (registrant)
401  m_AutoLaunchChars[registrant] = std::set<wxChar>(chars.begin(), chars.end());
402 }
403 
405 {
407  if (ed)
408  DoShowDocumentation(ed);
409 }
410 
412 {
413  m_pLastEditor = nullptr;
414  m_pLastCCPlugin = nullptr;
415 }
416 
417 void CCManager::InjectAutoCompShow(int lenEntered, const wxString& itemList)
418 {
420  if (ed)
421  {
422  ed->GetControl()->AutoCompShow(lenEntered, itemList);
423  m_OwnsAutocomp = false;
424  m_AutocompTokens.clear();
425  }
426 }
427 
428 // Change the current call tip to be the next or the previous.
429 // Do wrapping if the end is reached in both directions.
431 {
432  if (direction == Next)
433  {
434  ++m_CurCallTip;
435  if (m_CurCallTip == m_CallTips.end())
436  m_CurCallTip = m_CallTips.begin();
437  }
438  else
439  {
440  if (m_CurCallTip == m_CallTips.begin())
441  {
442  if (m_CallTips.size() > 1)
443  m_CurCallTip = m_CallTips.begin() + m_CallTips.size() - 1;
444  }
445  else
446  --m_CurCallTip;
447  }
448 }
449 
451 {
452  bool wasProcessed = false;
454  if (!ed)
455  return wasProcessed;
456  cbStyledTextCtrl* stc = ed->GetControl();
457  if (stc->CallTipActive() && m_CallTipActive != wxSCI_INVALID_POSITION && m_CallTips.size() > 1)
458  {
459  if (key == WXK_DOWN)
460  AdvanceTip(Next);
461  else if (key == WXK_UP)
462  AdvanceTip(Previous);
463  else
464  return wasProcessed;
465 
466  DoUpdateCallTip(ed);
467  wasProcessed = true;
468  }
469  return wasProcessed;
470 }
471 
472 // priority, then alphabetical
474 {
475  bool& m_PureAlphabetical; // modify the passed argument(set to false) if weight are different
477 
478  TokenSorter(bool& alphabetical, bool caseSensitive): m_PureAlphabetical(alphabetical), m_CaseSensitive(caseSensitive)
479  {
480  m_PureAlphabetical = true;
481  }
482 
484  {
485  int diff = a.weight - b.weight;
486  if (diff == 0)
487  {
488  if (m_CaseSensitive)
489  diff = a.displayName.Cmp(b.displayName);
490  else
491  { // cannot use CmpNoCase() because it compares lower case but Scintilla compares upper
492  diff = a.displayName.Upper().Cmp(b.displayName.Upper());
493  if (diff == 0)
494  diff = a.displayName.Cmp(b.displayName);
495  }
496  }
497  else
498  m_PureAlphabetical = false;
499 
500  return diff < 0;
501  }
502 };
503 
504 // cbEVT_COMPLETE_CODE
506 {
507  event.Skip();
508  ConfigManager* cfg = Manager::Get()->GetConfigManager(wxT("ccmanager"));
509  if (!cfg->ReadBool(wxT("/code_completion"), true))
510  return;
511 
513  if (!ed)
514  return;
515  cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
516  if (!ccPlugin)
517  return;
518 
519  cbStyledTextCtrl* stc = ed->GetControl();
520  int tknEnd = stc->GetCurrentPos();
521  if (tknEnd == m_LastACLaunchState[lsCaretStart] && !m_AutocompTokens.empty())
522  {
523  DoBufferedCC(stc);
524  return;
525  }
526  int tknStart = stc->WordStartPosition(tknEnd, true);
527 
528  m_AutocompTokens = ccPlugin->GetAutocompList(event.GetInt() == FROM_TIMER,
529  ed, tknStart, tknEnd);
530  if (m_AutocompTokens.empty())
531  return;
532 
533  if (m_AutocompTokens.size() == 1 && cfg->ReadBool(wxT("/auto_select_single"), false))
534  {
535  // Using stc->AutoCompSetChooseSingle() does not send wxEVT_SCI_AUTOCOMP_SELECTION,
536  // so manually emulate the behaviour.
537 
538  if (!stc->CallTipActive() && !stc->AutoCompActive())
539  m_CallTipActive = wxSCI_INVALID_POSITION;
540 
541  m_OwnsAutocomp = true;
542  m_LastACLaunchState[lsTknStart] = tknStart;
543  m_LastACLaunchState[lsCaretStart] = tknEnd;
544 
545  m_LastAutocompIndex = 0;
546 
547  wxScintillaEvent autoCompFinishEvt(wxEVT_SCI_AUTOCOMP_SELECTION);
548  autoCompFinishEvt.SetText(m_AutocompTokens.front().displayName);
549 
550  OnEditorHook(ed, autoCompFinishEvt);
551 
552  return;
553  }
554 
555  bool isPureAlphabetical = true;
556  bool isCaseSensitive = cfg->ReadBool(wxT("/case_sensitive"), false);
557  TokenSorter sortFunctor(isPureAlphabetical, isCaseSensitive);
558  std::sort(m_AutocompTokens.begin(), m_AutocompTokens.end(), sortFunctor);
559  if (isPureAlphabetical)
561  else
563  wxString items;
564  // experimentally, the average length per token seems to be 23 for the main CC plugin
565  items.Alloc(m_AutocompTokens.size() * 20); // TODO: measure performance
566  for (size_t i = 0; i < m_AutocompTokens.size(); ++i)
567  {
568  items += m_AutocompTokens[i].displayName;
569  if (m_AutocompTokens[i].category == -1)
570  items += wxT("\r");
571  else
572  items += F(wxT("\n%d\r"), m_AutocompTokens[i].category);
573  }
574  items.RemoveLast();
575 
576  if (!stc->CallTipActive() && !stc->AutoCompActive())
577  m_CallTipActive = wxSCI_INVALID_POSITION;
578 
579  stc->AutoCompSetIgnoreCase(!isCaseSensitive);
580  stc->AutoCompSetMaxHeight(14);
581  stc->AutoCompSetTypeSeparator(wxT('\n'));
582  stc->AutoCompSetSeparator(wxT('\r'));
583  stc->AutoCompShow(tknEnd - tknStart, items);
584  m_OwnsAutocomp = true;
585  if (isPureAlphabetical)
586  {
587  const wxString& contextStr = stc->GetTextRange(tknStart, stc->WordEndPosition(tknEnd, true));
588  std::vector<cbCodeCompletionPlugin::CCToken>::const_iterator tknIt
589  = std::lower_bound(m_AutocompTokens.begin(), m_AutocompTokens.end(),
590  cbCodeCompletionPlugin::CCToken(-1, contextStr),
591  sortFunctor);
592  if (tknIt != m_AutocompTokens.end() && tknIt->displayName.StartsWith(contextStr))
593  stc->AutoCompSelect(tknIt->displayName);
594  }
595  m_LastACLaunchState[lsTknStart] = tknStart;
596  m_LastACLaunchState[lsCaretStart] = tknEnd;
597 }
598 
599 // cbEVT_APP_DEACTIVATED
601 {
602  DoHidePopup();
604  if (ed)
605  {
606  cbStyledTextCtrl* stc = ed->GetControl();
607  if (stc->CallTipActive())
608  {
609  // calling 'stc->CallTipCancel()' directly can cause crashes for some users due to:
610  // http://forums.codeblocks.org/index.php/topic,19117.msg130969.html#msg130969
611  wxCommandEvent pendingCancel(cbEVT_DEFERRED_CALLTIP_CANCEL);
612  AddPendingEvent(pendingCancel);
613  }
614  m_CallTipActive = wxSCI_INVALID_POSITION;
615  }
616  event.Skip();
617 }
618 
619 // cbEVT_EDITOR_DEACTIVATED
621 {
622  DoHidePopup();
624  if (ed)
625  {
626  cbStyledTextCtrl* stc = ed->GetControl();
627  if (stc->CallTipActive())
628  stc->CallTipCancel();
629  m_CallTipActive = wxSCI_INVALID_POSITION;
630  }
631  event.Skip();
632 }
633 
634 static void setupColours(cbEditor *editor, ColourManager *manager)
635 {
636  cbStyledTextCtrl* stc = editor->GetControl();
637  stc->CallTipSetBackground(manager->GetColour(wxT("cc_tips_back")));
638  stc->CallTipSetForeground(manager->GetColour(wxT("cc_tips_fore")));
639  stc->CallTipSetForegroundHighlight(manager->GetColour(wxT("cc_tips_highlight")));
640 }
641 
642 // cbEVT_EDITOR_OPEN
644 {
646  if (ed)
647  {
648  cbStyledTextCtrl* stc = ed->GetControl();
649  stc->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED,
650  wxListEventHandler(CCManager::OnAutocompleteSelect), nullptr, this);
651 
652  setupColours(ed, Manager::Get()->GetColourManager());
653  }
654 }
655 
657 {
660 
661  int count = editors->GetEditorsCount();
662  for (int ii = 0; ii < count; ++ii)
663  {
664  cbEditor *editor = editors->GetBuiltinEditor(editors->GetEditor(ii));
665  if (editor)
666  setupColours(editor, cmgr);
667  }
668 }
669 
670 // cbEVT_EDITOR_CLOSE
672 {
673  DoHidePopup();
675  if (ed == m_pLastEditor)
676  m_pLastEditor = nullptr;
677  if (ed && ed->GetControl())
678  {
679  // TODO: is this ever called?
680  ed->GetControl()->Disconnect(wxEVT_COMMAND_LIST_ITEM_SELECTED,
681  wxListEventHandler(CCManager::OnAutocompleteSelect), nullptr, this);
682  }
683 }
684 
685 // cbEVT_EDITOR_TOOLTIP
687 {
688  event.Skip();
689 
690  int tooltipMode = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/tooltip_mode"), 1);
691  if (tooltipMode == tmDisable) // disabled
692  return;
693 
694  // if the event comes from user menu click, then its String field isn't empty
695  // @see CCManager::OnMenuSelect() for details
696  bool fromMouseDwell = event.GetString().IsEmpty();
697  if (wxGetKeyState(WXK_CONTROL) && fromMouseDwell)
698  return;
699  if (tooltipMode == tmKeyboundOnly && fromMouseDwell) // keybound only
700  return;
701 
702  EditorBase* base = event.GetEditor();
703  cbEditor* ed = base && base->IsBuiltinEditor() ? static_cast<cbEditor*>(base) : nullptr;
704  if (!ed || ed->IsContextMenuOpened())
705  return;
706 
707  cbStyledTextCtrl* stc = ed->GetControl();
708  cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
709  int pos = stc->PositionFromPointClose(event.GetX(), event.GetY());
710  if (!ccPlugin || pos < 0 || pos >= stc->GetLength())
711  {
712  if (stc->CallTipActive() && event.GetExtraLong() == 0 && m_CallTipActive == wxSCI_INVALID_POSITION)
713  static_cast<wxScintilla*>(stc)->CallTipCancel();
714  return;
715  }
716 
717  int hlStart, hlEnd, argsPos;
718  hlStart = hlEnd = argsPos = wxSCI_INVALID_POSITION;
719  bool allowCallTip = true;
720  const std::vector<cbCodeCompletionPlugin::CCToken>& tokens = ccPlugin->GetTokenAt(pos, ed, allowCallTip);
721  std::set<wxString> uniqueTips;
722  for (size_t i = 0; i < tokens.size(); ++i)
723  uniqueTips.insert(tokens[i].displayName);
724  wxStringVec tips(uniqueTips.begin(), uniqueTips.end());
725 
726  const int style = event.GetInt();
727  if (!tips.empty())
728  {
729  const int tknStart = stc->WordStartPosition(pos, true);
730  const int tknEnd = stc->WordEndPosition(pos, true);
731  if (tknEnd - tknStart > 2)
732  {
733  for (size_t i = 0; i < tips[0].Length(); ++i)
734  {
735  size_t hlLoc = tips[0].find(stc->GetTextRange(tknStart, tknEnd), i);
736  if (hlLoc == wxString::npos)
737  break;
738  hlStart = hlLoc;
739  hlEnd = hlStart + tknEnd - tknStart;
740  if ( (hlStart > 0 && (tips[0][hlStart - 1] == wxT('_') || wxIsalpha(tips[0][hlStart - 1])))
741  || (hlEnd < static_cast<int>(tips[0].Length()) - 1 && (tips[0][hlEnd] == wxT('_') || wxIsalpha(tips[0][hlEnd]))) )
742  {
743  i = hlEnd;
744  hlStart = hlEnd = wxSCI_INVALID_POSITION;
745  }
746  else
747  break;
748  }
749  }
750  }
751  else if ( allowCallTip
752  && !( stc->IsString(style)
753  || stc->IsComment(style)
754  || stc->IsCharacter(style)
755  || stc->IsPreprocessor(style) ) )
756  {
757  const int line = stc->LineFromPosition(pos);
758  if (pos + 4 > stc->PositionFromLine(line) + (int)ed->GetLineIndentString(line).Length())
759  {
760  const CallTipVec& cTips = ccPlugin->GetCallTips(pos, style, ed, argsPos);
761  for (size_t i = 0; i < cTips.size(); ++i)
762  tips.push_back(cTips[i].tip);
763  if (!tips.empty())
764  {
765  hlStart = cTips[0].hlStart;
766  hlEnd = cTips[0].hlEnd;
767  }
768  }
769  }
770  if (tips.empty())
771  {
772  if (stc->CallTipActive() && event.GetExtraLong() == 0 && m_CallTipActive == wxSCI_INVALID_POSITION)
773  static_cast<wxScintilla*>(stc)->CallTipCancel();
774  }
775  else
776  {
777  DoShowTips(tips, stc, pos, argsPos, hlStart, hlEnd);
778  event.SetExtraLong(1);
779  }
780  m_CallTipActive = wxSCI_INVALID_POSITION;
781 }
782 
784 {
785  wxEventType evtType = event.GetEventType();
786  if (evtType == wxEVT_SCI_CHARADDED)
787  {
788  const wxChar ch = event.GetKey();
789  CCPluginCharMap::const_iterator ctChars = m_CallTipChars.find(GetProviderFor(ed));
790  if (ctChars == m_CallTipChars.end())
791  ctChars = m_CallTipChars.find(nullptr); // default
792 
793  // Are there any characters which could trigger the call tip?
794  if (ctChars->second.find(ch) != ctChars->second.end())
795  {
796  int tooltipMode = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/tooltip_mode"), 1);
797  if ( tooltipMode != 3 // keybound only
798  || m_CallTipActive != wxSCI_INVALID_POSITION )
799  {
800  wxCommandEvent pendingShow(cbEVT_DEFERRED_CALLTIP_SHOW);
801  AddPendingEvent(pendingShow);
802  }
803  }
804  else
805  {
806  cbStyledTextCtrl* stc = ed->GetControl();
807  const int pos = stc->GetCurrentPos();
808  const int wordStartPos = stc->WordStartPosition(pos, true);
809  CCPluginCharMap::const_iterator alChars = m_AutoLaunchChars.find(GetProviderFor(ed));
810  if (alChars == m_AutoLaunchChars.end())
811  alChars = m_AutoLaunchChars.find(nullptr); // default
812 
813  // auto suggest list can be triggered either:
814  // 1, some number of chars are entered
815  // 2, an interested char belong to alChars is entered
816  int autolaunchCt = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/auto_launch_count"), 3);
817  if ( (pos - wordStartPos >= autolaunchCt && !stc->AutoCompActive())
818  || pos - wordStartPos == autolaunchCt + 4 )
819  {
821  Manager::Get()->ProcessEvent(evt);
822  }
823  else if (alChars->second.find(ch) != alChars->second.end())
824  {
825  m_AutoLaunchTimer.Start(10, wxTIMER_ONE_SHOT);
826  m_AutocompPosition = pos;
827  }
828  }
829  }
830  else if (evtType == wxEVT_SCI_UPDATEUI)
831  {
833  {
834  cbStyledTextCtrl* stc = ed->GetControl();
835  if (stc->CallTipActive())
836  {
837  // force to call the wxScintilla::CallTipCancel to avoid the smart indent condition check
838  // @see cbStyledTextCtrl::CallTipCancel() for the details
839  static_cast<wxScintilla*>(stc)->CallTipCancel();
840  if (m_CallTipActive != wxSCI_INVALID_POSITION && CCManagerHelper::IsPosVisible(m_CallTipActive, stc))
841  m_CallTipTimer.Start(SCROLL_REFRESH_DELAY, wxTIMER_ONE_SHOT);
842  }
843  else if (m_CallTipTimer.IsRunning())
844  {
846  m_CallTipTimer.Start(SCROLL_REFRESH_DELAY, wxTIMER_ONE_SHOT);
847  else
848  {
849  m_CallTipTimer.Stop();
850  m_CallTipActive = wxSCI_INVALID_POSITION;
851  }
852  }
853  if (m_AutoLaunchTimer.IsRunning())
854  {
856  m_AutoLaunchTimer.Start(SCROLL_REFRESH_DELAY, wxTIMER_ONE_SHOT);
857  else
858  m_AutoLaunchTimer.Stop();
859  }
860  else if (stc->AutoCompActive())
861  {
862  stc->AutoCompCancel();
863  m_AutocompPosition = stc->GetCurrentPos();
864  if (CCManagerHelper::IsPosVisible(m_AutocompPosition, stc))
865  m_AutoLaunchTimer.Start(SCROLL_REFRESH_DELAY, wxTIMER_ONE_SHOT);
866  }
867  }
868  }
869  else if (evtType == wxEVT_SCI_MODIFIED)
870  {
872  {
873  cbStyledTextCtrl* stc = ed->GetControl();
874  if (m_CallTipActive != wxSCI_INVALID_POSITION && stc->GetCurrentPos() >= m_CallTipActive)
875  m_CallTipTimer.Start(CALLTIP_REFRESH_DELAY, wxTIMER_ONE_SHOT);
876  else
877  static_cast<wxScintilla*>(stc)->CallTipCancel();
878  }
879  }
880  else if (evtType == wxEVT_SCI_AUTOCOMP_SELECTION)
881  {
882  DoHidePopup();
883  cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
884  if (ccPlugin && m_OwnsAutocomp)
885  {
886  if ( m_LastAutocompIndex != wxNOT_FOUND
887  && m_LastAutocompIndex < (int)m_AutocompTokens.size() )
888  {
889  ccPlugin->DoAutocomplete(m_AutocompTokens[m_LastAutocompIndex], ed);
890  }
891  else // this case should not normally happen
892  {
893  ccPlugin->DoAutocomplete(event.GetText(), ed);
894  }
895  CallSmartIndentCCDone(ed);
896  }
897  }
898  else if (evtType == wxEVT_SCI_AUTOCOMP_CANCELLED)
899  DoHidePopup();
900  else if (evtType == wxEVT_SCI_CALLTIP_CLICK)
901  {
902  switch (event.GetPosition())
903  {
904  case 1: // up
905  AdvanceTip(Previous);
906  DoUpdateCallTip(ed);
907  break;
908 
909  case 2: // down
910  AdvanceTip(Next);
911  DoUpdateCallTip(ed);
912  break;
913 
914  case 0: // elsewhere
915  default:
916  break;
917  }
918  }
919  event.Skip();
920 }
921 
922 // cbEVT_SHOW_CALL_TIP
923 // There are some caches used in this function
924 // see the comment "search long term recall" and "search short term recall"
925 // They remember which page on the calltip was last selected, and show that again first next time it
926 // is requested.
927 // Short term recall caches the current calltip, so it can be displayed exactly if a calltip is
928 // re-requested in the same location.
929 // Long term recall uses two dictionaries, the first one based on the tip's content, and will
930 // display the last shown page when a new calltip is requested that has the same content.
931 // The second (fuzzy) dictionary remembers which page was shown based on the typed word prefix
932 // (this is to support FortranProject, which uses more dynamic calltips).
934 {
935  event.Skip();
936 
937  int tooltipMode = Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadInt(wxT("/tooltip_mode"), 1);
938  // 0 - disable
939  // 1 - enable
940  // 2 - force single page
941  // 3 - keybound only
942  if (tooltipMode == tmDisable)
943  return;
944 
946  if (!ed)
947  return;
948 
949  cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
950  if (!ccPlugin)
951  return;
952 
953  cbStyledTextCtrl* stc = ed->GetControl();
954  if (!stc)
955  return;
956 
957  int pos = stc->GetCurrentPos();
958  int argsPos = wxSCI_INVALID_POSITION;
959  // save the current tip shown text for later recalling
960  wxString curTip;
961  // check whether m_CurCallTip is invalid(point to the end of m_CallTips)
962  if (!m_CallTips.empty() && m_CurCallTip != m_CallTips.end())
963  curTip = m_CurCallTip->tip;
964 
965  m_CallTips = ccPlugin->GetCallTips(pos, stc->GetStyleAt(pos), ed, argsPos);
966  // since m_CallTips get updated, we should update the m_CurCallTip, they are done in
967  // the following if/else statement.
968  if (!m_CallTips.empty() && (event.GetInt() != FROM_TIMER || argsPos == m_CallTipActive))
969  {
970  int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos));
971  while (wxIsspace(stc->GetCharAt(lnStart)))
972  ++lnStart; // do not show too far left on multi-line call tips
973  if ( m_CallTips.size() > 1
974  && tooltipMode == tmForceSinglePage ) // force single page
975  {
976  wxString tip;
977  int hlStart, hlEnd;
978  hlStart = hlEnd = wxSCI_INVALID_POSITION;
979  for (CallTipVec::const_iterator itr = m_CallTips.begin();
980  itr != m_CallTips.end(); ++itr)
981  {
982  if (hlStart == hlEnd && itr->hlStart != itr->hlEnd)
983  {
984  hlStart = tip.Length() + itr->hlStart;
985  hlEnd = tip.Length() + itr->hlEnd;
986  }
987  tip += itr->tip + wxT('\n');
988  }
989  m_CallTips.clear();
990  m_CallTips.push_back(cbCodeCompletionPlugin::CCCallTip(tip.RemoveLast(), hlStart, hlEnd));
991  }
992  m_CurCallTip = m_CallTips.begin();
993  if (m_CallTips.size() > 1)
994  {
995  // search long term recall
996  // convert the wxString to a hash value, then search the hash value map cache
997  // thus we can avoid directly lookup the cache by wxString
998  std::map<int, size_t>::const_iterator choiceItr =
999  m_CallTipChoiceDict.find(CCManagerHelper::CallTipToInt(m_CurCallTip->tip, m_CallTips.size()));
1000 
1001  // choiceItr is an iterator in the Dict, and choiceItr->second is the zero based index in m_CallTips
1002  if (choiceItr != m_CallTipChoiceDict.end() && choiceItr->second < m_CallTips.size())
1003  m_CurCallTip = m_CallTips.begin() + choiceItr->second;
1004 
1005  if (choiceItr == m_CallTipChoiceDict.end() || argsPos == m_CallTipActive)
1006  {
1007  int prefixEndPos = argsPos;
1008  while (prefixEndPos > 0 && wxIsspace(stc->GetCharAt(prefixEndPos - 1)))
1009  --prefixEndPos;
1010 
1011  // convert the prefix string to hash, check to see whether the hash is in the cache
1012  const wxString& prefix = stc->GetTextRange(stc->WordStartPosition(prefixEndPos, true), prefixEndPos);
1013  choiceItr = m_CallTipFuzzyChoiceDict.find(CCManagerHelper::CallTipToInt(prefix, m_CallTips.size()));
1014  if (choiceItr != m_CallTipFuzzyChoiceDict.end() && choiceItr->second < m_CallTips.size())
1015  m_CurCallTip = m_CallTips.begin() + choiceItr->second;
1016  }
1017  // search short term recall
1018  for (CallTipVec::const_iterator itr = m_CallTips.begin();
1019  itr != m_CallTips.end(); ++itr)
1020  {
1021  if (itr->tip == curTip)
1022  {
1023  m_CurCallTip = itr;
1024  break;
1025  }
1026  }
1027  }
1028  m_CallTipActive = argsPos;
1029  DoUpdateCallTip(ed);
1030  }
1031  else
1032  {
1033  if (m_CallTipActive != wxSCI_INVALID_POSITION)
1034  {
1035  static_cast<wxScintilla*>(stc)->CallTipCancel();
1036  m_CallTipActive = wxSCI_INVALID_POSITION;
1037  }
1038  // Make m_CurCallTip to be valid iterator, pointing to the end.
1039  m_CurCallTip = m_CallTips.end();
1040  }
1041 }
1042 
1044 {
1045  event.Skip();
1046  m_AutocompSelectTimer.Start(AUTOCOMP_SELECT_DELAY, wxTIMER_ONE_SHOT);
1047  wxObject* evtObj = event.GetEventObject();
1048  if (!evtObj)
1049  return;
1050 #ifdef __WXMSW__
1051  m_pAutocompPopup = static_cast<wxListView*>(evtObj);
1052 #endif // __WXMSW__
1053 
1054  wxWindow* evtWin = static_cast<wxWindow*>(evtObj)->GetParent();
1055  if (!evtWin)
1056  return;
1057 
1058  m_DocPos = m_pPopup->GetParent()->ScreenToClient(evtWin->GetScreenPosition());
1059  m_DocPos.x += evtWin->GetSize().x;
1061  wxRect edRect = ed->GetRect();
1062  if (!m_pPopup->IsShown())
1063  {
1064  cbStyledTextCtrl* stc = ed->GetControl();
1065  int acMaxHeight = stc->AutoCompGetMaxHeight() + 1;
1066  int textHeight = stc->TextHeight(stc->GetCurrentLine());
1067  m_DocSize.x = edRect.width * 5 / 12;
1068  m_DocSize.y = acMaxHeight * textHeight;
1069  evtWin->Connect(wxEVT_SHOW, wxShowEventHandler(CCManager::OnAutocompleteHide), nullptr, this);
1070 
1071  const int idx = wxDisplay::GetFromWindow(evtWin);
1072  m_WindowBound = m_DocPos.x + m_DocSize.x;
1073  if (idx != wxNOT_FOUND)
1074  {
1075  const wxPoint& corner = m_pPopup->GetParent()->ScreenToClient(wxDisplay(idx).GetGeometry().GetBottomRight());
1076  m_DocSize.y = std::max(9 * textHeight, std::min(m_DocSize.y, corner.y - m_DocPos.y - 2));
1077  m_DocSize.x = std::max(m_DocSize.y * 2 / 3, std::min(m_DocSize.x, corner.x - m_DocPos.x - 2));
1078  m_WindowBound = std::min(corner.x - 2, m_WindowBound);
1079  }
1080  }
1081  if ((m_DocPos.x + m_DocSize.x) > m_WindowBound)
1082  m_DocPos.x -= evtWin->GetSize().x + m_DocSize.x; // show to the left instead
1083  else
1084  m_DocSize.x = std::min(m_WindowBound - m_DocPos.x, edRect.width * 5 / 12);
1085 }
1086 
1087 // Note: according to documentation, this event is only available under wxMSW, wxGTK, and wxOS2
1089 {
1090  event.Skip();
1091  DoHidePopup();
1092  wxObject* evtObj = event.GetEventObject();
1093  if (evtObj)
1094  static_cast<wxWindow*>(evtObj)->Disconnect(wxEVT_SHOW, wxShowEventHandler(CCManager::OnAutocompleteHide), nullptr, this);
1095  if (m_CallTipActive != wxSCI_INVALID_POSITION && !m_AutoLaunchTimer.IsRunning())
1096  m_CallTipTimer.Start(CALLTIP_REFRESH_DELAY, wxTIMER_ONE_SHOT);
1097 }
1098 
1099 // cbEVT_DEFERRED_CALLTIP_SHOW
1101 {
1102  // Launching this event directly seems to be a candidate for race condition
1103  // and crash in OnShowCallTip() so we attempt to serialize it. See:
1104  // http://forums.codeblocks.org/index.php/topic,20181.msg137762.html#msg137762
1106  evt.SetInt(event.GetInt());
1107  Manager::Get()->ProcessEvent(evt);
1108 }
1109 
1110 // cbEVT_DEFERRED_CALLTIP_CANCEL
1112 {
1114  if (ed)
1115  static_cast<wxScintilla*>(ed->GetControl())->CallTipCancel();
1116 }
1117 
1118 #ifdef __WXMSW__
1120 {
1121  const wxPoint& pos = m_pLastEditor->GetControl()->ClientToScreen(event.GetPosition());
1122  if (m_pPopup->GetScreenRect().Contains(pos))
1123  m_pHtml->GetEventHandler()->ProcessEvent(event);
1124  else if (m_pAutocompPopup && m_pAutocompPopup->GetScreenRect().Contains(pos))
1125  m_pAutocompPopup->ScrollList(0, event.GetWheelRotation() / -4); // TODO: magic number... can we hook to the actual event?
1126  else
1127  event.Skip();
1128 }
1129 #endif // __WXMSW__
1130 
1131 void CCManager::OnHtmlLink(wxHtmlLinkEvent& event)
1132 {
1133  cbCodeCompletionPlugin* ccPlugin = GetProviderFor();
1134  if (!ccPlugin)
1135  return;
1136 
1137  bool dismissPopup = false;
1138  const wxString& html = ccPlugin->OnDocumentationLink(event, dismissPopup);
1139  if (dismissPopup)
1140  DoHidePopup();
1141  else if (!html.IsEmpty())
1142  m_pHtml->SetPage(html);
1143  // plugins are responsible to skip this event (if they choose to)
1144 }
1145 
1147 {
1148  if (event.GetId() == idCallTipTimer) // m_CallTipTimer
1149  {
1150  wxCommandEvent evt(cbEVT_DEFERRED_CALLTIP_SHOW);
1151  evt.SetInt(FROM_TIMER);
1152  AddPendingEvent(evt);
1153  }
1154  else if (event.GetId() == idAutoLaunchTimer) // m_AutoLaunchTimer
1155  {
1157  if (ed && ed->GetControl()->GetCurrentPos() == m_AutocompPosition)
1158  {
1160  evt.SetInt(FROM_TIMER);
1161  Manager::Get()->ProcessEvent(evt);
1162  }
1163  m_AutocompPosition = wxSCI_INVALID_POSITION;
1164  }
1165  else if (event.GetId() == idAutocompSelectTimer) // m_AutocompSelectTimer
1166  {
1168  if (ed)
1169  {
1170  cbStyledTextCtrl* stc = ed->GetControl();
1171  if (stc->AutoCompActive())
1172  {
1173  m_LastAutocompIndex = stc->AutoCompGetCurrent();
1174  DoShowDocumentation(ed);
1175  }
1176  }
1177  }
1178  else // ?!
1179  event.Skip();
1180 }
1181 
1183 {
1185  if (!ed)
1186  return;
1187  if (event.GetId() == idShowTooltip)
1188  {
1189  // compare this with cbStyledTextCtrl::EmulateDwellStart()
1190  cbStyledTextCtrl* stc = ed->GetControl();
1192  wxPoint pt = stc->PointFromPosition(stc->GetCurrentPos());
1193  evt.SetX(pt.x);
1194  evt.SetY(pt.y);
1195  evt.SetInt(stc->GetStyleAt(stc->GetCurrentPos()));
1196  evt.SetEditor(ed);
1197  evt.SetExtraLong(0);
1198  evt.SetString(wxT("evt from menu"));
1199  Manager::Get()->ProcessEvent(evt);
1200  return;
1201  }
1202  if (m_CallTips.empty() || m_CallTipActive == wxSCI_INVALID_POSITION)
1203  return;
1204  if (!ed->GetControl()->CallTipActive())
1205  return;
1206  if (event.GetId() == idCallTipNext)
1207  {
1208  AdvanceTip(Next);
1209  DoUpdateCallTip(ed);
1210  }
1211  else if (event.GetId() == idCallTipPrevious)
1212  {
1213  AdvanceTip(Previous);
1214  DoUpdateCallTip(ed);
1215  }
1216 }
1217 
1219 {
1220  if (stc->AutoCompActive())
1221  return; // already active, no need to rebuild
1222  // fill list of suggestions
1223  wxString items;
1224  items.Alloc(m_AutocompTokens.size() * 20);
1225  for (size_t i = 0; i < m_AutocompTokens.size(); ++i)
1226  {
1227  items += m_AutocompTokens[i].displayName;
1228  if (m_AutocompTokens[i].category == -1)
1229  items += wxT("\r");
1230  else
1231  items += F(wxT("\n%d\r"), m_AutocompTokens[i].category);
1232  }
1233  items.RemoveLast();
1234  if (!stc->CallTipActive())
1235  m_CallTipActive = wxSCI_INVALID_POSITION;
1236  // display
1237  stc->AutoCompShow(m_LastACLaunchState[lsCaretStart] - m_LastACLaunchState[lsTknStart], items);
1238  m_OwnsAutocomp = true;
1239 
1240  // We need to check if the auto completion is active, because if there are no matches scintilla will close
1241  // the popup and any call to AutoCompSelect will result in a crash.
1242  if (stc->AutoCompActive() &&
1243  (m_LastAutocompIndex != wxNOT_FOUND && m_LastAutocompIndex < (int)m_AutocompTokens.size()))
1244  {
1245  // re-select last selected entry
1246  const cbCodeCompletionPlugin::CCToken& token = m_AutocompTokens[m_LastAutocompIndex];
1247  const int sepIdx = token.displayName.Find('\n', true);
1248  if (sepIdx == wxNOT_FOUND)
1249  stc->AutoCompSelect(token.displayName);
1250  else
1251  stc->AutoCompSelect(token.displayName.Mid(0, sepIdx));
1252  }
1253 }
1254 
1256 {
1257  if (!m_pPopup->IsShown())
1258  return;
1259  m_pPopup->Hide();
1260 #ifdef __WXMSW__
1261  if (m_pLastEditor && m_pLastEditor->GetControl())
1262  m_pLastEditor->GetControl()->Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(CCManager::OnPopupScroll), nullptr, this);
1263 #endif // __WXMSW__
1264 }
1265 
1267 {
1268  if (!Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadBool(wxT("/documentation_popup"), true))
1269  return;
1270 
1271  cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
1272  if (!ccPlugin)
1273  return;
1274  if ( m_LastAutocompIndex == wxNOT_FOUND
1275  || m_LastAutocompIndex >= (int)m_AutocompTokens.size() )
1276  {
1277  return;
1278  }
1279  const wxString& html = ccPlugin->GetDocumentation(m_AutocompTokens[m_LastAutocompIndex]);
1280  if (html.IsEmpty())
1281  {
1282  DoHidePopup();
1283  return;
1284  }
1285 
1286  m_pPopup->Freeze();
1287  m_pHtml->SetSize(m_DocSize);
1288  m_pHtml->SetPage(html);
1289  m_pPopup->SetClientSize(m_DocSize);
1290  m_pPopup->SetPosition(m_DocPos);
1291  m_pPopup->Thaw();
1292  if (!m_pPopup->IsShown())
1293  {
1294  m_pPopup->Show();
1295 #ifdef __WXMSW__
1296  ed->GetControl()->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(CCManager::OnPopupScroll), nullptr, this);
1297 #endif // __WXMSW__
1298  }
1299 }
1300 
1302 {
1303  wxStringVec tips;
1304  int hlStart = m_CurCallTip->hlStart;
1305  int hlEnd = m_CurCallTip->hlEnd;
1306  size_t sRange = 0;
1307  size_t eRange = m_CurCallTip->tip.find(wxT('\n'));
1308  while (eRange != wxString::npos)
1309  {
1310  tips.push_back(m_CurCallTip->tip.Mid(sRange, eRange - sRange));
1311  CCManagerHelper::RipplePts(hlStart, hlEnd, eRange, -1);
1312  sRange = eRange + 1;
1313  eRange = m_CurCallTip->tip.find(wxT('\n'), sRange);
1314  }
1315  if (sRange < m_CurCallTip->tip.Length())
1316  tips.push_back(m_CurCallTip->tip.Mid(sRange));
1317  // for multiple tips (such as tips for some overload functions)
1318  // some more text were added to the single tip, such as the up/down arrows, the x/y indicator.
1319  int offset = 0;
1320  cbStyledTextCtrl* stc = ed->GetControl();
1321  if (m_CallTips.size() > 1)
1322  {
1323  tips.front().Prepend(wxT("\001\002")); // up/down arrows
1324  offset += 2;
1325 
1326  // display (curTipNumber/totalTipCount)
1327  wxString tip;
1328  tip << wxT("(") << (m_CurCallTip - m_CallTips.begin() + 1) << wxT("/") << m_CallTips.size() << wxT(")");
1329 
1330  tips.push_back(tip);
1331  // store for better first choice later
1332  m_CallTipChoiceDict[CCManagerHelper::CallTipToInt(m_CallTips.front().tip, m_CallTips.size())] = m_CurCallTip - m_CallTips.begin();
1333  // fuzzy store
1334  int prefixEndPos = m_CallTipActive;
1335  while (prefixEndPos > 0 && wxIsspace(stc->GetCharAt(prefixEndPos - 1)))
1336  --prefixEndPos;
1337  const wxString& prefix = stc->GetTextRange(stc->WordStartPosition(prefixEndPos, true), prefixEndPos);
1338  m_CallTipFuzzyChoiceDict[CCManagerHelper::CallTipToInt(prefix, m_CallTips.size())] = m_CurCallTip - m_CallTips.begin();
1339  }
1340  int pos = stc->GetCurrentPos();
1341  int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos));
1342  while (wxIsspace(stc->GetCharAt(lnStart)))
1343  ++lnStart;
1344 #ifdef __WXMSW__
1345  m_LastTipPos = wxSCI_INVALID_POSITION; // Windows hack to fix display update
1346 #endif // __WXMSW__
1347  DoShowTips(tips, stc, std::max(pos, lnStart), m_CallTipActive, hlStart + offset, hlEnd + offset);
1348 }
1349 
1350 void CCManager::DoShowTips(const wxStringVec& tips, cbStyledTextCtrl* stc, int pos, int argsPos, int hlStart, int hlEnd)
1351 {
1352  int maxLines = std::max(stc->LinesOnScreen() / 4, 5);
1353  int marginWidth = stc->GetMarginWidth(wxSCI_MARGIN_SYMBOL) + stc->GetMarginWidth(wxSCI_MARGIN_NUMBER);
1354  int maxWidth = (stc->GetSize().x - marginWidth) / stc->TextWidth(wxSCI_STYLE_LINENUMBER, wxT("W")) - 1;
1355  maxWidth = std::min(std::max(60, maxWidth), 135);
1356  wxString tip;
1357  int lineCount = 0;
1358  wxString lineBreak = wxT('\n');
1359  if (!tips.front().IsEmpty() && tips.front()[0] <= wxT('\002'))
1360  {
1361  // indent line break as needed, if tip prefixed with up/down arrows
1362  lineBreak += wxT(' ');
1363  if (tips.front().Length() > 1 && tips.front()[1] <= wxT('\002'))
1364  lineBreak += wxT(" ");
1365  }
1366 
1367  for (size_t i = 0; i < tips.size() && lineCount < maxLines; ++i)
1368  {
1369  if (tips[i].Length() > (size_t)maxWidth + 6) // line is too long, try breaking it
1370  {
1371  wxString tipLn = tips[i];
1372  while (!tipLn.IsEmpty())
1373  {
1374  wxString segment = tipLn.Mid(0, maxWidth);
1375  int index = segment.Find(wxT(' '), true); // break on a space
1376  if (index < 20) // no reasonable break?
1377  {
1378  segment = tipLn.Mid(0, maxWidth * 6 / 5); // increase search width a bit
1379  index = segment.Find(wxT(' '), true);
1380  }
1381  for (int commaIdx = index - 1; commaIdx > maxWidth / 2; --commaIdx) // check back for a comma
1382  {
1383  if (segment[commaIdx] == wxT(',') && segment[commaIdx + 1] == wxT(' '))
1384  {
1385  index = commaIdx + 1; // prefer splitting on a comma, if that does not set us back too far
1386  break;
1387  }
1388  }
1389  if (index < 20 || segment == tipLn) // end of string, or cannot split
1390  {
1391  tip += tipLn + lineBreak;
1392  CCManagerHelper::RipplePts(hlStart, hlEnd, tip.Length(), lineBreak.Length());
1393  tipLn.Clear();
1394  }
1395  else // continue splitting
1396  {
1397  tip += segment.Mid(0, index) + lineBreak + wxT(' ');
1398  CCManagerHelper::RipplePts(hlStart, hlEnd, tip.Length(), lineBreak.Length() + 1);
1399  // already starts with a space, so all subsequent lines are prefixed by two spaces
1400  tipLn = tipLn.Mid(index);
1401  }
1402  ++lineCount;
1403  }
1404  }
1405  else // just add the line
1406  {
1407  tip += tips[i] + lineBreak;
1408  CCManagerHelper::RipplePts(hlStart, hlEnd, tip.Length(), lineBreak.Length());
1409  ++lineCount;
1410  }
1411  }
1412  tip.Trim(); // trailing linefeed
1413 
1414  // try to show the tip at the start of the token/arguments, or at the margin if we are scrolled right
1415  // an offset of 2 helps deal with the width of the folding bar (TODO: does an actual calculation exist?)
1416  int line = stc->LineFromPosition(pos);
1417  if (argsPos == wxSCI_INVALID_POSITION)
1418  argsPos = stc->WordStartPosition(pos, true);
1419  else
1420  argsPos = std::min(CCManagerHelper::FindColumn(line, stc->GetColumn(argsPos), stc), stc->WordStartPosition(pos, true));
1421  int offset = stc->PointFromPosition(stc->PositionFromLine(line)).x > marginWidth ? 0 : 2;
1422  pos = std::max(argsPos, stc->PositionFromPoint(wxPoint(marginWidth, stc->PointFromPosition(pos).y)) + offset);
1423  pos = std::min(pos, stc->GetLineEndPosition(line)); // do not go to next line
1424  if (stc->CallTipActive() && m_LastTipPos != pos)
1425  stc->CallTipCancel(); // force tip popup to invalidate (sometimes fails to otherwise do so on Windows)
1426  stc->CallTipShow(pos, tip);
1427  if (hlStart >= 0 && hlEnd > hlStart)
1428  stc->CallTipSetHighlight(hlStart, hlEnd);
1429  m_LastTipPos = pos;
1430 }
1431 
1433 {
1435  event.SetEditor(ed);
1436  // post event in the host's event queue
1437  Manager::Get()->ProcessEvent(event);
1438 }
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
EVTIMPORT const wxEventType cbEVT_EDITOR_TOOLTIP
Definition: sdk_events.cpp:88
bool CallTipActive()
Is there an active call tip?
const int idShowTooltip
Definition: ccmanager.cpp:117
#define wxFRAME_SHAPED
virtual std::vector< CCToken > GetTokenAt(int pos, cbEditor *ed, bool &allowCallTip)=0
Supply the definition of the token at the specified location.
virtual std::vector< CCToken > GetAutocompList(bool isAuto, cbEditor *ed, int &tknStart, int &tknEnd)=0
Supply content for the autocompletion list.
void SetText(const wxString &t)
Kept for backwards compatibility, use SetString().
Definition: wxscintilla.h:5420
#define wxSCI_MARGIN_NUMBER
Definition: wxscintilla.h:151
int WordEndPosition(int pos, bool onlyWordCharacters)
Get position of end of word.
EVTIMPORT const wxEventType cbEVT_EDITOR_CC_DONE
Definition: sdk_events.cpp:93
bool Destroy() override
Definition: ccmanager.cpp:201
int wxNewId()
Base class for code-completion plugins.
Definition: cbplugin.h:732
PluginManager * GetPluginManager() const
Definition: manager.cpp:444
const_iterator begin() const
std::vector< cbCodeCompletionPlugin::CCCallTip > CallTipVec
Definition: ccmanager.h:182
#define wxSIZE_AUTO
bool AutoCompActive()
Is there an auto-completion list visible?
void CallTipSetHighlight(int highlightStart, int highlightEnd)
Highlight a segment of the definition.
void OnPopupScroll(wxMouseEvent &event)
Intercept cbStyledTextCtrl scroll events and forward to autocomplete/documentation popups...
Definition: ccmanager.cpp:1119
bool wxIsspace(const wxUniChar &c)
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
CCProviderStatus
Level of functionality a CC plugin is able to provide.
Definition: cbplugin.h:738
int ReadInt(const wxString &name, int defaultVal=0)
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
#define wxPOPUP_WINDOW
bool IsComment(int style)
Is style classified as comment for current language?
#define wxSCI_MARGIN_SYMBOL
Definition: wxscintilla.h:150
int GetUpdated() const
Definition: wxscintilla.h:5474
void CallTipSetForegroundHighlight(const wxColour &fore)
Set the foreground colour for the highlighted part of the call tip.
int Cmp(const wxString &s) const
#define wxSCI_UPDATE_V_SCROLL
Definition: wxscintilla.h:438
#define wxDynamicCast(ptr, classname)
void OnEditorOpen(CodeBlocksEvent &event)
Event handler to avoid tooltips getting stuck active.
Definition: ccmanager.cpp:643
void NotifyDocumentation()
Let CCManager know that new results are available from cbCodeCompletionPlugin::GetDocumentation().
Definition: ccmanager.cpp:404
void OnAutocompleteSelect(wxListEvent &event)
Event handler to show documentation, when user changes autocomplete selection.
Definition: ccmanager.cpp:1043
void RegisterColour(const wxString &category, const wxString &name, const wxString &id, const wxColour &defaultColour)
Structure representing an individual calltip with an optional highlighted range.
Definition: cbplugin.h:782
int GetColumn(int pos) const
Retrieve the column number of a position, taking tab width into account.
void NotifyPluginStatus()
Let CCManager know that a change (e.g.
Definition: ccmanager.cpp:411
#define wxSCI_PERFORMED_UNDO
Definition: wxscintilla.h:418
bool ReadBool(const wxString &name, bool defaultVal=false)
void OnAutocompleteHide(wxShowEvent &event)
Event handler to tear down documentation, when autocomplete closes.
Definition: ccmanager.cpp:1088
void AutoCompSetOrder(int order)
Set the way autocompletion lists are ordered.
bool Show(bool show=true) override
Definition: ccmanager.cpp:247
size_t Length() const
int GetX() const
Definition: sdk_events.h:53
int VisibleFromDocLine(int docLine)
Find the display line of a document line taking hidden lines into account.
void OnDeferredCallTipCancel(wxCommandEvent &event)
Defer canceling the calltip to avoid a crash issue.
Definition: ccmanager.cpp:1111
void CallTipSetForeground(const wxColour &fore)
Set the foreground colour for the call tip.
const int idAutoLaunchTimer
Definition: ccmanager.cpp:115
#define AUTOCOMP_SELECT_DELAY
Definition: ccmanager.cpp:126
void OnTimer(wxTimerEvent &event)
Grouped event handler for several timers.
Definition: ccmanager.cpp:1146
int FindColumn(int line, int column, wxScintilla *stc)
Definition: ccmanager.cpp:51
void CallTipShow(int pos, const wxString &definition)
Show a call tip containing a definition near position pos.
std::vector< wxString > wxStringVec
Definition: globals.h:205
int TextHeight(int line)
Retrieve the height of a particular line of text in pixels.
void OnDeactivateEd(CodeBlocksEvent &event)
Event handler to avoid tooltips getting stuck active.
Definition: ccmanager.cpp:620
void RegisterCallTipChars(const wxString &chars, cbCodeCompletionPlugin *registrant)
Register a new set of characters that, when typed, invoke calltip requests.
Definition: ccmanager.cpp:392
EditorBase * GetEditor() const
Definition: sdk_events.h:44
#define wxFRAME_NO_TASKBAR
wxEventType wxEVT_MOUSEWHEEL
#define wxT(string)
int GetModificationType() const
Definition: wxscintilla.h:5457
#define wxSCI_ORDER_PRESORTED
Definition: wxscintilla.h:371
wxPopupWindow BaseClass
Definition: ccmanager.cpp:167
EVTIMPORT const wxEventType cbEVT_SHOW_CALL_TIP
Definition: sdk_events.cpp:177
int GetWheelRotation() const
void OnCompleteCode(CodeBlocksEvent &event)
Event handler to list the suggestion, when a user press Ctrl-space (by default).
Definition: ccmanager.cpp:505
void RegisterAutoLaunchChars(const wxString &chars, cbCodeCompletionPlugin *registrant)
Register a new set of characters that, when typed, auto-launch codecomplete requests.
Definition: ccmanager.cpp:398
A generic Code::Blocks event.
Definition: sdk_events.h:20
static void setupColours(cbEditor *editor, ColourManager *manager)
Definition: ccmanager.cpp:634
wxPoint GetPosition() const
int GetLineEndPosition(int line) const
Get the position after the last visible characters on a line.
static int GetDefaultHTMLFontSize()
Definition: ccmanager.cpp:99
const int idCallTipPrevious
Definition: ccmanager.cpp:119
int WordStartPosition(int pos, bool onlyWordCharacters)
Get position of start of word.
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
bool IsPosVisible(int pos, wxScintilla *stc)
Definition: ccmanager.cpp:63
#define wxSCI_UPDATE_H_SCROLL
Definition: wxscintilla.h:439
void DoSetSize(int x, int y, int width, int height, int sizeFlags=wxSIZE_AUTO) override
Definition: ccmanager.cpp:233
wxUSE_UNICODE_dependent wxChar
#define wxSCI_STYLE_LINENUMBER
Definition: wxscintilla.h:164
wxEventType wxEVT_SHOW
CC plugin provides specialized functionality.
Definition: cbplugin.h:741
int weight
Lower numbers are placed earlier in listing, 5 is default; try to keep 0-10.
Definition: cbplugin.h:776
PluginsArray GetCodeCompletionOffers()
EVTIMPORT const wxEventType cbEVT_EDITOR_CLOSE
Definition: sdk_events.cpp:80
Event functor class.
Definition: cbfunctor.h:37
UnfocusablePopupWindow(wxWindow *parent, int style=wxBORDER_NONE)
Definition: ccmanager.cpp:169
void SetX(int x)
Definition: sdk_events.h:54
int PositionFromPointClose(int x, int y)
Find the position from a point within the window but return wxSCI_INVALID_POSITION if not close to te...
void DoShowDocumentation(cbEditor *ed)
Show the documentation popup.
Definition: ccmanager.cpp:1266
int GetCurrentLine()
Manually declared methods.
static int CallTipToInt(const wxString &firstTip, int numPages)
Definition: ccmanager.cpp:71
wxString & RemoveLast(size_t n=1)
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
wxColour GetColour(const wxString &id) const
#define wxHW_SCROLLBAR_AUTO
void AutoCompShow(int lengthEntered, const wxString &itemList)
Display a auto-completion list.
virtual wxString GetDocumentation(const CCToken &token)=0
Supply html formatted documentation for the passed token.
void CallTipCancel()
Cancel calltip only if not jumping braces via tab.
TooltipMode
the CC tooltip options in Editor setting dialog
Definition: ccmanager.cpp:130
wxPoint PointFromPosition(int pos)
Retrieve the point in the window where a position is displayed.
void CallTipSetBackground(const wxColour &back)
Set the background colour for the call tip.
bool Alloc(size_t nLen)
EVTIMPORT const wxEventType cbEVT_APP_DEACTIVATED
Definition: sdk_events.cpp:71
cbCodeCompletionPlugin * GetProviderFor(cbEditor *ed=nullptr)
Get the ccPlugin instant for the cbEditor.
Definition: ccmanager.cpp:367
wxFrame * GetAppFrame() const
Definition: manager.cpp:419
void AutoCompSetMaxHeight(int rowCount)
Set the maximum height, in rows, of auto-completion and user lists.
const wxSize wxDefaultSize
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
#define CALLTIP_REFRESH_DELAY
Definition: ccmanager.cpp:125
const wxPoint wxDefaultPosition
void DoUpdateCallTip(cbEditor *ed)
Update which tip to show next and where to show it.
Definition: ccmanager.cpp:1301
void AutoCompCancel()
Remove the auto-completion list from the screen.
void RemoveAllEventSinksFor(void *owner)
Definition: manager.cpp:570
void OnFocus(wxFocusEvent &event)
Definition: ccmanager.cpp:216
bool IsCharacter(int style)
Is style classified as character for current language?
Base class that all "editors" should inherit from.
Definition: editorbase.h:30
int GetCurrentPos() const
Returns the position of the caret.
void AdvanceTip(Direction direction)
Switch the tip window to the next item.
Definition: ccmanager.cpp:430
Structure representing a generic token, passed between CC plugins and CCManager.
Definition: cbplugin.h:746
bool IsString(int style)
Is style classified as string for current language?
int GetLength() const
Returns the number of bytes in the document.
virtual bool IsContextMenuOpened() const
Is there a context (right click) menu open.
Definition: editorbase.cpp:441
wxString displayName
Verbose string representing the token.
Definition: cbplugin.h:777
wxEventType wxEVT_TIMER
#define wxTIMER_ONE_SHOT
wxString GetTextRange(int startPos, int endPos)
Retrieve a range of text.
void AutoCompSetSeparator(int separatorCharacter)
Change the separator character in the string setting up an auto-completion list.
wxFont * wxNORMAL_FONT
virtual bool IsBuiltinEditor() const
Is this a built-in editor?
Definition: editorbase.cpp:209
wxMenu * GetMenu(size_t menuIndex) const
int GetHeight() const
#define wxFRAME_FLOAT_ON_PARENT
void OnEditorClose(CodeBlocksEvent &event)
Event handler to avoid tooltips getting stuck active.
Definition: ccmanager.cpp:671
wxColour * wxWHITE
wxString wxEmptyString
EVTIMPORT const wxEventType cbEVT_EDITOR_DEACTIVATED
Definition: sdk_events.cpp:84
#define FROM_TIMER
FROM_TIMER means the event is automatically fired from the ccmanager, not explicitly called by the us...
Definition: ccmanager.cpp:146
EVTIMPORT const wxEventType cbEVT_COMPLETE_CODE
Definition: sdk_events.cpp:176
Definition: manager.h:183
int width
bool & m_PureAlphabetical
Definition: ccmanager.cpp:475
const wxString & _(const wxString &string)
wxString & Trim(bool fromRight=true)
int FindMenu(const wxString &title) const
Code Completion Plugin Manager.
Definition: ccmanager.h:47
EditorBase * GetEditor(int index)
cbEditor * GetBuiltinEditor(EditorBase *eb)
void AutoCompSetTypeSeparator(int separatorCharacter)
Change the type-separator character in the string setting up an auto-completion list.
void OnMenuSelect(wxCommandEvent &event)
Handle the CC related menu click.
Definition: ccmanager.cpp:1182
Functor class for use as a editor modification operations hook.
Definition: editor_hooks.h:52
void UpdateEnvSettings()
Called after env settings have changed, so the changes can be applied.
Definition: ccmanager.cpp:656
const int idCallTipNext
Definition: ccmanager.cpp:118
int PositionFromPoint(wxPoint pt) const
Find the position from a point within the window.
int PositionFromLine(int line) const
Retrieve the position at the start of a line.
static int GetFromWindow(const wxWindow *win)
const int idCallTipTimer
Definition: ccmanager.cpp:114
void DoBufferedCC(cbStyledTextCtrl *stc)
CC launched in the same state as last run, display via cached data.
Definition: ccmanager.cpp:1218
ColourManager * GetColourManager() const
Definition: manager.cpp:489
const int idAutocompSelectTimer
Definition: ccmanager.cpp:116
A file editor.
Definition: cbeditor.h:43
bool IsEmpty() const
int GetCharAt(int pos) const
Returns the character byte at the position.
void SetEditor(EditorBase *editor)
Definition: sdk_events.h:45
size_type size() const
bool wxIsalpha(const wxUniChar &c)
void AutoCompSetIgnoreCase(bool ignoreCase)
Set whether case is significant when performing auto-completion searches.
void Clear()
TokenSorter(bool &alphabetical, bool caseSensitive)
Definition: ccmanager.cpp:478
wxString Upper() const
static const size_t npos
void CallSmartIndentCCDone(cbEditor *ed)
Code completion as just insert some text in the editor, ask the smart indent plugin to adjust the ind...
Definition: ccmanager.cpp:1432
void SetY(int y)
Definition: sdk_events.h:57
#define SCROLL_REFRESH_DELAY
Definition: ccmanager.cpp:127
wxString GetLineIndentString(int line=-1) const
Returns the specified line&#39;s (0-based) indentation (whitespace) string.
Definition: cbeditor.cpp:2778
Direction
User click the next or previous small button of the tip window.
Definition: ccmanager.h:161
#define wxNO_BORDER
#define wxSCI_INVALID_POSITION
Definition: wxscintilla.h:70
const_iterator end() const
bool ProcessEvent(CodeBlocksEvent &event)
Definition: manager.cpp:246
void OnShowCallTip(CodeBlocksEvent &event)
Event handler to show the call tip, when user press Ctrl-Shift-Space.
Definition: ccmanager.cpp:933
void OnEditorHook(cbEditor *ed, wxScintillaEvent &event)
Hook to the editor.
Definition: ccmanager.cpp:783
void DoHidePopup()
Hide the documentation popup.
Definition: ccmanager.cpp:1255
void RegisterEventSink(wxEventType eventType, IEventFunctorBase< CodeBlocksEvent > *functor)
Definition: manager.cpp:550
virtual int GetPointSize() const
DLLIMPORT HookFunctorBase * UnregisterHook(int id, bool deleteHook=true)
Unregister a previously registered project loading/saving hook.
int GetStyleAt(int pos) const
Returns the style byte at the position.
void SetHeight(int height)
int LineFromPosition(int pos) const
Retrieve the line containing a position.
~CCManager() override
Definition: ccmanager.cpp:348
void InjectAutoCompShow(int lenEntered, const wxString &itemList)
If for some reason you need to use wxScintilla::AutoCompShow(), call this instead so CCManager does n...
Definition: ccmanager.cpp:417
static void BuildFontSizes(int *sizes, int size)
Definition: ccmanager.cpp:84
int LinesOnScreen() const
Retrieves the number of lines completely visible.
int Find(wxUniChar ch, bool fromEnd=false) const
EVTIMPORT const wxEventType cbEVT_EDITOR_OPEN
Definition: sdk_events.cpp:81
int wxEventType
int TextWidth(int style, const wxString &text)
Measure the pixel width of some text in a particular style.
int GetMarginWidth(int margin) const
Retrieve the width of a margin in pixels.
void OnDeactivateApp(CodeBlocksEvent &event)
Event handler to avoid tooltips getting stuck active.
Definition: ccmanager.cpp:600
#define wxSCI_ORDER_CUSTOM
Definition: wxscintilla.h:373
bool m_CaseSensitive
Definition: ccmanager.cpp:476
virtual std::vector< CCCallTip > GetCallTips(int pos, int style, cbEditor *ed, int &argsPos)=0
Supply content for the calltip at the specified location.
void OnEditorTooltip(CodeBlocksEvent &event)
Mouse hover event.
Definition: ccmanager.cpp:686
ACLaunchState
Definition: ccmanager.cpp:148
bool ProcessArrow(int key)
Used by cbStyledTextCtrl to process ArrowUp and ArrowDown key press.
Definition: ccmanager.cpp:450
void OnDeferredCallTipShow(wxCommandEvent &event)
Defer showing the calltip to avoid a crash issue.
Definition: ccmanager.cpp:1100
wxMenuItemList & GetMenuItems()
wxCoord wxDefaultCoord
void AutoCompSelect(const wxString &select)
Select the item in the auto-completion list that starts with a string.
#define NULL
Definition: prefix.cpp:59
bool wxGetKeyState(wxKeyCode key)
wxString GetText() const
Kept for backwards compatibility, use GetString().
Definition: wxscintilla.h:5459
wxString Mid(size_t first, size_t nCount=wxString::npos) const
virtual void DoAutocomplete(const CCToken &token, cbEditor *ed)
Callback for inserting the selected autocomplete entry into the editor.
bool operator()(const cbCodeCompletionPlugin::CCToken &a, const cbCodeCompletionPlugin::CCToken &b)
Definition: ccmanager.cpp:483
wxMenuItem * Insert(size_t pos, wxMenuItem *menuItem)
int AutoCompGetCurrent() const
Get currently selected item position in the auto-completion list.
void RipplePts(int &ptA, int &ptB, int len, int delta)
Definition: ccmanager.cpp:40
bool IsPreprocessor(int style)
Is style classified as preprocessor for current language?
int GetPosition() const
Definition: wxscintilla.h:5454
int GetFirstVisibleLine() const
Retrieve the display line at the top of the display.
int AutoCompGetMaxHeight() const
Set the maximum height, in rows, of auto-completion and user lists.
wxWindow * wxGetTopLevelParent(wxWindow *window)
void DoShowTips(const wxStringVec &tips, cbStyledTextCtrl *stc, int pos, int argsPos, int hlStart, int hlEnd)
Format tips by breaking long lines at (hopefully) logical places.
Definition: ccmanager.cpp:1350
DLLIMPORT int RegisterHook(HookFunctorBase *functor)
Register a project loading/saving hook.
CC plugin provides generic functionality.
Definition: cbplugin.h:742