home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / MozillaApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  32.5 KB  |  1,235 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    MozillaApp.cpp -- class definition for Mozilla-global stuff
  20.    Created: Spence Murray <spence@netscape.com>, 12-Nov-96.
  21.  */
  22.  
  23.  
  24.  
  25. #include "Frame.h"
  26. #include "MozillaApp.h"
  27. #include "ViewGlue.h"
  28. #include "Dashboard.h"
  29.  
  30. #ifdef MOZ_MAIL_NEWS
  31. #include "MNView.h"
  32. #endif
  33.  
  34. #include <np.h>
  35. #include "secnav.h"
  36. #ifdef JAVA
  37. #include "mozjava.h"
  38. #endif /* JAVA */
  39.  
  40. #include "libmocha.h"
  41. #include "libevent.h"
  42.  
  43. #include "BookmarkFrame.h" /* Used for FE_GetNetHelpContext */
  44. #include "prefs.h"
  45.  
  46. #ifdef DEBUG_username
  47. #define D(x) x
  48. #else
  49. #define D(x)
  50. #endif
  51.  
  52. #define STANDARD_INSTALL_PATH "/usr/local/lib/netscape/"
  53.  
  54. extern "C" { 
  55.     void xfe_TextCopy  (MWContext*, Widget, XP_Bool);
  56.     void xfe_TextPaste (MWContext*, Widget, XP_Bool);
  57. }
  58.  
  59. /* Keep track how many windows are about to be closed upon exit */
  60. extern "C" void fe_GetProgramDirectory(char *path, int len); /* Used by FE_GetNetHelpDir */
  61. #ifndef NO_WEB_FONTS
  62. extern "C" void fe_ShutdownWebfonts(void);    /* fonts.c : Webfonts */
  63. #endif /* NO_WEB_FONTS */
  64.  
  65. static XFE_MozillaApp *_app = NULL;
  66.  
  67. const char *XFE_MozillaApp::appBusyCallback = "XFE_MozillaApp::appBusyCallback";
  68. const char *XFE_MozillaApp::appNotBusyCallback = "XFE_MozillaApp::appNotBusyCallback";
  69. const char *XFE_MozillaApp::changeInToplevelFrames = "XFE_MozillaApp::changeInToplevelFrames";
  70. const char *XFE_MozillaApp::bookmarksHaveChanged = "XFE_MozillaApp::bookmarksHaveChanged";
  71. const char *XFE_MozillaApp::biffStateChanged = "XFE_MozillaApp::biffStateChanged";
  72. const char *XFE_MozillaApp::updateToolbarAppearance = "XFE_MozillaApp::updateToolbarAppearance";
  73. const char *XFE_MozillaApp::linksAttributeChanged = "XFE_MozillaApp::linksAttributeChanged";
  74. const char *XFE_MozillaApp::defaultColorsChanged = "XFE_MozillaApp::defaultColorsChanged";
  75. const char *XFE_MozillaApp::defaultFontChanged = "XFE_MozillaApp::defaultFontChanged";
  76. const char *XFE_MozillaApp::refreshMsgWindow = "XFE_MozillaApp::refreshMsgWindow";
  77. const char *XFE_MozillaApp::personalToolbarFolderChanged = "XFE_MozillaApp::personalToolbarFolderChanged";
  78.  
  79. static void xfeDoCommandAction(Widget w, XEvent *, String *, Cardinal *);
  80. static void xfeDoTextAction(Widget w, XEvent *, String *, Cardinal *);
  81. static void xfeDoPopupAction(Widget w, XEvent *, String *, Cardinal *);
  82. static void xfeDoClickAction(Widget w, XEvent *, String *, Cardinal *);
  83. static void xfeUndefinedKeyAction(Widget w, XEvent *, String *, Cardinal *);
  84.  
  85. XFE_MozillaApp::XFE_MozillaApp(int */*argc*/, char **/*argv*/)
  86. {
  87.   XFE_MozillaApp();
  88. }
  89.  
  90. // hacked constructor.  should go away soon...
  91. XFE_MozillaApp::XFE_MozillaApp()
  92. {
  93.   // only allow one XFE_MozillaApp to be created.
  94.   XP_ASSERT(_app == NULL);
  95.  
  96.   m_frameList = XP_ListNew();
  97.   m_editorFrameList = XP_ListNew();
  98.   m_composeFrameList = XP_ListNew();
  99.   m_msgFrameList = XP_ListNew();
  100.   m_threadFrameList = XP_ListNew();
  101.   m_folderFrameList = XP_ListNew();
  102.   m_browserFrameList = XP_ListNew();
  103.   m_addressbookFrameList = XP_ListNew();
  104.   m_bookmarkFrameList = XP_ListNew();
  105.   m_mailfilterFrameList = XP_ListNew();
  106.   m_searchFrameList = XP_ListNew();
  107.   m_ldapFrameList = XP_ListNew();
  108.   m_maildownloadFrameList = XP_ListNew();
  109.   m_historyFrameList = XP_ListNew();
  110.   m_downloadFrameList = XP_ListNew();
  111.   m_htmldialogFrameList = XP_ListNew();
  112.   m_navcenterFrameList = XP_ListNew();
  113.  
  114.   m_isbusy = FALSE;
  115.   m_exiting = FALSE;
  116.   m_exitstatus = 0;
  117.   m_actioninstalled = FALSE;
  118.   m_exitwindowcount = 0;
  119.  
  120.   fe_MNWindowCount = 0;
  121.   session_frame = NULL;
  122.  
  123.   _app = this;
  124.  
  125.   theApp()->registerInterest(XFE_MozillaApp::appBusyCallback,
  126.                              this,
  127.                              (XFE_FunctionNotification)updateBusyState_cb,
  128.                              (void*)True);
  129.   theApp()->registerInterest(XFE_MozillaApp::appNotBusyCallback,
  130.                              this,
  131.                              (XFE_FunctionNotification)updateBusyState_cb,
  132.                              (void*)False);
  133. }
  134.  
  135. /* recursively close all frames because frames might be removed from
  136.    the list inside "doClose()". Therefore, the head of the frame list
  137.    is easily moved around */
  138. static void
  139. next_and_close(XP_List* list_entry)
  140. {
  141.     XFE_Frame* frame = (XFE_Frame*)list_entry->object;
  142.     XP_List*   next = list_entry->next;
  143.  
  144.     if (next != NULL)
  145.         next_and_close(next);
  146.  
  147.     if (frame != NULL)
  148.         frame->doClose();
  149. }
  150.  
  151. void
  152. XFE_MozillaApp::closeFrames(XP_List *frame_list)
  153. {
  154.     if (frame_list && frame_list->next)
  155.         next_and_close(frame_list->next);
  156. }
  157.  
  158. XP_Bool
  159. XFE_MozillaApp::isOkToExitFrameList(XP_List *frame_list)
  160. {
  161.         XP_List *start;
  162.     XP_Bool okFlag = True;
  163.         XFE_Frame *frame;
  164.  
  165.         start = frame_list;
  166.  
  167.         while ((frame = (XFE_Frame*)XP_ListNextObject(start)) != NULL)
  168.         {
  169.             XP_ASSERT(frame);
  170.             if (frame && ( fe_IsContextProtected(frame->getContext()) ||
  171.                 !(okFlag = frame->isOkToClose())  ) ) 
  172.             { 
  173.               okFlag = False;
  174.               break;
  175.             }
  176.         }
  177.     return okFlag;    
  178. }
  179.  
  180. XP_Bool
  181. XFE_MozillaApp::isOkToExitMailNewsFrames()
  182. {
  183.   XP_Bool okFlag = True;
  184.     if (isOkToExitFrameList(m_msgFrameList) ) 
  185.     {
  186.        closeFrames(m_msgFrameList);
  187.        if ( isOkToExitFrameList(m_threadFrameList) )
  188.        {
  189.            closeFrames(m_threadFrameList);
  190.         if ( isOkToExitFrameList(m_folderFrameList) )
  191.         {
  192.                closeFrames(m_folderFrameList);
  193.         }
  194.         else okFlag = False;
  195.        }
  196.        else okFlag = False;
  197.     }
  198.     else okFlag = False;
  199.  
  200.   return okFlag;
  201. }
  202.  
  203. XP_Bool
  204. XFE_MozillaApp::isOkToExitNonMailNewsFrames()
  205. {
  206.   if ( isOkToExitFrameList(m_bookmarkFrameList) &&
  207.      isOkToExitFrameList(m_editorFrameList) &&
  208.      isOkToExitFrameList(m_composeFrameList) &&
  209.      isOkToExitFrameList(m_searchFrameList) &&
  210.      isOkToExitFrameList(m_ldapFrameList) &&
  211.      isOkToExitFrameList(m_addressbookFrameList) &&
  212.      isOkToExitFrameList(m_mailfilterFrameList) &&
  213.      isOkToExitFrameList(m_maildownloadFrameList) &&
  214.      isOkToExitFrameList(m_historyFrameList) &&
  215.      isOkToExitFrameList(m_downloadFrameList) &&
  216.      isOkToExitFrameList(m_htmldialogFrameList) &&
  217.      isOkToExitFrameList(m_navcenterFrameList)
  218.        )
  219.      return True;
  220.  
  221.   return False;
  222. }
  223.  
  224. void
  225. XFE_MozillaApp::exit(int status)
  226. {
  227.     // if we end up here again somehow, don't free the stuff again.
  228.     D(printf ("XFE_MozillaApp::exiting...%d\n", m_exiting);)
  229.  
  230.     if (m_exiting)
  231.         {
  232.             return;
  233.         }
  234.  
  235.     /* Try to do these in decreasing order of importance, in case the user
  236.        gets impatient and kills us harder. */
  237.  
  238.     m_exiting = TRUE;
  239.  
  240.     /* Non-MailNews-Frame check */
  241.     if (!isOkToExitNonMailNewsFrames())  
  242.         {
  243.             m_exiting = FALSE;
  244.             return;
  245.         }
  246.     else 
  247.         {
  248. #ifdef MOZ_TASKBAR
  249.             // Close the floating taskbar
  250.             XFE_Dashboard::stopFloatingTaskBar();
  251. #endif
  252.  
  253.             closeFrames(m_bookmarkFrameList);
  254.             closeFrames(m_editorFrameList); 
  255.             closeFrames(m_composeFrameList); 
  256.             closeFrames(m_searchFrameList);
  257.             closeFrames(m_ldapFrameList);
  258.             closeFrames(m_addressbookFrameList);
  259.             closeFrames(m_mailfilterFrameList);
  260.             closeFrames(m_maildownloadFrameList);
  261.             closeFrames(m_historyFrameList);
  262.             closeFrames(m_downloadFrameList);
  263.             closeFrames(m_htmldialogFrameList);
  264.             closeFrames(m_browserFrameList);
  265.             closeFrames(m_navcenterFrameList);
  266.         }
  267.     if (!isOkToExitMailNewsFrames() )
  268.         {
  269.             m_exiting = FALSE;
  270.             return;
  271.         }
  272.  
  273.     //
  274.     //    At this point we are commited to exiting. We can't do everything
  275.     //    yet, but we've started. We've do far XtDestroy()ed all Frames
  276.     //    but Bookmarks. Once we get back to the event loop, Xt will start
  277.     //    the second (and real) phase of destruction, and will call all
  278.     //    the Component sub-class destructors in the process. Frame
  279.     //    destructors call MozillaApp::unregisterFrame() below, and this
  280.     //    counts down the number of frames. When there are only Bookmarks
  281.     //    (or no) frames left, we do the final exit: MOZ_byebye().
  282.     //
  283.     //    Save the requested exit status here.
  284.     //
  285.     m_exitstatus = status;
  286.  
  287.     /* My theory for putting this first is that if the user's keys get
  288.      * trashed they are really hurt, and if their certs get trashed
  289.      * they may have to pay $$$ to get new ones.  If you disagree,
  290.      * lets talk about it.  --jsw
  291.      */
  292.     SECNAV_Shutdown();
  293.  
  294.     GH_SaveGlobalHistory ();
  295.  
  296.     //
  297.     //    Check now if we are done. If no Frame are up any more,
  298.     //    there is nothing to callback from a destroy callback,
  299.     //    so we'd just go back to fe_EventLoop() and spin forever.
  300.     //    Let's not do that. Instead, just go now.
  301.     //
  302.     //    We should only go this path when the last thing out is
  303.     //    a non-XFE_Frame - for example XFE_TaskBar.
  304.     //
  305.     if (timeToDie()) {
  306.         byebye(m_exitstatus);
  307.         /*NOTREACHED*/
  308.     }
  309. }
  310.  
  311. static XtActionsRec xfe_actions[] = {
  312.     { "xfeDoCommand", xfeDoCommandAction },
  313.     { "xfeDoText",    xfeDoTextAction    },
  314.     { "xfeDoPopup",   xfeDoPopupAction   },
  315.     { "xfeDoClick",   xfeDoClickAction   },
  316.     { "undefined-key", xfeUndefinedKeyAction },
  317. };
  318.  
  319. void
  320. XFE_MozillaApp::byebye(int status)
  321. {
  322.     D(printf("MOZ_byebye() entered, grim reaper doing his stuff.... die die die..\n");)
  323.  
  324.     //
  325.     //    Shutdown bookmarks.
  326.     //
  327.     D(printf("Bookmark frame....die die die..\n");)
  328.     XFE_Frame* b_frame = (XFE_Frame*)XP_ListNextObject(m_bookmarkFrameList);
  329.     if (b_frame != NULL) {
  330.         XtDestroyWidget(b_frame->getBaseWidget());
  331.     }
  332.  
  333. #ifdef MOZ_MAIL_NEWS
  334.     /* This only calls MSG_blah functions, so I'm assuming it isn't necessary for non MOZ_MAIL_NEWS. */
  335.     XFE_MNView::destroyMasterAndShutdown();
  336. #endif
  337.  
  338.     ET_FinishMocha ();
  339.  
  340. #ifdef JAVA
  341.     LJ_ShutdownJava();
  342. #endif /* JAVA */
  343.     NET_CleanupCacheDirectory (FE_CacheDir, "cache");
  344.     GH_SaveGlobalHistory ();
  345.     GH_FreeGlobalHistory ();
  346.     NET_ShutdownNetLib ();
  347.     NPL_Shutdown ();
  348.     HOT_FreeBookmarks ();
  349.     GH_FreeGlobalHistory ();
  350.  
  351.     /* Mailcap and MimeType have been written out when the prefdialog was closed */
  352.     /* We don't need to write again. Just, Clean up these cached mailcap */
  353.     /* and mimetype link list */
  354.     NET_CleanupFileFormat(NULL);
  355.     NET_CleanupMailCapList(NULL);
  356.  
  357.     /* Cleanup webfonts */
  358.     fe_ShutdownWebfonts();
  359.  
  360.     /* Save prefs so some pref strings can be saved when the user exits. e.g. print command
  361.      */
  362.  
  363.     XFE_SavePrefs ((char *) fe_globalData.user_prefs_file, &fe_globalPrefs);
  364.  
  365.     if (fe_pidlock) unlink (fe_pidlock);
  366.     fe_pidlock = 0;
  367.     ::exit(status);
  368.  
  369.     /*NOTREACHED*/
  370. }
  371.  
  372. XP_Bool
  373. XFE_MozillaApp::timeToDie()
  374. {
  375.     //
  376.     //    Test to see if the last non-singleton frame has been destroyed.
  377.     //    If it has, then it's time to exit().
  378.     //
  379.     //    The only possible singleton frames are history and bookmarks.
  380.     //
  381.     int singleton_count = 
  382.         XP_ListCount(m_bookmarkFrameList) + 
  383.         XP_ListCount(m_historyFrameList);
  384.  
  385.     //
  386.     // Cannot exit if the taskbar is not docked (ie, floating)
  387.     //
  388.     int taskbar_count;
  389.  
  390. #ifdef MOZ_TASKBAR
  391.     taskbar_count = !XFE_Dashboard::isTaskBarDocked();
  392. #else
  393.     taskbar_count = 0;
  394. #endif
  395.  
  396.     if ((m_exitwindowcount + taskbar_count) <= singleton_count)
  397.         return TRUE;
  398.     else
  399.         return FALSE;
  400. }
  401.  
  402. void
  403. XFE_MozillaApp::unregisterFrame(XFE_Frame * /*f*/)
  404. {
  405.     m_exitwindowcount--;
  406.  
  407.     if (timeToDie()) {
  408.         byebye(m_exitstatus);
  409.         /*NOTREACHED*/
  410.     }
  411. }
  412.  
  413. void
  414. XFE_MozillaApp::registerFrame(XFE_Frame *f)
  415. {
  416.   XP_ListAddObject(m_frameList, f);
  417.  
  418.   D(printf ("Registering frame : ");)
  419.   switch (f->getType())
  420.     {
  421.     case FRAME_MAILNEWS_MSG:
  422.       D(printf ("type=MailNewsMsg\n");)
  423.       XP_ListAddObject(m_msgFrameList, f);
  424.       fe_WindowCount++;
  425.       fe_MNWindowCount++;
  426.       break;
  427.     case FRAME_MAILNEWS_THREAD:
  428.       D(printf ("type=MailNewsThread\n");)
  429.       XP_ListAddObject(m_threadFrameList, f);
  430.       fe_WindowCount++;
  431.       fe_MNWindowCount++;
  432.       break;
  433.     case FRAME_MAILNEWS_FOLDER:
  434.       D(printf ("type=MailNewsFolder\n");)
  435.       XP_ListAddObject(m_folderFrameList, f);
  436.       fe_WindowCount++;
  437.       fe_MNWindowCount++;
  438.       break;
  439.     case FRAME_MAILNEWS_COMPOSE:
  440.       D(printf ("type=MailNewsCompose\n");)
  441.       XP_ListAddObject(m_composeFrameList, f);
  442.       fe_WindowCount++;
  443.       break;
  444.     case FRAME_MAILNEWS_SEARCH:
  445.       D(printf ("type=MailNewsSearch\n");)
  446.       XP_ListAddObject(m_searchFrameList, f);
  447.       fe_WindowCount++;
  448.       break;
  449.     case FRAME_HTML_DIALOG:
  450.       D(printf ("type=HtmlDialog\n");)
  451.       XP_ListAddObject(m_htmldialogFrameList, f);
  452.       fe_WindowCount++;
  453.       break;
  454.     case FRAME_MAILNEWS_DOWNLOAD:
  455.       D(printf ("type=MailNewsDownload\n");)
  456.       XP_ListAddObject(m_maildownloadFrameList, f);
  457.       fe_WindowCount++;
  458.       break;
  459.     case FRAME_LDAP_SEARCH:
  460.       D(printf ("type=LdapSearch\n");)
  461.       XP_ListAddObject(m_ldapFrameList, f);
  462.       fe_WindowCount++;
  463.       break;
  464.     case FRAME_EDITOR:
  465.       D(printf ("type=Editor\n");)
  466.       XP_ListAddObject(m_editorFrameList, f);
  467.       fe_WindowCount++;
  468.       break;
  469.     case FRAME_BROWSER:
  470.       D(printf ("type=Browser\n");)
  471.       XP_ListAddObject(m_browserFrameList, f);
  472.       fe_WindowCount++;
  473.       break;
  474.     case FRAME_ADDRESSBOOK:
  475.       D(printf ("type=AddressBook\n");)
  476.       XP_ListAddObject(m_addressbookFrameList, f);
  477.       fe_WindowCount++;
  478.       break;
  479.     case FRAME_BOOKMARK:
  480.       D(printf ("type=Bookmark\n");)
  481.       XP_ListAddObject(m_bookmarkFrameList, f);
  482.       break;
  483.     case FRAME_MAILFILTER:
  484.       D(printf ("type=MailFilter\n");)
  485.       XP_ListAddObject(m_mailfilterFrameList, f);
  486.       break;
  487.     case FRAME_HISTORY:
  488.       D(printf ("type=History\n");)
  489.       XP_ListAddObject(m_historyFrameList, f);
  490.       break;
  491.     case FRAME_DOWNLOAD:
  492.       D(printf ("type=Download\n");)
  493.       XP_ListAddObject(m_downloadFrameList, f);
  494.       fe_WindowCount++;
  495.       break;
  496.     case FRAME_NAVCENTER:
  497.       D(printf ("type=NavCenter\n");)
  498.       XP_ListAddObject(m_navcenterFrameList, f);
  499.       fe_WindowCount++;
  500.       break;
  501.     default:
  502.       XP_ASSERT(0);
  503.       break;
  504.     }
  505.  
  506.   f->registerInterest(XFE_Frame::beforeDestroyCallback,
  507.               this,
  508.               (XFE_FunctionNotification)frameUnregistering_cb);
  509.  
  510.   // set up the xfeDoCommand stuff if it hasn't already been installed.
  511.   if (!m_actioninstalled)
  512.     {
  513.       XtAppAddActions(fe_XtAppContext, xfe_actions, XtNumber(xfe_actions));
  514.  
  515.       m_actioninstalled = TRUE;
  516.     }
  517.  
  518.   // now we let everyone know that there has been a change in the frames
  519.   // so the Frames can update their close menu items, and the menubar can
  520.   // regenerate the windows menu.
  521.   notifyInterested(changeInToplevelFrames, (void*)fe_WindowCount);
  522.  
  523.   //
  524.   // One more window to add to the number we must wait for when existing.
  525.   //
  526.   m_exitwindowcount++;
  527. }
  528.  
  529. XP_Bool XFE_MozillaApp::getBusy()
  530. {
  531.     return m_isbusy;
  532. }
  533.  
  534. XFE_CALLBACK_DEFN(XFE_MozillaApp, updateBusyState)(XFE_NotificationCenter */*obj*/,
  535.                                                    void *clientData,
  536.                                                    void */*callData*/)
  537. {
  538.     m_isbusy = (XP_Bool)(int)clientData;
  539. }
  540.  
  541. XFE_CALLBACK_DEFN(XFE_MozillaApp, frameUnregistering)(XFE_NotificationCenter *obj,
  542.                           void */*clientData*/,
  543.                           void */*callData*/)
  544. {
  545.   XFE_Frame *f = (XFE_Frame*)obj;
  546.  
  547.   /* only worry about keeping the lists up-to-date if we're going to
  548.      be sticking around. */
  549.     {   
  550.       D(printf ("Unregistering frame : ");)
  551.     
  552.     /* Unmap the window right away to give feedback that the delete
  553.        is in progress */
  554.     Widget w = f->getBaseWidget();
  555.     if (XtWindow(w))
  556.       XUnmapWindow(XtDisplay(w), XtWindow(w));
  557.  
  558.       fe_WindowCount --;
  559.  
  560.       XP_ListRemoveObject(m_frameList, f);
  561.       
  562.       switch (f->getType())
  563.     {
  564.     case FRAME_MAILNEWS_MSG:
  565.       D(printf ("type=MailNewsMsg\n");)
  566.       XP_ListRemoveObject(m_msgFrameList, f);
  567.           fe_MNWindowCount--;
  568.       break;
  569.     case FRAME_MAILNEWS_THREAD:
  570.       D(printf ("type=MailNewsThread\n");)
  571.       XP_ListRemoveObject(m_threadFrameList, f);
  572.           fe_MNWindowCount--;
  573.       break;
  574.     case FRAME_MAILNEWS_FOLDER:
  575.       D(printf ("type=MailNewsFolder\n");)
  576.       XP_ListRemoveObject(m_folderFrameList, f);
  577.           fe_MNWindowCount--;
  578.       break;
  579.     case FRAME_MAILNEWS_COMPOSE:
  580.       D(printf ("type=MailNewsCompose\n");)
  581.       XP_ListRemoveObject(m_composeFrameList, f);
  582.       break;
  583.     case FRAME_MAILNEWS_SEARCH:
  584.       D(printf ("type=MailNewsSearch\n");)
  585.       XP_ListRemoveObject(m_searchFrameList, f);
  586.       break;
  587.     case FRAME_MAILNEWS_DOWNLOAD:
  588.       D(printf ("type=MailNewsDownload\n");)
  589.       XP_ListRemoveObject(m_maildownloadFrameList, f);
  590.       break;
  591.     case FRAME_LDAP_SEARCH:
  592.       D(printf ("type=LdapSearch\n");)
  593.       XP_ListRemoveObject(m_ldapFrameList, f);
  594.       break;
  595.     case FRAME_EDITOR:
  596.       D(printf ("type=Editor\n");)
  597.       XP_ListRemoveObject(m_editorFrameList, f);
  598.       break;
  599.     case FRAME_BROWSER:
  600.       D(printf ("type=Browser\n");)
  601.       XP_ListRemoveObject(m_browserFrameList, f);
  602.       break;
  603.     case FRAME_ADDRESSBOOK:
  604.       D(printf ("type=AddressBook\n");)
  605.       XP_ListRemoveObject(m_addressbookFrameList, f);
  606.       break;
  607.     case FRAME_BOOKMARK:
  608.       D(printf ("type=Bookmark\n");)
  609.       XP_ListRemoveObject(m_bookmarkFrameList, f);
  610.       break;
  611.     case FRAME_MAILFILTER:
  612.       D(printf ("type=MailFilter\n");)
  613.       XP_ListRemoveObject(m_mailfilterFrameList, f);
  614.       break;
  615.     case FRAME_HISTORY:
  616.       D(printf ("type=History\n");)
  617.       XP_ListRemoveObject(m_historyFrameList, f);
  618.       break;
  619.     case FRAME_DOWNLOAD:
  620.       D(printf ("type=Download\n");)
  621.       XP_ListRemoveObject(m_downloadFrameList, f);
  622.       break;
  623.     case FRAME_HTML_DIALOG:
  624.       D(printf ("type=HtmlDialog\n");)
  625.       XP_ListRemoveObject(m_htmldialogFrameList, f);
  626.       break;
  627.     case FRAME_NAVCENTER:
  628.       D(printf ("type=navcenter\n");)
  629.       XP_ListRemoveObject(m_navcenterFrameList, f);
  630.       break;
  631.     }
  632.  
  633.       // Call exit() *after* removing the frame from the XP list
  634.       // to avoid closing the same frame twice.
  635.       if (fe_WindowCount == 0 && (!m_exiting))
  636.     exit(0);
  637.  
  638.       // FIX ME : Do session manager stuff here if this frame was the one
  639.       // with the session manager callback stuff being handled.
  640.  
  641.       // now we let everyone know that there has been a change in the frames
  642.       // so the Frames can update their close menu items, and the menubar can
  643.       // regenerate the windows menu.
  644.       notifyInterested(changeInToplevelFrames, (void*)fe_WindowCount);
  645.     }
  646. }
  647.  
  648. XP_List *
  649. XFE_MozillaApp::getAllFrameList()
  650. {
  651.     return m_frameList;
  652. }
  653.  
  654.  
  655. XP_List *
  656. XFE_MozillaApp::getFrameList(EFrameType type)
  657. {
  658.   switch (type)
  659.     {
  660.     case FRAME_BROWSER:
  661.       return m_browserFrameList;
  662.     case FRAME_EDITOR:
  663.       return m_editorFrameList;
  664.     case FRAME_MAILNEWS_COMPOSE:
  665.       return m_composeFrameList;
  666.     case FRAME_MAILNEWS_SEARCH:
  667.       return m_searchFrameList;
  668.     case FRAME_LDAP_SEARCH:
  669.       return m_ldapFrameList;
  670.     case FRAME_MAILNEWS_MSG:
  671.       return m_msgFrameList;
  672.     case FRAME_MAILNEWS_THREAD:
  673.       return m_threadFrameList;
  674.     case FRAME_MAILNEWS_FOLDER:
  675.       return m_folderFrameList;
  676.     case FRAME_MAILNEWS_DOWNLOAD:
  677.       return m_maildownloadFrameList;
  678.     case FRAME_MAILFILTER:
  679.       return m_mailfilterFrameList;
  680.     case FRAME_ADDRESSBOOK:
  681.       return m_addressbookFrameList;
  682.     case FRAME_BOOKMARK:
  683.       return m_bookmarkFrameList;
  684.     case FRAME_HISTORY:
  685.       return m_historyFrameList;
  686.     case FRAME_NAVCENTER:
  687.       return m_navcenterFrameList;
  688.     default:
  689.       XP_ASSERT(0);
  690.       return NULL;
  691.     }
  692. }
  693.  
  694.  
  695. XFE_MozillaApp *
  696. XFE_MozillaApp::theApp()
  697. {
  698.   if (!_app)
  699.     {
  700.       new XFE_MozillaApp(); // create _app
  701.     }
  702.   
  703.   return _app;
  704. }
  705.  
  706. int
  707. XFE_MozillaApp::toplevelWindowCount()
  708. {
  709.   return fe_WindowCount;
  710. }
  711.  
  712. int
  713. XFE_MozillaApp::mailNewsWindowCount()
  714. {
  715.   return fe_MNWindowCount;
  716. }
  717.  
  718. // C API.  so we can initialize it in main
  719. XFE_MozillaApp *
  720. theMozillaApp()
  721. {
  722.   return XFE_MozillaApp::theApp();
  723. }
  724.  
  725. // The text cut/copy/paste action handler for the entire app...
  726. //
  727. static void
  728. xfeDoTextAction(Widget w, XEvent *event,
  729.                 String *params, Cardinal *num_params)
  730. {
  731.     MWContext *context = fe_WidgetToMWContext(w);
  732.     CommandType cmd;
  733.  
  734.     if (!context) {
  735. #ifdef DEBUG_rhess
  736.         fprintf(stderr, "xfeDoTextAction::[ no context ] **\n");
  737. #endif
  738.         return;
  739.     }
  740.  
  741.     if (*num_params < 1) { 
  742. #ifdef DEBUG_rhess
  743.         fprintf(stderr, "xfeDoTextAction::[ no command ] **\n");
  744. #endif
  745.         // We must be sent the command to be performed.
  746.         return;
  747.     }
  748.     
  749.     cmd = Command::intern(params[0]);
  750.  
  751.     if (!XmIsText(w) && !XmIsTextField(w)) {
  752. #ifdef DEBUG_rhess
  753.         fprintf(stderr, "xfeDoTextAction::[ no widget ] **\n");
  754. #endif
  755.         // We must be sent the command to be performed.
  756.         return;
  757.     }
  758.  
  759.     if (cmd == xfeCmdCut) {
  760. #ifdef DEBUG_rhess
  761.         fprintf(stderr, "xfeDoTextAction::[ %s ]\n", cmd);
  762. #endif
  763.         xfe_TextCopy (context, w, TRUE);
  764.     }
  765.     else {
  766.         if (cmd == xfeCmdCopy) {
  767. #ifdef DEBUG_rhess
  768.             fprintf(stderr, "xfeDoTextAction::[ %s ]\n", cmd);
  769. #endif
  770.             xfe_TextCopy (context, w, FALSE);
  771.         }
  772.         else {
  773.             if (cmd == xfeCmdPaste) {
  774. #ifdef DEBUG_rhess
  775.                 fprintf(stderr, "xfeDoTextAction::[ %s ]\n", cmd);
  776. #endif
  777.                 xfe_TextPaste (context, w, FALSE);
  778.             }
  779.             else {
  780. #ifdef DEBUG_rhess
  781.                 fprintf(stderr,
  782.                         "xfeDoTextAction::[ no handler ][ %s ] **\n", 
  783.                         cmd);
  784. #endif
  785.                 XBell (XtDisplay(w), 0);
  786.                 return;
  787.             }
  788.         }
  789.     }
  790. }
  791.  
  792. // C API to our xfeDoCommandAction() function. We use this as our
  793. // remote entry point.
  794. extern "C" void
  795. xfeDoRemoteCommand (Widget w, XEvent *event,
  796.             String *params, Cardinal *num_params)
  797. {
  798.   int first_param = 0;
  799.   Cardinal numparams = *num_params;
  800.   String old_first;
  801.  
  802. #ifdef DEBUG_spence
  803.   printf ("xfeDoRemoteCommand: params[0] = %s\n", params[0]);
  804. #endif
  805.  
  806.   /* if the first argument is xfeDoCommand, skip it. */
  807.   if (!strcmp(params[0], "xfeDoCommand"))
  808.     {
  809.       first_param = 1;
  810.       numparams --;
  811.     }
  812.  
  813.   old_first = params[first_param];
  814.   params[first_param] = Command::convertOldRemote(params[first_param]);
  815.  
  816.   xfeDoCommandAction (w, event, ¶ms[first_param], &numparams);
  817.  
  818.   params[first_param] = old_first;
  819. }
  820.  
  821. // The *one* action handler for the entire app.  All it does is figure out
  822. // what frame it's suppose to use, verify that the command (sent as params[0])
  823. // is handled and enabled, and then calls doCommand().  Neat, huh?
  824. static void
  825. xfeDoCommandAction(Widget w, XEvent *event,
  826.            String *params, Cardinal *num_params)
  827. {
  828.     MWContext *context = fe_WidgetToMWContext(w);
  829.     CommandType cmd;
  830.     XFE_Frame *f;
  831.     
  832.     if (*num_params < 1) // We must be sent the command to be performed.
  833.         {
  834.             D(  printf ("There must be at least 1 parameter.  There is %d\n", *num_params);)
  835.                 return;
  836.         }
  837.     
  838.     f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  839.     
  840.     if (!f) // hmm... don't know *how* we could have gotten here otherwise...
  841.         return;
  842.     
  843.     cmd = Command::intern(params[0]);
  844. #ifdef DEBUG_spence
  845.     printf ("cmd: %s\n", cmd);
  846. #endif
  847.     
  848.     /* xfeDoCommand(showPopup) and popup() both do the same thing */
  849.     if (cmd == xfeCmdShowPopup
  850.         && // dealing with xfeDoPopupAction() is beyond me...djw
  851.         XP_STRCMP(XtName(w), "editorDrawingArea") != 0)
  852.         {
  853.             xfeDoPopupAction(w, event, params, num_params);
  854.             return;
  855.         }
  856.     // Further justification: I really want commands to be delivered to
  857.     // the Frame. xfeDoPopupAction() delivers the command to the view.
  858.     // This is different from every other command, and breaks the
  859.     // way EditorFrame and EditorView talk to each other. So, for now,
  860.     // I'm special casing this (I know it's hacky) for the Editor
  861.     // and HTML mail compose...djw
  862.     
  863.     String* p_params = NULL;
  864.     XFE_CommandEventType cmd_type;
  865.     int num_cmd_params = *num_params;
  866.     int i;
  867.  
  868.     if (*num_params > 1) // first is name of command.
  869.       p_params = ¶ms[1];
  870.     else
  871.       p_params = NULL;
  872.  
  873.     num_cmd_params -= 1;
  874.  
  875.     if (p_params && 
  876.         p_params[num_cmd_params - 1] &&
  877.         !strcmp(p_params[num_cmd_params - 1], "<remote>"))
  878.       {
  879.         cmd_type = XFE_COMMAND_REMOTE_ACTION;
  880.         num_cmd_params -= 1;
  881.       }
  882.     else
  883.       cmd_type = XFE_COMMAND_EVENT_ACTION;
  884.  
  885.     if (num_cmd_params == 0)
  886.         p_params = NULL;
  887.     
  888.     XFE_CommandInfo info(cmd_type, w, event,
  889.                          p_params, num_cmd_params);
  890.  
  891.     /* if the frame doesn't handle the command, bomb out early */
  892.     if (!f->handlesCommand(cmd, NULL, &info))
  893.       {
  894.         XBell (XtDisplay(f->getBaseWidget()), 0);
  895.         return;
  896.       }
  897.  
  898.     /* if hotkeys are disabled, beep and return */
  899.     if (cmd_type != XFE_COMMAND_REMOTE_ACTION &&
  900.         f->hotKeysDisabled() &&
  901.         /*
  902.         ** This following set of commands is allowed through regardless of
  903.         ** whether or not hot keys are enabled
  904.         */
  905.         cmd != xfeCmdExit &&
  906.         cmd != xfeCmdViewSecurity &&
  907.         cmd != xfeCmdCut &&
  908.         cmd != xfeCmdCopy &&
  909.         cmd != xfeCmdPaste)
  910.       {
  911.         XBell (XtDisplay(f->getBaseWidget()), 0);
  912.         return;
  913.       }
  914.  
  915.     if (f->isCommandEnabled(cmd, NULL, &info)) {
  916.         
  917.         xfe_ExecuteCommand(f, cmd, NULL, &info);
  918.     }
  919. }
  920.  
  921. static void
  922. xfeDoPopupAction(Widget w,
  923.          XEvent *event,
  924.          String */*params*/, Cardinal */*num_params*/)
  925. {
  926.   CommandType cmd;
  927.   XFE_Frame *f;
  928.  
  929. #ifdef MOZ_MAIL_NEWS
  930.   XFE_View *v;
  931. #endif
  932.  
  933.   MWContext *context = fe_WidgetToMWContext(w);
  934.  
  935.   f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  936.  
  937.   if (!f) {
  938.       // hmm... don't know *how* we could have gotten here otherwise...
  939.       return;
  940.   }/* if */
  941.  
  942.   cmd = xfeCmdShowPopup;
  943.  
  944.   XFE_CommandInfo info(XFE_COMMAND_EVENT_ACTION, w, event, NULL, 0);
  945.  
  946. #ifdef MOZ_MAIL_NEWS
  947.   v = f->widgetToView(w);
  948.  
  949.   if (!v) {
  950. #endif
  951.       if (f) {
  952.           if (f->handlesCommand(cmd))
  953.               f->doCommand(cmd, NULL, &info);
  954.       }/* if */
  955. #ifdef MOZ_MAIL_NEWS
  956.   }/* if */
  957.   else if (v->handlesCommand(cmd))
  958.       v->doCommand(cmd, NULL, &info);
  959. #endif
  960. }
  961.  
  962. //
  963. //    This action is used to diferentiate single/double clicks,
  964. //    which Xt does a bad job on. In your translation use:
  965. //
  966. //    binding: xfeDoClick(single, { command1,p1,p2,p3,...,}, \
  967. //                        double, { command2,p1,p2,p3,})
  968. //
  969. //    Note: the zero length string as the param before double.
  970. //
  971. //    xfeDoClick() will dispatch via xfeDoCommand(). If it's a single click,
  972. //    xfeDoCommand(command1, p1, p2, ...) will be called. If it's a double,
  973. //    xfeDoCommand(command2, p1, p2, ...) will be called. It doesn't handle
  974. //    triple clicks.
  975. //
  976. static Time fe_click_action_last; /* this is very lazy */
  977. static void
  978. xfeDoClickAction(Widget widget, XEvent *event, String *av, Cardinal *ac)
  979. {
  980.     Time     time;
  981.     unsigned n;
  982.     unsigned m;
  983.     unsigned n_clicks = 1;
  984.     unsigned c_clicks = 1;
  985.     String   command_name;
  986.     unsigned depth;
  987.  
  988.     time = fe_GetTimeFromEvent(event);
  989.     
  990.     int delta = (time - fe_click_action_last);
  991.  
  992.     if (delta <    XtGetMultiClickTime(XtDisplay(widget)))
  993.         n_clicks = 2;
  994.     
  995.     fe_click_action_last = time;
  996.     
  997.     for (n = 0; n + 1 < *ac; n++) {
  998.         
  999.         command_name = NULL;
  1000.         
  1001.         if (XP_STRCASECMP(av[n], "double") == 0) {
  1002.             c_clicks = 2;
  1003.             n++;
  1004.         } else if (XP_STRCASECMP(av[n], "single") == 0) {
  1005.             c_clicks = 1;
  1006.             n++;
  1007.         } else {
  1008.             c_clicks = 1;
  1009.         }
  1010.  
  1011.         if (XP_STRCMP(av[n], "{") == 0) {
  1012.             n++;
  1013.         } else {
  1014.             // syntax error.
  1015.             return;
  1016.         }
  1017.  
  1018.         // find closing brace.
  1019.         for (depth = 1, m = n; av[m] != NULL && m < *ac; m++) {
  1020.             if (XP_STRCMP(av[m], "{") == 0)
  1021.                 depth++;
  1022.             else if (XP_STRCMP(av[m], "}") == 0)
  1023.                 depth--;
  1024.             
  1025.             if (depth == 0)
  1026.                 break;
  1027.         }
  1028.  
  1029.         if (c_clicks == n_clicks && m > n && av[m] != NULL) {
  1030.             Cardinal foo = m - n;
  1031.             xfeDoCommandAction(widget, event, &av[n], &foo);
  1032.             break; // done
  1033.         }
  1034.         
  1035.         n = m;
  1036.     }
  1037. }
  1038.  
  1039. static void
  1040. xfeUndefinedKeyAction(Widget w,
  1041.                       XEvent */*event*/,
  1042.                       String */*params*/, Cardinal */*num_params*/)
  1043. {
  1044.     XBell(XtDisplay(w), 0);
  1045. }
  1046.  
  1047. // Stole this from xp_file.c
  1048. static const char *
  1049. fe_config_directory(char* buf)
  1050. {
  1051.   static XP_Bool initted = FALSE;
  1052.   const char *dir = ".netscape";
  1053.   char *home;
  1054.   if (initted)
  1055.     return buf;
  1056.  
  1057.   home = getenv ("HOME");
  1058.   if (!home)
  1059.     home = "";
  1060.  
  1061. #ifdef OLD_UNIX_FILES
  1062.  
  1063.   sprintf (buf, "%.900s", home);
  1064.   if (buf[strlen(buf)-1] == '/')
  1065.     buf[strlen(buf)-1] = 0;
  1066.  
  1067. #else  /* !OLD_UNIX_FILES */
  1068.  
  1069.   if (*home && home[strlen(home)-1] == '/')
  1070.     sprintf (buf, "%.900s%s", home, dir);
  1071.   else
  1072.     sprintf (buf, "%.900s/%s", home, dir);
  1073.  
  1074. #endif /* !OLD_UNIX_FILES */
  1075.  
  1076.   return buf;
  1077. }
  1078.  
  1079. typedef enum {
  1080.   XFE_STAT_ISDIR,
  1081.   XFE_STAT_ISREG
  1082. } xfeStatType; 
  1083.  
  1084. // Stole this from xp_file.c
  1085. static int
  1086. fe_sprintf_stat( char * buf,
  1087.                  const char * dirName,
  1088.                  const char * lang,
  1089.                  const char * fileName,
  1090.                  xfeStatType whichStat)
  1091. {
  1092.     int               result;
  1093.     int               len = 0;
  1094.     XP_StatStruct     outStat;
  1095.  
  1096.     if (dirName == NULL || 0 == (len = strlen(dirName)) || len > 900)
  1097.       return -1;
  1098.  
  1099.     while (--len > 0 && dirName[len] == '/')
  1100.     /* do nothing */;        /* strip trailing slashes */
  1101.  
  1102.     strncpy(buf, dirName, ++len);
  1103.     buf[len++] = '/';
  1104.     buf[len]   =  0;
  1105.  
  1106.     if (lang != NULL && *lang == 0)
  1107.       lang  = NULL;
  1108.  
  1109.     if (lang != NULL) 
  1110.       sprintf(buf+len, "%.100s/%s", lang, fileName);
  1111.     else
  1112.       strcpy(buf+len, fileName);
  1113.  
  1114.     result = stat( buf, &outStat );
  1115.     if (result < 0 
  1116.         || (whichStat == XFE_STAT_ISDIR && !S_ISDIR(outStat.st_mode))
  1117.         || (whichStat == XFE_STAT_ISREG && !S_ISREG(outStat.st_mode))) {
  1118.       result = -1;
  1119.     }
  1120.     if (result < 0 && lang != NULL) {
  1121.       result = fe_sprintf_stat(buf, dirName, NULL, fileName, whichStat);
  1122.     }
  1123.     return result;
  1124. }
  1125.  
  1126.  
  1127. // Called from XFE_BookmarkView::loadBookmarks() to get the
  1128. //   location of the default bookmarks.
  1129. //
  1130. // Search order:
  1131. //    $MOZILLA_HOME/bookmark.htm
  1132. //    <program directory>/bookmark.htm
  1133. //    /usr/local/lib/netscape/bookmark.htm
  1134. //
  1135. extern "C"
  1136. char *
  1137. fe_getDefaultBookmarks(void)
  1138. {
  1139. #ifdef PATH_MAX
  1140.   char bmDir[PATH_MAX];
  1141. #else
  1142.   char bmDir[1024]; // we probably should use pathconf here
  1143. #endif
  1144.   char *bmFilename = "bookmark.htm";
  1145.   char *mozHome  = getenv("MOZILLA_HOME");
  1146.   char *lang     = getenv("LANG");
  1147.   char  progDir[1024];
  1148.     
  1149.   // Setup the URL prefix
  1150.     
  1151.   fe_GetProgramDirectory(progDir, sizeof progDir);
  1152.  
  1153.   if (!fe_sprintf_stat(bmDir, mozHome, lang, bmFilename, XFE_STAT_ISREG)
  1154.       || !fe_sprintf_stat(bmDir, progDir, lang, bmFilename, XFE_STAT_ISREG)
  1155.       || !fe_sprintf_stat(bmDir, STANDARD_INSTALL_PATH, lang, bmFilename,
  1156.                           XFE_STAT_ISREG))
  1157.     {
  1158.       // Found it
  1159.       return XP_STRDUP(bmDir);
  1160.     }
  1161.   else
  1162.     {
  1163.       return NULL;
  1164.     }
  1165. }
  1166.  
  1167. // Called from mkhelp.c to get the standard location
  1168. //    of the NetHelp folder as a URL
  1169. //
  1170. // Search order:
  1171. //    ~/.netscape/nethelp
  1172. //    $NS_NETHELP_PATH
  1173. //    $MOZILLA_HOME/nethelp
  1174. //    <program directory>/nethelp
  1175. //    /usr/local/lib/netscape/nethelp
  1176. //
  1177. char * FE_GetNetHelpDir()
  1178. {
  1179. #ifdef PATH_MAX
  1180.   char nethelpDir[PATH_MAX+15];
  1181. #else
  1182.   char nethelpDir[1024+15]; // we probably should use pathconf here
  1183. #endif
  1184.   int  filePrefixLen;
  1185.   char *nethelpSuffix = "nethelp/";
  1186.   static char  configBuf[1024];
  1187.   const char *conf_dir = fe_config_directory(configBuf);
  1188.   char *helpPath = getenv("NS_NETHELP_PATH");
  1189.   char *mozHome  = getenv("MOZILLA_HOME");
  1190.   char *lang     = getenv("LANG");
  1191.   char  progDir[1024];
  1192.     
  1193.   // Setup the URL prefix
  1194.     
  1195.   XP_STRCPY(nethelpDir, "file:");
  1196.   filePrefixLen = strlen(nethelpDir);
  1197.   fe_GetProgramDirectory(progDir, sizeof progDir);
  1198.  
  1199.   if (!fe_sprintf_stat(nethelpDir + filePrefixLen, 
  1200.                        conf_dir, lang, nethelpSuffix, XFE_STAT_ISDIR) 
  1201.       || !fe_sprintf_stat(nethelpDir + filePrefixLen,
  1202.                           helpPath, lang, nethelpSuffix, XFE_STAT_ISDIR)
  1203.       || !fe_sprintf_stat(nethelpDir + filePrefixLen,
  1204.                           mozHome, lang, nethelpSuffix, XFE_STAT_ISDIR)
  1205.       || !fe_sprintf_stat(nethelpDir + filePrefixLen,
  1206.                           progDir, lang, nethelpSuffix, XFE_STAT_ISDIR)
  1207.       || !fe_sprintf_stat(nethelpDir + filePrefixLen,
  1208.                           STANDARD_INSTALL_PATH, lang, nethelpSuffix,
  1209.                           XFE_STAT_ISDIR))
  1210.     {
  1211.       // Found it - result already copied into nethelpDir
  1212.       ;
  1213.     }
  1214.  
  1215.   // Found it or not, we return a valid URL
  1216.   return XP_STRDUP(nethelpDir);
  1217. }
  1218.  
  1219.  
  1220.  
  1221. MWContext *FE_GetNetHelpContext()
  1222. {
  1223.     /* Per: mcafee, use the bookmark context as our dummy context */
  1224.     
  1225.     MWContext    *pActiveContext = fe_getBookmarkContext();
  1226.  
  1227.     return pActiveContext;
  1228. }
  1229.  
  1230. extern "C" void
  1231. fe_Exit(int status)
  1232. {
  1233.     XFE_MozillaApp::theApp()->exit(status);
  1234. }
  1235.