home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / appcmn.cpp next >
C/C++ Source or Header  |  2002-09-24  |  17KB  |  646 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        common/appcmn.cpp
  3. // Purpose:     wxAppBase methods common to all platforms
  4. // Author:      Vadim Zeitlin
  5. // Modified by:
  6. // Created:     18.10.99
  7. // RCS-ID:      $Id: appcmn.cpp,v 1.43.2.1 2002/09/24 13:40:18 JS Exp $
  8. // Copyright:   (c) Vadim Zeitlin
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // ============================================================================
  13. // declarations
  14. // ============================================================================
  15.  
  16. // ---------------------------------------------------------------------------
  17. // headers
  18. // ---------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "appbase.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #if defined(__BORLANDC__)
  28.     #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.     #include "wx/app.h"
  33.     #include "wx/intl.h"
  34.     #include "wx/list.h"
  35.     #if wxUSE_LOG
  36.         #include "wx/log.h"
  37.     #endif // wxUSE_LOG
  38.     #if wxUSE_GUI
  39.         #include "wx/msgdlg.h"
  40.     #endif // wxUSE_GUI
  41. #endif
  42.  
  43. #include "wx/cmdline.h"
  44. #include "wx/thread.h"
  45. #include "wx/confbase.h"
  46. #include "wx/tokenzr.h"
  47. #include "wx/utils.h"
  48. #include "wx/msgout.h"
  49.  
  50. #if wxUSE_GUI
  51.     #include "wx/artprov.h"
  52. #endif // wxUSE_GUI
  53.  
  54. #if !defined(__WXMSW__) || defined(__WXMICROWIN__)
  55.   #include  <signal.h>      // for SIGTRAP used by wxTrap()
  56. #endif  //Win/Unix
  57.  
  58. #if defined(__WXMSW__)
  59.   #include  "wx/msw/private.h"  // includes windows.h for MessageBox()
  60. #endif
  61.  
  62. #if defined(__WXMAC__)
  63.   #include  "wx/mac/private.h"  // includes mac headers
  64. #endif
  65.  
  66. // private functions prototypes
  67. #ifdef __WXDEBUG__
  68.     static void LINKAGEMODE SetTraceMasks();
  69. #endif // __WXDEBUG__
  70.  
  71. // ===========================================================================
  72. // implementation
  73. // ===========================================================================
  74.  
  75. // ----------------------------------------------------------------------------
  76. // initialization and termination
  77. // ----------------------------------------------------------------------------
  78.  
  79. wxAppBase::wxAppBase()
  80. {
  81.     wxTheApp = (wxApp *)this;
  82.  
  83. #if WXWIN_COMPATIBILITY_2_2
  84.     m_wantDebugOutput = FALSE;
  85. #endif // WXWIN_COMPATIBILITY_2_2
  86.  
  87. #if wxUSE_GUI
  88.     m_topWindow = (wxWindow *)NULL;
  89.     m_useBestVisual = FALSE;
  90.     m_isActive = TRUE;
  91.  
  92.     // We don't want to exit the app if the user code shows a dialog from its
  93.     // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
  94.     // to Yes initially as this dialog would be the last top level window.
  95.     // OTOH, if we set it to No initially we'll have to overwrite it with Yes
  96.     // when we enter our OnRun() because we do want the default behaviour from
  97.     // then on. But this would be a problem if the user code calls
  98.     // SetExitOnFrameDelete(FALSE) from OnInit().
  99.     //
  100.     // So we use the special "Later" value which is such that
  101.     // GetExitOnFrameDelete() returns FALSE for it but which we know we can
  102.     // safely (i.e. without losing the effect of the users SetExitOnFrameDelete
  103.     // call) overwrite in OnRun()
  104.     m_exitOnFrameDelete = Later;
  105. #endif // wxUSE_GUI
  106.  
  107. #ifdef __WXDEBUG__
  108.     SetTraceMasks();
  109. #endif
  110. }
  111.  
  112. wxAppBase::~wxAppBase()
  113. {
  114.     // this destructor is required for Darwin
  115. }
  116.  
  117. #if wxUSE_GUI
  118.  
  119. bool wxAppBase::OnInitGui()
  120. {
  121. #ifdef __WXUNIVERSAL__
  122.     if ( !wxTheme::Get() && !wxTheme::CreateDefault() )
  123.         return FALSE;
  124.     wxArtProvider *art = wxTheme::Get()->GetArtProvider();
  125.     if ( art )
  126.         wxArtProvider::PushProvider(art);
  127. #endif // __WXUNIVERSAL__
  128.  
  129.     return TRUE;
  130. }
  131.  
  132. int wxAppBase::OnRun()
  133. {
  134.     // see the comment in ctor: if the initial value hasn't been changed, use
  135.     // the default Yes from now on
  136.     if ( m_exitOnFrameDelete == Later )
  137.     {
  138.         m_exitOnFrameDelete = Yes;
  139.     }
  140.     //else: it has been changed, assume the user knows what he is doing
  141.  
  142.     return MainLoop();
  143. }
  144.  
  145. #endif // wxUSE_GUI
  146.  
  147. int wxAppBase::OnExit()
  148. {
  149. #if wxUSE_CONFIG
  150.     // delete the config object if any (don't use Get() here, but Set()
  151.     // because Get() could create a new config object)
  152.     delete wxConfigBase::Set((wxConfigBase *) NULL);
  153. #endif // wxUSE_CONFIG
  154.  
  155. #ifdef __WXUNIVERSAL__
  156.     delete wxTheme::Set(NULL);
  157. #endif // __WXUNIVERSAL__
  158.  
  159.     // use Set(NULL) and not Get() to avoid creating a message output object on
  160.     // demand when we just want to delete it
  161.     delete wxMessageOutput::Set(NULL);
  162.  
  163.     return 0;
  164. }
  165.  
  166. // ----------------------------------------------------------------------------
  167. // customization hooks
  168. // ----------------------------------------------------------------------------
  169.  
  170. #if wxUSE_LOG
  171.  
  172. wxLog *wxAppBase::CreateLogTarget()
  173. {
  174. #if wxUSE_GUI && wxUSE_LOGGUI && !defined(__WXMICROWIN__)
  175.     return new wxLogGui;
  176. #else // !GUI
  177.     return new wxLogStderr;
  178. #endif // wxUSE_GUI
  179. }
  180.  
  181. #endif // wxUSE_LOG
  182.  
  183. wxMessageOutput *wxAppBase::CreateMessageOutput()
  184. {
  185.     // The standard way of printing help on command line arguments (app --help)
  186.     // is (according to common practice):
  187.     //     - console apps: to stderr (on any platform)
  188.     //     - GUI apps: stderr on Unix platforms (!)
  189.     //                 message box under Windows and others
  190. #if wxUSE_GUI && !defined(__UNIX__)
  191.     // wxMessageOutputMessageBox doesn't work under Motif
  192.     #ifdef __WXMOTIF__
  193.         return new wxMessageOutputLog;
  194.     #else
  195.         return new wxMessageOutputMessageBox;
  196.     #endif
  197. #else // !wxUSE_GUI || __UNIX__
  198.     return new wxMessageOutputStderr;
  199. #endif
  200. }
  201.  
  202. // ---------------------------------------------------------------------------
  203. // wxAppBase
  204. // ----------------------------------------------------------------------------
  205.  
  206. void wxAppBase::ProcessPendingEvents()
  207. {
  208.     // ensure that we're the only thread to modify the pending events list
  209.     wxENTER_CRIT_SECT( *wxPendingEventsLocker );
  210.  
  211.     if ( !wxPendingEvents )
  212.     {
  213.         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
  214.         return;
  215.     }
  216.  
  217.     // iterate until the list becomes empty
  218.     wxNode *node = wxPendingEvents->First();
  219.     while (node)
  220.     {
  221.         wxEvtHandler *handler = (wxEvtHandler *)node->Data();
  222.         delete node;
  223.  
  224.         // In ProcessPendingEvents(), new handlers might be add
  225.         // and we can safely leave the critical section here.
  226.         wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
  227.         handler->ProcessPendingEvents();
  228.         wxENTER_CRIT_SECT( *wxPendingEventsLocker );
  229.  
  230.         node = wxPendingEvents->First();
  231.     }
  232.  
  233.     wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
  234. }
  235.  
  236. // ----------------------------------------------------------------------------
  237. // misc
  238. // ----------------------------------------------------------------------------
  239.  
  240. #if wxUSE_GUI
  241.  
  242. void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
  243. {
  244.     if ( active == m_isActive )
  245.         return;
  246.  
  247.     m_isActive = active;
  248.  
  249.     wxActivateEvent event(wxEVT_ACTIVATE_APP, active);
  250.     event.SetEventObject(this);
  251.  
  252.     (void)ProcessEvent(event);
  253. }
  254.  
  255. #endif // wxUSE_GUI
  256.  
  257. int wxAppBase::FilterEvent(wxEvent& WXUNUSED(event))
  258. {
  259.     // process the events normally by default
  260.     return -1;
  261. }
  262.  
  263. // ----------------------------------------------------------------------------
  264. // cmd line parsing
  265. // ----------------------------------------------------------------------------
  266.  
  267. bool wxAppBase::OnInit()
  268. {
  269. #if wxUSE_CMDLINE_PARSER
  270.     wxCmdLineParser parser(argc, argv);
  271.  
  272.     OnInitCmdLine(parser);
  273.  
  274.     bool cont;
  275.     switch ( parser.Parse(FALSE /* don't show usage */) )
  276.     {
  277.         case -1:
  278.             cont = OnCmdLineHelp(parser);
  279.             break;
  280.  
  281.         case 0:
  282.             cont = OnCmdLineParsed(parser);
  283.             break;
  284.  
  285.         default:
  286.             cont = OnCmdLineError(parser);
  287.             break;
  288.     }
  289.  
  290.     if ( !cont )
  291.         return FALSE;
  292. #endif // wxUSE_CMDLINE_PARSER
  293.  
  294.     return TRUE;
  295. }
  296.  
  297. #if wxUSE_CMDLINE_PARSER
  298.  
  299. #define OPTION_VERBOSE _T("verbose")
  300. #define OPTION_THEME   _T("theme")
  301. #define OPTION_MODE    _T("mode")
  302.  
  303. void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser)
  304. {
  305.     // the standard command line options
  306.     static const wxCmdLineEntryDesc cmdLineDesc[] =
  307.     {
  308.         {
  309.             wxCMD_LINE_SWITCH,
  310.             _T("h"),
  311.             _T("help"),
  312.             gettext_noop("show this help message"),
  313.             wxCMD_LINE_VAL_NONE,
  314.             wxCMD_LINE_OPTION_HELP
  315.         },
  316.  
  317. #if wxUSE_LOG
  318.         {
  319.             wxCMD_LINE_SWITCH,
  320.             _T(""),
  321.             OPTION_VERBOSE,
  322.             gettext_noop("generate verbose log messages"),
  323.             wxCMD_LINE_VAL_NONE,
  324.             0x0
  325.         },
  326. #endif // wxUSE_LOG
  327.  
  328. #ifdef __WXUNIVERSAL__
  329.         {
  330.             wxCMD_LINE_OPTION,
  331.             _T(""),
  332.             OPTION_THEME,
  333.             gettext_noop("specify the theme to use"),
  334.             wxCMD_LINE_VAL_STRING,
  335.             0x0
  336.         },
  337. #endif // __WXUNIVERSAL__
  338.  
  339. #if defined(__WXMGL__)
  340.         // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports
  341.         //     should provide this option. That's why it is in common/appcmn.cpp
  342.         //     and not mgl/app.cpp
  343.         {
  344.             wxCMD_LINE_OPTION,
  345.             _T(""),
  346.             OPTION_MODE,
  347.             gettext_noop("specify display mode to use (e.g. 640x480-16)"),
  348.             wxCMD_LINE_VAL_STRING,
  349.             0x0
  350.         },
  351. #endif // __WXMGL__
  352.  
  353.         // terminator
  354.         {
  355.             wxCMD_LINE_NONE,
  356.             _T(""),
  357.             _T(""),
  358.             _T(""),
  359.             wxCMD_LINE_VAL_NONE,
  360.             0x0
  361.         }
  362.     };
  363.  
  364.     parser.SetDesc(cmdLineDesc);
  365. }
  366.  
  367. bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser)
  368. {
  369. #if wxUSE_LOG
  370.     if ( parser.Found(OPTION_VERBOSE) )
  371.     {
  372.         wxLog::SetVerbose(TRUE);
  373.     }
  374. #endif // wxUSE_LOG
  375.  
  376. #ifdef __WXUNIVERSAL__
  377.     wxString themeName;
  378.     if ( parser.Found(OPTION_THEME, &themeName) )
  379.     {
  380.         wxTheme *theme = wxTheme::Create(themeName);
  381.         if ( !theme )
  382.         {
  383.             wxLogError(_("Unsupported theme '%s'."), themeName.c_str());
  384.  
  385.             return FALSE;
  386.         }
  387.  
  388.         wxTheme::Set(theme);
  389.     }
  390. #endif // __WXUNIVERSAL__
  391.  
  392. #if defined(__WXMGL__)
  393.     wxString modeDesc;
  394.     if ( parser.Found(OPTION_MODE, &modeDesc) )
  395.     {
  396.         unsigned w, h, bpp;
  397.         if ( wxSscanf(modeDesc.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3 )
  398.         {
  399.             wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str());
  400.  
  401.             return FALSE;
  402.         }
  403.  
  404.         if ( !SetDisplayMode(wxDisplayModeInfo(w, h, bpp)) )
  405.             return FALSE;
  406.     }
  407. #endif // __WXMGL__
  408.  
  409.     return TRUE;
  410. }
  411.  
  412. bool wxAppBase::OnCmdLineHelp(wxCmdLineParser& parser)
  413. {
  414.     parser.Usage();
  415.  
  416.     return FALSE;
  417. }
  418.  
  419. bool wxAppBase::OnCmdLineError(wxCmdLineParser& parser)
  420. {
  421.     parser.Usage();
  422.  
  423.     return FALSE;
  424. }
  425.  
  426. #endif // wxUSE_CMDLINE_PARSER
  427.  
  428. // ----------------------------------------------------------------------------
  429. // debugging support
  430. // ----------------------------------------------------------------------------
  431.  
  432. /* static */
  433. bool wxAppBase::CheckBuildOptions(const wxBuildOptions& opts)
  434. {
  435. #define wxCMP(what)   (what == opts.m_ ## what)
  436.  
  437.     bool
  438. #ifdef __WXDEBUG__
  439.     isDebug = TRUE;
  440. #else
  441.     isDebug = FALSE;
  442. #endif
  443.  
  444.     int verMaj = wxMAJOR_VERSION,
  445.         verMin = wxMINOR_VERSION;
  446.  
  447.     if ( !(wxCMP(isDebug) && wxCMP(verMaj) && wxCMP(verMin)) )
  448.     {
  449.         wxString msg;
  450.         wxString libDebug, progDebug;
  451.  
  452.         if (isDebug)
  453.             libDebug = wxT("debug");
  454.         else
  455.             libDebug = wxT("no debug");
  456.  
  457.         if (opts.m_isDebug)
  458.             progDebug = wxT("debug");
  459.         else
  460.             progDebug = wxT("no debug");
  461.         
  462.         msg.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %d.%d (%s), and your program used %d.%d (%s)."),
  463.                    verMaj, verMin, libDebug.c_str(), opts.m_verMaj, opts.m_verMin, progDebug.c_str());
  464.         
  465.         wxLogFatalError(msg);
  466.  
  467.         // normally wxLogFatalError doesn't return
  468.         return FALSE;
  469.     }
  470. #undef wxCMP
  471.  
  472.     return TRUE;
  473. }
  474.  
  475. #ifdef  __WXDEBUG__
  476.  
  477. static void LINKAGEMODE SetTraceMasks()
  478. {
  479.     wxString mask;
  480.     if ( wxGetEnv(wxT("WXTRACE"), &mask) )
  481.     {
  482.         wxStringTokenizer tkn(mask, wxT(","));
  483.         while ( tkn.HasMoreTokens() )
  484.             wxLog::AddTraceMask(tkn.GetNextToken());
  485.     }
  486. }
  487.  
  488. // wxASSERT() helper
  489. bool wxAssertIsEqual(int x, int y)
  490. {
  491.     return x == y;
  492. }
  493.  
  494. // break into the debugger
  495. void wxTrap()
  496. {
  497. #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
  498.     DebugBreak();
  499. #elif defined(__WXMAC__) && !defined(__DARWIN__)
  500. #if __powerc
  501.     Debugger();
  502. #else
  503.     SysBreak();
  504. #endif
  505. #elif defined(__UNIX__)
  506.     raise(SIGTRAP);
  507. #else
  508.     // TODO
  509. #endif // Win/Unix
  510. }
  511.  
  512.  
  513. void wxAssert(int cond,
  514.                   const wxChar *szFile,
  515.                   int nLine,
  516.                   const wxChar *szCond,
  517.                   const wxChar *szMsg) 
  518. {
  519.    if ( !cond )
  520.           wxOnAssert(szFile, nLine, szCond, szMsg);
  521. }
  522.   
  523. // show the assert modal dialog
  524. static
  525. void ShowAssertDialog(const wxChar *szFile,
  526.                       int nLine,
  527.                       const wxChar *szCond,
  528.                       const wxChar *szMsg)
  529. {
  530.     // this variable can be set to true to suppress "assert failure" messages
  531.     static bool s_bNoAsserts = FALSE;
  532.  
  533.     wxChar szBuf[4096];
  534.  
  535.     // make life easier for people using VC++ IDE by using this format: like
  536.     // this, clicking on the message will take us immediately to the place of
  537.     // the failed assert
  538.     wxSnprintf(szBuf, WXSIZEOF(szBuf),
  539.                wxT("%s(%d): assert \"%s\" failed"),
  540.                szFile, nLine, szCond);
  541.  
  542.     if ( szMsg != NULL )
  543.     {
  544.         wxStrcat(szBuf, wxT(": "));
  545.         wxStrcat(szBuf, szMsg);
  546.     }
  547.     else // no message given
  548.     {
  549.         wxStrcat(szBuf, wxT("."));
  550.     }
  551.  
  552.     if ( !s_bNoAsserts )
  553.     {
  554.         // send it to the normal log destination
  555.         wxLogDebug(szBuf);
  556.  
  557. #if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__)
  558.         // this message is intentionally not translated - it is for
  559.         // developpers only
  560.         wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings."));
  561.  
  562.         // use the native message box if available: this is more robust than
  563.         // using our own
  564. #if defined(__WXMSW__) && !defined(__WXMICROWIN__)
  565.         switch ( ::MessageBox(NULL, szBuf, _T("Debug"),
  566.                               MB_YESNOCANCEL | MB_ICONSTOP ) )
  567.         {
  568.             case IDYES:
  569.                 wxTrap();
  570.                 break;
  571.  
  572.             case IDCANCEL:
  573.                 s_bNoAsserts = TRUE;
  574.                 break;
  575.  
  576.             //case IDNO: nothing to do
  577.         }
  578. #else // !MSW
  579.         switch ( wxMessageBox(szBuf, wxT("Debug"),
  580.                               wxYES_NO | wxCANCEL | wxICON_STOP ) )
  581.         {
  582.             case wxYES:
  583.                 wxTrap();
  584.                 break;
  585.  
  586.             case wxCANCEL:
  587.                 s_bNoAsserts = TRUE;
  588.                 break;
  589.  
  590.             //case wxNO: nothing to do
  591.         }
  592. #endif // GUI or MSW
  593.  
  594. #else // !GUI
  595.         wxTrap();
  596. #endif // GUI/!GUI
  597.     }
  598. }
  599.  
  600. // this function is called when an assert fails
  601. void wxOnAssert(const wxChar *szFile,
  602.                 int nLine,
  603.                 const wxChar *szCond,
  604.                 const wxChar *szMsg)
  605. {
  606.     // FIXME MT-unsafe
  607.     static bool s_bInAssert = FALSE;
  608.  
  609.     if ( s_bInAssert )
  610.     {
  611.         // He-e-e-e-elp!! we're trapped in endless loop
  612.         wxTrap();
  613.  
  614.         s_bInAssert = FALSE;
  615.  
  616.         return;
  617.     }
  618.  
  619.     s_bInAssert = TRUE;
  620.  
  621.     if ( !wxTheApp )
  622.     {
  623.         // by default, show the assert dialog box - we can't customize this
  624.         // behaviour
  625.         ShowAssertDialog(szFile, nLine, szCond, szMsg);
  626.     }
  627.     else
  628.     {
  629.         // let the app process it as it wants
  630.         wxTheApp->OnAssert(szFile, nLine, szCond, szMsg);
  631.     }
  632.  
  633.     s_bInAssert = FALSE;
  634. }
  635.  
  636. void wxAppBase::OnAssert(const wxChar *file,
  637.                          int line,
  638.                          const wxChar *cond,
  639.                          const wxChar *msg)
  640. {
  641.     ShowAssertDialog(file, line, cond, msg);
  642. }
  643.  
  644. #endif  //WXDEBUG
  645.  
  646.