1 // ----------------------------------------------------------------------------
2 // JumpTracker.cpp
3 // ----------------------------------------------------------------------------
4 #include <sdk.h> // Code::Blocks SDK
5 #include <configurationpanel.h>
6 #include <cbstyledtextctrl.h>
7 #include <projectmanager.h>
8 #include <editormanager.h>
9 #include <cbeditor.h>
10 #include <wx/xrc/xmlres.h>
11
12 #include "Version.h"
13 #include "JumpTracker.h"
14 #include "JumpData.h"
15
16 // now that we have ArrayOfJumpData declaration in scope we may finish the
17 // definition -- note that this expands into some C++
18 // code and so should only be compiled once (i.e., don't put this in the
19 // header, but into a source file or you will get linking errors)
20 #include <wx/arrimpl.cpp> // this is a magic incantation which must be done!
21 WX_DEFINE_OBJARRAY(ArrayOfJumpData);
22
23 // ----------------------------------------------------------------------------
24 // namespace
25 // ----------------------------------------------------------------------------
26 // Register the plugin with Code::Blocks.
27 // We are using an anonymous namespace so we don't litter the global one.
28 namespace
29 {
30 //-PluginRegistrant<JumpTracker> reg(_T("JumpTracker"));
31 int idMenuJumpView = wxNewId();
32 int idMenuJumpBack = wxNewId();
33 int idMenuJumpNext = wxNewId();
34 int idMenuJumpClear = wxNewId();
35 int idMenuJumpDump = wxNewId();
36
37 int idToolJumpPrev = XRCID("idJumpPrev");
38 int idToolJumpNext = XRCID("idJumpNext");
39 }
40
41 // ----------------------------------------------------------------------------
42 // Events Table
43 // ----------------------------------------------------------------------------
44 // events handling
BEGIN_EVENT_TABLE(JumpTracker,cbPlugin)45 BEGIN_EVENT_TABLE(JumpTracker, cbPlugin)
46 // add any events you want to handle here
47 // Now doing Connect() in BuildMenu()
48 // EVT_MENU( idMenuJumpBack, JumpTracker::OnMenuJumpBack)
49 // EVT_MENU( idMenuJumpNext, JumpTracker::OnMenuJumpNext)
50 // EVT_MENU( idMenuJumpClear, JumpTracker::OnMenuJumpClear)
51 // EVT_MENU( idMenuJumpDump, JumpTracker::OnMenuJumpDump)
52
53 END_EVENT_TABLE()
54
55 // constructor
56 // ----------------------------------------------------------------------------
57 JumpTracker::JumpTracker()
58 // ----------------------------------------------------------------------------
59 {
60 // Make sure our resources are available.
61 // In the generated boilerplate code we have no resources but when
62 // we add some, it will be nice that this code is in place already ;)
63 // if(!Manager::LoadResource(_T("JumpTracker.zip")))
64 // {
65 // NotifyMissingFile(_T("JumpTracker.zip"));
66 // }
67
68 m_bShuttingDown = false;
69 m_FilenameLast = wxEmptyString;
70 m_PosnLast = 0;
71 m_cursor = 0;
72 m_insertNext = maxJumpEntries;
73 m_ArrayOfJumpData.Clear();
74 m_bProjectClosing = false;
75 m_IsAttached = false;
76 m_bJumpInProgress = false;
77 m_bWrapJumpEntries = false;
78 m_pToolBar = 0;
79 }
80 // ----------------------------------------------------------------------------
~JumpTracker()81 JumpTracker::~JumpTracker()
82 // ----------------------------------------------------------------------------
83 {
84 // destructor
85 }
86 // ----------------------------------------------------------------------------
OnAttach()87 void JumpTracker::OnAttach()
88 // ----------------------------------------------------------------------------
89 {
90 // do whatever initialization you need for your plugin
91 // :NOTE: after this function, the inherited member variable
92 // m_IsAttached will be TRUE...
93 // You should check for it in other functions, because if it
94 // is FALSE, it means that the application did *not* "load"
95 // (see: does not need) this plugin...
96
97 // --------------------------------------------------
98 // Initialize a debugging log/version control
99 // --------------------------------------------------
100 // PlgnVersion plgnVersion;
101 // #if LOGGING
102 // wxLog::EnableLogging(true);
103 // m_pPlgnLog = new wxLogWindow( Manager::Get()->GetAppWindow(), _T(" JumpTracker"),true,false);
104 // wxLog::SetActiveTarget( m_pPlgnLog);
105 // m_pPlgnLog->GetFrame()->SetSize(20,30,600,300);
106 // LOGIT( _T("JT JumpTracker Logging Started[%s]"),plgnVersion.GetVersion().c_str());
107 // m_pPlgnLog->Flush();
108 // #endif
109
110 // // Set current plugin version
111 // PluginInfo* pInfo = (PluginInfo*)(Manager::Get()->GetPluginManager()->GetPluginInfo(this));
112 // pInfo->version = plgnVersion.GetVersion();
113
114 m_bJumpInProgress = false;
115
116 wxWindow* appWin = Manager::Get()->GetAppWindow();
117 appWin->PushEventHandler(this);
118 appWin->Connect(idMenuJumpBack, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpBack), 0, this);
119 appWin->Connect(idMenuJumpNext, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpNext), 0, this);
120 appWin->Connect(idMenuJumpClear, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpClear), 0, this);
121 appWin->Connect(idMenuJumpDump, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpDump), 0, this);
122
123 appWin->Connect(idToolJumpPrev, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(JumpTracker::OnMenuJumpBack), 0, this);
124 appWin->Connect(idToolJumpNext, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(JumpTracker::OnMenuJumpNext), 0, this);
125 appWin->Connect(idToolJumpPrev, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(JumpTracker::OnUpdateUI), 0, this);
126 appWin->Connect(idToolJumpNext, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(JumpTracker::OnUpdateUI), 0, this);
127
128
129 // Codeblocks Events registration
130 Manager::Get()->RegisterEventSink(cbEVT_EDITOR_UPDATE_UI , new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnEditorUpdateEvent));
131 //-Manager::Get()->RegisterEventSink(cbEVT_EDITOR_ACTIVATED, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnEditorActivated));
132 Manager::Get()->RegisterEventSink(cbEVT_EDITOR_DEACTIVATED, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnEditorDeactivated));
133 Manager::Get()->RegisterEventSink(cbEVT_EDITOR_CLOSE, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnEditorClosed));
134
135 Manager::Get()->RegisterEventSink(cbEVT_APP_START_SHUTDOWN, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnStartShutdown));
136 // -- Project events
137 Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnProjectActivatedEvent));
138 Manager::Get()->RegisterEventSink(cbEVT_PROJECT_CLOSE, new cbEventFunctor<JumpTracker, CodeBlocksEvent>(this, &JumpTracker::OnProjectClosing));
139
140 }
141 // ----------------------------------------------------------------------------
OnRelease(bool appShutDown)142 void JumpTracker::OnRelease(bool appShutDown)
143 // ----------------------------------------------------------------------------
144 {
145 // do de-initialization for your plugin
146 // if appShutDown is true, the plugin is unloaded because Code::Blocks is being shut down,
147 // which means you must not use any of the SDK Managers
148 // NOTE: after this function, the inherited member variable
149 // m_IsAttached will be FALSE...
150
151 wxWindow* appWin = Manager::Get()->GetAppWindow();
152
153 //If appShutdown leave the event handler, else wxWidgets asserts on linux
154 if (not appShutDown)
155 appWin->RemoveEventHandler(this); //2017/11/23 stop uninstall crash 2017/12/6 crashes linux
156
157 // Free JumpData memory
158 wxCommandEvent evt;
159 OnMenuJumpClear(evt);
160
161 appWin->Disconnect(idMenuJumpBack, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpBack), 0, this);
162 appWin->Disconnect(idMenuJumpNext, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpNext), 0, this);
163 appWin->Disconnect(idMenuJumpClear, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpClear), 0, this);
164 appWin->Disconnect(idMenuJumpDump, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(JumpTracker::OnMenuJumpDump), 0, this);
165
166 appWin->Disconnect(idToolJumpPrev, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(JumpTracker::OnMenuJumpBack), 0, this);
167 appWin->Disconnect(idToolJumpNext, wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler(JumpTracker::OnMenuJumpNext), 0, this);
168 appWin->Disconnect(idToolJumpPrev, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(JumpTracker::OnUpdateUI), 0, this);
169 appWin->Disconnect(idToolJumpNext, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(JumpTracker::OnUpdateUI), 0, this);
170
171 Manager::Get()-> Manager::Get()->RemoveAllEventSinksFor(this); //2017/11/23
172
173 }
174 // ----------------------------------------------------------------------------
BuildMenu(wxMenuBar * menuBar)175 void JumpTracker::BuildMenu(wxMenuBar* menuBar)
176 // ----------------------------------------------------------------------------
177 {
178 //The application is offering its menubar for your plugin,
179 //to add any menu items you want...
180 //Append any items you need in the menu...
181 //NOTE: Be careful in here... The application's menubar is at your disposal.
182 //-NotImplemented(_T("JumpTracker::BuildMenu()"));
183
184 // insert menu items
185 wxMenu* jump_submenu = new wxMenu;
186 jump_submenu->Append(idMenuJumpBack, _("Jump Back"), _("Jump back to previous ed position"));
187 jump_submenu->Append(idMenuJumpNext, _("Jump Frwd"), _("Jump to next ed position"));
188 jump_submenu->Append(idMenuJumpClear, _("Jump Clear"), _("Jump Clear History"));
189 #if defined(LOGGING)
190 jump_submenu->Append(idMenuJumpDump, _("Jump Dump"), _("Jump Dump Array"));
191 #endif
192
193 int viewPos = menuBar->FindMenu(_("&View"));
194
195 if ( viewPos == wxNOT_FOUND )
196 return;
197
198 // Place the menu inside the View Menu
199 wxMenu* pViewMenu = menuBar->GetMenu(viewPos);
200 pViewMenu->Append(idMenuJumpView, _("Jump"), jump_submenu, _("Jump"));
201
202 }
203 // ----------------------------------------------------------------------------
BuildModuleMenu(const ModuleType,wxMenu *,const FileTreeData *)204 void JumpTracker::BuildModuleMenu(const ModuleType /*type*/, wxMenu* /*menu*/, const FileTreeData* /*data*/)
205 // ----------------------------------------------------------------------------
206 {
207 //Some library module is ready to display a pop-up menu.
208 //Check the parameter \"type\" and see which module it is
209 //and append any items you need in the menu...
210 //TIP: for consistency, add a separator as the first item...
211 //-NotImplemented(_T("JumpTracker::BuildModuleMenu()"));
212 }
213 // ----------------------------------------------------------------------------
BuildToolBar(wxToolBar * toolBar)214 bool JumpTracker::BuildToolBar(wxToolBar* toolBar)
215 // ----------------------------------------------------------------------------
216 {
217 m_pToolBar = toolBar;
218
219 //The application is offering its toolbar for your plugin,
220 //to add any toolbar items you want...
221 //Append any items you need on the toolbar...
222 //-NotImplemented(_T("JumpTracker::BuildToolBar()"));
223
224 // return true if you add toolbar items
225 return false;
226 }
227 // ----------------------------------------------------------------------------
OnEditorUpdateEvent(CodeBlocksEvent & event)228 void JumpTracker::OnEditorUpdateEvent(CodeBlocksEvent& event)
229 // ----------------------------------------------------------------------------
230 {
231 event.Skip();
232
233 if ( m_bShuttingDown )
234 return;
235 if (m_bJumpInProgress)
236 return;
237
238 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
239 if(not ed)
240 return;
241
242 wxString edFilename = ed->GetFilename();
243 cbStyledTextCtrl* edstc = ed->GetControl();
244 if(edstc->GetCurrentLine() == wxSCI_INVALID_POSITION)
245 return;
246
247 long edLine = edstc->GetCurrentLine();
248 long edPosn = edstc->GetCurrentPos();
249
250 long topLine = edstc->GetFirstVisibleLine();
251 long scnSize = edstc->LinesOnScreen();
252 long botLine = (topLine+scnSize)-1; // In keeping with top line == 0 origin
253 botLine = (botLine < 0) ? 0 : botLine;
254 botLine = (botLine > edstc->GetLineCount()) ? edstc->GetLineCount() : botLine;
255
256 #if defined(LOGGING)
257 //LOGIT( _T("JT OnEditorUpdateEvent Filename[%s] line[%ld] pos[%ld] "), edFilename.c_str(), edLine, edPosn);
258 //LOGIT( _T("JT \ttopLine[%ld] botLine[%ld] OnScrn[%ld] "), topLine, botLine, edstc->LinesOnScreen());
259 #endif
260
261 // New editor activated?
262 if (m_FilenameLast not_eq edFilename)
263 {
264 m_PosnLast = edPosn;
265 m_FilenameLast = edFilename;
266 //if ( m_cursor not_eq JumpDataContains(edFilename, edPosn) )
267 JumpDataAdd(edFilename, edPosn, edLine);
268 }
269
270 // If new line within half screen of old line, don't record current line
271 //-long lineLast = edstc->LineFromPosition(m_PosnLast);
272
273 //-bool bIsVis = ( edstc->GetLineVisible(lineLast) ); doesnt work
274 //-if ( (lineLast >= topLine) && doesnt work
275 //- (lineLast < botLine) )
276 //-int halfPageSize = edstc->LinesOnScreen()>>1;
277 //-if ( halfPageSize > abs(edLine - lineLast))
278 //- ;//return;
279
280 // if user has not moved cursor, ignore this update
281 if (m_PosnLast == edPosn)
282 return;
283
284 // record new posn
285 m_PosnLast = edPosn;
286 m_FilenameLast = edFilename;
287 //if ( m_cursor not_eq JumpDataContains(edFilename, edPosn) )
288 JumpDataAdd(edFilename, edPosn, edLine);
289
290 return;
291 }//OnEditorUpdateEvent
292 // ----------------------------------------------------------------------------
OnEditorActivated(CodeBlocksEvent & event)293 void JumpTracker::OnEditorActivated(CodeBlocksEvent& event)
294 // ----------------------------------------------------------------------------
295 {
296 // Record this activation event and place activation in history
297 event.Skip();
298
299 if (m_bShuttingDown) return;
300 if (not IsAttached()) return;
301
302 // Don't record closing editor activations
303 if (m_bProjectClosing)
304 return;
305
306 EditorBase* eb = event.GetEditor();
307 wxString edFilename = eb->GetFilename();
308 cbEditor* cbed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(eb);
309
310 if (not cbed)
311 {
312 // Since wxAuiNotebook added, there's no cbEditor associated during
313 // an initial cbEVT_EDITOR_ACTIVATED event. So we ignore the inital
314 // call and get OnEditorOpened() to re-issue OnEditorActivated() when
315 // it does have a cbEditor, but no cbProject associated;
316 #if defined(LOGGING)
317 LOGIT( _T("JT [OnEditorActivated ignored:no cbEditor[%s]"), edFilename.c_str());
318 #endif
319 return;
320 }
321
322 #if defined(LOGGING)
323 LOGIT( _T("JT Editor Activated[%s]"), eb->GetShortName().c_str() );
324 #endif
325
326 cbStyledTextCtrl* edstc = cbed->GetControl();
327 if(edstc->GetCurrentLine() == wxSCI_INVALID_POSITION)
328 return;
329
330 long edPosn = edstc->GetCurrentPos();
331 //if ( m_cursor not_eq JumpDataContains(edFilename, edPosn) )
332 JumpDataAdd(edFilename, edPosn, edstc->GetCurrentLine());
333 return;
334 }//OnEditorActivated
335 // ----------------------------------------------------------------------------
OnEditorDeactivated(CodeBlocksEvent & event)336 void JumpTracker::OnEditorDeactivated(CodeBlocksEvent& event)
337 // ----------------------------------------------------------------------------
338 {
339 // Record this deactivation event and place deactivation location in history
340 event.Skip();
341
342 if (m_bShuttingDown) return;
343 if (not IsAttached()) return;
344
345 // Don't record closing editor deactivations
346 if (m_bProjectClosing)
347 return;
348
349 if ( Manager::Get()->GetProjectManager()->IsLoading() )
350 return;
351
352 EditorBase* eb = event.GetEditor();
353 wxString edFilename = eb->GetFilename();
354 cbEditor* cbed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(eb);
355
356 if (not cbed)
357 {
358 // We ignore events with no associated editor
359 #if defined(LOGGING)
360 LOGIT( _T("JT [OnEditorDeactivated ignored:no cbEditor[%s]"), edFilename.c_str());
361 #endif
362 return;
363 }
364
365 #if defined(LOGGING)
366 LOGIT( _T("JT Editor DeActivated[%s]"), eb->GetShortName().c_str() );
367 #endif
368
369 cbStyledTextCtrl* edstc = cbed->GetControl();
370 if(edstc->GetCurrentLine() == wxSCI_INVALID_POSITION)
371 return;
372
373 long edPosn = edstc->GetCurrentPos();
374 //if ( m_cursor not_eq JumpDataContains(edFilename, edPosn) )
375 JumpDataAdd(edFilename, edPosn, edstc->GetCurrentLine());
376 return;
377 }//OnEditorDeactivated
378 // ----------------------------------------------------------------------------
OnEditorClosed(CodeBlocksEvent & event)379 void JumpTracker::OnEditorClosed(CodeBlocksEvent& event)
380 // ----------------------------------------------------------------------------
381 {
382 // clear this editor out of our arrays and pointers
383
384 //_NOTE: using Manager::Get->GetEditorManager()->GetEditor... etc will
385 // fail in this codeblocks event.
386 // The cbEditors are nolonger available
387
388 event.Skip();
389
390 if (not IsAttached())
391 return;
392
393 wxString filePath = event.GetString();
394
395 #if defined(LOGGING)
396 EditorBase* eb = event.GetEditor();
397 LOGIT( _T("JT OnEditorClosed Eb[%p][%s]"), eb, eb->GetShortName().c_str() );
398 #endif
399
400
401 for (int ii=m_ArrayOfJumpData.GetCount()-1; ii > -1; --ii)
402 {
403 if (m_ArrayOfJumpData[ii].GetFilename() == filePath)
404 m_ArrayOfJumpData.RemoveAt(ii);
405 if (((int)m_ArrayOfJumpData.GetCount()-1) < m_cursor)
406 m_cursor = GetPreviousIndex(m_cursor);
407 if (((int)m_ArrayOfJumpData.GetCount()-1) < m_insertNext)
408 m_insertNext = GetPreviousIndex(m_insertNext);
409 }
410 #if defined(LOGGING)
411 wxCommandEvent evt;
412 OnMenuJumpDump(evt);
413 #endif
414
415 }//OnEditorClosed
416
417 // ----------------------------------------------------------------------------
OnStartShutdown(CodeBlocksEvent &)418 void JumpTracker::OnStartShutdown(CodeBlocksEvent& /*event*/)
419 // ----------------------------------------------------------------------------
420 {
421 m_bShuttingDown = true;
422 }
423 // ----------------------------------------------------------------------------
OnProjectClosing(CodeBlocksEvent & event)424 void JumpTracker::OnProjectClosing(CodeBlocksEvent& event)
425 // ----------------------------------------------------------------------------
426 {
427 event.Skip();
428
429 // This hook occurs before the editors are closed. That allows
430 // us to reference CB project and editor related data before CB
431 // deletes it all.
432
433 if (m_bShuttingDown) return;
434 if (not IsAttached()) return;
435
436 //cbProject* pProject = event.GetProject();
437 //if (not pProject) return; //It happens!
438
439 m_bProjectClosing = true;
440 }
441 // ----------------------------------------------------------------------------
OnProjectActivatedEvent(CodeBlocksEvent & event)442 void JumpTracker::OnProjectActivatedEvent(CodeBlocksEvent& event)
443 // ----------------------------------------------------------------------------
444 {
445 event.Skip();
446
447 // NB: EVT_PROJECT_ACTIVATE is occuring before EVT_PROJECT_OPEN
448 // NB: EVT_EDITOR_ACTIVATE event occur before EVT_PROJECT_ACTIVATE or EVT_PROJECT_OPEN
449
450 event.Skip();
451 if (m_bShuttingDown) return;
452 if (not IsAttached()) return;
453
454 // Previous project was closing
455 if (m_bProjectClosing)
456 m_bProjectClosing = false;
457
458 }//OnProjectActivatedEvent
459 // ----------------------------------------------------------------------------
OnUpdateUI(wxUpdateUIEvent & event)460 void JumpTracker::OnUpdateUI(wxUpdateUIEvent& event)
461 // ----------------------------------------------------------------------------
462 {
463 int count = m_ArrayOfJumpData.GetCount();
464 //-m_pToolBar->EnableTool(idToolJumpNext, count > 0 /*&& m_cursor != m_insertNext - 1*/);
465 //-m_pToolBar->EnableTool(idToolJumpPrev, count > 0 /*&& m_cursor != m_insertNext*/);
466
467 // If not wrapping && we're about to advance into the insert index, diable
468 bool enableNext = (count > 0);
469 if (not m_bWrapJumpEntries)
470 if (m_cursor == m_insertNext)
471 enableNext = false;
472
473 bool enablePrev = count > 0;
474 // If not wrapping && we're about to backup into the insert index, disable
475 if (not m_bWrapJumpEntries)
476 if (GetPreviousIndex(m_cursor) == m_insertNext)
477 enablePrev = false;
478
479 m_pToolBar->EnableTool( idToolJumpNext, enableNext);
480 m_pToolBar->EnableTool( idToolJumpPrev, enablePrev);
481
482 event.Skip();
483 }
484 // ----------------------------------------------------------------------------
JumpDataAdd(const wxString & filename,const long posn,const long lineNum)485 void JumpTracker::JumpDataAdd(const wxString& filename, const long posn, const long lineNum)
486 // ----------------------------------------------------------------------------
487 {
488 // Do not record old jump locations when a jump is in progress
489 // Caused by activating an editor inside the jump routines
490 if (m_bJumpInProgress)
491 return;
492
493 // Dont record position if line number is < 1 since a newly loaded
494 // file always reports an event for line 0
495 if (lineNum < 1) // user requested feature 2010/06/1
496 return;
497
498 // if current entry is identical edit line, just update position
499 if ( JumpDataContains(m_cursor,filename, posn))
500 {
501 m_ArrayOfJumpData[m_cursor].SetPosition(posn);
502 return;
503 }
504 if ( JumpDataContains(GetPreviousIndex(m_insertNext), filename, posn))
505 {
506 m_ArrayOfJumpData[GetPreviousIndex(m_insertNext)].SetPosition(posn);
507 return;
508 }
509
510 //
511 // record new jump entry
512 //
513
514 size_t kount = m_ArrayOfJumpData.GetCount();
515 if ( m_insertNext > maxJumpEntries-1 )
516 m_insertNext = 0;
517
518 #if defined(LOGGING)
519 LOGIT( _T("JT JumpDataAdd[%s][%ld][%d]"), filename.c_str(), posn, m_insertNext);
520 #endif
521
522 if ( kount == maxJumpEntries )
523 { //remove last item in the array
524 m_ArrayOfJumpData.RemoveAt(maxJumpEntries-1);
525 }
526
527 //initialize new item
528 m_insertNext = GetNextIndex(m_insertNext);
529 m_ArrayOfJumpData.Insert(new JumpData(filename, posn), m_insertNext);
530 m_cursor = m_insertNext;
531
532 #if defined(LOGGING)
533 wxCommandEvent evt;
534 OnMenuJumpDump(evt);
535 #endif
536 return;
537 }
538 // ----------------------------------------------------------------------------
FindJumpDataContaining(const wxString & filename,const long posn)539 int JumpTracker::FindJumpDataContaining(const wxString& filename, const long posn)
540 // ----------------------------------------------------------------------------
541 {
542 size_t kount = m_ArrayOfJumpData.GetCount();
543 if (not kount) return wxNOT_FOUND;
544
545 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(filename);
546 if (not ed) return wxNOT_FOUND;
547
548 cbStyledTextCtrl* pstc = ed->GetControl();
549 if (not pstc) return wxNOT_FOUND;
550
551 int halfPageSize = pstc->LinesOnScreen()>>1;
552
553 // search from array insertion point so we check last entered entry first
554 size_t j = m_insertNext;
555 for (size_t i=0; i<kount; ++i, ++j)
556 {
557 j = GetPreviousIndex(j);
558 JumpData& jumpData = m_ArrayOfJumpData.Item(j);
559 if ( jumpData.GetFilename() not_eq filename )
560 continue;
561 long jumpLine = pstc->LineFromPosition(jumpData.GetPosition());
562 long currLine = pstc->LineFromPosition(posn);
563 if ( halfPageSize > abs(jumpLine - currLine))
564 return j;
565 }
566
567 return wxNOT_FOUND;
568 }
569 // ----------------------------------------------------------------------------
JumpDataContains(const int indx,const wxString & filename,const long posn)570 bool JumpTracker::JumpDataContains(const int indx, const wxString& filename, const long posn)
571 // ----------------------------------------------------------------------------
572 {
573 size_t kount = m_ArrayOfJumpData.GetCount();
574 if (not kount) return false;
575
576 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(filename);
577 if (not ed) return false;
578
579 cbStyledTextCtrl* pstc = ed->GetControl();
580 if (not pstc) return false;
581
582 int halfPageSize = pstc->LinesOnScreen()>>1;
583
584 JumpData& jumpData = m_ArrayOfJumpData.Item(indx);
585 if ( jumpData.GetFilename() not_eq filename )
586 return false;
587 long jumpLine = pstc->LineFromPosition(jumpData.GetPosition());
588 long currLine = pstc->LineFromPosition(posn);
589 if ( halfPageSize > abs(jumpLine - currLine))
590 return true;
591
592
593 return false;
594 }
595 // ----------------------------------------------------------------------------
OnMenuJumpBack(wxCommandEvent &)596 void JumpTracker::OnMenuJumpBack(wxCommandEvent &/*event*/)
597 // ----------------------------------------------------------------------------
598 {
599 #if defined(LOGGING)
600 LOGIT( _T("JT [%s]"), _T("OnMenuJumpBack"));
601 #endif
602
603 int knt = m_ArrayOfJumpData.GetCount();
604 if (0 == knt)
605 return;
606
607 // If not wrapping && we're about to backup into the insert index, return
608 if (not m_bWrapJumpEntries)
609 if (GetPreviousIndex(m_cursor) == m_insertNext)
610 return;
611
612
613 EditorManager* edmgr = Manager::Get()->GetEditorManager();
614 EditorBase* eb = edmgr->GetActiveEditor();
615 cbEditor* cbed = (eb ? edmgr->GetBuiltinEditor(eb) : nullptr);
616
617 if (not cbed)
618 return;
619
620 m_bJumpInProgress = true;
621
622 //-long activeEdLine = 0;
623 long activeEdPosn = 0;
624 wxString activeEdFilename = wxEmptyString;
625 if (cbed)
626 {
627 //-activeEdLine = cbed->GetControl()->GetCurrentLine();
628 activeEdPosn = cbed->GetControl()->GetCurrentPos();
629 activeEdFilename = cbed->GetFilename();
630 }
631
632 // if active editor line == m_cursor, back up the m_cursor
633 // until finding an entry that does not match this m_cursor entry.
634 // else
635 // find the previous m_insertNext entry that does not match this editor or line number
636
637 do { // find the previous appropriate jump position
638
639 // if current cursor position is also current editor and line,
640 // return the previous m_cursor entry
641 if ( JumpDataContains(m_cursor, cbed->GetFilename(), activeEdPosn))
642 {
643 // FIXME (ph#): a dead editor can be returned here
644 m_cursor = GetPreviousIndex(m_cursor);
645 }
646 else //find an entry (backward) from the insertion point
647 {
648 int idx = m_insertNext;
649
650 for (int ii=0; ii<knt; ++ii)
651 {
652 idx = GetPreviousIndex(idx);
653 if ( idx == wxNOT_FOUND)
654 break;
655 JumpData& jumpdata = m_ArrayOfJumpData[idx];
656 if (not edmgr->IsOpen(jumpdata.GetFilename()))
657 continue;
658 // skip entry when same as current position
659 if ( JumpDataContains(idx, activeEdFilename, activeEdPosn))
660 continue;
661 else
662 {
663 m_cursor = idx;
664 break; //for
665 }
666 }//for
667 }//else
668
669 JumpData& jumpData = m_ArrayOfJumpData[m_cursor];
670 wxString edFilename = jumpData.GetFilename();
671 long edPosn = jumpData.GetPosition();
672 #if defined(LOGGING)
673 LOGIT( _T("JT OnMenuJumpBack [%s][%ld]curs[%d]"), edFilename.wx_str(), edPosn, m_cursor);
674 #endif
675
676 // activate editor
677 eb = edmgr->GetEditor(edFilename);
678 if (not eb) break;
679
680 edmgr->SetActiveEditor(eb); // cause a cbEVT_EditorActivated event
681 // position to editor line
682 cbed = edmgr->GetBuiltinEditor(eb);
683 if (not cbed) break;
684
685 cbed->GotoLine(cbed->GetControl()->LineFromPosition(edPosn)); //center on scrn
686 cbed->GetControl()->GotoPos(edPosn);
687
688 }while(0);
689
690 #if defined(LOGGING)
691 LOGIT( _T("JT [%s]"), _T("END OnMenuJumpBack"));
692 wxCommandEvent evt;
693 OnMenuJumpDump(evt);
694 #endif
695
696 m_bJumpInProgress = false;
697 return;
698 }
699 // ----------------------------------------------------------------------------
OnMenuJumpNext(wxCommandEvent &)700 void JumpTracker::OnMenuJumpNext(wxCommandEvent &/*event*/)
701 // ----------------------------------------------------------------------------
702 {
703 #if defined(LOGGING)
704 LOGIT( _T("JT [%s]"), _T("OnMenuJumpNext"));
705 #endif
706
707 int knt = m_ArrayOfJumpData.GetCount();
708 if (0 == knt)
709 return;
710
711 // If not wrapping && we're about to advance into the insert index, return
712 //-if (GetNextIndex(m_cursor) == m_insertNext)
713 if (not m_bWrapJumpEntries)
714 if (m_cursor == m_insertNext)
715 return;
716
717
718 EditorManager* edmgr = Manager::Get()->GetEditorManager();
719 EditorBase* eb = edmgr->GetActiveEditor();
720 cbEditor* cbed = (eb ? edmgr->GetBuiltinEditor(eb) : nullptr);
721
722 if (not cbed)
723 return;
724
725 m_bJumpInProgress = true;
726
727 //-long activeEdLine = 0;
728 long activeEdPosn = 0;
729 wxString activeEdFilename = wxEmptyString;
730 if (cbed)
731 {
732 //-activeEdLine = cbed->GetControl()->GetCurrentLine();
733 activeEdPosn = cbed->GetControl()->GetCurrentPos();
734 activeEdFilename = cbed->GetFilename();
735 }
736
737 // if active editor line == m_cursor, advance up the m_cursor
738 // until finding an entry that does not match this m_cursor entry.
739 // else
740 // find the next m_insertNext entry that does not match this editor or line number
741
742 do { // find the next appropriate jump position
743
744 // if current cursor position is also current editor and line,
745 // return the next m_cursor entry
746 if ( JumpDataContains(m_cursor, cbed->GetFilename(), activeEdPosn))
747 {
748 m_cursor = GetNextIndex(m_cursor);
749 }
750 else //find an entry (forward) from the insertion point
751 {
752 int idx = m_insertNext;
753
754 for (int ii=0; ii<knt; ++ii)
755 {
756 idx = GetNextIndex(idx);
757 if ( idx == wxNOT_FOUND)
758 break;
759 JumpData& jumpdata = m_ArrayOfJumpData[idx];
760 if (not edmgr->IsOpen(jumpdata.GetFilename()))
761 continue;
762
763 if ( not JumpDataContains(idx, activeEdFilename, activeEdPosn))
764 {
765 m_cursor = idx;
766 break; //for
767 }
768 }//for
769 }
770
771 JumpData& jumpData = m_ArrayOfJumpData[m_cursor];
772 wxString edFilename = jumpData.GetFilename();
773 long edPosn = jumpData.GetPosition();
774 #if defined(LOGGING)
775 LOGIT( _T("JT OnMenuJumpBack [%s][%ld]curs[%d]"), edFilename.wx_str(), edPosn, m_cursor);
776 #endif
777
778 // activate editor
779 eb = edmgr->GetEditor(edFilename);
780 if (not eb) break;
781
782 edmgr->SetActiveEditor(eb); // cause a cbEVT_EditorActivated event
783 // position to editor line
784 cbed = edmgr->GetBuiltinEditor(eb);
785 if (not cbed) break;
786
787 cbed->GotoLine(cbed->GetControl()->LineFromPosition(edPosn)); //center on scrn
788 cbed->GetControl()->GotoPos(edPosn);
789
790 }while(0);
791
792 #if defined(LOGGING)
793 LOGIT( _T("JT [%s]"), _T("END OnMenuJumpBack"));
794 wxCommandEvent evt;
795 OnMenuJumpDump(evt);
796 #endif
797
798 m_bJumpInProgress = false;
799 return;
800 }
801 // ----------------------------------------------------------------------------
OnMenuJumpClear(wxCommandEvent &)802 void JumpTracker::OnMenuJumpClear(wxCommandEvent &/*event*/)
803 // ----------------------------------------------------------------------------
804 {
805 m_insertNext = m_cursor = maxJumpEntries;
806 m_ArrayOfJumpData.Clear();
807 }
808 // ----------------------------------------------------------------------------
OnMenuJumpDump(wxCommandEvent &)809 void JumpTracker::OnMenuJumpDump(wxCommandEvent &/*event*/)
810 // ----------------------------------------------------------------------------
811 {
812 #if defined(LOGGING)
813 if (not m_ArrayOfJumpData.GetCount())
814 LOGIT( _T("JumpDump Empty"));
815
816 for (size_t count = 0; count < m_ArrayOfJumpData.GetCount(); ++count)
817 {
818 JumpData& jumpData = m_ArrayOfJumpData.Item(count);
819 wxString edFilename = jumpData.GetFilename();
820 long edLine = wxNOT_FOUND;
821 long edPosn = jumpData.GetPosition();
822 cbStyledTextCtrl* pstc = 0;
823 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(edFilename);
824 if ( ed )
825 {
826 pstc = ed->GetControl();
827 if (not pstc) pstc = 0;
828 if (pstc)
829 edLine = pstc->LineFromPosition(jumpData.GetPosition());
830 edLine +=1; //editors are 0 origin
831 }
832
833 wxString msg = wxString::Format(_T("[%d][%s][%ld][%ld]"), count, edFilename.c_str(), edPosn, edLine);
834 if (count == (size_t)m_cursor)
835 msg.Append(_T("<--c"));
836 if (count == (size_t)m_insertNext)
837 msg.Append(_T("<--i"));
838 LOGIT( msg );
839 }
840
841 #endif
842 }
843 // ----------------------------------------------------------------------------
SetWrapJumpEntries(const bool tf)844 void JumpTracker::SetWrapJumpEntries(const bool tf)
845 // ----------------------------------------------------------------------------
846 {
847 m_bWrapJumpEntries = tf;
848 }
849 // ----------------------------------------------------------------------------
GetPreviousIndex(const int idx)850 int JumpTracker::GetPreviousIndex(const int idx)
851 // ----------------------------------------------------------------------------
852 {
853 int prev = idx;
854 int knt = m_ArrayOfJumpData.GetCount();
855 prev--;
856 if ( prev < 0 )
857 prev = knt-1;
858 if ( prev < 0 )
859 prev = 0;
860 return prev;
861 }
862 // ----------------------------------------------------------------------------
GetNextIndex(const int idx)863 int JumpTracker::GetNextIndex(const int idx)
864 // ----------------------------------------------------------------------------
865 {
866 int next = idx;
867 int knt = m_ArrayOfJumpData.GetCount();
868 next++;
869 if ( next > (knt-1) )
870 next = 0;
871 return next;
872 }
873