~efargaspro/+junk/codeblocks-16.01-release

1 by damienlmoore at gmail
Code::Blocks 16.01
1
#include "Addr2LineUIMain.h"
2
3
//(*InternalHeaders(Addr2LineUIDialog)
4
#include <wx/settings.h>
5
#include <wx/font.h>
6
#include <wx/intl.h>
7
#include <wx/string.h>
8
//*)
9
10
#include <wx/busyinfo.h>
11
#include <wx/msgdlg.h>
12
#include <wx/regex.h>
13
#include <wx/textfile.h>
14
#include <wx/utils.h> // wxExecute
15
16
//(*IdInit(Addr2LineUIDialog)
17
const long Addr2LineUIDialog::ID_CRASH_LOG = wxNewId();
18
const long Addr2LineUIDialog::ID_ADDR2LINE = wxNewId();
19
const long Addr2LineUIDialog::ID_DIR_PREPEND = wxNewId();
20
const long Addr2LineUIDialog::ID_CHK_REPLACE = wxNewId();
21
const long Addr2LineUIDialog::ID_TXT_REPLACE_THIS = wxNewId();
22
const long Addr2LineUIDialog::ID_LBL_REPLACE = wxNewId();
23
const long Addr2LineUIDialog::ID_TXT_REPLACE_THAT = wxNewId();
24
const long Addr2LineUIDialog::ID_CHK_SKIP_UNRESOLVABLE = wxNewId();
25
const long Addr2LineUIDialog::ID_TXT_CRASH_LOG_CONTENT = wxNewId();
26
const long Addr2LineUIDialog::ID_TXT_RESULT = wxNewId();
27
const long Addr2LineUIDialog::ID_BTN_OPERATE = wxNewId();
28
const long Addr2LineUIDialog::ID_BTN_QUIT = wxNewId();
29
//*)
30
31
BEGIN_EVENT_TABLE(Addr2LineUIDialog,wxDialog)
32
  //(*EventTable(Addr2LineUIDialog)
33
  //*)
34
END_EVENT_TABLE()
35
36
Addr2LineUIDialog::Addr2LineUIDialog(wxWindow* parent) :
37
  mFileConfig(),
38
  mCrashLog(),
39
  mCrashLogFileContent(),
40
  mAddr2Line(wxT("addr2line")),
41
  mDirPrepend()
42
{
43
  //(*Initialize(Addr2LineUIDialog)
44
  wxStaticText* lblDirPrepend;
45
  wxBoxSizer* bszAddr2Line;
46
  wxButton* btnQuit;
47
  wxBoxSizer* bszMainV;
48
  wxStaticText* lblCrashLog;
49
  wxBoxSizer* bszReplace;
50
  wxBoxSizer* bszMainH;
51
  wxStaticText* lblAddr2Line;
52
  wxStaticLine* stlLine;
53
54
  Create(parent, wxID_ANY, _("Addr2LineUI"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX, _T("wxID_ANY"));
55
  bszMainH = new wxBoxSizer(wxHORIZONTAL);
56
  bszMainV = new wxBoxSizer(wxVERTICAL);
57
  bszAddr2Line = new wxBoxSizer(wxVERTICAL);
58
  lblCrashLog = new wxStaticText(this, wxID_ANY, _("Select crash log file:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
59
  bszAddr2Line->Add(lblCrashLog, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
60
  m_FPCrashLog = new wxFilePickerCtrl(this, ID_CRASH_LOG, wxEmptyString, _("Select crash log"), _T("Report files (*.rpt)|*.rpt|Log files (*.log)|*.log|All files (*.*)|*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_CRASH_LOG"));
61
  bszAddr2Line->Add(m_FPCrashLog, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
62
  lblAddr2Line = new wxStaticText(this, wxID_ANY, _("Select Addr2Line tool:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
63
  bszAddr2Line->Add(lblAddr2Line, 0, wxTOP|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
64
  m_FPAddr2Line = new wxFilePickerCtrl(this, ID_ADDR2LINE, wxEmptyString, _("Select addr2line tool"), _T("Executables (*.exe)|*.exe|All files (*.*)|*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_ADDR2LINE"));
65
  bszAddr2Line->Add(m_FPAddr2Line, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
66
  lblDirPrepend = new wxStaticText(this, wxID_ANY, _("(Optionally) Select directory to prepend:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
67
  bszAddr2Line->Add(lblDirPrepend, 0, wxTOP|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
68
  m_DPDirPrepend = new wxDirPickerCtrl(this, ID_DIR_PREPEND, wxEmptyString, _("Select directory to prepend"), wxDefaultPosition, wxDefaultSize, wxDIRP_DIR_MUST_EXIST|wxDIRP_USE_TEXTCTRL, wxDefaultValidator, _T("ID_DIR_PREPEND"));
69
  bszAddr2Line->Add(m_DPDirPrepend, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
70
  bszMainV->Add(bszAddr2Line, 0, wxALL|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
71
  bszReplace = new wxBoxSizer(wxHORIZONTAL);
72
  chkReplace = new wxCheckBox(this, ID_CHK_REPLACE, _("Replace:"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHK_REPLACE"));
73
  chkReplace->SetValue(false);
74
  bszReplace->Add(chkReplace, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
75
  txtReplaceThis = new wxTextCtrl(this, ID_TXT_REPLACE_THIS, _("this"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TXT_REPLACE_THIS"));
76
  txtReplaceThis->Disable();
77
  bszReplace->Add(txtReplaceThis, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
78
  lblReplace = new wxStaticText(this, ID_LBL_REPLACE, _("...with:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_LBL_REPLACE"));
79
  lblReplace->Disable();
80
  bszReplace->Add(lblReplace, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
81
  txtReplaceThat = new wxTextCtrl(this, ID_TXT_REPLACE_THAT, _("that"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TXT_REPLACE_THAT"));
82
  txtReplaceThat->Disable();
83
  bszReplace->Add(txtReplaceThat, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
84
  chkSkipUnresolvable = new wxCheckBox(this, ID_CHK_SKIP_UNRESOLVABLE, _("Skip unresolvable"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHK_SKIP_UNRESOLVABLE"));
85
  chkSkipUnresolvable->SetValue(false);
86
  bszReplace->Add(chkSkipUnresolvable, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
87
  bszMainV->Add(bszReplace, 0, wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
88
  txtCrashLogContent = new wxTextCtrl(this, ID_TXT_CRASH_LOG_CONTENT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE, wxDefaultValidator, _T("ID_TXT_CRASH_LOG_CONTENT"));
89
  txtCrashLogContent->SetMinSize(wxSize(450,200));
90
  wxFont txtCrashLogContentFont = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT);
91
  if ( !txtCrashLogContentFont.Ok() ) txtCrashLogContentFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
92
  txtCrashLogContent->SetFont(txtCrashLogContentFont);
93
  bszMainV->Add(txtCrashLogContent, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
94
  txtResult = new wxTextCtrl(this, ID_TXT_RESULT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE, wxDefaultValidator, _T("ID_TXT_RESULT"));
95
  txtResult->SetMinSize(wxSize(450,200));
96
  wxFont txtResultFont = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT);
97
  if ( !txtResultFont.Ok() ) txtResultFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
98
  txtResult->SetFont(txtResultFont);
99
  bszMainV->Add(txtResult, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
100
  stlLine = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxSize(10,-1), wxLI_HORIZONTAL, _T("wxID_ANY"));
101
  bszMainV->Add(stlLine, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_LEFT|wxALIGN_TOP, 5);
102
  btnOperate = new wxButton(this, ID_BTN_OPERATE, _("Operate"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BTN_OPERATE"));
103
  btnOperate->Disable();
104
  bszMainV->Add(btnOperate, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_TOP|wxALIGN_CENTER_HORIZONTAL, 5);
105
  btnQuit = new wxButton(this, ID_BTN_QUIT, _("Quit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_BTN_QUIT"));
106
  bszMainV->Add(btnQuit, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_TOP|wxALIGN_CENTER_HORIZONTAL, 5);
107
  bszMainH->Add(bszMainV, 1, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
108
  SetSizer(bszMainH);
109
  bszMainH->Fit(this);
110
  bszMainH->SetSizeHints(this);
111
112
  Connect(ID_CRASH_LOG,wxEVT_COMMAND_FILEPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnCrashLogFile));
113
  Connect(ID_ADDR2LINE,wxEVT_COMMAND_FILEPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnAddr2LineFile));
114
  Connect(ID_DIR_PREPEND,wxEVT_COMMAND_DIRPICKER_CHANGED,wxFileDirPickerEventHandler(Addr2LineUIDialog::OnDirPrependDir));
115
  Connect(ID_CHK_REPLACE,wxEVT_COMMAND_CHECKBOX_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnReplaceClick));
116
  Connect(ID_BTN_OPERATE,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnOperateClick));
117
  Connect(ID_BTN_QUIT,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(Addr2LineUIDialog::OnQuit));
118
  //*)
119
120
  mFileConfig.Read(wxT("CrashLog"),   &mCrashLog,   wxT("")); m_FPCrashLog->SetPath(mCrashLog);
121
  mFileConfig.Read(wxT("Addr2Line"),  &mAddr2Line,  wxT("")); m_FPAddr2Line->SetPath(mAddr2Line);
122
  mFileConfig.Read(wxT("DirPrepend"), &mDirPrepend, wxT("")); m_DPDirPrepend->SetPath(mDirPrepend);
123
124
  bool     Replace;          mFileConfig.Read(wxT("Replace"),          &Replace,          false  ); chkReplace->SetValue(Replace);
125
  if (Replace) { txtReplaceThis->Enable(); lblReplace->Enable(); txtReplaceThat->Enable(); }
126
  wxString ReplaceThis;      mFileConfig.Read(wxT("ReplaceThis"),      &ReplaceThis,      wxT("")); txtReplaceThis->SetValue(ReplaceThis);
127
  wxString ReplaceThat;      mFileConfig.Read(wxT("ReplaceThat"),      &ReplaceThat,      wxT("")); txtReplaceThat->SetValue(ReplaceThat);
128
129
  bool     SkipUnresolvable; mFileConfig.Read(wxT("SkipUnresolvable"), &SkipUnresolvable, false  ); chkSkipUnresolvable->SetValue(SkipUnresolvable);
130
}
131
132
Addr2LineUIDialog::~Addr2LineUIDialog()
133
{
134
  //(*Destroy(Addr2LineUIDialog)
135
  //*)
136
}
137
138
void Addr2LineUIDialog::OnCrashLogFile(wxFileDirPickerEvent& event)
139
{
140
  mCrashLog = event.GetPath();
141
142
  wxTextFile file(mCrashLog);
143
  if (file.Open())
144
  {
145
    mCrashLogFileContent.Clear();
146
    txtCrashLogContent->Clear();
147
    for (wxString line = file.GetFirstLine(); !file.Eof(); line = file.GetNextLine())
148
    {
149
      mCrashLogFileContent.Add(line);
150
      txtCrashLogContent->AppendText(line + wxT("\n"));
151
    }
152
153
    if (mCrashLogFileContent.Count()>0) btnOperate->Enable(); else btnOperate->Disable();
154
  }
155
  else
156
    wxMessageBox(wxT("Error: File could not be opened."), wxT("Addr2LineUI"), wxOK|wxICON_ERROR, this);
157
}
158
159
void Addr2LineUIDialog::OnAddr2LineFile(wxFileDirPickerEvent& event)
160
{
161
  mAddr2Line = event.GetPath();
162
}
163
164
void Addr2LineUIDialog::OnDirPrependDir(wxFileDirPickerEvent& event)
165
{
166
  mDirPrepend = event.GetPath();
167
}
168
169
void Addr2LineUIDialog::OnReplaceClick(wxCommandEvent& event)
170
{
171
  if (event.IsChecked())
172
  { txtReplaceThis->Enable();  lblReplace->Enable();  txtReplaceThat->Enable();  }
173
  else
174
  { txtReplaceThis->Disable(); lblReplace->Disable(); txtReplaceThat->Disable(); }
175
}
176
177
void Addr2LineUIDialog::OnOperateClick(wxCommandEvent& WXUNUSED(event))
178
{
179
  // Style w/  debug symbols:
180
  /*
181
004013AE 00000008 60000000 40166666  sample_d.exe!Function  [C:\Devel\CodeBlocks\MinGW\bin\DrMinGW\demo/sample.cpp @ 10]
182
	...
183
184
	static void Function(int i, double j, const char * pszString) {
185
>	    sscanf("12345", "%i", (int *)1);
186
	}
187
188
	...
189
190
00401CCE 00000004 40B33333 0028FF08  sample_d.exe!StaticMethod  [C:\Devel\CodeBlocks\MinGW\bin\DrMinGW\demo/sample.cpp @ 15]
191
	...
192
	struct Class {
193
	    static void StaticMethod(int i, float j) {
194
>	        Function(i * 2, j, "Hello");
195
	    }
196
197
	...
198
  */
199
200
  // Sytle w/o debug symbols:
201
  /*
202
004013AE 00000008 60000000 40166666  sample_r.exe!Function(int, double, char const*)
203
00401CCE 00000004 40B33333 0028FF08  sample_r.exe!Class::StaticMethod(int, float)
204
  */
205
206
  // The address element "XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX " needs to be removed later, compute size here.
207
  wxRegEx reAddr32(wxT("([A-Fa-f0-9]{8})"));  wxString tag32(wxT("AddrPC   Params"));         size_t len32 = 4*8 +4; // 4 times 8bit  address + 4 times space
208
  wxRegEx reAddr64(wxT("([A-Fa-f0-9]{16})")); wxString tag64(wxT("AddrPC           Params")); size_t len64 = 4*16+4; // 4 times 16bit address + 4 times space
209
  bool is64Bit = false;
210
  txtResult->Clear();
211
212
  txtResult->AppendText(wxT("Working directory is '") + wxGetCwd() + wxT("'.\n"));
213
214
215
  bool operate_line = false;
216
  for (size_t i=0; i<mCrashLogFileContent.Count(); i++)
217
  {
218
    wxString line = mCrashLogFileContent.Item(i);
219
    if (line.IsSameAs(tag32))
220
    {
221
      txtResult->AppendText(wxT("*************************************\n"));
222
      txtResult->AppendText(wxT("* Found (another) 32 bit call stack *\n"));
223
      txtResult->AppendText(wxT("*************************************\n"));
224
      operate_line = true;
225
      continue;
226
    }
227
    else if (line.IsSameAs(tag64))
228
    {
229
      txtResult->AppendText(wxT("*************************************\n"));
230
      txtResult->AppendText(wxT("* Found (another) 64 bit call stack *\n"));
231
      txtResult->AppendText(wxT("*************************************\n"));
232
      operate_line = true;
233
      is64Bit = true;
234
      continue;
235
    }
236
237
    if (!operate_line)
238
      continue;
239
240
    line = line.Trim(true).Trim(false);
241
    if (line.IsEmpty())
242
      continue;
243
244
    if (!is64Bit && !reAddr32.Matches(line) )
245
      continue;
246
    if ( is64Bit && !reAddr64.Matches(line) )
247
      continue;
248
249
    wxString theAddr;
250
    wxString theFile;
251
252
253
    // Obtain address
254
    if (is64Bit)
255
    {
256
      for (size_t j=1; j<=reAddr64.GetMatchCount(); j++)
257
      {
258
        switch (j)
259
        {
260
          case 1: { theAddr = reAddr64.GetMatch(line, 1); } break;
261
          case 2: // fall through
262
          case 3: // fall through
263
          case 4: // fall through
264
          default: break;
265
        }
266
      }
267
    }
268
    else // 32 bit
269
    {
270
      for (size_t j=1; j<=reAddr32.GetMatchCount(); j++)
271
      {
272
        switch (j)
273
        {
274
          case 1: { theAddr = reAddr32.GetMatch(line, 1); } break;
275
          case 2: // fall through
276
          case 3: // fall through
277
          case 4: // fall through
278
          default: break;
279
        }
280
      }
281
    }
282
283
    // Verify address
284
    if (theAddr.IsEmpty())
285
    {
286
      txtResult->AppendText(wxT("Skipping empty address '") + line + wxT("'\n"));
287
      continue;
288
    }
289
290
    // Remove "XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX "
291
    line = line.Right(line.Length() - (is64Bit ? len64 : len32)).Trim(true).Trim(false) ; // 8 times address + 8 times space
292
    wxString sep = wxT("!");
293
    int sep_pos = line.Find(wxT('!'), true);
294
    if (sep_pos!=wxNOT_FOUND)
295
      theFile = line.SubString(0,sep_pos-1);
296
297
    // Verify file
298
    if (theFile.IsEmpty())
299
    {
300
      txtResult->AppendText(wxT("Skipping address '") + theAddr + wxT("' for unknown file : '") + theFile + wxT("'\n"));
301
      continue;
302
    }
303
304
    // prepend directory if requested
305
    if (!mDirPrepend.IsEmpty())
306
      theFile = mDirPrepend + wxFILE_SEP_PATH + theFile;
307
308
    // replacements in command (if any):
309
    if (chkReplace->IsChecked())
310
    {
311
      wxString repl_this = txtReplaceThis->GetValue();
312
      wxString repl_that = txtReplaceThat->GetValue();
313
      // avoid endless loops
314
      if (   !repl_this.IsSameAs(repl_that)
315
          && !(   repl_this.Trim(true).Trim(false).IsEmpty()
316
               && repl_that.Trim(true).Trim(false).IsEmpty() )
317
          && !(repl_this.Trim(true).Trim(false).IsSameAs(
318
                 repl_that.Trim(true).Trim(false)) ) )
319
      {
320
        theFile.Replace(repl_this, repl_that);
321
      }
322
      else
323
      {
324
        wxMessageBox(wxT("Error: Invalid setup for replacements (would cause a loop)."), wxT("Addr2LineUI"), wxOK|wxICON_ERROR, this);
325
        chkReplace->SetValue(false);
326
      }
327
    }
328
329
    if ( !wxFileExists(theFile) )
330
    {
331
      txtResult->AppendText(wxT("Skipping non-existent file '") + theFile + wxT("'\n"));
332
      continue;
333
    }
334
335
    // apply file mask if needed
336
    if (theFile.Contains(wxT(" "))) theFile = wxT("\"") + theFile + wxT("\"");
337
338
    // compute (initial) command line argument to addr2line
339
    wxString command_args = wxT(" -C -e ") + theFile + wxT(" ") + theAddr;
340
    // Now prepend the addr2line tool and compile the full command
341
    wxString command      = mAddr2Line + command_args;
342
343
    { // BEGIN Lifetime of wxWindowDisabler and wxBusyInfo
344
      wxWindowDisabler disableAll;
345
      wxBusyInfo       wait(wxT("Please wait, operating:\n") + command);
346
347
      wxArrayString output, error;
348
      long ret = wxExecute(command, output, error); // sync process
349
      if (ret==-1)
350
      {
351
        txtResult->AppendText(command + wxT(":\n"));
352
        txtResult->AppendText(wxT("-1 for: ") + command + wxT("\n"));
353
        txtResult->AppendText(wxT("----------------------------------------\n"));
354
      }
355
      else if (!error.IsEmpty())
356
      {
357
        txtResult->AppendText(command + wxT(":\n"));
358
        txtResult->AppendText(wxT("Error for: ") + command + wxT("\n:"));
359
        for (size_t j=0; j<error.Count(); j++)
360
          txtResult->AppendText(error.Item(j) + wxT("\n"));
361
        txtResult->AppendText(wxT("----------------------------------------\n"));
362
      }
363
      else
364
      {
365
        bool do_show = true;
366
        if (chkSkipUnresolvable->IsChecked())
367
        {
368
          if (output.Count()>0 && output.Item(0).Contains(wxT("??:0")))
369
            do_show = false;
370
        }
371
372
        if (do_show)
373
        {
374
          txtResult->AppendText(command + wxT(":\n"));
375
          txtResult->AppendText(theFile + wxT("[") + theAddr + wxT("]:\n"));
376
          for (size_t j=0; j<output.Count(); j++)
377
            txtResult->AppendText(output.Item(j) + wxT("\n"));
378
          txtResult->AppendText(wxT("----------------------------------------\n"));
379
        }
380
      }
381
    }// END Lifetime of wxWindowDisabler and wxBusyInfo
382
  }// for
383
}
384
385
void Addr2LineUIDialog::OnQuit(wxCommandEvent& WXUNUSED(event))
386
{
387
  mFileConfig.Write(wxT("CrashLog"),         mCrashLog                       );
388
  mFileConfig.Write(wxT("Addr2Line"),        mAddr2Line                      );
389
  mFileConfig.Write(wxT("DirPrepend"),       mDirPrepend                     );
390
  mFileConfig.Write(wxT("Replace"),          chkReplace->IsChecked()         );
391
  mFileConfig.Write(wxT("ReplaceThis"),      txtReplaceThis->GetValue()      );
392
  mFileConfig.Write(wxT("ReplaceThat"),      txtReplaceThat->GetValue()      );
393
  mFileConfig.Write(wxT("SkipUnresolvable"), chkSkipUnresolvable->IsChecked());
394
395
  EndModal(wxID_OK);
396
  Destroy();
397
}