errors.cpp

Go to the documentation of this file.
00001 // $Id: errors.cpp 1783 2007-10-21 21:58:59Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // errors.cpp : implementation file
00099 //
00100 
00101 /*
00102 */
00103 
00104 
00105 #include "camtypes.h"
00106 
00107 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "camelot.h"
00109 #include "gdraw.h"
00110 #include "cversion.h"
00111 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #if !defined(EXCLUDE_FROM_XARLIB)
00113 //#include "tool.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 #include "helpuser.h"
00115 #include "basebar.h"        // For gallery creation error box fix...
00116 //#include "ralphint.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 #include "ralphdoc.h"
00118 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 #include "ralpherr.h"
00120 #include "camprofile.h"
00121 #include "cartprov.h"
00122 #include "dragmgr.h"
00123 #endif
00124 
00125 // Put the source file into the revision list
00126 DECLARE_SOURCE("$Revision: 1783 $");
00127 
00128 #if 0
00129 #ifdef _DEBUG
00130 #undef THIS_FILE
00131 static char BASED_CODE THIS_FILE[] = __FILE__;
00132 #endif
00133 #endif
00134 
00135 static BOOL ErrorHasBeenReported = TRUE;
00136 static UINT32   InSetError = 0;         // In either of the SetError routines
00137 UINT32 Error::ErrorBoxRecurse = 0;  // Incremented as per how many recursive error boxes we have
00138 
00139 // Used to indicate what kind of error message is currently defined.
00140 typedef enum
00141 {
00142     ERRORSTAT_NONE,
00143     ERRORSTAT_TEXT,
00144     ERRORSTAT_ID
00145 } ErrorStatus;
00146 
00147 static ErrorStatus ErrStatus = ERRORSTAT_NONE;
00148 
00149 
00150 UINT32 Error::RenderThread = 0; // We're not in the thread
00151 
00152 wxString Error::UserName;
00153 
00154 #if !defined(EXCLUDE_FROM_XARLIB)
00155 /********************************************************************************************
00156 
00157 >   ErrorInfo::ErrorInfo()
00158 
00159     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00160     Created:    23/05/94
00161     Purpose:    Initialises the fields of the error info structure to sensible defaults.
00162 
00163 ********************************************************************************************/
00164 
00165 ErrorInfo::ErrorInfo()
00166 {
00167     ErrorMsg  = 0;
00168     Title     = 0;
00169     Button[0] = _R(IDS_OK);
00170     Button[1] = 0;
00171     Button[2] = 0;
00172     Button[3] = 0;
00173     OK        = 1;
00174     Cancel    = 2;
00175     Help      = 0;              // by default there is no help button
00176 }
00177 #endif
00178 
00179 /********************************************************************************************
00180 
00181 >   HRESULT Error::ErrIDToHRESULT(UINT32 ErrID)
00182 
00183     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00184     Created:    23/05/94
00185     Purpose:    Convert our ErrID's to HRESULTS if we're not interested return S_OK
00186 
00187 ********************************************************************************************/
00188 HRESULT Error::ErrIDToHRESULT(UINT32 ErrID)
00189 {
00190 #ifdef RALPH
00191     return GetHRESULTFromID(ErrID);
00192 #endif
00193     return S_OK;
00194 }
00195 
00196 #if !defined(EXCLUDE_FROM_XARLIB)
00197 /********************************************************************************************
00198 
00199 >   HRESULT Error::GetRalphError()
00200 
00201     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00202     Created:    23/05/94
00203     Purpose:    ERROR1 - No local reporting -pass the mapped Error code to the harness
00204                 ERROR2 - Report the Error locally - don't pass to handler 
00205                 ERROR3 - Report as ERROR2's - won't occur in retails - 
00206 
00207 ********************************************************************************************/
00208 HRESULT Error::GetRalphError()
00209 {
00210     
00211     UINT32 Err = Error::GetRalphErrorNumber();
00212     wxString ErrStr( Error::GetErrorString() );
00213     HRESULT hr = S_OK;
00214 
00215     // ERROR2's 3's
00216     if(Err==0)
00217     {
00218         if(!ErrStr.IsEmpty())
00219         {
00220 #if defined(_DEBUG) && defined(__WXMSW__)
00221             MessageBox(NULL,ErrStr,_T("Error"),MB_OK);
00222 #endif
00223             // make sure we clear ERROR2's 'cause we report them now
00224             Error::ClearError();
00225         }   
00226     }
00227 
00228     //ERROR1
00229     if(Err!=0)
00230     {
00231         // Do Mapping
00232         hr = ErrIDToHRESULT(Err);
00233     
00234     }
00235     // ERROR 2's 3's
00236     if(Err==0)
00237     {
00238         if(!ErrStr.IsEmpty())
00239            hr = RALPH_E_INTERNAL;
00240     }
00241     
00242     return hr;
00243 }
00244 
00245 
00246 /********************************************************************************************
00247 
00248 >   INT32 InformGeneral(UINT32 Error, UINT32 ModID, UINT32 ErrorMsg, 
00249                       UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4,
00250                       UINT32 OK, UINT32 Cancel)
00251 
00252     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> (then Andy)
00253     Created:    15/6/93
00254     Inputs:     Error - either ERRORTYPE_NORMAL, 
00255                                ERRORTYPE_ERROR, 
00256                                ERRORTYPE_WARNING or 
00257                                ERRORTYPE_SERIOUS
00258                 ModID - Module ID to obtain messages (0=Kernel).
00259                 ErrorMsg - The Error Message to display. 0 means use static Error
00260                 Butt1-4  - The Text for the buttons. Up to 4 buttons can be specified
00261                            If Butt1 is 0, it means use '_R(IDS_OK)', i.e. "OK".
00262                 OK - which button (1-4) should be the OK (default) button.
00263                 Cancel - button should be the 'Cancel' button (and hence responds to Esc).
00264     Returns:    The number of the button used to close the dialog.
00265     Purpose:    The underlying function for [Tool-Module]Inform[Warning-Error].
00266     SeeAlso:    InformWarning; InformGeneral; ToolInformWarning; ToolInformError; 
00267                 ModuleInformWarning; ModuleInformError
00268 
00269 ********************************************************************************************/
00270 #ifdef RALPH
00271 // **RALPH** error reporting
00272 
00273 INT32 InformGeneral(UINT32 Error, UINT32 modID, UINT32 ErrorMsg, 
00274                   UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4,
00275                   UINT32 OK, UINT32 Cancel)
00276 {    
00277     
00278     // ** this is the RALPH version of  InformError **
00279     // it's job is to report the error back to ralph's current harness
00280     
00281 
00282     // get a pointer to the kernel document
00283     Document *pkDoc = Document::GetCurrent();
00284     RalphDocument * pRalphDoc = NULL;
00285     if(pkDoc==NULL)
00286         return _R(IDS_OK);
00287     // get a pointer to it's attached ralphdoc
00288     pRalphDoc = pkDoc->GetRalphDoc();
00289 
00290     if(pRalphDoc== NULL)
00291         return _R(IDS_OK);
00292 
00293 
00294     if (ErrorMsg != 0)
00295     {
00296         // It's a new error message
00297         Error::SetError(ErrorMsg, modID);
00298     }
00299 
00300     // Make sure we haven't already reported this error!
00301 /*  ENSURE((!ErrorHasBeenReported), 
00302            "Ralph InformGeneral: This error has already been reported!");
00303 */
00304     if ( Error::IsInRenderThread() )
00305         TRACE( _T("Ralph InformGeneral called within RenderThread => serious rendering error"));
00306 
00307 
00308     ErrStatus = ERRORSTAT_NONE;
00309 
00310     if ( Error::IsInRenderThread() )
00311     {
00312         TRACE( _T("In RenderThread so clearing up system"));
00313         Error::RenderThreadReset();
00314         CamProfile::AtBase(CAMPROFILE_OTHER);
00315     }
00316     
00317     // if we're outside a ralph method
00318     // pass ERROR1's back to the harness
00319     // and report other errors immediately
00320     // and clear the error
00321     HRESULT hr = Error::GetRalphError();
00322     if(!pRalphDoc->IsInRalphMethod())
00323     {
00324         // get the error mapped to an HRESULT
00325         if(hr !=S_OK && hr!= RALPH_E_INTERNAL)
00326         {
00327             if(pRalphDoc)
00328             {
00329                 pRalphDoc->PassErrorToHarness(hr);
00330             }
00331         }
00332         // and clear the error
00333         Error::ClearError();
00334     }
00335 
00336     // We don't want to report this error again.
00337     ErrorHasBeenReported = TRUE;
00338     ErrorBoxRecurse--;
00339     return _R(IDS_OK) ; //result;
00340 }
00341 
00342 #else
00343 
00344 #ifdef HAVE_DEBUGREPORT
00345 class wxCamDebugReport : public wxDebugReport
00346 {
00347 public:
00348     virtual void DoAddCustomContext(wxXmlNode * nodeRoot)
00349     {
00350         wxString            strMessage;
00351 
00352 #if FALSE == wxUSE_UNICODE
00353         TCHAR*          pszCDrawVer = GDraw_GetSvnVersion();
00354 #else
00355         TCHAR           pszCDrawVer[32];
00356         camMbstowcs( pszCDrawVer, GDraw_GetSvnVersion(), 31 );
00357 #endif
00358         // Add the applications version information
00359         wxXmlNode *nodeVersion = new wxXmlNode(wxXML_ELEMENT_NODE, _T("camelot"));
00360         nodeVersion->AddProperty(_T("xtremeversion"), wxString(g_pszAppVersion));
00361         nodeVersion->AddProperty(_T("xtremerevision"), wxString(g_pszSvnVersion));
00362         nodeVersion->AddProperty(_T("xaradrawversion"), wxString::Format(_T("%d.03d"), HIWORD(GDraw_GetVersion()), LOWORD(GDraw_GetVersion())));
00363         nodeVersion->AddProperty(_T("xaradrawrevision"), pszCDrawVer);
00364         nodeVersion->AddProperty(_T("builddate"), CAMELOT_BUILD_DATE);
00365         nodeRoot->AddChild(nodeVersion);
00366     }
00367 };
00368 #endif
00369 
00370 class CamErrorDialog : public wxDialog
00371 {
00372 public:
00373     CamErrorDialog(ResourceID TitleID) :  wxDialog( NULL, -1, CamResource::GetText(TitleID),
00374                                             wxDefaultPosition, wxDefaultSize,
00375                                             wxDEFAULT_DIALOG_STYLE | wxSTAY_ON_TOP )
00376     {
00377         m_nHelpContext = Error::GetErrorNumber();
00378         if (! m_nHelpContext) m_nHelpContext = GetNextMsgHelpContext();
00379     }
00380 
00381     wxButton * AddErrorButton(wxSizer * pButtonSizer, const TCHAR * pText, INT32 id)
00382     {
00383         wxButton* pButton = new wxButton( this, id, pText, wxDefaultPosition, wxDefaultSize, 0 );
00384         if (!pButton)
00385             return NULL;
00386         pButtonSizer->Add(pButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
00387         return pButton;
00388     }
00389 
00390     void ButtonClicked(wxCommandEvent &event)
00391     {
00392         ResourceID id = event.GetId();
00393         if (id == _R(IDS_HELP)) // Help always has a fixed ID.
00394         {
00395 #if !defined(EXCLUDE_FROM_RALPH)
00396             // It is, so run the help topic associated with the message ID.
00397             HelpUser(m_nHelpContext);
00398 #endif
00399         }
00400         else if (id == _R(IDS_ERRORBOX_DEBUGREPORT))
00401         {
00402 #ifdef HAVE_DEBUGREPORT
00403             wxCamDebugReport report;
00404             wxDebugReportPreviewStd preview;
00405         
00406             report.AddAll();
00407         
00408             if ( preview.Show(report) )
00409                 report.Process();
00410 #else
00411             // This string is not translatable in case translation errors. Note it should never
00412             // appear as the button to call this is disabled where the build does not support
00413             // debug reports.
00414             ::wxMessageBox(_T("Your build was not compiled to support debug reports"));
00415 #endif
00416         }
00417         else
00418         {
00419             EndModal(id);
00420         }
00421     }
00422 
00423     INT32 m_nHelpContext;
00424 
00425     DECLARE_EVENT_TABLE()
00426 };
00427 
00428 BEGIN_EVENT_TABLE( CamErrorDialog, wxDialog )
00429     EVT_COMMAND (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, CamErrorDialog::ButtonClicked)
00430 END_EVENT_TABLE()
00431 
00432 
00433 // **CAMELOT Error reporting** 
00434 INT32 InformGeneral(UINT32 Error, UINT32 modID, UINT32 ErrorMsg, 
00435                   UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4,
00436                   UINT32 OK, UINT32 Cancel)
00437 {    
00438     // Make sure there is at least one valid button.
00439     if (Butt1 == 0) Butt1 = _R(IDS_OK);
00440 
00441     if (Error::ErrorBoxRecurse)
00442     {
00443         // Oh dear oh dear. Someone wants to put up an error box in the error handler. This is
00444         // **BAD** news. The most likely cause is an exception within this routine (or the other
00445         // InformGeneral).
00446         TRACE( _T("Recursive InformGeneral - Error in error handler! (1)\n"));
00447         // Don't risk putting up another error box - just return OK & hope for the best
00448         Beep(); // shouldn't cause too much trouble
00449         return(OK);
00450     }
00451 
00452     Error::ErrorBoxRecurse++;
00453     if (ErrorMsg != 0)
00454     {
00455         // It's a new error message
00456         Error::SetError(ErrorMsg, modID);
00457     }
00458 
00459     // Make sure we haven't already reported this error!
00460     ENSURE((!ErrorHasBeenReported), 
00461            "InformGeneral: This error has already been reported!");
00462 
00463     // In retail builds, we report the error anyway, just in case - it's better to have
00464     // two errors reported than none at all!
00465 
00466     // we should get our bitmap from the OS
00467     ResourceID TitleID = 0;
00468 
00469     ResourceID DebugReport = 0;
00470 
00471     wxArtID bitmap=wxART_MISSING_IMAGE;
00472 
00473     switch (Error)
00474     {
00475         case ERRORTYPE_NORMAL:
00476             // No sound for this one - it's just a message; nothing to shout about.
00477             bitmap = wxART_INFORMATION;
00478             TitleID = _R(IDS_ERRORBOX_NORMAL);
00479             break;
00480 
00481         case ERRORTYPE_QUESTION:
00482             //MessageBeep(MB_ICONQUESTION);
00483             bitmap = wxART_QUESTION;
00484             TitleID = _R(IDS_ERRORBOX_NORMAL);
00485             break;
00486 
00487         case ERRORTYPE_WARNING:
00488             //MessageBeep(MB_ICONASTERISK);
00489             bitmap = wxART_WARNING;
00490             TitleID = _R(IDS_ERRORBOX_WARNING);
00491             break;
00492 
00493         case ERRORTYPE_SERIOUS:
00494             //MessageBeep(MB_ICONHAND);
00495             bitmap = wxART_ERROR;
00496             TitleID = _R(IDS_ERRORBOX_SERIOUS);
00497             DebugReport = _R(IDS_ERRORBOX_DEBUGREPORT);
00498             break;
00499 
00500         case ERRORTYPE_ENSURE:
00501             //MessageBeep(MB_ICONHAND);
00502             bitmap = wxART_ERROR;
00503             TitleID = _R(IDS_ERRORBOX_ENSURE);
00504             DebugReport = _R(IDS_ERRORBOX_DEBUGREPORT);
00505             break;
00506 
00507         case ERRORTYPE_ERROR:
00508         default:
00509             //MessageBeep(MB_ICONEXCLAMATION);
00510             bitmap = wxART_ERROR;
00511             TitleID = _R(IDS_ERRORBOX_ERROR);
00512             break;
00513 
00514     }
00515 
00516     // We really should detect an error here, and if so use a stock wxMessageBox, but that
00517     // doesn't seem to support help (oh dear).
00518     // but in anticipation of that being fixed, we use a pointer
00519 
00520     wxDialog * pBox = new CamErrorDialog(TitleID);
00521 
00522     if (!pBox)
00523     {
00524         Beep();
00525         Error::ErrorBoxRecurse--;
00526         return OK;
00527     }
00528 
00529 #ifdef __WXMAC__
00530     pBox->SetExtraStyle(wxDIALOG_EX_METAL);
00531     pBox->SetBackgroundStyle(wxBG_STYLE_COLOUR);
00532     pBox->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
00533 #endif
00534 
00535     // Note we add these to the dialog as soon as we can. Thus delete pBox will take
00536     // care of them
00537     wxBoxSizer* pVSizer = new wxBoxSizer(wxVERTICAL);
00538     if (!pVSizer)
00539     {
00540         Beep();
00541         Error::ErrorBoxRecurse--;
00542         delete pBox;
00543         return OK;
00544     }
00545     pBox->SetSizer(pVSizer);
00546 
00547     wxBoxSizer* pMessageSizer = new wxBoxSizer(wxHORIZONTAL);
00548     if (!pMessageSizer)
00549     {
00550         Beep();
00551         Error::ErrorBoxRecurse--;
00552         delete pBox;
00553         return OK;
00554     }
00555     pVSizer->Add(pMessageSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
00556 
00557 
00558     CamArtProvider * pArtProv = CamArtProvider::Get();
00559     // Art provider may not have been initialized...
00560     if (pArtProv)
00561     {
00562         wxStaticBitmap* pStaticBitmap = new wxStaticBitmap( pBox, -1,
00563                                                             wxArtProvider::GetBitmap(bitmap, wxART_MESSAGE_BOX),
00564                                                             wxDefaultPosition, wxDefaultSize, 0 );
00565         if (!pStaticBitmap)
00566         {
00567             Beep();
00568             Error::ErrorBoxRecurse--;
00569             delete pBox;
00570             return OK;
00571         }
00572         pMessageSizer->Add(pStaticBitmap, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
00573     }
00574 
00575     // Perform manual expansion of newline escape sequences...
00576     wxString temp = (TCHAR *)Error::GetErrorString();
00577     temp.Replace(_T("\\n"), _T("\n"), TRUE);
00578 
00579     //wxTextCtrl* pMessage = new wxTextCtrl( pBox, -1, (TCHAR *)Error::GetErrorString(),
00580     //                                     wxDefaultPosition, wxSize(400, -1),
00581     //                                     wxTE_MULTILINE|wxTE_READONLY|wxTE_CENTRE|wxNO_BORDER );
00582 
00583     wxStaticText* pMessage = new wxStaticText( pBox, -1, temp,
00584                                            wxDefaultPosition, wxSize(400, -1),
00585                                            wxALIGN_CENTRE|wxNO_BORDER );
00586     if (!pMessage)
00587     {
00588         Beep();
00589         Error::ErrorBoxRecurse--;
00590         delete pBox;
00591         return OK;
00592     }
00593 
00594     CamResource::DoneInit();
00595 
00596     pMessage->Wrap(400);
00597     //pMessage->Enable(false); // this annoyingly does not grey it
00598     //pMessage->SetBackgroundColour(pBox->GetBackgroundColour());
00599     pMessageSizer->Add(pMessage, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxFIXED_MINSIZE, 5);
00600 
00601     wxBoxSizer* pButtonSizer = new wxBoxSizer(wxHORIZONTAL);
00602     if (!pButtonSizer)
00603     {
00604         Beep();
00605         Error::ErrorBoxRecurse--;
00606         delete pBox;
00607         return OK;
00608     }
00609     pVSizer->Add(pButtonSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
00610 
00611 #define EB_MAXBUTS 7
00612     wxButton * pButt[EB_MAXBUTS]; // see help below, note we don't use zero, 5 is reserved for help
00613     ResourceID butres[EB_MAXBUTS];
00614     butres[0]=0;
00615     butres[1]=Butt1;
00616     butres[2]=Butt2;
00617     butres[3]=Butt3;
00618     butres[4]=Butt4;
00619     butres[5]=0; // for _R(IDS_HELP) - see below
00620     butres[6]=DebugReport;
00621 
00622 #if !defined(EXCLUDE_FROM_RALPH)
00623     // See if there is any on-line help associated with the given warning/error message.
00624     // If there is then we will add a "Help" button to the dialog.
00625     if (CanHelpUser(Error::GetErrorNumber()))
00626         butres[5]=_R(IDS_HELP);
00627 #endif
00628     
00629     INT32 butt;
00630     for (butt=0; butt<EB_MAXBUTS; butt++)
00631     {
00632         if (butres[butt])
00633         {
00634             pButt[butt] = ((CamErrorDialog *)pBox)->AddErrorButton(pButtonSizer, CamResource::GetText(butres[butt]),
00635                                                                 butres[butt]);
00636             if (!pButt[butt])
00637             {
00638                 Beep();
00639                 Error::ErrorBoxRecurse--;
00640                 delete pBox;
00641                 return OK;
00642             }
00643 
00644 #ifndef HAVE_DEBUGREPORT
00645             if (butt==6)
00646             {
00647                 pButt[butt]->Enable(FALSE);
00648             }
00649 #endif
00650 
00651         }
00652         else
00653             pButt[butt]=NULL;
00654     }
00655 
00656     // Set the default
00657     if ( ((UINT32)OK <EB_MAXBUTS) && butres[OK] && pButt[OK])
00658     {
00659         pButt[OK]->SetDefault();
00660         pBox->SetDefaultItem(pButt[OK]);
00661     }
00662 
00663     pBox->GetSizer()->Fit(pBox);
00664     pBox->GetSizer()->SetSizeHints(pBox);
00665     pBox->Centre();
00666 
00667     // Disable the system's functionality for serious errors (i.e. stop rendering etc).
00668     if (Error == ERRORTYPE_SERIOUS || Error == ERRORTYPE_ENSURE) CCamApp::DisableSystem(pBox);
00669 
00670     if ( Error::IsInRenderThread() )
00671         TRACE( _T("InformGeneral called within RenderThread => serious rendering error"));
00672 
00673     // Bodge because ReleaseCapture() sometimes doesn't send WM_CANCELMODE (e.g. to custom controls) which
00674     // appears to be a bug somewhere in the Windows API
00675     if (wxWindow::GetCapture()) wxWindow::GetCapture()->ReleaseMouse();
00676 
00677 #if !defined(EXCLUDE_FROM_RALPH)
00678 #ifndef EXCLUDE_FROM_XARALX
00679 // Keep Control Helper system informed
00680     ControlHelper::InformModalDialogOpened();
00681 #endif
00682     // Bodge so error boxes are given focus when bars/galleries are being created
00683     BaseBar::StartErrorBox();
00684 #endif
00685 
00686     // 'Do' the dialog
00687     ResourceID pressed = pBox->ShowModal();
00688     INT32 result = Cancel;
00689 
00690     for (butt=0; butt<EB_MAXBUTS; butt++)
00691     {
00692         if (butres[butt] == pressed)
00693             result = butt;
00694     }
00695 
00696     ErrStatus = ERRORSTAT_NONE;
00697 
00698     delete pBox;
00699 
00700 #if !defined(EXCLUDE_FROM_RALPH)
00701     // Make sure we forget the old help content.
00702     SetNextMsgHelpContext(0);
00703 
00704 #ifndef EXCLUDE_FROM_XARALX
00705     // Keep Control Helper system informed
00706     ControlHelper::InformModalDialogClosed();
00707 #endif
00708 
00709     // Bodge so error boxes are given focus when bars/galleries are being created
00710     BaseBar::FinishErrorBox();
00711 #endif
00712 
00713     if ( Error::IsInRenderThread() )
00714     {
00715         TRACE( _T("In RenderThread so clearing up system"));
00716         Error::RenderThreadReset();
00717         CamProfile::AtBase(CAMPROFILE_OTHER);
00718     }
00719 
00720     // Enable system if necessary.
00721     if (Error == ERRORTYPE_SERIOUS || Error == ERRORTYPE_ENSURE) CCamApp::EnableSystem();
00722 
00723     // We don't want to report this error again.
00724     ErrorHasBeenReported = TRUE;
00725     Error::ClearError();
00726         
00727     Error::ErrorBoxRecurse--;
00728 
00729     // if we were in a drag operation, cancel it (to prevent invalid drag state) fixes #11455
00730     DragManagerOp::AbortDrag();
00731 
00732     return result;
00733 }
00734 
00735 #endif
00736 
00737 /********************************************************************************************
00738 
00739 >   INT32 InformGeneral(UINT32 Error, ErrorInfo *pInfo, UINT32 ModID)
00740 
00741     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00742     Created:    04/07/94
00743     Inputs:     Error - the type of error (e.g. ERRORTYPE_SERIOUS)
00744                 pInfo - pointer to the ErrorInfo object which desvribes this 'error'.
00745                 ModID - module ID, if required (may be 0).
00746     Returns:    ID of the button that was pressed (NB. NOT the index of the button - i.e.
00747                 it returns a resource ID).
00748     Purpose:    The underlying function for [Tool-Module]Inform[Warning-Error].
00749     SeeAlso:    InformWarning; InformGeneral; ToolInformWarning; ToolInformError; 
00750                 ModuleInformWarning; ModuleInformError
00751 
00752 ********************************************************************************************/
00753 
00754 INT32 InformGeneral(UINT32 Error, ErrorInfo* pInfo, UINT32 ModID)
00755 {
00756     if (!pInfo) return _R(IDS_OK); // Catch this early
00757     INT32 num = InformGeneral(Error,ModID, pInfo->ErrorMsg, 
00758                   pInfo->Button[0],pInfo->Button[1],pInfo->Button[2],pInfo->Button[3],
00759                   pInfo->OK,pInfo->Cancel);
00760     return num?pInfo->Button[num-1]:_R(IDS_OK);
00761     
00762 }
00763 
00764 
00765 
00766 /********************************************************************************************
00767 
00768 >   void InformLastError(UINT32 ErrorType = ERRORTYPE_ERROR)
00769 
00770     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
00771     Created:    24/8/93
00772     Inputs:     ErrorType is the error type (e.g. ERRORTYPE_WARNING) Defaults to ERRORTYPE_ERROR
00773                 THIS PARAM IS NOW IGNORED.
00774     Outputs:    None
00775     Returns:    None
00776     Purpose:    Report the last error that was set with ERROR, ERRORIF, TOOLERROR et al.
00777                 Always presents the user with an OK button. If there isn't an unreported
00778                 error, does nothing.
00779     SeeAlso:    ERROR; ERRORIF; TOOLERROR
00780 
00781 ********************************************************************************************/
00782 
00783 void InformLastError(UINT32)
00784 {
00785     if (ErrStatus != ERRORSTAT_NONE)
00786     {
00787         InformError();
00788         ErrStatus = ERRORSTAT_NONE;
00789     }
00790 }
00791 
00792 
00793 
00794 /********************************************************************************************
00795 
00796 >   INT32 InformError(UINT32 ErrorMsg = 0, 
00797                     UINT32 Butt1 = 0, UINT32 Butt2 = 0, UINT32 Butt3 = 0, UINT32 Butt4 = 0, 
00798                     UINT32 OK = 1, UINT32 Cancel = 2)
00799 
00800     INT32 ToolInformError(UINT32 ToolID, <as above>)
00801 
00802     INT32   ModuleInformError(UINT32 ModuleID, <as above>)
00803 
00804 
00805     INT32 InformSeriousError(UINT32 ErrorMsg = 0, 
00806                            UINT32 Butt1 = 0, UINT32 Butt2 = 0, UINT32 Butt3 = 0, UINT32 Butt4 = 0,
00807                            UINT32 OK = 1, UINT32 Cancel = 2)
00808 
00809     INT32 ToolInformSeriousError(UINT32 ToolID, <as above>)
00810 
00811     INT32   ModuleInformSeriousError(UINT32 ModuleID, <as above>)
00812 
00813 
00814     INT32 InformMessage(UINT32 ErrorMsg = 0, 
00815                       UINT32 Butt1 = 0, UINT32 Butt2 = 0, UINT32 Butt3 = 0, UINT32 Butt4 = 0,
00816                       UINT32 OK = 1, UINT32 Cancel = 2)
00817 
00818     INT32 ToolInformMessage(UINT32 ToolID, <as above>)
00819 
00820     INT32   ModuleInformMessage(UINT32 ModuleID, <as above>)
00821 
00822 
00823     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>, then Alex
00824     Created:    15/6/93
00825     Inputs:     ErrorMsg - The Error Message to display. 0 means use static Error
00826                 Butt1-4  - The Text for the buttons. Up to 4 buttons can be specified
00827                            If Butt1 is 0, it means use '_R(IDS_OK)', i.e. "OK".
00828                 OK - which button (1-4) should be the OK (default) button.
00829                 Cancel - button should be the 'Cancel' button (and hence responds to Esc).
00830     Returns:    The number of the button used to close the dialog
00831     Purpose:    To display a dialog that gives an error message of some description. Up
00832                 to 3 buttons can be defined for the user to select. It should be used
00833                 when an error occurs that the user could make a decision about eg. Camelot
00834                 failed to save the file, so give them the option to give up, try again or
00835                 try a new filename/path etc.
00836                 If ErrorMsg is zero, the box will use the last error returned by a function 
00837                 with the RETURNERROR macro.
00838                 ToolInformError takes an additional parameter on the front of the Tool ID.
00839                 ModuleInformError takes a module ID. Both of these will try to find the strings
00840                 used for errors and buttons in the owner module first, then the main .exe file.
00841                 These are all in-line function stubs which call InformGeneral.
00842                 The equivalent routines with 'Serious' in their name are the equivalent of those
00843                 without except that they pass ERRORTYPE_SERIOUS and not ERRORTYPE_ERROR
00844                 It's also worth noting tat these are just inline functions that call InformGeneral
00845                 and they live solely in Errors.h
00846     SeeAlso:    InformWarning; RETURNERROR; InformGeneral
00847 
00848 ********************************************************************************************/
00849 
00850 
00851 
00852 
00853 
00854 /********************************************************************************************
00855 
00856 >   INT32 InformWarning( UINT32 ErrorMsg, UINT32 Butt1=0, UINT32 Butt2=0, UINT32 Butt3=0, UINT32 Butt4=0 )
00857 
00858     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
00859     Created:    15/6/93
00860     Inputs:     ErrorMsg - The Error Message to display - 0 means use static Error
00861                 Butt1-3  - The Text for the buttons. Up to 3 buttons can be specified
00862     Returns:    The number of the button used to close the dialog
00863     Purpose:    To display a dialog that gives a warning message of some description. Up
00864                 to 3 buttons can be defined for the user to select. If ErrorMsg is zero
00865                 the error string will be taken from the static Error variables, bringing 
00866                 up the last error that was set by a function calling RETURNERROR.
00867     SeeAlso:    InformError
00868 
00869 ********************************************************************************************/
00870 #endif  // EXCLUDE_FROM_XARLIB
00871 
00872 // Define the instances of the static variables belonging to the Error class
00873 
00874 TCHAR Error::ErrorString[256];
00875 UINT32  Error::ErrorID = 0;
00876 UINT32  Error::RalphErrorID = 0;
00877 UINT32  Error::ModuleID = 0;
00878 UINT32  Error::LastErrorLine;                           // line number of last error (or 0)
00879 const char* Error::LastErrorFile = "Unknown.File";  // ptr to filename of last error - don't translate
00880 
00881 
00883 // Error handling routines
00884 
00885 /***********************************************************************************************
00886 
00887 >   void Error::SetError(UINT32 number, TCHAR* errstring, UINT32 module)
00888     void Error::SetError(UINT32 number, UINT32 module)
00889     void Error::SetErrorTool(UINT32 number, UINT32 tool)
00890     void Error::SetErrorSerious( const TCHAR* errstring )
00891 
00892     Author:     Jim_Lynn (Xara Group Ltd) <camelotdev@xara.com>
00893     Created:    9/7/93
00894     Inputs:     number is the error number - usually a resource ID
00895                 errstring pointer to a TCHAR array containing the string for the error
00896                 module is a UINT32 uniquely identifying the module (0 if kernel)
00897                 tool is a tool ID. The SetErrorSerious call is for serious error handlers
00898                 who must succeed in setting the error regardless.
00899     Outputs:    -
00900     Returns:    -
00901     Purpose:    Called before exiting a routine that failed, this function sets up the static 
00902                 variables which allow the calling routine to see what the error was.
00903                 If the errstring parameter is passed, the module UINT32 is stored, but not used. This
00904                 form of the function would usually be used for routines which want to build up an 
00905                 error string on the fly. If the errstring is absent, the routine uses the UINT32 to
00906                 identify the module, and loads a string from the appropriate resources.
00907     Errors:     -
00908     SeeAlso:    SmartLoadString
00909 
00910 ***********************************************************************************************/
00911 
00912 void Error::SetError(UINT32 number, const TCHAR* errstring, UINT32 module)
00913 {
00914     static TCHAR BASED_CODE LastResort[] = wxT("Cannot perform SetError (1)");
00915     // We now check for a real recursive call. Should only happen if we can't get translate
00916     // an ID to an error string. Perhaps if we're really low on memory. We must then set the
00917     // minimum acceptable error string...
00918     if (InSetError)
00919     {
00920         TRACE(_T("SetError really has been called recursively (1)\n"));
00921         RalphErrorID =ErrorID = _R(IDE_EX_BADOP); // should have it's own, but...
00922         ErrStatus = ERRORSTAT_TEXT;
00923         ErrorHasBeenReported=FALSE;
00924         ModuleID = module;
00925         camStrcpy( ErrorString, LastResort );
00926         return;
00927     }
00928     InSetError++;
00929 
00930 // Andy has stubbed this code out as it caused problems, e.g.
00931 // 'save changes' dialog after a GP fault had been caught made the dialog have the 'save
00932 // changes' buttons, with the GP fault text
00933 #if 0
00934     if (!ErrorHasBeenReported)
00935     {
00936         // ENSURE(FALSE, "Recursive SetError call"); IMHO this is pointless - Alex
00937         TRACE( _T("SetError called twice: ID = %u: %s\n"), number, errstring);
00938         InSetError--;
00939         return;
00940     }
00941 #endif
00942 
00943     RalphErrorID = ErrorID = number;
00944     camStrcpy(ErrorString, errstring);
00945     ModuleID = module;
00946     ErrStatus = ERRORSTAT_TEXT;
00947     ErrorHasBeenReported = FALSE;
00948     TRACE( _T("Setting error: ID = %u: %s\n"), ErrorID, ErrorString);
00949     InSetError--;
00950 }                          
00951 
00952 void Error::SetErrorSerious( const TCHAR* errstring )
00953 {
00954     // this must succeed. In particular it must NOT cause any other errors or ENSUREs
00955     ErrorID = 0; 
00956     ModuleID = 0;
00957     InSetError = 0;
00958     ErrStatus = ERRORSTAT_TEXT;
00959     ErrorHasBeenReported = FALSE;
00960     camStrcpy( ErrorString, errstring );
00961 }
00962 
00963 void Error::SetError(UINT32 number, UINT32 module)
00964 {
00965     static TCHAR BASED_CODE LastResort[] = _T("Cannot perform SetError (2)");
00966     // We now check for a real recursive call. Should only happen if we can't get translate
00967     // an ID to an error string. Perhaps if we're really low on memory. We must then set the
00968     // minimum acceptable error string...
00969     if (InSetError)
00970     {
00971         TRACE(_T("SetError really has been called recursively (2)\n"));
00972         ErrorID = _R(IDE_EX_BADOP); // should have it's own, but...
00973         ErrStatus = ERRORSTAT_TEXT;
00974         ErrorHasBeenReported=FALSE;
00975         ModuleID = module;
00976         camStrcpy( ErrorString, LastResort );
00977         return;
00978     }
00979     InSetError++;
00980     if (!ErrorHasBeenReported)
00981     {
00982         // ENSURE(FALSE, "Recursive SetError call"); IMHO this is pointless - Alex
00983         TRACE( _T("SetError called twice: ID = %u  Module = %u\n"), number, module);
00984         InSetError--;
00985         return;
00986     }
00987     RalphErrorID = ErrorID = number;
00988     ModuleID = module;
00989     ErrorString[0] = 0;
00990     ErrStatus = ERRORSTAT_ID;
00991     ErrorHasBeenReported = FALSE;
00992     if (!SmartLoadString(module, ErrorID, ErrorString, 256 * sizeof(TCHAR)) )
00993     {
00994         camSnprintf( ErrorString, 256, _T("Error Number %u from module ID %u"), ErrorID, ModuleID );
00995     }
00996     
00997     TRACE( _T("Setting error: ID = %d: \"%s\"\n"), ErrorID, ErrorString);
00998     InSetError--;
00999 }
01000 
01001 #if !defined(EXCLUDE_FROM_XARLIB)
01002 void Error::SetErrorTool(UINT32 number, UINT32 toolID)
01003 {
01004     Error::SetError(number, Tool::GetModuleID(toolID));
01005 }
01006 #endif
01007 
01008 
01009 /********************************************************************************************
01010 
01011 >   static void Error::ClearError()
01012 
01013     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01014     Created:    8/12/93
01015     Inputs:     -
01016     Outputs:    -
01017     Returns:    -
01018     Purpose:    Resets the error system to "no current error".
01019     Errors:     -
01020     SeeAlso:    Error::SetError
01021 
01022 ********************************************************************************************/
01023 
01024 void Error::ClearError()
01025 {
01026     TRACEUSER( "Chris", _T("Clear Error now \n") );
01027     RalphErrorID = ErrorID = ModuleID = 0;
01028     ErrorString[0] = 0;
01029 
01030     // Added 15/2/95 so that the function does as it name suggests and actually does clear
01031     // the current error completely from the system rather than just clearing out the error
01032     // id and the error string.
01033     ErrorHasBeenReported = TRUE;
01034     ErrStatus = ERRORSTAT_NONE;
01035 }
01036 
01037 
01038 
01039 /********************************************************************************************
01040 
01041 >   void Error::MarkError( UINT32 LineNumber, const char *Filename )
01042 
01043     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01044     Created:    4/10/94
01045     Inputs:     Line number and filename, usually generated with __LINE__ and __FILE__
01046     Purpose:    Used to 'remember' where an error ocurred. Cannot be done with extra params
01047                 to InternalSetError due to vararg strangeness. The function is declared inline
01048                 on retail builds.
01049     Scope:      Public Static
01050 
01051 ********************************************************************************************/
01052 
01053 /* Tech Note: The MARKERRORBODY macro lives in errors.h. The same macro is used for the inline
01054     version and out of line version - if you need to change the function body, edit the macro
01055 */
01056 
01057 #if !INLINE_MARKERROR
01058 
01059 void Error::MarkError( UINT32 LineNumber, const char *Filename )
01060 MARKERROR_BODY( LineNumber, Filename )
01061 
01062 #endif
01063 
01064 #define ResetWhere()        LastErrorLine = 0; LastErrorFile = "Unknown.File";
01065 
01066 // \n's needed on the end of these
01067 
01068 BOOL Error::IsUserName(const char *wanted)
01069 {
01070     // CmpNoCase returns 0 for a match
01071 
01072     if (!UserName.CmpNoCase(_T("ALL")))
01073         return TRUE;
01074 
01075     if (!UserName.CmpNoCase(_T("")))
01076         return FALSE;
01077 
01078     wxString target (wanted, wxConvUTF8);
01079 
01080     if (!target.CmpNoCase(_T("ALL")))
01081         return TRUE;
01082 
01083     return (!UserName.CmpNoCase(target));
01084 }
01085 
01086 #ifdef _DEBUG
01087 
01088 void Error::TraceWrite(const TCHAR * bufp, va_list args)
01089 {
01090     // wxWidgets doesn't expect newlines in the string, but Camelot source provides them. So we print each bit
01091     // separately
01092 #if 1
01093     // replace \n by a space - the real solution is to remove the \n from all the trace statements (yawn)
01094     TCHAR buf[MAXERRORFORMATLENGTH];
01095     camStrncpy(buf, bufp, MAXERRORFORMATLENGTH);
01096     buf[MAXERRORFORMATLENGTH-1]=0;
01097     TCHAR * b=buf;
01098     do
01099     {
01100         if (*b == '\n') *b=' ';
01101     } while(*b++);
01102     wxVLogDebug(buf, args);
01103 
01104 #else
01105     // this way is bad as it doesn't work with args either side of the newline
01106 
01107     TCHAR * newline;
01108 
01109     do
01110     {
01111         newline = camStrchr(bufp, _T('\n'));
01112         if (newline) *newline++=0;
01113         // We really should pass only the args before the newline here, but...
01114         wxVLogDebug(bufp, args);
01115 
01116         bufp=newline;
01117     } while (bufp && *bufp);
01118 #endif
01119 }   
01120 
01121 #if 0 != wxUSE_UNICODE
01122 // wxWidgets does this if we let it use the vsnprintf in wxLogDebug
01123 // so we don't currently do this - this one converts from a char *
01124 // and is only enabled on Unicode builds
01125 void Error::FixFormat (const char * fmt, TCHAR * fmt2)
01126 {
01127     wxString FString(fmt, wxConvUTF8);
01128     FixFormat(FString.c_str(), fmt2);
01129 }
01130 #endif
01131 
01132 // wxWidgets does this if we let it use the vsnprintf in wxLogDebug
01133 // so we don't currently do this
01134 void Error::FixFormat (const TCHAR * fmt, TCHAR * fmt2)
01135 {
01136     // Unicode - replace %s with %ls
01137     INT32 i=0;
01138     INT32 j=0;
01139     TCHAR c;
01140 
01141     do
01142     {
01143         c = fmt[i++];
01144         fmt2[j++]=c;
01145         if ( (c == _T('%')) && (fmt[i]==_T('s')) )
01146             fmt2[j++]=_T('l'); // this is safe as we know we had at least 2 spare chars
01147     } while ( c && (j < MAXERRORFORMATLENGTH-1)); // Strict comparison deliberate
01148 
01149     // for safety
01150     fmt2[MAXERRORFORMATLENGTH-1]=_T('\0');
01151 }
01152 
01153 void CDECL Error::TraceUser(const char *User, LPCTSTR fmt, ...)
01154 {
01155     if (!IsUserName(User)) return;
01156 
01157     va_list marker;
01158     va_start( marker, fmt );
01159 //  wxVLogDebug(fmt, marker);
01160     TraceWrite(fmt, marker);
01161     va_end( marker );
01162 }
01163 
01164 void CDECL Error::TraceAll(LPCTSTR fmt, ...)
01165 {
01166     va_list marker;
01167     va_start( marker, fmt );
01168 //  wxVLogDebug(fmt, marker);
01169     TraceWrite(fmt, marker);
01170     va_end( marker );
01171 }
01172 
01173 void CDECL Error::TraceTime (TCHAR * t)
01174 {
01175     TCHAR buf[256];
01176 #if !defined(EXCLUDE_FROM_XARLIB)
01177     CamProfile::GetTimeString(buf, 256);
01178 #else
01179     camStrcpy(buf, _T("unknown"));
01180 #endif
01181     TraceAll(_T("[%s] %s"), buf, t);
01182 }
01183 
01184 #endif
01185 
01186 void CDECL Error::ReleaseTrace(LPCTSTR fmt, ...)
01187 {
01188     TCHAR               buf[256];
01189     va_list             marker;
01190     va_start( marker, fmt );
01191     camVsnprintf( buf, 256, fmt, marker );
01192 
01193 #if defined( __WXMSW__ )
01194     OutputDebugString( buf );
01195 #elif defined( __WXGTK__ )
01196     camPrintf( buf );
01197 #else
01198     #pragma error( "Not support on this architechure" )
01199 #endif
01200 
01201     va_end( marker );
01202 }
01203 
01204 
01205 
01206 /********************************************************************************************
01207 
01208 >   void CalcInternalMessage( LPTCHAR result, UINT32 Line, const TCHAR* Filename )
01209 
01210     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01211     Created:    4/10/94
01212     Inputs:     Line number and filename, usually generated with __LINE__ and __FILE__
01213     Outputs:    result is updated with a suitable string
01214     Purpose:    Used to translate something such as 1234 in kernel\blobby.cpp into something
01215                 less readable (in fact 1234@k.bl.by). This is so source & line numbers can be
01216                 reported to an ordinary user without giving too much away.
01217 
01218 ********************************************************************************************/
01219 
01220 static void CalcInternalMessage( LPTCHAR result, UINT32 Line, const TCHAR* Filename )
01221 {
01222     const TCHAR* Slash    = camStrrchr( Filename, TEXT('\\') );
01223     const TCHAR* Dot      = camStrrchr( Filename, TEXT('.')  );
01224     TCHAR CodedFile[20];
01225 
01226     if (Slash && Dot)
01227     {
01228         TCHAR* p = CodedFile;
01229 
01230         *p++ = Filename[0];                 // 1st char is first letter of dirname
01231         *p++ = TEXT('.');                   // seperators
01232         *p++ = Slash[1];                    // 1st 2 chars of filename
01233         *p++ = Slash[2];
01234         *p++ = TEXT('.');
01235         *p++ = Dot[-2];                     // last 2 chars of filename
01236         *p++ = Dot[-1];
01237         *p = 0;
01238 
01239         Filename = CodedFile; 
01240     }
01241 
01242     // this message should not be translated
01243     String_256 jcf(_R(IDS_INTERNAL_ERROR_MSG));
01244     camSnprintf(result, 256, jcf, (UINT32) Line, (LPCTSTR) Filename);
01245 }
01246 
01247 
01248 
01249 /********************************************************************************************
01250 
01251 >   void CDECL Error::XSetError( const TCHAR *fmt, ...)
01252 
01253     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01254     Created:    4/10/94
01255     Inputs:     printf-style arguments.
01256     Purpose:    Do NOT call directly. Called via the ERROR2xx macros. In debug builds, puts
01257                 up an ensure box. In all builds, sets an error. Do NOT put \n's or \r's on the
01258                 end.
01259     Scope:      Public Static
01260 
01261 ********************************************************************************************/
01262 #ifndef RALPH
01263 // ** normal XSetError **
01264 void CDECL Error::XSetError( const TCHAR *fmt, ...)
01265 {
01266 #ifdef _DEBUG
01267     TCHAR               buf[256];
01268 #if 0 != wxUSE_UNICODE
01269     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01270     FixFormat(fmt, fmt2);
01271 #else
01272     const TCHAR * fmt2=fmt;
01273 #endif
01274 
01275     va_list marker;
01276     va_start( marker, fmt );
01277     camVsnprintf( buf, 256, fmt2, marker );
01278     va_end( marker );
01279     
01280     // in debug builds we put up an ensure box
01281     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01282 
01283 #endif
01284 
01285     XSetErrorC();
01286     return;
01287 }
01288 #if 0 != wxUSE_UNICODE
01289 // ** normal XSetError ** extra version for Unicode build
01290 void CDECL Error::XSetError( const char *fmt, ...)
01291 {
01292 #ifdef _DEBUG
01293     TCHAR               buf[256];
01294     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01295     FixFormat(fmt, fmt2);
01296 
01297     va_list marker;
01298     va_start( marker, fmt );
01299     camVsnprintf( buf, 256, fmt2, marker );
01300     va_end( marker );
01301     
01302     // in debug builds we put up an ensure box
01303     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01304 
01305 #endif
01306 
01307     XSetErrorC();
01308     return;
01309 }
01310 #endif
01311 #else
01312 // ** RALPH XSetError() **
01313 void CDECL Error::XSetError( const TCHAR *fmt, ...)
01314 {
01315     TCHAR buf[256];
01316     TRACEUSER( "Chris", _T("oOoOo Ralph Set Error \n"));
01317 
01318 #ifdef _DEBUG
01319 #if 0 != wxUSE_UNICODE
01320     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01321     FixFormat(fmt, fmt2);
01322 #else
01323     const TCHAR * fmt2=fmt;
01324 #endif
01325 
01326     va_list marker;
01327     va_start( marker, fmt );
01328     camVsnprintf( buf, 256, fmt2, marker );
01329     va_end( marker );
01330     // in debug builds we put up an ensure box
01331     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01332 
01333 #else
01334     XSetErrorC();
01335     InformError();
01336 #endif
01337     return;
01338 }
01339 #if 0 != wxUSE_UNICODE
01340 // Extra version for Unicode build
01341 void CDECL Error::XSetError( const char *fmt, ...)
01342 {
01343     TCHAR buf[256];
01344     TRACEUSER( "Chris", _T("oOoOo Ralph Set Error \n"));
01345 
01346 #ifdef _DEBUG
01347     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01348     FixFormat(fmt, fmt2);
01349 
01350     va_list marker;
01351     va_start( marker, fmt );
01352     camVsnprintf( buf, 256, fmt2, marker );
01353     va_end( marker );
01354     // in debug builds we put up an ensure box
01355     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01356 
01357 #else
01358     XSetErrorC();
01359     InformError();
01360 #endif
01361     return;
01362 }
01363 #endif
01364 #endif
01365 
01366 /********************************************************************************************
01367 
01368 >   void CDECL Error::XSetErrorC()
01369 
01370     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com>
01371     Created:    30/5/95
01372     Inputs:     None
01373     Purpose:    Do NOT call directly. Sets up the internal error
01374     Scope:      Public Static
01375 
01376 ********************************************************************************************/
01377 
01378 void CDECL Error::XSetErrorC()
01379 {
01380     TCHAR               buf[256];
01381     // the error we set features a coded version of where the problem was
01382     CalcInternalMessage( buf, LastErrorLine, String_256( LastErrorFile ) );
01383     SetErrorSerious( buf );
01384     ResetWhere();
01385     return;
01386 }
01387 
01388 /********************************************************************************************
01389 
01390 >   void CDECL Error::XSetError( UINT32 errID, ...)
01391 
01392     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01393     Created:    4/10/94
01394     Inputs:     An error ID, followed by _MakeMsg-style variable arguments
01395     Purpose:    Do NOT call directly. Called via the ERROR1xx macros.
01396     Scope:      Public Static
01397 
01398 ********************************************************************************************/
01399 
01400 void CDECL Error::XSetError( UINT32 errID, ...)
01401 {
01402 
01403 
01404     if ( (errID==FALSE) || (errID==TRUE) )
01405     {
01406         // someone probably used the wrong macro parameters e.g. TRUE and FALSE instead of ID
01407         // This call will set an _R(IDE_INTERNAL_ERROR) for us
01408         ERROR2RAW( "ERROR1 macro used with invalid parameters" );
01409         return;
01410     }
01411 
01412     TCHAR               buf[256];
01413 
01414     va_list marker;
01415 
01416     va_start( marker, errID );
01417 
01418     String_256 result;
01419 
01420     // load the format string as a resoure (note no module ID yet)
01421     if (!SmartLoadString(0, errID, buf, sizeof(buf)))
01422     {
01423         camSnprintf( buf, 256, wxT("Error<%u>"), errID ); // keep inline
01424     }
01425 
01426     // now do _MakeMsg type formatting
01427     result.CCvsprintf(buf, marker);
01428 
01429 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
01430     // Set the help context.
01431     SetNextMsgHelpContext(errID);
01432 #endif
01433     // ralph needs this so that he can map the ID to a HRESULT before passing it
01434     // back to a harness
01435     TRACEUSER( "Chris", wxT("oOoOo Ralph Set Error %d \n"), RalphErrorID );
01436 
01437     RalphErrorID =errID;
01438 
01439     // and copy result into ErrorString
01440     SetErrorSerious( result );
01441 
01442     // trace output because SetErrorSerious doesn't bother
01443     TRACE( wxT("Setting error: ID = %d: \"%s\"\n"), errID, ErrorString);
01444 
01445     // then tidy up 
01446     va_end( marker );
01447 
01448     ResetWhere();
01449 }
01450 
01451 /********************************************************************************************
01452 
01453 >   void CDECL Error::XComplain( const TCHAR *fmt, ...)
01454 
01455     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
01456     Created:    4/10/94
01457     Inputs:     printf-style arg list.
01458     Purpose:    Do NOT call directly. This func is used by the ERROR3xx macros. It does the
01459                 _stprintf-thing, then puts up an ensure-type dialog box. It exists only in
01460                 debug builds. Error:MarkError should be called beforehand.
01461     Scope:      Public Static
01462 
01463 ********************************************************************************************/
01464 
01465 #ifdef _DEBUG
01466 void CDECL Error::XComplain( const TCHAR *fmt, ...)
01467 {
01468     TCHAR               buf[256];
01469 
01470 #if 0 != wxUSE_UNICODE
01471     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01472     FixFormat(fmt, fmt2);
01473 #else
01474     const TCHAR * fmt2=fmt;
01475 #endif
01476 
01477     va_list marker;
01478     va_start( marker, fmt );
01479     camVsnprintf( buf, 256, fmt2, marker );                             // convert the args
01480     va_end( marker );
01481 
01482     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01483     ResetWhere();
01484 }
01485 
01486 #if 0 != wxUSE_UNICODE
01487 void CDECL Error::XComplain( const char *fmt, ...)
01488 {
01489     TCHAR               buf[256];
01490     TCHAR   fmt2[MAXERRORFORMATLENGTH];
01491     FixFormat(fmt, fmt2);
01492 
01493     va_list marker;
01494     va_start( marker, fmt );
01495     camVsnprintf( buf, 256, fmt2, marker );                             // convert the args
01496     va_end( marker );
01497 
01498     EnsureFailedLine( buf, LastErrorFile, LastErrorLine );      // put up box
01499     ResetWhere();
01500 }
01501 #endif
01502 
01503 #endif
01504 
01505 
01506 #if !defined(EXCLUDE_FROM_XARLIB)
01507 INT32 InformError(UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK,   UINT32 Cancel)
01508 {
01509     return InformGeneral(ERRORTYPE_ERROR, 0, ErrorMsg, 
01510                          Butt1, Butt2, Butt3, Butt4,
01511                          OK, Cancel);
01512 
01513 }
01514 
01515 
01516 INT32 ToolInformError(UINT32 ToolID, UINT32 ErrorMsg,   UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01517 {
01518     return InformGeneral(ERRORTYPE_ERROR, Tool::GetModuleID(ToolID), ErrorMsg, 
01519                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01520 
01521 }
01522 
01523 
01524 INT32 ModuleInformError(UINT32 ModID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01525 {
01526     return InformGeneral(ERRORTYPE_ERROR, ModID, ErrorMsg, 
01527                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01528 
01529 }
01530 
01531 
01532 INT32 InformError(ErrorInfo *pInfo)
01533 {
01534     return InformGeneral(ERRORTYPE_ERROR, pInfo);
01535 }
01536 
01537 
01538 INT32 ToolInformError(UINT32 ToolID, ErrorInfo *pInfo)
01539 {
01540     return InformGeneral(ERRORTYPE_ERROR, pInfo, Tool::GetModuleID(ToolID));
01541 }
01542 
01543 
01544 INT32 ModuleInformError(UINT32 ModID, ErrorInfo *pInfo)
01545 {
01546     return InformGeneral(ERRORTYPE_ERROR, pInfo, ModID);
01547 }
01548 
01549 
01550 INT32 InformSeriousError(UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01551 {
01552     return InformGeneral(ERRORTYPE_SERIOUS, 0, ErrorMsg, 
01553                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01554 }
01555 
01556 
01557 INT32 ToolInformSeriousError(UINT32 ToolID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01558 {
01559     return InformGeneral(ERRORTYPE_SERIOUS, Tool::GetModuleID(ToolID), ErrorMsg, 
01560                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01561 }
01562 
01563 
01564 INT32 ModuleInformSeriousError(UINT32 ModID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01565 {
01566     return InformGeneral(ERRORTYPE_SERIOUS, ModID, ErrorMsg, 
01567                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01568 }
01569 
01570 
01571 INT32 InformSeriousError(ErrorInfo *pInfo)
01572 {
01573     return InformGeneral(ERRORTYPE_SERIOUS, pInfo);
01574 }
01575 
01576 INT32 ToolInformSeriousError(UINT32 ToolID, ErrorInfo *pInfo)
01577 {
01578     return InformGeneral(ERRORTYPE_SERIOUS, pInfo, Tool::GetModuleID(ToolID));
01579 }
01580 
01581 INT32 ModuleInformSeriousError(UINT32 ModID, ErrorInfo *pInfo)
01582 {
01583     return InformGeneral(ERRORTYPE_SERIOUS, pInfo, ModID);
01584 }
01585 
01586 INT32 InformWarning(UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01587 {
01588 
01589     return InformGeneral(ERRORTYPE_WARNING, 0, ErrorMsg, 
01590                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01591 }
01592 
01593 INT32 ToolInformWarning(UINT32 ToolID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01594 {
01595     return InformGeneral(ERRORTYPE_WARNING, Tool::GetModuleID(ToolID), ErrorMsg, 
01596                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01597 }
01598 
01599 INT32 ModuleInformWarning(UINT32 ModID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01600 {
01601     return InformGeneral(ERRORTYPE_WARNING, ModID, ErrorMsg, 
01602                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01603 }
01604 
01605 INT32 InformWarning(ErrorInfo *pInfo)
01606 {
01607     return InformGeneral(ERRORTYPE_WARNING, pInfo);
01608 }
01609 
01610 
01611 INT32 ToolInformWarning(UINT32 ToolID, ErrorInfo *pInfo)
01612 {
01613     return InformGeneral(ERRORTYPE_WARNING, pInfo, Tool::GetModuleID(ToolID));
01614 }
01615 
01616 
01617 INT32 ModuleInformWarning(UINT32 ModID, ErrorInfo *pInfo)
01618 {
01619     return InformGeneral(ERRORTYPE_WARNING, pInfo, ModID);
01620 }
01621 
01622 
01623 
01624 UINT32 AskQuestion(UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01625 {
01626     return InformGeneral(ERRORTYPE_QUESTION, 0, ErrorMsg, 
01627                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01628 }
01629 
01630 UINT32 ToolAskQuestion(UINT32 ToolID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01631 {
01632     return InformGeneral(ERRORTYPE_QUESTION, Tool::GetModuleID(ToolID), ErrorMsg, 
01633                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01634 }
01635 
01636 
01637 
01638 INT32 ModuleAskQuestion(UINT32 ModID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01639 {
01640     return InformGeneral(ERRORTYPE_QUESTION, ModID, ErrorMsg, 
01641                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01642 }
01643 
01644 
01645 INT32 AskQuestion(ErrorInfo *pInfo)
01646 {
01647     return InformGeneral(ERRORTYPE_QUESTION, pInfo);
01648 }
01649 
01650 
01651 INT32 ToolAskQuestion(UINT32 ToolID, ErrorInfo *pInfo)
01652 {
01653     return InformGeneral(ERRORTYPE_QUESTION, pInfo, Tool::GetModuleID(ToolID));
01654 }
01655 
01656 
01657 INT32 ModuleAskQuestion(UINT32 ModID, ErrorInfo *pInfo)
01658 {
01659     return InformGeneral(ERRORTYPE_QUESTION, pInfo, ModID);
01660 }
01661 
01662 
01663 
01664 INT32 InformMessage(UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01665 {
01666     return InformGeneral(ERRORTYPE_NORMAL, 0, ErrorMsg, 
01667                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01668 
01669 }
01670 
01671 
01672 INT32 ToolInformMessage(UINT32 ToolID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01673 {
01674     return InformGeneral(ERRORTYPE_NORMAL, Tool::GetModuleID(ToolID), ErrorMsg, 
01675                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01676 
01677 }
01678 
01679 
01680 INT32 ModuleInformMessage(UINT32 ModID, UINT32 ErrorMsg, UINT32 Butt1, UINT32 Butt2, UINT32 Butt3, UINT32 Butt4, UINT32 OK, UINT32 Cancel)
01681 {
01682     return InformGeneral(ERRORTYPE_NORMAL, ModID, ErrorMsg, 
01683                          Butt1, Butt2, Butt3, Butt4, OK, Cancel);
01684 }
01685 
01686 
01687 INT32 InformMessage(ErrorInfo *pInfo)
01688 {
01689     return InformGeneral(ERRORTYPE_NORMAL, pInfo);
01690 }
01691 
01692 
01693 INT32 ToolInformMessage(UINT32 ToolID, ErrorInfo *pInfo)
01694 {
01695     return InformGeneral(ERRORTYPE_NORMAL, pInfo, Tool::GetModuleID(ToolID));
01696 }
01697 
01698 
01699 INT32 ModuleInformMessage(UINT32 ModID, ErrorInfo *pInfo)
01700 {
01701     return InformGeneral(ERRORTYPE_NORMAL, pInfo, ModID);
01702 }
01703 #endif
01704 
01705 
01706 #if 0
01707 // old errors test code
01708 
01709 INT32 test1(INT32 which)
01710 {
01711     if (which==0)
01712     {
01713         ERROR1RAW( _R(IDE_INTERNAL_ERROR) );
01714         return 0;
01715     }
01716     if (which==1)
01717         ERROR1( 10, _R(IDE_INTERNAL_ERROR) );
01718     if (which==2)
01719         ERROR1IF( TRUE, 20, _R(IDE_INTERNAL_ERROR) );
01720     if (which==3)
01721         ERROR1_MSG( 30, (_R(IDT_EPS_BADSYNTAX), 2, 200) );
01722     if (which==4)
01723         ERROR1IF_MSG( TRUE, 40, (_R(IDT_EPS_BADSYNTAX), 1, 100) );
01724     return 0;
01725 }
01726 
01727 
01728 
01729 INT32 test2(INT32 which)
01730 {
01731     if (which==0)
01732     {
01733         ERROR2RAW( "Simple raw error" );
01734         return 0;
01735     }
01736     if (which==1)
01737         ERROR2( 10, "Simple error" );
01738     if (which==2)
01739         ERROR2IF( TRUE, 20, "Simple error if");
01740     if (which==3)
01741         ERROR2_PF( 30, ("String (%s)", "blobby") );
01742     if (which==4)
01743         ERROR2IF_PF( TRUE, 40, ("Numbers (%d,%d)" , 42,43) );
01744     return 0;
01745 }
01746 
01748 // CMainFrame message handlers
01749 
01750 void TestErrorStuff()
01751 {
01752     test1(0);
01753     test1(1);
01754     test1(2);
01755     test1(3);
01756     test1(4);
01757 
01758     InformError();
01759 
01760     test2(0);
01761     test2(1);
01762     test2(2);
01763     test2(3);
01764     test2(4);
01765 
01766     InformError();
01767 
01768     ERROR3("simple");
01769     ERROR3IF( TRUE, "simple" );
01770     ERROR3_PF( ("doc is %lx", 0x123456) );
01771     ERROR3IF_PF( TRUE, ("doc %s is %lx", "blobdoc", 0x123456) );
01772 
01773     TRACEUSER( "Andy", _T("simple trace\n"));
01774     TRACEUSER( "Andy", "complex %d %s trace", 42, _T("blobby\n") );
01775 }
01776 
01777 #endif
01778 
01779 
01780 /********************************************************************************************
01781 
01782 >   void Error::DumpStack(UINT32 frames)
01783 
01784     Author:     Alex Bligh <alex@alex.org.uk>
01785     Created:    14-Mar-2006
01786     Inputs:     None
01787     Purpose:    Dumps the stack
01788     Scope:      Public Static
01789 
01790 ********************************************************************************************/
01791 
01792 void Error::DumpStack(UINT32 frames)
01793 {
01794 #ifdef _DEBUG
01795 #if !defined(__WXMAC__) && !defined(__FreeBSD__)
01796     Error::StackWalker s;
01797     s.Walk(frames);
01798 #else
01799     TRACE( _T("Request to dump stack not supported on this platform") );
01800 #endif
01801 #endif
01802 }
01803 
01804 /********************************************************************************************
01805 
01806 >   void Error::StackWalker::OnStackFrame(const wxStackFrame & frame)
01807 
01808     Author:     Alex Bligh <alex@alex.org.uk>
01809     Created:    14-Mar-2006
01810     Inputs:     None
01811     Purpose:    Dumps the stack
01812     Scope:      Public
01813 
01814 ********************************************************************************************/
01815 
01816 #if !defined(__WXMAC__) && !defined(__FreeBSD__)
01817 void Error::StackWalker::OnStackFrame(const wxStackFrame & frame)
01818 {
01819 #ifdef _DEBUG
01820     wxString l;
01821     l.Printf(_T("%d %s:%d %s"), frame.GetLevel(), frame.GetFileName().c_str(), frame.GetLine(), frame.GetName().c_str());
01822 //  l = wxString(frame.GetName().c_str();
01823     wxLogDebug(l);
01824 #endif
01825 }
01826 #endif

Generated on Sat Nov 10 03:48:26 2007 for Camelot by  doxygen 1.4.4