Code::Blocks  SVN r11506
app.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11427 $
6  * $Id: app.cpp 11427 2018-06-30 19:37:11Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/src/app.cpp $
8  */
9 
10 #include <sdk.h>
11 #include "app.h"
12 
13 #include <wx/arrstr.h>
14 #include <wx/fs_zip.h>
15 #include <wx/fs_mem.h>
16 #include <wx/xrc/xmlres.h>
17 #include <wx/cmdline.h>
18 #include <wx/regex.h>
19 #include <wx/filefn.h>
20 #include <wx/log.h> // for wxSafeShowMessage()
21 #include <wx/msgdlg.h>
22 #include <wx/choicdlg.h>
23 #include <wx/notebook.h>
24 #include <wx/clipbrd.h>
25 #include <wx/debugrpt.h>
26 #include <wx/ipc.h>
27 #include <wx/msgout.h>
28 
29 #include <cbexception.h>
30 #include <configmanager.h>
31 #include <debuggermanager.h>
32 #include <editormanager.h>
33 #include <globals.h>
34 #include <loggers.h>
35 #include <logmanager.h>
36 #include <manager.h>
37 #include <personalitymanager.h>
38 #include <pluginmanager.h>
39 #include <projectmanager.h>
40 #include <scriptingmanager.h>
41 #include <sdk_events.h>
42 #include <sqplus.h>
43 
44 #include "appglobals.h"
45 #include "associations.h"
46 #include "cbauibook.h"
47 #include "cbstyledtextctrl.h"
48 #include "crashhandler.h"
49 #include "projectmanagerui.h"
50 #include "splashscreen.h"
51 
52 #ifndef __WXMSW__
53  #include "prefix.h" // binreloc
54 #endif
55 
56 #if defined(__APPLE__) && defined(__MACH__)
57 #include <sys/param.h>
58 #include <mach-o/dyld.h>
59 #endif
60 
61 #ifndef CB_PRECOMP
62  #include <wx/dir.h>
63  #include "xtra_res.h"
64  #include "filemanager.h" // LoaderBase
65 #endif
66 
67 #ifndef APP_PREFIX
68 #define APP_PREFIX ""
69 #endif
70 
71 #ifdef __WXMSW__
72 #include "exchndl.h" // Crash handler DLL -> includes windows.h, therefore
73 #include <wx/msw/winundef.h> // ...include this header file on the NEXT LINE (wxWidgets docs say so)
74 #endif
75 
76 #ifndef __WXMAC__
78 #endif
79 
80 namespace
81 {
82 bool s_Loading = false;
83 
84 class DDEServer : public wxServer
85 {
86  public:
87  DDEServer(MainFrame* frame) : m_Frame(frame) { ; }
88  wxConnectionBase *OnAcceptConnection(const wxString& topic) override;
89  MainFrame* GetFrame() { return m_Frame; }
90  void SetFrame(MainFrame* frame) { m_Frame = frame; }
91  private:
92  MainFrame* m_Frame;
93 };
94 
95 class DDEConnection : public wxConnection
96 {
97  public:
98  DDEConnection(MainFrame* frame) : m_Frame(frame) { ; }
99 #if wxCHECK_VERSION(3, 0, 0)
100  bool OnExecute(const wxString& topic, const void *data, size_t size,
101  wxIPCFormat format) override;
102 #else
103  bool OnExecute(const wxString& topic, wxChar *data, int size, wxIPCFormat format) override;
104 #endif
105  bool OnDisconnect() override;
106  private:
107  MainFrame* m_Frame;
108 };
109 
110 wxConnectionBase* DDEServer::OnAcceptConnection(const wxString& topic)
111 {
112  return topic == DDE_TOPIC ? new DDEConnection(m_Frame) : nullptr;
113 }
114 
115 #if wxCHECK_VERSION(3, 0, 0)
116 bool DDEConnection::OnExecute(cb_unused const wxString& topic, const void *data, size_t size,
117  wxIPCFormat format)
118 {
119  const wxString strData = wxConnection::GetTextFromData(data, size, format);
120 #else
121 bool DDEConnection::OnExecute(cb_unused const wxString& topic, wxChar *data, int size,
122  wxIPCFormat format)
123 {
124  const wxString strData((wxChar*)data);
125 #endif
126 
127  if (strData.StartsWith(_T("[IfExec_Open(\"")))
128  return false; // let Shell Open handle the request as we *know* that we have registered the Shell Open command, too
129 
130  if (strData.StartsWith(_T("[Open(\"")))
131  {
132  wxRegEx reCmd(_T("\"(.*)\""));
133  if (reCmd.Matches(strData))
134  {
135  const wxString file = reCmd.GetMatch(strData, 1);
136  // always put files in the delayed queue, the will either be loaded in OnDisconnect, or after creating of MainFrame
137  // if we open the files directly it can lead to an applicaton hang (at least when opening C::B's project-file on linux)
139  if (cb)
140  cb->AddFileToOpenDelayed(file);
141  }
142  return true;
143  }
144  else if (strData.StartsWith(_T("[OpenLine(\"")))
145  {
146  wxRegEx reCmd(_T("\"(.*)\""));
147  if (reCmd.Matches(strData))
148  {
149  wxString file = reCmd.GetMatch(strData, 1);
151  cb->SetAutoFile(file);
152  }
153  return true;
154  }
155  else if (strData.StartsWith(_T("[Raise]")))
156  {
157  if (m_Frame)
158  {
159  if (m_Frame->IsIconized())
160  m_Frame->Iconize(false);
161  m_Frame->Raise();
162  }
163  return true;
164  }
165  else if (strData.StartsWith(_T("[CmdLine({")))
166  {
167  int pos = strData.Find(_T("})]"));
168  if (pos!=wxNOT_FOUND)
169  {
170  wxString line = strData.Mid(10, pos-10);
171  line.Replace(_T("\\)"), _T(")"));
172  line.Replace(_T("\\("), _T("("));
174  if (m_Frame && !line.empty())
175  {
176  // Manager::Get()->GetLogManager()->Log(wxString::Format(_T("DDEConnection::OnExecute line = ") + line));
177  cb->ParseCmdLine(m_Frame, line);
179  Manager::Get()->ProcessEvent(event);
180  }
181 
182  }
183  return true;
184  }
185  wxSafeShowMessage(wxT("Warning"),wxString::Format(wxT("DDE topic %s not handled."),strData.wx_str()));
186  return false;
187 }
188 
189 bool DDEConnection::OnDisconnect()
190 {
191  // delayed files will be loaded automatically if MainFrame already exists,
192  // otherwise it happens automatically in OnInit after MainFrame is created
193  if (!s_Loading && m_Frame)
194  {
196  cb->LoadDelayedFiles(m_Frame);
197  cb->AttachDebugger();
198  }
199  return true;
200 }
201 
202 DDEServer* g_DDEServer = nullptr;
203 
204 class DDEClient: public wxClient {
205  public:
206  DDEClient(void) {}
207  wxConnectionBase *OnMakeConnection(void) override { return new DDEConnection(nullptr); }
208 };
209 
210 #if wxUSE_CMDLINE_PARSER
211 #if wxCHECK_VERSION(3, 0, 0)
212 #define CMD_ENTRY(X) X
213 #else
214 #define CMD_ENTRY(X) _T(X)
215 #endif
216 const wxCmdLineEntryDesc cmdLineDesc[] =
217 {
218  { wxCMD_LINE_SWITCH, CMD_ENTRY("h"), CMD_ENTRY("help"), CMD_ENTRY("show this help message"),
220  { wxCMD_LINE_SWITCH, CMD_ENTRY("?"), CMD_ENTRY("?"), CMD_ENTRY("show this help message (alias for help)"),
221  wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
222  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("safe-mode"), CMD_ENTRY("load in safe mode (all plugins will be disabled)"),
224 #ifdef __WXMSW__
225  { wxCMD_LINE_SWITCH, CMD_ENTRY("na"), CMD_ENTRY("no-check-associations"), CMD_ENTRY("don't perform any association checks"),
226  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
227  { wxCMD_LINE_SWITCH, CMD_ENTRY("nd"), CMD_ENTRY("no-dde"), CMD_ENTRY("don't start a DDE server"),
228  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
229 #endif
230 #ifndef __WXMSW__
231  { wxCMD_LINE_SWITCH, CMD_ENTRY("ni"), CMD_ENTRY("no-ipc"), CMD_ENTRY("don't start an IPC server"),
232  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
233 #endif
234  { wxCMD_LINE_SWITCH, CMD_ENTRY("ns"), CMD_ENTRY("no-splash-screen"), CMD_ENTRY("don't display a splash screen while loading"),
235  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
236  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("multiple-instance"), CMD_ENTRY("allow running multiple instances"),
237  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
238  { wxCMD_LINE_SWITCH, CMD_ENTRY("d"), CMD_ENTRY("debug-log"), CMD_ENTRY("display application's debug log"),
239  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
240  { wxCMD_LINE_SWITCH, CMD_ENTRY("nc"), CMD_ENTRY("no-crash-handler"), CMD_ENTRY("don't use the crash handler (useful for debugging C::B)"),
241  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
242  { wxCMD_LINE_SWITCH, CMD_ENTRY("v"), CMD_ENTRY("verbose"), CMD_ENTRY("show more debugging messages"),
243  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
244  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("prefix"), CMD_ENTRY("the shared data dir prefix"),
246  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("user-data-dir"), CMD_ENTRY("set a custom location for user settings and plugins"),
247  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
248  { wxCMD_LINE_OPTION, CMD_ENTRY("p"), CMD_ENTRY("personality"), CMD_ENTRY("the personality to use: \"ask\" or <personality-name>"),
249  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
250  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("no-log"), CMD_ENTRY("turn off the application log"),
251  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
252  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("log-to-file"), CMD_ENTRY("redirect application log to a file"),
253  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
254  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("debug-log-to-file"), CMD_ENTRY("redirect application debug log to a file"),
255  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
256  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("profile"), CMD_ENTRY("synonym to personality"),
257  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
258  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("rebuild"), CMD_ENTRY("clean and then build the project/workspace"),
259  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
260  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("build"), CMD_ENTRY("just build the project/workspace"),
261  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
262  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("clean"), CMD_ENTRY("clean the project/workspace"),
263  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
264  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("target"), CMD_ENTRY("the target for the batch build"),
265  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
266  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("no-batch-window-close"), CMD_ENTRY("do not auto-close log window when batch build is done"),
267  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
268  { wxCMD_LINE_SWITCH, CMD_ENTRY(""), CMD_ENTRY("batch-build-notify"), CMD_ENTRY("show message when batch build is done"),
269  wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
270  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("script"), CMD_ENTRY("execute script file"),
271  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
272  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("file"), CMD_ENTRY("open file and optionally jump to specific line (file[:line])"),
273  wxCMD_LINE_VAL_STRING, wxCMD_LINE_NEEDS_SEPARATOR },
274  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("dbg-config"), CMD_ENTRY("selects the debugger config used for attaching (uses the current selected target if omitted) "),
275  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
276  { wxCMD_LINE_OPTION, CMD_ENTRY(""), CMD_ENTRY("dbg-attach"), CMD_ENTRY("string passed to the debugger plugin which is used for attaching to a process"),
277  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_NEEDS_SEPARATOR },
278  { wxCMD_LINE_PARAM, CMD_ENTRY(""), CMD_ENTRY(""), CMD_ENTRY("filename(s)"),
279  wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE },
280  { wxCMD_LINE_NONE }
281 };
282 #endif // wxUSE_CMDLINE_PARSER
283 
284 class Splash
285 {
286  public:
287  Splash(const bool show) : m_pSplash(nullptr)
288  {
289  if (show)
290  {
291  wxBitmap bmp = cbLoadBitmap(ConfigManager::ReadDataPath() + _T("/images/splash_1312.png"));
292  wxMemoryDC dc;
293  dc.SelectObject(bmp);
295  dc.SelectObject(wxNullBitmap);
296  m_pSplash = new cbSplashScreen(bmp);
297  Manager::Yield();
298  }
299  }
300  ~Splash()
301  {
302  Hide();
303  }
304  void Hide()
305  {
306  if (m_pSplash)
307  {
308  m_pSplash->Destroy();
309  m_pSplash = nullptr;
310  }
311  }
312 
313  private:
314  cbSplashScreen* m_pSplash;
315 };
316 
317 class cbMessageOutputNull : public wxMessageOutput
318 {
319 public:
320 
321 #if wxCHECK_VERSION(3, 0, 0)
322  virtual void Output(const wxString &str);
323 #else
324  #ifdef WX_ATTRIBUTE_PRINTF
325  virtual void Printf(const wxChar* format, ...) WX_ATTRIBUTE_PRINTF_2;
326  #else
327  void Printf(const wxChar* format, ...) override ATTRIBUTE_PRINTF_2;
328  #endif
329 #endif // wxCHECK_VERSION
330 };
331 #if wxCHECK_VERSION(3, 0, 0)
332 void cbMessageOutputNull::Output(cb_unused const wxString &str){}
333 #else
334 void cbMessageOutputNull::Printf(cb_unused const wxChar* format, ...){}
335 #endif
336 } // namespace
337 
338 IMPLEMENT_APP(CodeBlocksApp) // TODO: This gives a "redundant declaration" warning, though I think it's false. Dig through macro and check.
339 
340 BEGIN_EVENT_TABLE(CodeBlocksApp, wxApp)
341  EVT_ACTIVATE_APP(CodeBlocksApp::OnAppActivate)
342  EVT_TASKBAR_LEFT_DOWN(CodeBlocksApp::OnTBIconLeftDown)
343 END_EVENT_TABLE()
344 
345 #ifdef __WXMAC__
346 #if wxCHECK_VERSION(3, 0, 0)
347 #include "wx/osx/core/cfstring.h"
348 #else
349 #include "wx/mac/corefoundation/cfstring.h"
350 #endif
351 #include "wx/intl.h"
352 
353 #include <CoreFoundation/CFBundle.h>
354 #include <CoreFoundation/CFURL.h>
355 
356 // returns e.g. "/Applications/appname.app/Contents/Resources" if application is bundled,
357 // or the directory of the binary, e.g. "/usr/local/bin/appname", if it is *not* bundled.
358 static wxString GetResourcesDir()
359 {
360  CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
361  CFURLRef absoluteURL = CFURLCopyAbsoluteURL(resourcesURL); // relative -> absolute
362  CFRelease(resourcesURL);
363  CFStringRef cfStrPath = CFURLCopyFileSystemPath(absoluteURL,kCFURLPOSIXPathStyle);
364  CFRelease(absoluteURL);
365  #if wxCHECK_VERSION(3, 0, 0)
366  return wxCFStringRef(cfStrPath).AsString(wxLocale::GetSystemEncoding());
367  #else
368  return wxMacCFStringHolder(cfStrPath).AsString(wxLocale::GetSystemEncoding());
369  #endif
370 }
371 #endif
372 
374 {
375  if (m_UserDataDir!=wxEmptyString)
376  {
377  // if --user-data-dir=path was specified we tell
378  //ConfigManager (and CfgMgrBldr) about it, which will propagate
379  //it through the app and plugins
380  if ( !ConfigManager::SetUserDataFolder(m_UserDataDir) )
381  return false;
382  }
383 
384  ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
385 
386  wxString data(wxT(APP_PREFIX));
387 
388  if (platform::windows)
389  data.assign(GetAppPath());
390  else if (platform::macosx)
391  {
392  data.assign(GetResourcesDir()); // CodeBlocks.app/Contents/Resources
393  if (!data.Contains(wxString(_T("/Resources")))) // not a bundle, use relative path
394  data = GetAppPath() + _T("/..");
395  }
396 
397  if (data.IsEmpty())
398  {
399  data.assign(GetAppPath()); // fallback
400  data.Replace(_T("/bin"),_T(""));
401  }
402 
403 
404  if (!m_Prefix.IsEmpty()) // --prefix command line switch overrides builtin value
405  data = m_Prefix;
406  else // also, check for environment
407  {
408 
409  wxString env;
410  wxGetEnv(_T("CODEBLOCKS_DATA_DIR"), &env);
411  if (!env.IsEmpty())
412  data = env;
413  }
414 
415  data.append(_T("/share/codeblocks"));
416 
417  cfg->Write(_T("data_path"), data);
418 
419  //m_HasDebugLog = Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/has_debug_log"), false) || m_HasDebugLog;
420  //Manager::Get()->GetConfigManager(_T("message_manager"))->Write(_T("/has_debug_log"), m_HasDebugLog);
421 
422  return true;
423 }
424 
426 {
427 #ifdef __WXMSW__
428  ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
429  if (m_Assocs && cfg->ReadBool(_T("/environment/check_associations"), true))
430  {
431  if (!Associations::Check())
432  {
433  AskAssocDialog dlg(Manager::Get()->GetAppWindow());
434  PlaceWindow(&dlg);
435 
436  switch(dlg.ShowModal())
437  {
439  cfg->Write(_T("/environment/check_associations"), false);
440  break;
442  break;
445  break;
448  break;
449  default:
450  break;
451  };
452  }
453  }
454 #endif
455 }
456 
458 {
459 #ifdef __WXMSW__
460  #ifdef __CBDEBUG__
461  // Remember to compile as a console application!
462  AllocConsole();
463  HANDLE myhandle = GetStdHandle(STD_OUTPUT_HANDLE);
464  COORD co = {80,2000};
465  SetConsoleScreenBufferSize(myhandle, co);
466  fprintf(stdout,"CONSOLE DEBUG ACTIVATED\n");
467  // wxLogWindow *myerr = new wxLogWindow(NULL,"debug");
468  #endif
469 #endif
470 }
471 
473 {
474 #ifdef __WXMSW__
475  ExcHndlInit();
476 #endif
477 }
478 
480 {
481  if ( !Manager::LoadResource(_T("resources.zip")) )
482  {
483 
484  wxString msg;
485  msg.Printf(_T("Cannot find resources...\n"
486  "%s was configured to be installed in '%s'.\n"
487  "Please use the command-line switch '--prefix' or "
488  "set the CODEBLOCKS_DATA_DIR environment variable "
489  "to point where %s is installed,\n"
490  "or try re-installing the application..."),
491  appglobals::AppName.wx_str(),
492  ConfigManager::ReadDataPath().wx_str(),
493  appglobals::AppName.wx_str());
494  cbMessageBox(msg);
495 
496  return false;
497  }
498  return true;
499 }
500 
502 {
503  static_assert(wxMinimumVersion<2,8,12>::eval, "wxWidgets 2.8.12 is required");
504 
505  MainFrame *frame = new MainFrame();
507  SetTopWindow(nullptr);
508 
509  if (g_DDEServer && m_DDE)
510  g_DDEServer->SetFrame(frame); // Set m_Frame in DDE-Server
511 
512  return frame;
513 }
514 
516 {
517  // This is a remnant from early 2006 (Windows only), but keep the revision tag for possible future use
518  ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
519 
520  if (cfg->Read(_T("version")) != appglobals::AppActualVersion)
521  cfg->Write(_T("version"), appglobals::AppActualVersion);
522 }
523 
525 {
526  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
527 
528  wxString path(ConfigManager::GetDataFolder() + _T("/locale"));
529 
530  if (cfg->ReadBool(_T("/locale/enable"), false) == false)
531  return;
532 
533  wxString lang(cfg->Read(_T("/locale/language")));
534 
536 
537 
538  const wxLanguageInfo *info;
539 
540  if (!lang.IsEmpty()) // Note: You can also write this line of code as !(!lang) from wx-2.9 onwards
541  info = wxLocale::FindLanguageInfo(lang);
542  else
544 
545  if (info == nullptr) // should never happen, but who knows...
546  return;
547 
548  m_locale.Init(info->Language);
549 
550  path.Alloc(path.length() + 10);
551  path.Append(_T('/'));
552  path.Append(info->CanonicalName);
553 
554  if ( !wxDirExists(path) )
555  return;
556 
557  wxDir dir(path);
558  if (!dir.IsOpened())
559  return;
560 
561  wxString moName;
562 
563  if (dir.GetFirst(&moName, _T("*.mo"), wxDIR_FILES))
564  {
565  do
566  {
567  m_locale.AddCatalog(moName);
568  } while (dir.GetNext(&moName));
569  }
570 }
571 
573 {
574 #ifdef __WXMSW__
575  InitCommonControls();
576 #endif
577 
578  wxLog::EnableLogging(true);
579 
580  SetAppName(_T("codeblocks"));
581 
582  s_Loading = true;
583  m_pBatchBuildDialog = nullptr;
584  m_BatchExitCode = 0;
585  m_Batch = false;
586  m_BatchNotify = false;
587  m_Build = false;
588  m_ReBuild = false;
589  m_Clean = false;
590  m_HasProject = false;
591  m_HasWorkSpace = false;
592  m_SafeMode = false;
593  m_BatchWindowAutoClose = true;
594 
595  wxTheClipboard->Flush();
596 
598  parser.SetDesc(cmdLineDesc);
599 
600  // NOTE: crash handler explicitly disabled because it causes problems
601  // with plugins loading/unloading...
602  //
603  // static CrashHandler crash_handler(!m_CrashHandler);
604 
605  // we'll do this once and for all at startup
612 
613  Manager::Get()->GetLogManager()->Log(F(wxT("Starting ") + appglobals::AppName + wxT(" ") +
616 
617  try
618  {
619  #if (wxUSE_ON_FATAL_EXCEPTION == 1)
621  #endif
622 
623  InitExceptionHandler();
624 
625  delete wxMessageOutput::Set(new cbMessageOutputNull); // No output. (suppress warnings about unknown options from plugins)
626  if (ParseCmdLine(nullptr) == -1) // only abort if '--help' was passed in the command line
627  {
629  parser.Usage();
630  return false;
631  }
632 
633  if ( !LoadConfig() )
634  return false;
635 
636  // set safe-mode appropriately
637  PluginManager::SetSafeMode(m_SafeMode);
638 
639  // If not in batch mode, and no startup-script defined, initialise XRC
640  if(!m_Batch && m_Script.IsEmpty() && !InitXRCStuff())
641  return false;
642 
643  InitLocale();
644 
645  if (m_DDE && !m_Batch && Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/use_ipc"), true))
646  {
647  // Create a new client
648  DDEClient *client = new DDEClient;
649  DDEConnection* connection = nullptr;
650  wxLogNull ln; // own error checking implemented -> avoid debug warnings
651  connection = (DDEConnection *)client->MakeConnection(_T("localhost"), F(DDE_SERVICE, wxGetUserId().wx_str()), DDE_TOPIC);
652 
653  if (connection)
654  {
655  // don't eval here just forward the whole command line to the other instance
656  wxString cmdLine;
657  for (int i = 1 ; i < argc; ++i)
658  cmdLine += wxString(argv[i]) + _T(' ');
659 
660  if ( !cmdLine.IsEmpty() )
661  {
662  // escape openings and closings so it is easily possible to find the end on the rx side
663  cmdLine.Replace(_T("("), _T("\\("));
664  cmdLine.Replace(_T(")"), _T("\\)"));
665  connection->Execute(_T("[CmdLine({") + cmdLine + _T("})]"));
666  }
667 
668  // On Linux, C::B has to be raised explicitly if it's wanted
669  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/raise_via_ipc"), true))
670  connection->Execute(_T("[Raise]"));
671  connection->Disconnect();
672  delete connection;
673  delete client;
674 
676  log->Log(wxT("Ending application because another instance has been detected!"));
677 
678  // return false to end the application
679  return false;
680  }
681  // free memory DDE-/IPC-clients, if we are here connection could not be established and there is no need to free it
682  delete client;
683  }
684  // Now we can start the DDE-/IPC-Server, if we did it earlier we would connect to ourselves
685  if (m_DDE && !m_Batch)
686  {
687  g_DDEServer = new DDEServer(nullptr);
688  g_DDEServer->Create(F(DDE_SERVICE, wxGetUserId().wx_str()));
689  }
690 
691  m_pSingleInstance = nullptr;
692  if ( Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/single_instance"), true)
693  && !parser.Found(_T("multiple-instance")) )
694  {
695  const wxString name = wxString::Format(_T("Code::Blocks-%s"), wxGetUserId().wx_str());
696 
697  m_pSingleInstance = new wxSingleInstanceChecker(name, ConfigManager::GetTempFolder());
698  if (m_pSingleInstance->IsAnotherRunning())
699  {
700  /* NOTE: Due to a recent change in logging code, this visual warning got disabled.
701  So the wxLogError() has been changed to a cbMessageBox(). */
702  cbMessageBox(_("Another program instance is already running.\nCode::Blocks is currently configured to only allow one running instance.\n\nYou can access this Setting under the menu item 'Environment'."),
703  _T("Code::Blocks"), wxOK | wxICON_ERROR);
704  return false;
705  }
706  }
707  // Splash screen moved to this place, otherwise it would be short visible, even if we only pass filenames via DDE/IPC
708  // we also don't need it, if only a single instance is allowed
709  Splash splash(!m_Batch && m_Script.IsEmpty() && m_Splash &&
710  Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/show_splash"), true));
711  InitDebugConsole();
712 
713  Manager::SetBatchBuild(m_Batch || !m_Script.IsEmpty());
715  MainFrame* frame = nullptr;
716  frame = InitFrame();
717  m_Frame = frame;
718 
719  // plugins loaded -> check command line arguments again
720  delete wxMessageOutput::Set(new wxMessageOutputBest); // warn about unknown options
721  if ( ParseCmdLine(m_Frame) == 0 )
722  {
723  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/blank_workspace"), true) == false)
725  }
726 
727  if (m_SafeMode) wxLog::EnableLogging(true); // re-enable logging in safe-mode
728 
729  if (m_Batch)
730  {
732 
733  // the compiler plugin might be waiting for this
735  Manager::Get()->ProcessEvent(event);
736 
738  s_Loading = false;
739  LoadDelayedFiles(frame);
740 
741  BatchJob();
742  frame->Close();
743  return true;
744  }
745 
746  if (!m_Script.IsEmpty())
747  {
748  s_Loading = false;
749  LoaderBase* loader = Manager::Get()->GetFileManager()->Load(m_Script);
750 
751  if (loader->GetData())
753 
754  delete loader;
755  frame->Close();
756  return true;
757  }
758 
759  CheckVersion();
760 
761  // run startup script
762  try
763  {
765  if (!startup.IsEmpty())
767  }
768  catch (SquirrelError& exception)
769  {
771  }
773 
774  // finally, show the app
775  splash.Hide();
776  SetTopWindow(frame);
777  frame->Show();
778 
779  frame->StartupDone();
780 
781  frame->ShowTips(); // this func checks if the user wants tips, so no need to check here
782 
783  if (platform::windows)
784  InitAssociations();
785 
786  s_Loading = false;
787 
788  LoadDelayedFiles(frame);
789  AttachDebugger();
791 
792  // all done
794 
796  Manager::Get()->ProcessEvent(event);
797 
798  return true;
799  }
800  catch (cbException& exception)
801  {
802  exception.ShowErrorMessage();
803  }
804  catch (SquirrelError& exception)
805  {
807  }
808  catch (const char* message)
809  {
810  wxSafeShowMessage(_T("Exception"), cbC2U(message));
811  }
812  catch (...)
813  {
814  wxSafeShowMessage(_T("Exception"), _T("Unknown exception was raised. The application will terminate immediately..."));
815  }
816  // if we reached here, return error
817  return false;
818 }
819 
821 {
822  wxTheClipboard->Flush();
823 
824  if (g_DDEServer) delete g_DDEServer;
825 
826  if (m_pSingleInstance)
827  delete m_pSingleInstance;
828 
829  // ultimate shutdown...
830  Manager::Free();
831 
832  // WX docs say that this function's return value is ignored,
833  // but we return our value anyway. It might not be ignored at some point...
834  return m_Batch ? m_BatchExitCode : 0;
835 }
836 
837 #ifdef __WXMSW__
838  inline void EnableLFH()
839  {
840  typedef BOOL (WINAPI *HeapSetInformation_t)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T);
841  typedef DWORD (WINAPI *GetProcessHeaps_t)(DWORD, PHANDLE);
842 
843  HINSTANCE kh = GetModuleHandle(TEXT("kernel32.dll"));
844  HeapSetInformation_t HeapSetInformation_func = (HeapSetInformation_t) GetProcAddress(kh, "HeapSetInformation");
845  GetProcessHeaps_t GetProcessHeaps_func = (GetProcessHeaps_t) GetProcAddress(kh, "GetProcessHeaps");
846 
847  if (GetProcessHeaps_func && HeapSetInformation_func)
848  {
849  ULONG HeapFragValue = 2;
850 
851  int n = GetProcessHeaps_func(0, 0);
852  HANDLE *h = new HANDLE[n];
853  GetProcessHeaps_func(n, h);
854 
855  for (int i = 0; i < n; ++i)
856  HeapSetInformation_func(h[i], HeapCompatibilityInformation, &HeapFragValue, sizeof(HeapFragValue));
857 
858  delete[] h;
859  }
860  }
861 #else
862  inline void EnableLFH() {}
863 #endif
864 
866 {
867  EnableLFH();
868  try
869  {
870  int retval = wxApp::OnRun();
871  // wx 2.6.3 docs says that OnRun() function's return value is used as exit code
872  return m_Batch ? m_BatchExitCode : retval;
873  }
874  catch (cbException& exception)
875  {
876  exception.ShowErrorMessage();
877  }
878  catch (SquirrelError& exception)
879  {
881  }
882  catch (const char* message)
883  {
884  wxSafeShowMessage(_("Exception"), cbC2U(message));
885  }
886  catch (...)
887  {
888  wxSafeShowMessage(_("Exception"), _("Unknown exception was raised. The application will terminate immediately..."));
889  }
890  // if we reached here, return error
891  return -1;
892 }
893 
895 {
896  return wxApp::OnCmdLineParsed(parser);
897 }
898 
900 {
901 #if wxUSE_DEBUGREPORT && wxUSE_XML && wxUSE_ON_FATAL_EXCEPTION
902  wxDebugReport report;
903  wxDebugReportPreviewStd preview;
904 
905  report.AddAll();
906  if ( preview.Show(report) )
907  report.Process();
908 #else
909  cbMessageBox(wxString::Format(_("Something has gone wrong inside %s and it will terminate immediately.\n"
910  "We are sorry for the inconvenience..."), appglobals::AppName.wx_str()));
911 #endif
912 }
913 
915 {
916  if (!m_Batch)
917  return -1;
918 
919  // find compiler plugin
921  if (!compiler)
922  return -3;
923 
924  if (!m_Clean && m_BatchTarget.Lower() == _T("ask"))
925  {
926  m_BatchTarget.Clear();
928  if (prj)
929  {
930  int idx = -1;
931  wxString defTarget = prj->GetActiveBuildTarget();
932  // find active target's index
933  // TODO: make this easier in the SDK
934  for (int i = 0; i < prj->GetBuildTargetsCount(); ++i)
935  {
936  ProjectBuildTarget* target = prj->GetBuildTarget(i);
937  if ( target->GetTitle().Matches(defTarget) )
938  {
939  idx = i;
940  break;
941  }
942  }
943  idx = prj->SelectTarget(idx, false);
944  if (idx == -1)
945  return 0; // no target selected: just abort
946  m_BatchTarget = prj->GetBuildTarget(idx)->GetTitle();
947  }
948  }
949 
950  m_pBatchBuildDialog = m_Frame->GetBatchBuildDialog();
951  PlaceWindow(m_pBatchBuildDialog);
952 
953  wxString title = _("Building '") + wxFileNameFromPath(wxString(argv[argc-1])) + _("' (target '") + m_BatchTarget + _T("')");
954  wxTaskBarIcon* tbIcon = new wxTaskBarIcon();
955  tbIcon->SetIcon(
956  #ifdef __WXMSW__
957  wxICON(A_MAIN_ICON),
958  #else
959  wxIcon(app),
960  #endif // __WXMSW__
961  title);
962 
963  wxString bb_title = m_pBatchBuildDialog->GetTitle();
964  m_pBatchBuildDialog->SetTitle(bb_title + _T(" - ") + title);
965  m_pBatchBuildDialog->Show();
966 
967  if (m_ReBuild)
968  {
969  if (m_HasProject)
970  compiler->Rebuild(m_BatchTarget);
971  else if (m_HasWorkSpace)
972  compiler->RebuildWorkspace(m_BatchTarget);
973  }
974  else if (m_Build)
975  {
976  if (m_HasProject)
977  compiler->Build(m_BatchTarget);
978  else if (m_HasWorkSpace)
979  compiler->BuildWorkspace(m_BatchTarget);
980  }
981  else if (m_Clean)
982  {
983  if (m_HasProject)
984  compiler->Clean(m_BatchTarget);
985  else if (m_HasWorkSpace)
986  compiler->CleanWorkspace(m_BatchTarget);
987  }
988 
989  // The batch build log might have been deleted in
990  // CodeBlocksApp::OnBatchBuildDone().
991  // If it has not, it's still compiling.
992  if (m_pBatchBuildDialog)
993  {
994  // If operation is "--clean", there is no need to display the dialog
995  // as the operation is synchronous and it already has finished by the
996  // time the call to Clean() returned.
997  if (!m_Clean)
998  m_pBatchBuildDialog->ShowModal();
999 
1000  if ( m_pBatchBuildDialog->IsModal() )
1001  m_pBatchBuildDialog->EndModal(wxID_OK);
1002  else
1003  {
1004  m_pBatchBuildDialog->Destroy();
1005  m_pBatchBuildDialog = nullptr;
1006  }
1007  }
1008 
1009  if (tbIcon)
1010  {
1011  tbIcon->RemoveIcon();
1012  delete tbIcon;
1013  }
1014 
1015  return 0;
1016 }
1017 
1019 {
1020  event.Skip();
1021  // the event comes more than once. deal with it...
1022  static bool one_time_only = false;
1023  if (!m_Batch || one_time_only)
1024  return;
1025  one_time_only = true;
1026 
1027  cbCompilerPlugin* compiler = static_cast<cbCompilerPlugin*>(event.GetPlugin());
1028  m_BatchExitCode = compiler->GetExitCode();
1029 
1030  if (m_BatchNotify)
1031  {
1032  wxString msg;
1033  if (m_BatchExitCode == 0)
1034  msg << _("Batch build ended.\n");
1035  else
1036  msg << _("Batch build stopped with errors.\n");
1037  msg << wxString::Format(_("Process exited with status code %d."), m_BatchExitCode);
1038  cbMessageBox(msg, appglobals::AppName, m_BatchExitCode == 0 ? wxICON_INFORMATION : wxICON_WARNING, m_pBatchBuildDialog);
1039  }
1040  else
1041  wxBell();
1042 
1043  if (m_pBatchBuildDialog && m_BatchWindowAutoClose)
1044  {
1045  if (m_pBatchBuildDialog->IsModal())
1046  m_pBatchBuildDialog->EndModal(wxID_OK);
1047  else
1048  {
1049  m_pBatchBuildDialog->Destroy();
1050  m_pBatchBuildDialog = nullptr;
1051  }
1052  }
1053 }
1054 
1056 {
1057  event.Skip();
1058  if (m_pBatchBuildDialog)
1059  {
1060  m_pBatchBuildDialog->Raise();
1061  m_pBatchBuildDialog->Refresh();
1062  }
1063 }
1064 
1066 {
1067  wxString base;
1068 #ifdef __WXMSW__
1069  wxChar name[MAX_PATH] = {0};
1070  GetModuleFileName(0L, name, MAX_PATH);
1071  wxFileName fname(name);
1072  base = fname.GetPath(wxPATH_GET_VOLUME);
1073 #else
1074  if (!m_Prefix.IsEmpty())
1075  return m_Prefix;
1076 
1077 #ifdef SELFPATH
1078  // SELFPATH is a macro from prefix.h (binreloc)
1079  // it returns the absolute filename of us
1080  // similar to win32 GetModuleFileName()...
1081  base = wxString(SELFPATH,wxConvUTF8);
1082  base = wxFileName(base).GetPath();
1083 #endif
1084 #if defined(sun) || defined(__sun)
1085  base = wxString(getexecname(),wxConvCurrent);
1086  base = wxFileName(base).GetPath();
1087 #endif
1088 #if defined(__APPLE__) && defined(__MACH__)
1089  char path[MAXPATHLEN+1];
1090  uint32_t path_len = MAXPATHLEN;
1091  // SPI first appeared in Mac OS X 10.2
1092  _NSGetExecutablePath(path, &path_len);
1093  base = wxString(path, wxConvUTF8);
1094  base = wxFileName(base).GetPath();
1095 #endif
1096  if (base.IsEmpty())
1097  base = _T(".");
1098 #endif
1099  return base;
1100 }
1101 
1103 {
1104  m_AutoFile = file;
1105 }
1106 
1107 int CodeBlocksApp::ParseCmdLine(MainFrame* handlerFrame, const wxString& CmdLineString)
1108 {
1109  // code shamelessely taken from the console wxWindows sample :)
1110  bool filesInCmdLine = false;
1111 
1112 #if wxUSE_CMDLINE_PARSER
1114  if ( CmdLineString.IsEmpty() )
1115  parser.SetCmdLine(argc, argv);
1116  else
1117  parser.SetCmdLine(CmdLineString);
1118  // wxApp::argc is a wxChar**
1119 
1120  // don't display errors as plugins will have the chance to parse the command-line
1121  // too, so we don't know here what exactly are the supported options
1122  int res = parser.Parse(false);
1123  if (res == -1)
1124  {
1125  return -1;
1126  }
1127  else
1128  {
1129  if (handlerFrame)
1130  {
1131  m_HasProject = false;
1132  m_HasWorkSpace = false;
1133  int count = parser.GetParamCount();
1134 
1135  parser.Found(_T("file"), &m_AutoFile);
1136 
1137  filesInCmdLine = (count != 0) || (!m_AutoFile.empty());
1138 
1139  for (int param = 0; param < count; ++param)
1140  {
1141  // is it a project/workspace?
1142  FileType ft = FileTypeOf(parser.GetParam(param));
1143  wxFileName fn(parser.GetParam(param));
1144  fn.Normalize(); // really important so that two same files with different names are not loaded twice
1145  if (ft == ftCodeBlocksProject)
1146  {
1147  m_HasProject = true;
1148  m_DelayedFilesToOpen.Add(parser.GetParam(param));
1149  }
1150  else if (ft == ftCodeBlocksWorkspace)
1151  {
1152  // only one workspace can be opened
1153  m_HasWorkSpace = true;
1154  m_DelayedFilesToOpen.Clear(); // remove all other files
1155  m_DelayedFilesToOpen.Add(fn.GetFullPath()); // and add only the workspace
1156  break; // and stop processing any more files
1157  }
1158  //else if (ft == ftSource || ft == ftHeader || ft == ftResource)
1159  else if (wxFile::Exists(fn.GetFullPath())) //also try to open non source, header and resource files
1160  {
1161  m_DelayedFilesToOpen.Add(fn.GetFullPath());
1162  }
1163  }
1164 
1165  // batch jobs
1166  m_Batch = m_HasProject || m_HasWorkSpace;
1167  m_Batch = m_Batch && (m_Build || m_ReBuild || m_Clean);
1168  }
1169  else
1170  {
1171  wxString val;
1172  parser.Found(_T("prefix"), &m_Prefix);
1173  parser.Found(_T("user-data-dir"), &m_UserDataDir);
1174 #ifdef __WXMSW__
1175  m_DDE = !parser.Found(_T("no-dde"));
1176  m_Assocs = !parser.Found(_T("no-check-associations"));
1177 #else
1178  m_DDE = !parser.Found(_T("no-ipc"));
1179 #endif
1180  m_SafeMode = parser.Found(_T("safe-mode"));
1181  m_Splash = !parser.Found(_T("no-splash-screen"));
1182  m_HasDebugLog = parser.Found(_T("debug-log"));
1183  m_CrashHandler = !parser.Found(_T("no-crash-handler"));
1184 
1185  wxLog::EnableLogging(parser.Found(_T("verbose")));
1186 
1187  if ( parser.Found(_T("personality"), &val)
1188  || parser.Found(_T("profile"), &val) )
1189  {
1190  SetupPersonality(val);
1191  }
1192 
1193  // batch jobs
1194  m_BatchNotify = parser.Found(_T("batch-build-notify"));
1195  m_BatchWindowAutoClose = !parser.Found(_T("no-batch-window-close"));
1196  m_Build = parser.Found(_T("build"));
1197  m_ReBuild = parser.Found(_T("rebuild"));
1198  m_Clean = parser.Found(_T("clean"));
1199  parser.Found(_T("target"), &m_BatchTarget);
1200  parser.Found(_T("script"), &m_Script);
1201  // initial setting for batch flag (will be reset when ParseCmdLine() is called again).
1202  m_Batch = m_Build || m_ReBuild || m_Clean;
1203 
1204 
1205  if (parser.Found(_T("no-log")) == false)
1207  if (parser.Found(_T("log-to-file")))
1208  Manager::Get()->GetLogManager()->SetLog(new FileLogger(_T("codeblocks.log")), LogManager::app_log);
1209  if (m_HasDebugLog)
1211  if (parser.Found(_T("debug-log-to-file")))
1212  Manager::Get()->GetLogManager()->SetLog(new FileLogger(_T("codeblocks-debug.log")), LogManager::debug_log);
1213  }
1214 
1215  // Always parse the debugger attach parameters.
1216  parser.Found(_T("dbg-attach"), &m_DebuggerAttach);
1217  parser.Found(_T("dbg-config"), &m_DebuggerConfig);
1218  }
1219 #endif // wxUSE_CMDLINE_PARSER
1220  return filesInCmdLine ? 1 : 0;
1221 }
1222 
1224 {
1225  if (personality.CmpNoCase(_T("ask")) == 0)
1226  {
1227  const wxArrayString items(Manager::Get()->GetPersonalityManager()->GetPersonalitiesList());
1228 
1229  wxSingleChoiceDialog dlg(nullptr, _("Please choose which personality (profile) to load:"),
1230  _("Personalities (profiles)"),
1231  items);
1232 
1233  if (dlg.ShowModal() == wxID_OK)
1235  }
1236  else
1237  Manager::Get()->GetPersonalityManager()->SetPersonality(personality, true);
1238 }
1239 
1241 {
1242  std::set<wxString> uniqueFilesToOpen(m_DelayedFilesToOpen.begin(), m_DelayedFilesToOpen.end());
1243  for (std::set<wxString>::const_iterator it = uniqueFilesToOpen.begin(); it != uniqueFilesToOpen.end(); ++it)
1244  frame->Open(*it, true);
1245  m_DelayedFilesToOpen.Clear();
1246 
1247  // --file foo.cpp[:line]
1248  if (!m_AutoFile.IsEmpty())
1249  {
1250  wxString linePart;
1251  // We always want to open the file no matter if there is a line number or not.
1252  wxString filePart = m_AutoFile;
1253  long linePos = m_AutoFile.Find(_T(':'), true);
1254  if (linePos != wxNOT_FOUND)
1255  {
1256  linePart = m_AutoFile.Mid(linePos + 1, wxString::npos);
1257  filePart.Remove(linePos);
1258  }
1259 
1260  long line = -1;
1261  if (linePos != wxNOT_FOUND)
1262  {
1263  // on windows, if ":line" is omitted:
1264  // assuming drive letter before the colon if ToLong fails
1265  // c:\foo\bar.h gives \foo\bar.h
1266  if ( !linePart.ToLong(&line) )
1267  {
1268  // on windows, if :line is omitted: c:\foo\bar.h -> \foo\bar.h is not the line number!
1269  filePart = m_AutoFile;
1270  }
1271  }
1272  // Make sure filePart is not empty, because if it is empty Normalize turns the full path in
1273  // to the path of the current working folder.
1274  if (!filePart.empty())
1275  {
1276  wxFileName fn(filePart);
1277  fn.Normalize(); // really important so that two same files with different names are not loaded twice
1278  if (frame->Open(fn.GetFullPath(), false))
1279  {
1281  if (eb && (line != -1))
1282  eb->GotoLine(line - 1, true);
1283  }
1284  }
1285  m_AutoFile.Clear();
1286  }
1287 }
1288 
1290 {
1291  const wxString localAttach = m_DebuggerAttach;
1292  const wxString localConfig = m_DebuggerConfig;
1293  // Reset the values to prevent old values to be used when the user forgets to pass all required
1294  // command line parameters.
1295  m_DebuggerAttach = m_DebuggerConfig = wxString();
1296 
1297  LogManager *logManager = Manager::Get()->GetLogManager();
1298 
1299  if (localAttach.empty() || localConfig.empty())
1300  {
1301  if (localAttach.empty() != localConfig.empty())
1302  {
1303  logManager->LogError(
1304  _("For attaching to work you need to provide both '--dbg-attach' and '--dbg-config'"));
1305  logManager->Log(wxT(" --dbg-attach='") + localAttach + wxT("'"));
1306  logManager->Log(wxT(" --dbg-config='") + localConfig + wxT("'"));
1307  }
1308  return;
1309  }
1310 
1311  logManager->Log(wxString::Format(_("Attach debugger '%s' to '%s'"), localConfig.wx_str(),
1312  localAttach.wx_str()));
1313 
1314  // Split the dbg-config to plugin name and config name
1315  wxString::size_type pos = localConfig.find(wxT(':'));
1316  if (pos == wxString::npos || pos == 0)
1317  {
1318  logManager->LogError(
1319  _("No delimiter found. The --dbg-config format is 'plugin-name:config-name'"));
1320  return;
1321  }
1322 
1323  const wxString pluginName = localConfig.substr(0, pos);
1324  const wxString configName = localConfig.substr(pos + 1);
1325 
1326  // Find the plugin and the config.
1327  DebuggerManager *debuggerManager = Manager::Get()->GetDebuggerManager();
1328  const DebuggerManager::RegisteredPlugins &debuggers = debuggerManager->GetAllDebuggers();
1329  if (debuggers.empty())
1330  {
1331  logManager->LogError(_("No debugger plugins loaded!"));
1332  return;
1333  }
1334 
1335  cbDebuggerPlugin *plugin = nullptr;
1336  int configIndex = -1;
1337  const DebuggerManager::PluginData *pluginData = nullptr;
1338 
1339  for (const auto &info : debuggers)
1340  {
1341  if (info.first->GetSettingsName() == pluginName)
1342  {
1343  plugin = info.first;
1344  pluginData = &info.second;
1345  break;
1346  }
1347  }
1348 
1349  if (!plugin)
1350  {
1351  logManager->LogError(wxString::Format(_("Debugger plugin '%s' not found!"),
1352  pluginName.wx_str()));
1353  logManager->Log(_("Available plugins:"));
1354  for (const auto &info : debuggers)
1355  {
1356  cbDebuggerPlugin *p = info.first;
1357  logManager->Log(wxString::Format(_(" '%s' (%s)"), p->GetSettingsName().wx_str(),
1358  p->GetGUIName().wx_str()));
1359  }
1360  return;
1361  }
1362 
1363  const DebuggerManager::ConfigurationVector &configs = pluginData->GetConfigurations();
1364  for (auto it = configs.begin(); it != configs.end(); ++it)
1365  {
1366  if ((*it)->GetName() == configName)
1367  {
1368  configIndex = std::distance(configs.begin(), it);
1369  break;
1370  }
1371  }
1372 
1373  if (configIndex == -1)
1374  {
1375  logManager->LogError(wxString::Format(_("Debugger configuration '%s' not found!"),
1376  configName.wx_str()));
1377  logManager->Log(_("Available configurations:"));
1378  for (const cbDebuggerConfiguration *config : configs)
1379  logManager->Log(wxString::Format(_(" '%s'"), config->GetName().wx_str()));
1380  return;
1381  }
1382 
1383  // We have a debugger plugin and config, so lets try to attach...
1384  logManager->Log(_("Debugger plugin and configuration found. Attaching!!!"));
1385  plugin->SetActiveConfig(configIndex);
1386  plugin->AttachToProcess(localAttach);
1387 }
1388 
1389 #ifdef __WXMAC__
1390 
1391 void CodeBlocksApp::MacOpenFile(const wxString & fileName )
1392 {
1393  if (s_Loading)
1394  m_DelayedFilesToOpen.Add(fileName);
1395  else if (m_Frame)
1396  m_Frame->Open(fileName, true);
1397 }
1398 
1399 void CodeBlocksApp::MacPrintFile(const wxString & fileName )
1400 {
1401  // TODO
1402  wxApp::MacPrintFile(fileName);
1403 }
1404 
1405 #endif // __WXMAC__
1406 
1407 // event handlers
1408 
1410 {
1411  // allow others to process this event
1412  event.Skip();
1413 
1414  if (s_Loading)
1415  return; // still loading; we can't possibly be interested for this event ;)
1416 
1417  Manager *manager = Manager::Get();
1418  if (!manager || manager->IsAppShuttingDown())
1419  return;
1420 
1421  // Activation & De-Activation event
1422  CodeBlocksEvent cbEvent;
1423  if (event.GetActive())
1424  cbEvent.SetEventType(cbEVT_APP_ACTIVATED);
1425  else
1426  cbEvent.SetEventType(cbEVT_APP_DEACTIVATED);
1427  Manager::Get()->ProcessEvent(cbEvent);
1428 
1429  if (!event.GetActive())
1430  return;
1431 
1432  // fix for bug #18007: In batch build mode the following is not needed
1433  if ( !m_Batch
1435  && Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/check_modified_files"), true))
1436  {
1437  // for some reason a mouse up event doesn't make it into scintilla (scintilla bug)
1438  // therefore the workaround is not to directly call the editorManager, but
1439  // take a detour through an event
1440  // the bug is when the file has been offered to reload, no matter what answer you
1441  // give the mouse is in a selecting mode, adding/removing things to it's selection as you
1442  // move it around
1443  // so : idEditorManagerCheckFiles, EditorManager::OnCheckForModifiedFiles just exist for this workaround
1444  wxCommandEvent evt(wxEVT_COMMAND_MENU_SELECTED, idEditorManagerCheckFiles);
1445  wxPostEvent(Manager::Get()->GetEditorManager(), evt);
1446  cbProjectManagerUI *prjManUI = m_Frame->GetProjectManagerUI();
1447  if (prjManUI)
1448  static_cast<ProjectManagerUI*>(prjManUI)->CheckForExternallyModifiedProjects();
1449  }
1452  if (ed)
1453  {
1454  // hack for linux: without it, the editor loses the caret every second activate o.O
1455  Manager::Get()->GetEditorManager()->GetNotebook()->SetFocus();
1456  ed->GetControl()->SetFocus();
1457  }
1458 }
1459 
1461 {
1462  m_DelayedFilesToOpen.Add(filename);
1463 }
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
void wxSafeShowMessage(const wxString &title, const wxString &text)
Definition: main.h:60
wxApp * wxTheApp
void SetActiveConfig(int index)
Definition: cbplugin.cpp:280
static void SetUpdateInterval(long updateInterval)
void OnAppActivate(wxActivateEvent &event)
Definition: app.cpp:1409
IMPLEMENT_APP(CodeBlocksApp) bool CodeBlocksApp
Definition: app.cpp:338
bool wxGetEnv(const wxString &var, wxString *value)
bool Matches(const wxString &mask) const
PluginManager * GetPluginManager() const
Definition: manager.cpp:444
void SetPersonality(const wxString &personality, bool createIfNotExist=false)
Use this once, on program startup to set the working personality.
wxString GetAppPath() const
Definition: app.cpp:1065
virtual int GetExitCode() const =0
Get the exit code of the last build process.
static void ProcessPendingEvents()
Definition: manager.cpp:215
ConfigurationVector & GetConfigurations()
virtual bool SetIcon(const wxIcon &icon, const wxString &tooltip=wxEmptyString)
#define wxICON_WARNING
#define ASC_ASSOC_DLG_NO_ONLY_NOW
Definition: associations.h:71
static bool LoadResource(const wxString &file)
Definition: manager.cpp:499
void InitExceptionHandler()
Definition: app.cpp:472
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
Base class for debugger plugins.
Definition: cbplugin.h:397
static void Free()
Never, EVER, call this function! It is the last function called on shutdown....
Definition: manager.cpp:189
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
wxString substr(size_t nStart=0, size_t nLen=npos) const
bool IsOpened() const
EVTIMPORT const wxEventType cbEVT_COMPILER_FINISHED
Definition: sdk_events.cpp:149
void LoadDelayedFiles(MainFrame *frame)
Definition: app.cpp:1240
static void SetSafeMode(bool on)
static bool IsAppShuttingDown()
Definition: manager.cpp:333
virtual bool RemoveIcon()
size_t length() const
void Usage() const
static void SetBatchBuild(bool is_batch)
Definition: manager.cpp:205
bool GetFirst(wxString *filename, const wxString &filespec=wxEmptyString, int flags=wxDIR_DEFAULT) const
#define wxICON_ERROR
DLLIMPORT wxBitmap cbLoadBitmap(const wxString &filename, wxBitmapType bitmapType=wxBITMAP_TYPE_PNG)
This function loads a bitmap from disk.
Definition: globals.cpp:1102
PersonalityManager * GetPersonalityManager() const
Definition: manager.cpp:459
Scripts folder in base dir.
Definition: configmanager.h:80
void ShowTips(bool forceShow=false)
Definition: main.cpp:715
bool ReadBool(const wxString &name, bool defaultVal=false)
virtual void MacOpenFile(const wxString &fileName)
size_t GetParamCount() const
Scripts folder in user&#39;s dir.
Definition: configmanager.h:74
virtual int CleanWorkspace(const wxString &target=wxEmptyString)=0
Clean all open projects.
wxIPCFormat
FileManager * GetFileManager() const
Definition: manager.cpp:479
const wxString AppActualVersionVerb
Definition: appglobals.cpp:26
bool wxDirExists(const wxString &dirname)
bool Matches(const wxString &text, int flags=0) const
wxString & append(const wxString &str, size_t pos, size_t n)
#define _T(string)
void InitDebugConsole()
Definition: app.cpp:457
FileType
Known file types.
Definition: globals.h:49
void wxBell()
#define wxTheClipboard
DLLIMPORT FileType FileTypeOf(const wxString &filename)
Definition: globals.cpp:285
#define wxICON_INFORMATION
#define APP_PREFIX
Definition: app.cpp:68
bool wxHandleFatalExceptions(bool doIt=true)
wxString & Remove(size_t pos)
EVTIMPORT const wxEventType cbEVT_APP_CMDLINE
Definition: sdk_events.cpp:72
#define wxT(string)
#define wxNOT_FOUND
void SetCmdLine(int argc, char **argv)
bool empty() const
size_t find(const wxString &str, size_t nStart=0) const
A generic Code::Blocks event.
Definition: sdk_events.h:20
virtual int OnRun()
Definition: app.cpp:865
static const wxLanguageInfo * FindLanguageInfo(const wxString &locale)
int CmpNoCase(const wxString &s) const
virtual bool OnCmdLineParsed(wxCmdLineParser &parser)
virtual wxConnectionBase * OnAcceptConnection(const wxString &topic)
static wxString LocateDataFile(const wxString &filename, int search_dirs=sdAllKnown)
Locate a file in an installation- and platform-independent way.
Base class for compiler plugins.
Definition: cbplugin.h:263
virtual void AttachToProcess(const wxString &pid)=0
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
void LogError(const wxString &msg, int i=app_log)
Definition: logmanager.h:142
virtual int BuildWorkspace(const wxString &target=wxEmptyString)=0
Build all open projects.
bool Show(wxDebugReport &dbgrpt) const
wxUSE_UNICODE_dependent wxChar
wxString CanonicalName
void SetAutoFile(wxString &file)
Definition: app.cpp:1102
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
bool LoadScript(const wxString &filename)
Loads a script.
#define CMD_ENTRY(X)
Definition: app.cpp:212
bool Contains(const wxString &str) const
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
DebuggerManager * GetDebuggerManager() const
Definition: manager.cpp:484
void wxPostEvent(wxEvtHandler *dest, const wxEvent &event)
bool Found(const wxString &name) const
Event functor class.
Definition: cbfunctor.h:37
Represents a Code::Blocks project.
Definition: cbproject.h:96
const wxString & GetActiveBuildTarget() const
Definition: cbproject.cpp:1373
virtual int OnExit()
Definition: app.cpp:820
int BatchJob()
Definition: app.cpp:914
void SetupPersonality(const wxString &personality)
Definition: app.cpp:1223
const wxString AppActualVersion
Definition: appglobals.cpp:27
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
DLLIMPORT int idEditorManagerCheckFiles
void AddAll(Context context=Context_Exception)
static wxCmdLineParser * GetCmdLineParser()
Definition: manager.cpp:545
DLLIMPORT wxString cbC2U(const char *str)
Return str as a proper unicode-compatible string.
Definition: globals.cpp:733
virtual const wxString & GetTitle() const
Read the target&#39;s title.
wxString GetSettingsName() const
Definition: cbplugin.h:619
bool Alloc(size_t nLen)
EVTIMPORT const wxEventType cbEVT_APP_DEACTIVATED
Definition: sdk_events.cpp:71
void InitAssociations()
Definition: app.cpp:425
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
virtual int RebuildWorkspace(const wxString &target=wxEmptyString)=0
Rebuild all open projects.
static wxMessageOutput * Set(wxMessageOutput *msgout)
void AddFileToOpenDelayed(const wxString &filename)
Definition: app.cpp:1460
a logger which prints messages to a wxTextCtrl
Definition: loggers.h:90
EVTIMPORT const wxEventType cbEVT_APP_ACTIVATED
Definition: sdk_events.cpp:70
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
#define ASC_ASSOC_DLG_YES_ALL_FILES
Definition: associations.h:73
void SetDesc(const wxCmdLineEntryDesc *desc)
bool OnCmdLineParsed(wxCmdLineParser &parser)
Definition: app.cpp:894
bool GetMatch(size_t *start, size_t *len, size_t index=0) const
const wxString AppBuildTimestamp
Definition: appglobals.cpp:66
Base class that all "editors" should inherit from.
Definition: editorbase.h:30
LogManager * GetLogManager() const
Definition: manager.cpp:439
MainFrame * InitFrame()
Definition: app.cpp:501
cbProject * GetActiveProject()
Retrieve the active project.
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
static wxString GetTempFolder()
int Parse(bool giveUsage=true)
virtual int Clean(ProjectBuildTarget *target=nullptr)=0
Clean the project/target.
static void AddHandler(wxFileSystemHandler *handler)
void wxInitAllImageHandlers()
size_t size_type
void DisplayErrors(SquirrelError *exception=nullptr, bool clearErrors=true)
Display error dialog.
#define wxICON(iconName)
const wxStringCharType * wx_str() const
virtual int ShowModal()
static wxFontEncoding GetSystemEncoding()
int ParseCmdLine(MainFrame *handlerFrame, const wxString &CmdLine=wxEmptyString)
Definition: app.cpp:1107
wxString wxEmptyString
#define wxOK
wxString & assign(const wxString &str, size_t pos, size_t n)
virtual void MacPrintFile(const wxString &fileName)
void OnTBIconLeftDown(wxTaskBarIconEvent &event)
Definition: app.cpp:1055
const wxString & _(const wxString &string)
const wxString AppName
Definition: appglobals.cpp:22
EditorBase * GetEditor(int index)
bool LoadConfig()
void ShowErrorMessage(bool safe=true)
Display exception error message.
Definition: cbexception.cpp:31
std::map< cbDebuggerPlugin *, PluginData > RegisteredPlugins
int GetBuildTargetsCount()
Definition: cbproject.h:200
static void Yield()
Whenever you need to call wxYield(), call Manager::Yield(). It&#39;s safer.
Definition: manager.cpp:221
cb_must_consume_result LoaderBase * Load(const wxString &file, bool reuseEditors=false)
Loads a file, once this function is called, the actually loading process is done in the worker thread...
EVTIMPORT const wxEventType cbEVT_APP_STARTUP_DONE
Definition: sdk_events.cpp:68
static wxString GetDataFolder(bool global=true)
ProjectBuildTarget * GetBuildTarget(int index)
Access a build target.
Definition: cbproject.cpp:1392
static bool Exists(const wxString &filename)
void OnFatalException()
Definition: app.cpp:899
bool ToLong(long *val, int base=10) const
a logger which prints messages to a file
Definition: loggers.h:40
void WorkspaceChanged()
Sends message to the plugins that the workspace has been changed.
bool InitXRCStuff()
Definition: app.cpp:479
wxString & Append(const char *psz)
A file editor.
Definition: cbeditor.h:43
bool GetNext(wxString *filename) const
bool IsEmpty() const
DLLIMPORT void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode=pdlBest, bool enforce=false)
Definition: globals.cpp:1177
wxString GetResourcesDir()
Definition: app.cpp:77
RegisteredPlugins const & GetAllDebuggers() const
wxString GetGUIName() const
Definition: cbplugin.h:618
wxString GetPath(int flags=wxPATH_GET_VOLUME, wxPathFormat format=wxPATH_NATIVE) const
#define ASC_ASSOC_DLG_YES_C_FILES
Definition: associations.h:72
bool GetActive() const
static bool SetUserDataFolder(const wxString &user_data_path)
static const size_t npos
cbAuiNotebook * GetNotebook()
Definition: editormanager.h:73
void Log(const wxString &msg, int i=app_log, Logger::level lv=Logger::info)
Definition: logmanager.h:140
static void SetAppStartedUp(bool app_started_up)
Definition: manager.cpp:195
void CheckVersion()
Definition: app.cpp:515
bool ProcessEvent(CodeBlocksEvent &event)
Definition: manager.cpp:246
static bool EnableLogging(bool enable=true)
void StartupDone()
Definition: main.cpp:5125
static void DrawReleaseInfo(class wxDC &dc)
cbCompilerPlugin * GetFirstCompiler() const
void RegisterEventSink(wxEventType eventType, IEventFunctorBase< CodeBlocksEvent > *functor)
Definition: manager.cpp:550
char * GetData()
Definition: filemanager.cpp:42
wxBitmap wxNullBitmap
#define DDE_TOPIC
Definition: associations.h:23
static wxString ReadDataPath()
std::vector< cbDebuggerConfiguration * > ConfigurationVector
static const wxLanguageInfo * GetLanguageInfo(int lang)
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
virtual void GotoLine(int, bool=true)
Move the caret at the specified line.
Definition: editorbase.h:160
Represents a Code::Blocks project build target.
bool Normalize(int flags=wxPATH_NORM_ALL, const wxString &cwd=wxEmptyString, wxPathFormat format=wxPATH_NATIVE)
void InsertHandler(wxXmlResourceHandler *handler)
wxString GetStringSelection() const
static wxString GetTextFromData(const void *data, size_t size, wxIPCFormat format)
virtual int Build(ProjectBuildTarget *target=nullptr)=0
Build the project/target.
virtual bool OnInit()
Definition: app.cpp:572
int Find(wxUniChar ch, bool fromEnd=false) const
bool Open(const wxString &filename, bool addToHistory=true)
Definition: main.cpp:1725
static wxXmlResource * Get()
void EnableLFH()
Definition: app.cpp:838
void InitAllHandlers()
bool LoadWorkspace(const wxString &filename=DEFAULT_WORKSPACE)
Load a workspace.
ScriptingManager * GetScriptingManager() const
Definition: manager.cpp:469
void OnBatchBuildDone(CodeBlocksEvent &event)
Definition: app.cpp:1018
wxString wxGetUserId()
int Printf(const wxString &pszFormat,...)
void InitLocale()
Definition: app.cpp:524
virtual int OnRun()
wxString GetFullPath(wxPathFormat format=wxPATH_NATIVE) const
#define DDE_SERVICE
Definition: associations.h:19
bool LoadBuffer(const wxString &buffer, const wxString &debugName=_T("CommandLine"))
Loads a string buffer.
int SelectTarget(int initial=-1, bool evenIfOne=false)
Displays a target selection dialog.
Definition: cbproject.cpp:1130
size_t SetLog(Logger *l, int index=no_index)
Definition: logmanager.cpp:110
Code::Blocks error handling unit.
Definition: cbexception.h:23
static wxString Format(const wxString &format,...)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
#define ASC_ASSOC_DLG_NO_DONT_ASK
Definition: associations.h:70
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
void AttachDebugger()
Definition: app.cpp:1289
static void AddCatalogLookupPathPrefix(const wxString &prefix)
wxString GetParam(size_t n=0) const
virtual int Rebuild(ProjectBuildTarget *target=nullptr)=0
Rebuild the project/target.
wxString wxFileNameFromPath(const wxString &path)