home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / src / MNView.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  37.8 KB  |  1,305 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.    MNView.cpp -- Superclass for all mail news views (folder, thread, and message.)
  20.    Created: Chris Toshok <toshok@netscape.com>, 7-Aug-96.
  21.    */
  22.  
  23.  
  24. #include "MozillaApp.h"
  25. #include "ViewGlue.h"
  26. #include "Frame.h"
  27.  
  28. #ifdef MOZ_MAIL_NEWS
  29. #include "MNView.h"
  30. #include "MNListView.h"
  31. #include "MailDownloadFrame.h"
  32. #include "NewsPromptDialog.h"
  33. #include "ComposeFrame.h"
  34. #include "ABListSearchView.h"
  35. #include "ThreadView.h"
  36. #include "dirprefs.h"
  37. #endif
  38.  
  39. #include "Outlinable.h"
  40. #include "Outliner.h"
  41. #include "xfe.h"
  42. #include "xp_mem.h"
  43. #include "addrbook.h"
  44. #include "xp_time.h"
  45. #include <Xfe/Xfe.h>
  46.  
  47. #include "prefapi.h"
  48.  
  49. #include <dirent.h>
  50. #include <signal.h>
  51. #include <sys/wait.h>        /* for all the movemail crud */
  52.  
  53. #ifdef SCO_SV
  54. #include "mcom_db.h"
  55. #define _SVID3          /* for statvfs.h */
  56. #endif
  57. #include "xpgetstr.h"
  58.  
  59. #ifdef MOZ_MAIL_NEWS
  60.  
  61. extern int XFE_MAIL_PRIORITY_NONE;
  62. extern int XFE_MAIL_PRIORITY_LOWEST;
  63. extern int XFE_MAIL_PRIORITY_LOW;
  64. extern int XFE_MAIL_PRIORITY_NORMAL;
  65. extern int XFE_MAIL_PRIORITY_HIGH;
  66. extern int XFE_MAIL_PRIORITY_HIGHEST;
  67. extern int XFE_MAIL_SPOOL_UNKNOWN;
  68. extern int XFE_UNABLE_TO_OPEN;
  69. extern int XFE_NO_KEEP_ON_SERVER_WITH_MOVEMAIL;
  70.  
  71. extern int XFE_COULDNT_FORK_FOR_MOVEMAIL;
  72. extern int XFE_PROBLEMS_EXECUTING;
  73. extern int XFE_TERMINATED_ABNORMALLY;
  74. extern int XFE_APP_EXITED_WITH_STATUS;
  75. extern int XFE_COULDNT_FORK_FOR_DELIVERY;
  76.  
  77. extern int XFE_GET_NEXT_N_MSGS;
  78.  
  79. extern int XFE_MARKBYDATE_CAPTION;
  80. extern int XFE_MARKBYDATE;
  81. extern int XFE_DATE_MUST_BE_MM_DD_YY;
  82.  
  83. MSG_Master *XFE_MNView::m_master = NULL;
  84. MSG_Prefs *XFE_MNView::m_prefs = NULL;
  85.  
  86. MSG_BIFF_STATE XFE_MNView::m_biffstate = MSG_BIFF_Unknown;
  87.  
  88. fe_icon XFE_MNView::inboxIcon = { 0 };
  89. fe_icon XFE_MNView::inboxOpenIcon = { 0 };
  90. fe_icon XFE_MNView::draftsIcon = { 0 };
  91. fe_icon XFE_MNView::draftsOpenIcon = { 0 };
  92. fe_icon XFE_MNView::filedMailIcon = { 0 };
  93. fe_icon XFE_MNView::filedMailOpenIcon = { 0 };
  94. fe_icon XFE_MNView::outboxIcon = { 0 };
  95. fe_icon XFE_MNView::outboxOpenIcon = { 0 };
  96. fe_icon XFE_MNView::trashIcon = { 0 };
  97. fe_icon XFE_MNView::folderIcon = { 0 };
  98. fe_icon XFE_MNView::folderOpenIcon = { 0 };
  99. fe_icon XFE_MNView::folderServerIcon = { 0 };
  100. fe_icon XFE_MNView::folderServerOpenIcon = { 0 };
  101. fe_icon XFE_MNView::newsgroupIcon = { 0 };
  102. fe_icon XFE_MNView::mailLocalIcon = { 0 };
  103. fe_icon XFE_MNView::mailServerIcon = { 0 };
  104. fe_icon XFE_MNView::newsServerIcon = { 0 };
  105. fe_icon XFE_MNView::newsServerSecureIcon = { 0 };
  106. fe_icon XFE_MNView::mailMessageReadIcon = { 0 };
  107. fe_icon XFE_MNView::mailMessageUnreadIcon = { 0 };
  108. fe_icon XFE_MNView::newsPostIcon = { 0 };
  109. fe_icon XFE_MNView::draftIcon = { 0 };
  110. fe_icon XFE_MNView::newsNewIcon = { 0 };
  111. fe_icon XFE_MNView::msgReadIcon = { 0 };
  112. fe_icon XFE_MNView::msgUnreadIcon = { 0 };
  113. fe_icon XFE_MNView::deletedIcon = { 0 };
  114. fe_icon XFE_MNView::msgFlagIcon = { 0 };
  115. fe_icon XFE_MNView::collectionsIcon = { 0 };
  116.  
  117. fe_icon XFE_MNView::openSpoolIcon = { 0 };
  118. fe_icon XFE_MNView::closedSpoolIcon = { 0 };
  119. fe_icon XFE_MNView::openSpoolIgnoredIcon = { 0 };
  120. fe_icon XFE_MNView::closedSpoolIgnoredIcon = { 0 };
  121. fe_icon XFE_MNView::openSpoolWatchedIcon = { 0 };
  122. fe_icon XFE_MNView::closedSpoolWatchedIcon = { 0 };
  123. fe_icon XFE_MNView::openSpoolNewIcon = { 0 };
  124. fe_icon XFE_MNView::closedSpoolNewIcon = { 0 };
  125.  
  126. typedef struct fe_mn_incstate {
  127.   MWContext* context;
  128.   char filename[512];
  129.   XP_Bool wascrashbox;
  130.   XP_File file;
  131. } fe_mn_incstate;
  132.  
  133. static void fe_incdone(void* closure, XP_Bool result);
  134. static XP_Bool fe_run_movemail (MWContext *context, const char *from, const char *to);
  135. extern "C" char* fe_mn_getmailbox(void);
  136.  
  137. const char * XFE_MNView::bannerNeedsUpdating = "XFE_MNView::bannerNeedsUpdating";
  138. const char * XFE_MNView::foldersHaveChanged = "XFE_MNView::foldersHaveChanged";
  139. const char * XFE_MNView::newsgroupsHaveChanged = "XFE_MNView::newsgroupsHaveChanged";
  140. const char * XFE_MNView::folderChromeNeedsUpdating = "XFE_MNView::folderChromeNeedsUpdating";
  141. const char * XFE_MNView::MNChromeNeedsUpdating = "XFE_MNView::MNChromeNeedsUpdating";
  142. const char * XFE_MNView::msgWasDeleted = "XFE_MNView::msgWasDeleted";
  143. const char * XFE_MNView::folderDeleted = "XFE_MNView::folderDeleted";
  144.  
  145. XP_Bool XFE_MNView::m_messageDownloadInProgress = False;
  146. int  XFE_MNView::m_numFolderBeingLoaded = 0; // Indicate how many folder are loaded
  147.  
  148.  
  149. XFE_MNView::XFE_MNView(XFE_Component *toplevel_component,
  150.                XFE_View *parent_view, 
  151.                MWContext *context,
  152.                MSG_Pane *p) 
  153.   : XFE_View(toplevel_component, parent_view, context)
  154. {
  155.   m_pane = p;
  156.  
  157.   // a safe default;
  158.   m_displayingNewsgroup = FALSE;
  159.  
  160.   // initialize the mail master
  161.   getMaster();
  162.  
  163.  
  164.   XFE_MozillaApp::theApp()->registerInterest(
  165.         XFE_MozillaApp::biffStateChanged,
  166.         this,
  167.         (XFE_FunctionNotification) updateBiffState_cb);
  168. }
  169.  
  170. XFE_MNView::~XFE_MNView()
  171. {
  172.   XFE_MozillaApp::theApp()->unregisterInterest(
  173.         XFE_MozillaApp::biffStateChanged,
  174.         this,
  175.         (XFE_FunctionNotification)updateBiffState_cb);
  176. }
  177.  
  178. void
  179. XFE_MNView::destroyPane()
  180. {
  181.     if (m_pane)
  182.         {
  183.             XP_InterruptContext(m_contextData);
  184.             MSG_DestroyPane(m_pane);
  185.             
  186.             m_pane = NULL;
  187.         }
  188. }
  189.  
  190. MSG_Pane *
  191. XFE_MNView::getPane()
  192. {
  193.   return m_pane;
  194. }
  195.  
  196. void
  197. XFE_MNView::setPane(MSG_Pane *p)
  198. {
  199.   m_pane = p;
  200.  
  201.   // we only bind the view to the pane when
  202.   // the m_pane is not NULL. Otherwise, don't bind.
  203.   if ( m_pane ) 
  204.       MSG_SetFEData(m_pane, this);
  205. }
  206.  
  207. void
  208. XFE_MNView::updateCompToolbar()
  209. {
  210.     // NOTE:  we are using this to wait for the MSG layer to finish all
  211.     //        of it's connections before we attempt to initialize the 
  212.     //        Editor...
  213. }
  214.  
  215. MSG_MotionType
  216. XFE_MNView::commandToMsgNav(CommandType cmd)
  217. {
  218.   MSG_MotionType msg_cmd = (MSG_MotionType)~0;
  219.  
  220. #define BEGIN_MN_MSG_MAP() if (0)
  221. #define MN_MSGMAP(the_cmd, the_msg_cmd) else if (cmd == (the_cmd)) msg_cmd = (the_msg_cmd)
  222.   BEGIN_MN_MSG_MAP();
  223.   MN_MSGMAP(xfeCmdBack, MSG_Back);
  224.   MN_MSGMAP(xfeCmdForward, MSG_Forward);
  225.   MN_MSGMAP(xfeCmdNextMessage, MSG_NextMessage);
  226.   MN_MSGMAP(xfeCmdNextUnreadNewsgroup, MSG_NextUnreadGroup);
  227.   MN_MSGMAP(xfeCmdNextUnreadMessage, MSG_NextUnreadMessage);
  228.   MN_MSGMAP(xfeCmdNextUnreadThread, MSG_NextUnreadThread);
  229.   MN_MSGMAP(xfeCmdNextFlaggedMessage, MSG_NextFlagged);
  230.   MN_MSGMAP(xfeCmdFirstFlaggedMessage, MSG_FirstFlagged);
  231.   MN_MSGMAP(xfeCmdPreviousMessage, MSG_PreviousMessage);
  232.   MN_MSGMAP(xfeCmdPreviousUnreadMessage, MSG_PreviousUnreadMessage);
  233.   MN_MSGMAP(xfeCmdPreviousFlaggedMessage, MSG_PreviousFlagged);
  234. #undef MN_MSGMAP
  235. #undef BEGIN_MN_MSG_MAP
  236.  
  237.   return msg_cmd;
  238. }
  239.  
  240. MSG_CommandType
  241. XFE_MNView::commandToMsgCmd(CommandType cmd)
  242. {
  243.   MSG_CommandType msg_cmd = (MSG_CommandType)~0;
  244.  
  245. #define BEGIN_MN_MSG_MAP() if (0)
  246. #define MN_MSGMAP(the_cmd, the_msg_cmd) else if (cmd == (the_cmd)) msg_cmd = (the_msg_cmd)
  247.   BEGIN_MN_MSG_MAP();
  248.   MN_MSGMAP(xfeCmdAddAllToAddressBook, MSG_AddAll);
  249.   MN_MSGMAP(xfeCmdAddNewsgroup, MSG_AddNewsGroup);
  250.   MN_MSGMAP(xfeCmdAddSenderToAddressBook, MSG_AddSender);
  251.   MN_MSGMAP(xfeCmdCancelMessages, MSG_CancelMessage);
  252.   MN_MSGMAP(xfeCmdClearNewGroups, MSG_ClearNew); // subscribe ui only
  253.   MN_MSGMAP(xfeCmdCollapseAll, MSG_CollapseAll); // subscribe ui only
  254.   MN_MSGMAP(xfeCmdComposeArticle, MSG_PostNew);
  255.   MN_MSGMAP(xfeCmdComposeArticleHTML, MSG_PostNew);
  256.   MN_MSGMAP(xfeCmdComposeArticlePlain, MSG_PostNew);
  257.   MN_MSGMAP(xfeCmdComposeMessage, MSG_MailNew);
  258.   MN_MSGMAP(xfeCmdComposeMessageHTML, MSG_MailNew);
  259.   MN_MSGMAP(xfeCmdComposeMessagePlain, MSG_MailNew);
  260.   MN_MSGMAP(xfeCmdCompressAllFolders, MSG_CompressAllFolders);
  261.   MN_MSGMAP(xfeCmdCompressFolders, MSG_CompressFolder);
  262.   MN_MSGMAP(xfeCmdDeleteFolder, MSG_DeleteFolder);
  263.   MN_MSGMAP(xfeCmdDeleteMessage, MSG_DeleteMessage);
  264.   MN_MSGMAP(xfeCmdEditAddress, MSG_EditAddress);
  265.   MN_MSGMAP(xfeCmdEmptyTrash, MSG_EmptyTrash);
  266.   MN_MSGMAP(xfeCmdExpandAll, MSG_ExpandAll); // subscribe ui only
  267.   MN_MSGMAP(xfeCmdFetchGroupList, MSG_FetchGroupList); // subscribe ui only
  268.   MN_MSGMAP(xfeCmdForwardMessage, MSG_ForwardMessage);
  269.   MN_MSGMAP(xfeCmdForwardMessageQuoted, MSG_ForwardMessageQuoted);
  270.   MN_MSGMAP(xfeCmdGetNewGroups, MSG_CheckForNew); // subscribe ui only
  271.   MN_MSGMAP(xfeCmdGetNewMessages, MSG_GetNewMail);
  272.   MN_MSGMAP(xfeCmdGetNextNNewMsgs, MSG_GetNextChunkMessages);
  273.   MN_MSGMAP(xfeCmdIgnoreThread, MSG_ToggleThreadKilled);
  274.   MN_MSGMAP(xfeCmdWatchThread, MSG_ToggleThreadWatched);
  275.   MN_MSGMAP(xfeCmdMarkAllMessagesRead, MSG_MarkAllRead);
  276.   MN_MSGMAP(xfeCmdMarkMessage, MSG_MarkMessages);
  277.   MN_MSGMAP(xfeCmdMarkMessageRead, MSG_MarkMessagesRead);
  278.   MN_MSGMAP(xfeCmdMarkMessageUnread, MSG_MarkMessagesUnread);
  279.   MN_MSGMAP(xfeCmdMarkThreadRead, MSG_MarkThreadRead);
  280.   MN_MSGMAP(xfeCmdModerateDiscussion, MSG_ModerateNewsgroup);
  281.   MN_MSGMAP(xfeCmdNewCategory, MSG_NewCategory);
  282.   MN_MSGMAP(xfeCmdNewFolder, MSG_NewFolder);
  283.   MN_MSGMAP(xfeCmdOpenAddressBook, MSG_EditAddressBook);
  284.   MN_MSGMAP(xfeCmdOpenFolder, MSG_OpenFolder);
  285.   MN_MSGMAP(xfeCmdOpenMessageAsDraft, MSG_OpenMessageAsDraft);
  286.   MN_MSGMAP(xfeCmdEditMessage, MSG_OpenMessageAsDraft);
  287.   MN_MSGMAP(xfeCmdPrint, MSG_Print);
  288.   MN_MSGMAP(xfeCmdRedo, MSG_Redo);
  289.   MN_MSGMAP(xfeCmdRenameFolder, MSG_DoRenameFolder);
  290.   MN_MSGMAP(xfeCmdReplyToAll, MSG_ReplyToAll);
  291.   MN_MSGMAP(xfeCmdReplyToNewsgroup, MSG_PostReply);
  292.   MN_MSGMAP(xfeCmdReplyToSender, MSG_ReplyToSender);
  293.   MN_MSGMAP(xfeCmdReplyToSenderAndNewsgroup, MSG_PostAndMailReply);
  294.   MN_MSGMAP(xfeCmdResort, MSG_ReSort);
  295.   MN_MSGMAP(xfeCmdRetrieveMarkedMessages, MSG_RetrieveMarkedMessages);
  296.   MN_MSGMAP(xfeCmdRetrieveSelectedMessages, MSG_RetrieveSelectedMessages);
  297.   MN_MSGMAP(xfeCmdRot13Message, MSG_Rot13Message);
  298.   MN_MSGMAP(xfeCmdSaveMessagesAs, MSG_SaveMessagesAs);
  299.   MN_MSGMAP(xfeCmdSaveMessagesAsAndDelete, MSG_SaveMessagesAsAndDelete);
  300.   MN_MSGMAP(xfeCmdSendMessagesInOutbox, MSG_DeliverQueuedMessages);
  301.   MN_MSGMAP(xfeCmdShowAllHeaders, MSG_ShowAllHeaders);
  302.   MN_MSGMAP(xfeCmdShowNormalHeaders, MSG_ShowSomeHeaders);
  303.   MN_MSGMAP(xfeCmdShowBriefHeaders, MSG_ShowMicroHeaders);
  304.   MN_MSGMAP(xfeCmdShowAllMessages, MSG_ShowAllMessages);
  305.   MN_MSGMAP(xfeCmdShowOnlyUnreadMessages, MSG_ShowOnlyUnreadMessages);
  306.   MN_MSGMAP(xfeCmdSortBackward, MSG_SortBackward);
  307.   MN_MSGMAP(xfeCmdSortByDate, MSG_SortByDate);
  308.   MN_MSGMAP(xfeCmdSortByMessageNumber, MSG_SortByMessageNumber);
  309.   MN_MSGMAP(xfeCmdSortByPriority, MSG_SortByPriority);
  310.   MN_MSGMAP(xfeCmdSortBySender, MSG_SortBySender);
  311.   MN_MSGMAP(xfeCmdSortBySubject, MSG_SortBySubject);
  312.   MN_MSGMAP(xfeCmdSortByThread, MSG_SortByThread);
  313.   MN_MSGMAP(xfeCmdSortBySize, MSG_SortBySize);
  314.   MN_MSGMAP(xfeCmdSortByStatus, MSG_SortByStatus);
  315.   MN_MSGMAP(xfeCmdSortByFlag, MSG_SortByFlagged);
  316.   MN_MSGMAP(xfeCmdSortByUnread, MSG_SortByUnread);
  317.   MN_MSGMAP(xfeCmdToggleKilledThreads, MSG_ViewKilledThreads);
  318.   MN_MSGMAP(xfeCmdToggleMessageRead, MSG_ToggleMessageRead);
  319.   MN_MSGMAP(xfeCmdToggleSubscribe, MSG_ToggleSubscribed); // subscribe ui only.
  320.   MN_MSGMAP(xfeCmdToggleThreadKilled, MSG_ToggleThreadKilled);
  321.   MN_MSGMAP(xfeCmdToggleThreadWatched, MSG_ToggleThreadWatched);
  322.   MN_MSGMAP(xfeCmdUndo, MSG_Undo);
  323.   MN_MSGMAP(xfeCmdUnmarkMessage, MSG_UnmarkMessages);
  324.   MN_MSGMAP(xfeCmdUnsubscribe, MSG_Unsubscribe);
  325.   MN_MSGMAP(xfeCmdViewAllThreads, MSG_ViewAllThreads);
  326.   MN_MSGMAP(xfeCmdViewAttachmentsAsLinks, MSG_AttachmentsAsLinks);
  327.   MN_MSGMAP(xfeCmdViewAttachmentsInline, MSG_AttachmentsInline);
  328.   MN_MSGMAP(xfeCmdViewNew, MSG_ViewNewOnly);
  329.   MN_MSGMAP(xfeCmdViewThreadsWithNew, MSG_ViewThreadsWithNew);
  330.   MN_MSGMAP(xfeCmdViewWatchedThreadsWithNew, MSG_ViewWatchedThreadsWithNew);
  331.   MN_MSGMAP(xfeCmdWrapLongLines, MSG_WrapLongLines);
  332.   MN_MSGMAP(xfeCmdEditConfiguration, MSG_ManageMailAccount);
  333.   MN_MSGMAP(xfeCmdModerateDiscussion, MSG_ModerateNewsgroup);
  334. #undef BEGIN_MN_MSG_MAP
  335. #undef MN_MSG_MAP
  336.  
  337.   return msg_cmd;
  338. }
  339.  
  340. MSG_PRIORITY
  341. XFE_MNView::commandToPriority(CommandType cmd)
  342. {
  343.   MSG_PRIORITY priority = MSG_PriorityNotSet;
  344.  
  345. #define BEGIN_MN_PRI_MAP() if (0)
  346. #define MN_PRIMAP(the_cmd, the_priority) else if (cmd == (the_cmd)) priority = (the_priority)
  347.  
  348.   BEGIN_MN_PRI_MAP();
  349.   MN_PRIMAP(xfeCmdSetPriorityHighest, MSG_HighestPriority);
  350.   MN_PRIMAP(xfeCmdSetPriorityHigh, MSG_HighPriority);
  351.   MN_PRIMAP(xfeCmdSetPriorityNormal, MSG_NormalPriority);
  352.   MN_PRIMAP(xfeCmdSetPriorityLow, MSG_LowPriority);
  353.   MN_PRIMAP(xfeCmdSetPriorityLowest, MSG_LowestPriority);
  354.  
  355. #undef BEGIN_MN_MSG_MAP
  356. #undef MN_MSG_MAP
  357.  
  358.   return priority;
  359. }
  360.  
  361. char *
  362. XFE_MNView::priorityToString(MSG_PRIORITY priority)
  363. {
  364.   switch (priority)
  365.     {
  366.     case MSG_PriorityNotSet:
  367.     case MSG_NoPriority:
  368.     case MSG_NormalPriority:
  369.       return "";
  370.     case MSG_HighPriority:
  371.       return XP_GetString(XFE_MAIL_PRIORITY_HIGH);
  372.     case MSG_LowestPriority:
  373.       return XP_GetString(XFE_MAIL_PRIORITY_LOWEST);
  374.     case MSG_LowPriority:
  375.       return XP_GetString(XFE_MAIL_PRIORITY_LOW);
  376.     case MSG_HighestPriority:
  377.       return XP_GetString(XFE_MAIL_PRIORITY_HIGHEST);
  378.     default:
  379.       XP_ASSERT(0);
  380.       return 0;
  381.     }
  382. }
  383.  
  384. char *
  385. XFE_MNView::commandToString(CommandType cmd, void * calldata, XFE_CommandInfo* info)
  386. {
  387. #define IS_CMD(command) cmd == (command)  
  388.     if (IS_CMD(xfeCmdNewFolder)) 
  389.         {
  390.             if (m_displayingNewsgroup)
  391.                 return stringFromResource("newCategoryCmdString");
  392.             else
  393.                 return stringFromResource("newFolderCmdString");
  394.         }
  395.     else if (IS_CMD(xfeCmdDeleteMessage)) 
  396.         {
  397.             if (m_displayingNewsgroup)
  398.                 return stringFromResource("cancelMessageCmdString");
  399.             else
  400.                 return stringFromResource("deleteMessageCmdString");
  401.         }
  402.     else if (IS_CMD(xfeCmdNextCollection)) 
  403.         {
  404.             if (m_displayingNewsgroup)
  405.                 return stringFromResource("nextDiscussionCmdString");
  406.             else
  407.                 return stringFromResource("nextFolderCmdString");
  408.         }
  409.     else if (IS_CMD(xfeCmdNextUnreadCollection)) 
  410.         {
  411.             if (m_displayingNewsgroup)
  412.                 return stringFromResource("nextUnreadDiscussionCmdString");
  413.             else
  414.                 return stringFromResource("nextUnreadFolderCmdString");
  415.         }
  416.     else if (IS_CMD(xfeCmdGetNextNNewMsgs)) 
  417.       {
  418.           static char buf[100];
  419.           int32 num;
  420.  
  421.           if (PREF_GetIntPref("news.max_articles", &num) < 0) {
  422.             // Bad pref read, so make something up
  423.             num = 500;
  424.           }
  425.  
  426.           PR_snprintf(buf, sizeof(buf), XP_GetString(XFE_GET_NEXT_N_MSGS), num);
  427.  
  428.           return buf;
  429.       }
  430.     else
  431.         return XFE_View::commandToString(cmd, calldata, info);
  432.         
  433. #undef IS_CMD
  434. }
  435.  
  436. void
  437. XFE_MNView::markReadByDate()
  438. {
  439.     char *date;
  440.     char cur_date_buf[9];
  441.     struct tm *current_tm;
  442.     time_t entered_time;
  443.     time_t foo;
  444.     
  445.     foo = time(NULL);
  446.     current_tm = localtime(&foo);
  447.     
  448.     PR_snprintf (cur_date_buf, sizeof(cur_date_buf), "%02d/%02d/%02d",
  449.                  current_tm->tm_mon + 1,
  450.                  current_tm->tm_mday,
  451.                  current_tm->tm_year);
  452.     
  453.     date = XFE_PromptWithCaption(m_contextData, 
  454.                                  /* get title from resources
  455.                                   */
  456.                                  "markMessagesRead",
  457.                                  XP_GetString(XFE_MARKBYDATE),
  458.                                  cur_date_buf);
  459.     
  460.     if (date)
  461.         {
  462.             entered_time = XP_ParseTimeString(date, False);
  463.             
  464.             if (!entered_time)
  465.                 {
  466.                     FE_Alert(m_contextData, XP_GetString(XFE_DATE_MUST_BE_MM_DD_YY));
  467.                 }
  468.             else
  469.                 {
  470.                     MSG_MarkReadByDate(m_pane, 0, entered_time);
  471.                 }
  472.         }
  473.     
  474.     if (fe_IsContextDestroyed(m_contextData)) 
  475.         {
  476.             XP_FREE(CONTEXT_DATA(m_contextData));
  477.             XP_FREE(m_contextData);
  478.         }
  479. }
  480.  
  481. void
  482. XFE_MNView::getNewNews()
  483. {
  484.     int status;
  485.     const char *string = 0;
  486.     XP_Bool selectable_p = FALSE;
  487.     MSG_COMMAND_CHECK_STATE selected_p = MSG_NotUsed;
  488.  
  489.     status = MSG_CommandStatus (m_pane,
  490.                                 MSG_GetNextChunkMessages, NULL, 0,
  491.                                 &selectable_p, &selected_p,
  492.                                 &string, 0);
  493.  
  494.     if (status < 0 || !selectable_p)
  495.         return;
  496.  
  497.     XFE_MailDownloadFrame *download_frame = 
  498.         new XFE_MailDownloadFrame(XtParent(getToplevel()->getBaseWidget()),
  499.                                   ViewGlue_getFrame(m_contextData),
  500.                                   m_pane);
  501.     
  502.     download_frame->startNewsDownload();
  503. }
  504.  
  505. void
  506. XFE_MNView::getNewMail()
  507. {
  508.   int status;
  509.   const char *string = 0;
  510.   XP_Bool selectable_p = FALSE;
  511.   MSG_COMMAND_CHECK_STATE selected_p = MSG_NotUsed;
  512.  
  513.   if ( fe_globalPrefs.use_movemail_p &&
  514.        fe_globalPrefs.movemail_warn &&
  515.        !fe_MovemailWarning(getContext()) ) return;
  516.  
  517.   status = MSG_CommandStatus (m_pane,
  518.                   MSG_GetNewMail, NULL, 0,
  519.                               &selectable_p, &selected_p,
  520.                               &string, 0);
  521.  
  522.   if (status < 0 || !selectable_p)
  523.     return;
  524.  
  525.   if (!fe_globalPrefs.use_movemail_p)
  526.     {
  527.         XFE_MailDownloadFrame *download_frame = 
  528.             new XFE_MailDownloadFrame(XtParent(getToplevel()->getBaseWidget()),
  529.                                       ViewGlue_getFrame(m_contextData),
  530.                                       m_pane);
  531.         
  532.         download_frame->startDownload();
  533.     }
  534.   else
  535.     {
  536.       /* Use movemail to get the mail out of the spool area and into
  537.      our home directory, and then read out of the resultant file
  538.      (without locking.)
  539.      */
  540.       char *mailbox;
  541.       char *s;
  542.       XP_File file;
  543.       XP_StatStruct st;
  544.       fe_mn_incstate* state = 0;
  545.       
  546.       /* First, prevent the user from assuming that `Leave on Server' will
  547.          work with movemail.  A better way to do this might be to change the
  548.          selection/sensitivity of the dialog buttons, but this will do.
  549.          (bug 11561)
  550.          */
  551.       if (fe_globalPrefs.pop3_leave_mail_on_server)
  552.     {
  553.       FE_Alert(m_contextData, XP_GetString(XFE_NO_KEEP_ON_SERVER_WITH_MOVEMAIL));
  554.       return;
  555.     }
  556.       
  557.       state = XP_NEW_ZAP(fe_mn_incstate);
  558.       if (!state) return;
  559.       state->context = m_contextData;
  560.       
  561.       /* If this doesn't exist, there's something seriously wrong */
  562.       XP_ASSERT (fe_globalPrefs.movemail_program);
  563.       
  564.       mailbox = fe_mn_getmailbox();
  565.       if(!mailbox)
  566.     {
  567.       FE_Alert(m_contextData, XP_GetString(XFE_MAIL_SPOOL_UNKNOWN));
  568.       return;
  569.     }
  570.       
  571.       s = (char *) MSG_GetFolderDirectory(MSG_GetPrefs(m_pane));
  572.       PR_snprintf (state->filename, sizeof (state->filename),
  573.            "%s/.netscape.mail-recovery", s);
  574.       
  575.       if (!stat (state->filename, &st))
  576.     {
  577.       if (st.st_size == 0)
  578.         /* zero length - a mystery. */
  579.         unlink (state->filename);
  580.       else
  581.         {
  582.           /* The crashbox already exists - that means we didn't delete it
  583.          last time, possibly because we crashed.  So, read it now.
  584.          */
  585.           file = fopen (state->filename, "r");
  586.           if (!file)
  587.         {
  588.           char buf[1024];
  589.           PR_snprintf (buf, sizeof (buf), XP_GetString( XFE_UNABLE_TO_OPEN ),
  590.                    state->filename);
  591.           fe_perror (m_contextData, buf);
  592.           return;
  593.         }
  594.           state->file = file;
  595.           state->wascrashbox = TRUE;
  596.           MSG_IncorporateFromFile (m_pane, file, fe_incdone, state);
  597.           return;
  598.         }
  599.     }
  600.       
  601.       /* Now move mail into the tmp file.
  602.        */
  603.       if (fe_globalPrefs.builtin_movemail_p)
  604.     {
  605.       if (!fe_MoveMail (m_contextData, mailbox, state->filename))
  606.         {
  607.           return;
  608.         }
  609.     }
  610.       else
  611.     {
  612.       if (!fe_run_movemail (m_contextData, mailbox, state->filename))
  613.         return;
  614.     }
  615.       
  616.       /* Now move the mail from the crashbox to the folder.
  617.        */
  618.       file = fopen (state->filename, "r");
  619.       if (file)
  620.     {
  621.       state->file = file;
  622.       MSG_IncorporateFromFile(m_pane, file, fe_incdone, state);
  623.     }
  624.     }
  625. }
  626.  
  627. void 
  628. XFE_MNView::paneChanged(XP_Bool /*asynchronous*/,
  629.                         MSG_PANE_CHANGED_NOTIFY_CODE notify_code,
  630.                         int32 /*value*/)
  631. {
  632.   notifyInterested(XFE_MNView::bannerNeedsUpdating, (void*)notify_code);
  633. }
  634.  
  635. MSG_Master *
  636. XFE_MNView::getMaster()
  637. {
  638.   if (m_master == NULL)
  639.     {
  640.       //      XFE_MNView::m_prefs = MSG_CreatePrefs();
  641.       m_master = MSG_InitializeMail(fe_mailNewsPrefs);
  642.     }
  643.  
  644.   return m_master;
  645. }
  646.  
  647. void
  648. XFE_MNView::destroyMasterAndShutdown()
  649. {
  650.     MWContext *biffcontext = XP_FindContextOfType(NULL, MWContextBiff);
  651.     XP_ASSERT(biffcontext);
  652.     MSG_BiffCleanupContext(biffcontext);
  653.  
  654.   if (m_master)
  655.     MSG_DestroyMaster(m_master);
  656.  
  657.   MSG_ShutdownMsgLib();
  658. }
  659.  
  660. XP_Bool
  661. XFE_MNView::isDisplayingNews()
  662. {
  663.   return m_displayingNewsgroup;
  664. }
  665.  
  666. Boolean
  667. XFE_MNView::handlesCommand(CommandType cmd, void* calldata, XFE_CommandInfo* )
  668. {
  669. #define IS_CMD(command) cmd == (command)
  670. if (  IS_CMD(xfeCmdComposeMessage)
  671.       || IS_CMD(xfeCmdComposeMessageHTML)
  672.       || IS_CMD(xfeCmdComposeMessagePlain)
  673.       || IS_CMD(xfeCmdComposeArticle)
  674.       || IS_CMD(xfeCmdComposeArticleHTML)
  675.       || IS_CMD(xfeCmdComposeArticlePlain)
  676.       || IS_CMD(xfeCmdEditConfiguration) 
  677.       || IS_CMD(xfeCmdModerateDiscussion) )
  678.     return True;
  679. else if (IS_CMD(xfeCmdCleanUpDisk))
  680.     return True;
  681. else
  682.    {
  683.     return XFE_View::handlesCommand(cmd, calldata);
  684.    }
  685. #undef IS_CMD
  686. }
  687.  
  688. void
  689. XFE_MNView::doCommand(CommandType cmd, void *calldata, XFE_CommandInfo* info)
  690. {
  691.   if ( (cmd == xfeCmdComposeMessage) 
  692.     || (cmd == xfeCmdComposeArticle) )
  693.   {
  694.         if (info) {
  695.                                   CONTEXT_DATA(m_contextData)->stealth_cmd =
  696.                                           ((info->event->type == ButtonRelease) &&
  697.                                            (info->event->xkey.state & ShiftMask));
  698.                           }
  699.  
  700.             MSG_Command(m_pane, commandToMsgCmd(cmd), NULL, 0);
  701.    }
  702.    else if ( (cmd == xfeCmdComposeMessageHTML) 
  703.         || (cmd == xfeCmdComposeArticleHTML) )
  704.  
  705.    {
  706.             CONTEXT_DATA(m_contextData)->stealth_cmd = (fe_globalPrefs.send_html_msg == False);
  707.             MSG_Command(m_pane, commandToMsgCmd(cmd), NULL, 0);
  708.    }
  709.    else if ( (cmd == xfeCmdComposeMessagePlain)
  710.         || (cmd == xfeCmdComposeArticlePlain) )
  711.    {
  712.             CONTEXT_DATA(m_contextData)->stealth_cmd = (fe_globalPrefs.send_html_msg == True) ;
  713.             MSG_Command(m_pane, commandToMsgCmd(cmd), NULL, 0);
  714.    }
  715.    else if (cmd == xfeCmdCleanUpDisk)
  716.    {
  717.        if (MSG_CleanupNeeded(getMaster()))
  718.        {
  719.            // create progress pane
  720.            XFE_MailDownloadFrame* progressFrame = 
  721.                new XFE_MailDownloadFrame(XfeAncestorFindApplicationShell(getBaseWidget()),
  722.                                          ViewGlue_getFrame(m_contextData),
  723.                                          getPane());
  724.            progressFrame->cleanUpNews();
  725.        }
  726.    }
  727.    else 
  728.    {
  729.     XFE_View::doCommand(cmd, calldata, info);
  730.    }
  731.  
  732.  
  733. }
  734.  
  735. MSG_BIFF_STATE
  736. XFE_MNView::getBiffState()
  737. {
  738.   return m_biffstate;
  739. }
  740.  
  741. void
  742. XFE_MNView::setBiffState(MSG_BIFF_STATE state)
  743. {
  744.   m_biffstate = state;
  745. }
  746.  
  747. //////////////////////////////////////////////////////////////////////////
  748. XFE_CALLBACK_DEFN(XFE_MNView, updateBiffState)(XFE_NotificationCenter*,
  749.                         void *, void*cd)
  750. {
  751.   MSG_BIFF_STATE state = (MSG_BIFF_STATE)cd;
  752.  
  753.   // Update the desktop mail icons
  754.   fe_InitIcons(m_contextData, state);
  755. }
  756. //////////////////////////////////////////////////////////////////////////
  757.  
  758.  
  759. extern "C" void
  760. FE_PaneChanged(MSG_Pane *pane, XP_Bool asynchronous,
  761.                MSG_PANE_CHANGED_NOTIFY_CODE code, int32 value)
  762. {
  763.  
  764.   XFE_MNView *view = (XFE_MNView*)MSG_GetFEData(pane);
  765.  
  766.   if (view)
  767.     view->paneChanged(asynchronous, code, value);
  768.  
  769. //  MSG_HandlePaneChangedNotifications(pane, asynchronous, code, value);
  770. }
  771.  
  772. #endif  // MOZ_MAIL_NEWS
  773.  
  774.  
  775. #ifdef MOZ_MAIL_NEWS
  776.  
  777. extern "C" void
  778. FE_UpdateBiff(MSG_BIFF_STATE state)
  779. {
  780.   XFE_MNView::setBiffState(state);
  781.   XFE_MozillaApp::theApp()->notifyInterested(XFE_MozillaApp::biffStateChanged,
  782.                          (void*)state);
  783. }
  784.  
  785. extern "C" void
  786. FE_UpdateToolbar (MWContext *context)
  787. {
  788.   XFE_Frame *f = ViewGlue_getFrame(context);
  789.  
  790.   if (f)
  791.     f->notifyInterested(XFE_View::chromeNeedsUpdating, NULL);
  792. }
  793.  
  794. extern "C" void
  795. FE_UpdateCompToolbar(MSG_Pane* comppane)
  796. {
  797.   XFE_MNView *v = (XFE_MNView*)MSG_GetFEData(comppane);
  798.  
  799.   if (v) {
  800.       v->updateCompToolbar();
  801.       v->getToplevel()->notifyInterested(XFE_View::chromeNeedsUpdating, NULL);
  802.   }
  803. }
  804.  
  805. extern "C" {
  806.     MSG_Pane *fe_showCompose(Widget, Chrome *, MWContext *, MSG_CompositionFields*, const char *, MSG_EditorType editorType,XP_Bool defaultAddressIsNewsgroup);
  807.  
  808.     MSG_Pane *
  809.     FE_CreateCompositionPane(MWContext* old_context,
  810.                              MSG_CompositionFields* fields,
  811.                              const char* initialText,
  812.                              MSG_EditorType editorType)
  813.     {
  814.  
  815.       const char *real_addr = FE_UsersMailAddress();
  816.  
  817.       if ( MISC_ValidateReturnAddress(old_context, real_addr) < 0 )
  818.     return NULL;
  819.  
  820.       MSG_Pane* pane = fe_showCompose(XtParent(CONTEXT_WIDGET(old_context)),
  821.                                       NULL,
  822.                                       old_context, /* required for XP to retrieve url info */ 
  823.                                       fields, initialText, editorType, False);
  824.  
  825.       return pane; /* return NULL would be okay ?! */
  826.     }
  827. }
  828.  
  829. extern "C" void
  830. FE_DestroyMailCompositionContext(MWContext* context)
  831. {
  832.   XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  833.   XFE_ComposeFrame *cf;
  834.  
  835.   XP_ASSERT (f->getType() == FRAME_MAILNEWS_COMPOSE);
  836.  
  837.   cf = (XFE_ComposeFrame*)f;
  838.  
  839.   cf->destroyWhenAllConnectionsComplete();
  840. }
  841.  
  842. extern "C" MWContext*
  843. FE_GetAddressBookContext(MSG_Pane* pane, XP_Bool /*viewnow*/)
  844. {
  845.   return MSG_GetContext(pane);
  846. }
  847.  
  848. extern "C" const char*
  849. FE_GetFolderDirectory(MWContext* /*context*/)
  850. {
  851.   XP_ASSERT (fe_globalPrefs.mail_directory);
  852.   return fe_globalPrefs.mail_directory;
  853. }
  854.  
  855. extern "C" void
  856. FE_ListChangeStarting(MSG_Pane* pane, XP_Bool asynchronous,
  857.               MSG_NOTIFY_CODE notify, MSG_ViewIndex where, int32 num)
  858. {
  859.   XFE_MNListView *list_view;
  860.   XFE_Outliner *outliner;
  861.   //  int numsel;
  862.   //  MSG_ViewIndex *sellist;
  863.  
  864.   list_view = (XFE_MNListView*)MSG_GetFEData(pane);
  865.  
  866.   if (!list_view)
  867.     return;
  868.  
  869.   MSG_PaneType paneType = MSG_GetPaneType(pane);
  870.   if (paneType == MSG_THREADPANE &&
  871.       (notify == MSG_NotifyScramble ||
  872.        notify == MSG_NotifyAll)) {
  873.       XFE_ThreadView *threadView = (XFE_ThreadView *) list_view;
  874.       threadView->listChangeStarting(asynchronous, notify, where, num);
  875.   }/* else if */
  876.  
  877.   outliner = list_view->getOutliner();
  878.  
  879.   if (!outliner)
  880.     return;
  881.  
  882.   outliner->listChangeStarting(asynchronous, notify, where, num, MSG_GetNumLines(pane));
  883. }
  884.  
  885. void
  886. FE_ListChangeFinished(MSG_Pane* pane, XP_Bool asynchronous,
  887.               MSG_NOTIFY_CODE notify, MSG_ViewIndex where, int32 num)
  888. {
  889.   XFE_MNListView *list_view;
  890.   XFE_Outliner *outliner;
  891.   //  int numsel;
  892.   //  MSG_ViewIndex *sellist;
  893.  
  894.   list_view = (XFE_MNListView*)MSG_GetFEData(pane);
  895.  
  896.   //
  897.   // restore this quote out: use pane type to prevent mail/news pane 
  898.   // get into this flow wrongfully
  899.   //
  900.   if (!list_view)
  901.     return;
  902.  
  903.   MSG_PaneType paneType = MSG_GetPaneType(pane);
  904.   if (notify == MSG_NotifyInsertOrDelete) {
  905.       if (paneType == MSG_ADDRPANE) {
  906.           XFE_ABListSearchView *abView = (XFE_ABListSearchView *) list_view;
  907.           if (abView->isSearching())
  908.               /* Tao_12dec96
  909.                * Added for LDAP search in AddrBook
  910.                */
  911.  
  912. #if defined(USE_ABCOM)
  913.               {
  914.               int error = AB_LDAPSearchResultsAB2(pane,
  915.                                                   where, num);
  916.               }
  917. #else
  918.               AB_LDAPSearchResults((ABPane*)pane, where, num);
  919. #endif /* USE_ABCOM */
  920.       }/* if */
  921.       else if (paneType == MSG_THREADPANE
  922. #if !defined(DEL_5_0)
  923.                /* let them all fall through 
  924.                 */
  925.                && num <= 0
  926. #endif /* DEL_5_0 */
  927.                ) {
  928.           /* we do this hack :
  929.            * 1. to make our code concise; only threadview need to handle this
  930.            *    currently.
  931.            * 2. need to deal with general cases when the time comes!
  932.            */
  933.           XFE_ThreadView *threadView = (XFE_ThreadView *) list_view;
  934.           threadView->listChangeFinished(asynchronous, notify, where, num);
  935.       }/* else threadPane */
  936.   }/* if */
  937.   else if (paneType == MSG_THREADPANE &&
  938.            (notify == MSG_NotifyChanged ||
  939.             notify == MSG_NotifyScramble ||
  940.             notify == MSG_NotifyAll)) {
  941.       XFE_ThreadView *threadView = (XFE_ThreadView *) list_view;
  942.       threadView->listChangeFinished(asynchronous, notify, where, num);
  943.   }/* else if */
  944.  
  945.   outliner = list_view->getOutliner();
  946.  
  947.   if (!outliner)
  948.     return;
  949.  
  950.   if (notify == MSG_NotifyNone)
  951.   {
  952.   }
  953.  
  954.   outliner->listChangeFinished(asynchronous, notify, where, num, MSG_GetNumLines(pane));
  955. }
  956.  
  957. MSG_Master *
  958. fe_getMNMaster()
  959. {
  960.   return XFE_MNView::getMaster();
  961. }
  962.  
  963. static void
  964. fe_incdone(void* closure, XP_Bool result)
  965. {
  966.   fe_mn_incstate* state = (fe_mn_incstate*) closure;
  967.   XFE_Frame *f = ViewGlue_getFrame(state->context);
  968.   if (result) {
  969.     unlink(state->filename);
  970.     if (state->file) {
  971.       fclose(state->file);
  972.       state->file = NULL;
  973.     }
  974.     if (state->wascrashbox) {
  975.       CommandType cmd = xfeCmdGetNewMessages;
  976.       if (f
  977.       && f->handlesCommand(cmd))
  978.     f->doCommand(cmd);
  979.     } else {
  980.       FE_UpdateBiff(MSG_BIFF_NoMail);
  981.       // XXX hack to get the pending command stuff to execute.  We need to fake
  982.       // an allConnectionsComplete message here, since the backend doesn't notify
  983.       // us.
  984.       f->notifyInterested(XFE_Frame::allConnectionsCompleteCallback);
  985.     }
  986.   }
  987.   XP_FREE(state);
  988. }
  989.  
  990. extern "C" char*
  991. fe_mn_getmailbox(void)
  992. {
  993.   static char* mailbox = NULL;
  994.   if (mailbox == NULL) {
  995.     mailbox = getenv("MAIL");
  996.     if (mailbox && *mailbox)
  997.       {
  998.     /* Bug out if $MAIL is set to something silly: obscenely long,
  999.        or not an absolute path.  Returning 0 will cause the error
  1000.        message about "please set $MAIL ..." to be shown.
  1001.      */
  1002.     if (strlen(mailbox) >= 1024) /* NAME_LEN */
  1003.       mailbox = 0;
  1004.     else if (mailbox[0] != '/')
  1005.       mailbox = 0;
  1006.     else
  1007.       mailbox = strdup(mailbox);   /* copy result of getenv */
  1008.       }
  1009.     else
  1010.       {
  1011.     static const char *heads[] = {
  1012.       "/var/spool/mail",
  1013.       "/usr/spool/mail",
  1014.       "/var/mail",
  1015.       "/usr/mail",
  1016.       0 };
  1017.     const char **head = heads;
  1018.     while (*head)
  1019.       {
  1020.         struct stat st;
  1021.         if (!stat (*head, &st) && S_ISDIR(st.st_mode))
  1022.           break;
  1023.         head++;
  1024.       }
  1025.     if (*head)
  1026.       {
  1027.         char *uid = 0, *name = 0;
  1028.         fe_DefaultUserInfo (&uid, &name, True);
  1029.         if(uid && *uid)
  1030.           mailbox = PR_smprintf("%s/%s", *head, uid);
  1031.         if(uid) XP_FREE(uid);
  1032.         if(name) XP_FREE(name);
  1033.       }
  1034.       }
  1035.   }
  1036.   return mailbox;
  1037. }
  1038.  
  1039. static XP_Bool
  1040. fe_run_movemail (MWContext *context, const char *from, const char *to)
  1041. {
  1042.   struct sigaction newact, oldact;
  1043.   pid_t forked;
  1044.   int ac = 0;
  1045.   char **av = (char **) malloc (10 * sizeof (char *));
  1046.   av [ac++] = strdup (fe_globalPrefs.movemail_program);
  1047.   av [ac++] = strdup (from);
  1048.   av [ac++] = strdup (to);
  1049.   av [ac++] = 0;
  1050.  
  1051.   /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
  1052.   sigaction(SIGCHLD, NULL, &oldact);
  1053.  
  1054. #if (defined(SOLARIS) && defined(SOLARIS_24) && defined(NS_USE_NATIVE)) || (defined UNIXWARE)
  1055.   // Native Solaris2.4, Unixware.
  1056.   newact.sa_handler = (void (*)())SIG_DFL;
  1057. #elif (defined(SOLARIS) && !defined(NS_USE_NATIVE))
  1058.   // Solaris g++
  1059.   newact.sa_handler = (void (*)(...))SIG_DFL;
  1060. #else
  1061.   // Default. Native Solaris 2.5, IRIX, HPUX.  
  1062.   newact.sa_handler = SIG_DFL;
  1063. #endif
  1064.  
  1065.   newact.sa_flags = 0;
  1066.   sigfillset(&newact.sa_mask);
  1067.   sigaction (SIGCHLD, &newact, NULL);
  1068.  
  1069.   errno = 0;
  1070.   switch (forked = fork ())
  1071.     {
  1072.     case -1:
  1073.       while (--ac >= 0)
  1074.     free (av [ac]);
  1075.       free (av);
  1076.       /* fork() failed (errno is meaningful.) */
  1077.       fe_perror (context, XP_GetString( XFE_COULDNT_FORK_FOR_MOVEMAIL ) );
  1078.       /* Reset SIGCHLD handler before returning */
  1079.       sigaction (SIGCHLD, &oldact, NULL);
  1080.       return FALSE;
  1081.     case 0:
  1082.       {
  1083.     execvp (av[0], av);
  1084.     exit (-1);    /* execvp() failed (this exits the child fork.) */
  1085.     return FALSE; // not reached, but needed to shut the compiler up.
  1086.       }
  1087.     default:
  1088.       {
  1089.     /* This is the "old" process (subproc pid is in `forked'.) */
  1090.     char buf [2048];
  1091.     int status = 0;
  1092.     pid_t waited_pid;
  1093.  
  1094.     while (--ac >= 0)
  1095.       free (av [ac]);
  1096.     free (av);
  1097.  
  1098.     /* wait for the other process (and movemail) to terminate. */
  1099.     waited_pid = waitpid (forked, &status, 0);
  1100.  
  1101.     /* Reset the SIG CHILD signal handler */
  1102.     sigaction(SIGCHLD, &oldact, NULL);
  1103.  
  1104.     if (waited_pid <= 0 || waited_pid != forked)
  1105.       {
  1106.         /* We didn't fork properly, or something.  Let's hope errno
  1107.            has a meaningful value... (can it?) */
  1108.         PR_snprintf (buf, sizeof (buf), XP_GetString( XFE_PROBLEMS_EXECUTING ),
  1109.              fe_globalPrefs.movemail_program);
  1110.         fe_perror (context, buf);
  1111.         return FALSE;
  1112.       }
  1113.  
  1114.     if (!WIFEXITED (status))
  1115.       {
  1116.         /* Dumped core or was killed or something.  Let's hope errno
  1117.            has a meaningful value... (can it?) */
  1118.         PR_snprintf (buf, sizeof (buf),
  1119.          XP_GetString( XFE_TERMINATED_ABNORMALLY ),
  1120.          fe_globalPrefs.movemail_program);
  1121.         fe_perror (context, buf);
  1122.         return FALSE;
  1123.       }
  1124.  
  1125.     if (WEXITSTATUS (status) != 0)
  1126.       {
  1127.         PR_snprintf (buf, sizeof (buf), XP_GetString( XFE_APP_EXITED_WITH_STATUS ),
  1128.              fe_globalPrefs.movemail_program,
  1129.              WEXITSTATUS (status));
  1130.         FE_Alert (context, buf);
  1131.         return FALSE;
  1132.       }
  1133.     /* Else, exited with code 0 */
  1134.     return TRUE;
  1135.       }
  1136.     }
  1137. }
  1138.  
  1139. /* If we're set up to deliver mail/news by running a program rather
  1140.    than by talking to SMTP/NNTP, this does it.
  1141.  
  1142.    Returns positive if delivery via program was successful;
  1143.    Returns negative if delivery failed;
  1144.    Returns 0 if delivery was not attempted (in which case we
  1145.    should use SMTP/NNTP instead.)
  1146.  
  1147.    $NS_MSG_DELIVERY_HOOK names a program which is invoked with one argument,
  1148.    a tmp file containing a message.  (Lines are terminated with CRLF.)
  1149.    This program is expected to parse the To, CC, BCC, and Newsgroups headers,
  1150.    and effect delivery to mail and/or news.  It should exit with status 0
  1151.    iff successful.
  1152.  
  1153.    #### This really wants to be defined in libmsg, but it wants to
  1154.    be able to use fe_perror, so...
  1155.  */
  1156. extern "C" int
  1157. msg_DeliverMessageExternally(MWContext *context, const char *msg_file)
  1158. {
  1159.   struct sigaction newact, oldact;
  1160.   static char *cmd = 0;
  1161.   if (!cmd)
  1162.     {
  1163.       /* The first time we're invoked, look up the command in the
  1164.      environment.  Use "" as the `no command' tag. */
  1165.       cmd = getenv("NS_MSG_DELIVERY_HOOK");
  1166.       if (!cmd)
  1167.     cmd = "";
  1168.       else
  1169.     cmd = XP_STRDUP(cmd);
  1170.     }
  1171.  
  1172.   if (!cmd || !*cmd)
  1173.     /* No external command -- proceed with "normal" delivery. */
  1174.     return 0;
  1175.   else
  1176.     {
  1177.       pid_t forked;
  1178.       int ac = 0;
  1179.       char **av = (char **) malloc (10 * sizeof (char *));
  1180.       av [ac++] = XP_STRDUP (cmd);
  1181.       av [ac++] = XP_STRDUP (msg_file);
  1182.       av [ac++] = 0;
  1183.  
  1184.       /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
  1185.       sigaction(SIGCHLD, NULL, &oldact);
  1186.  
  1187. #if (defined(SOLARIS) && defined(SOLARIS_24) && defined(NS_USE_NATIVE)) || (defined UNIXWARE)
  1188.   // Native Solaris2.4, Unixware.
  1189.   newact.sa_handler = (void (*)())SIG_DFL;
  1190. #elif (defined(SOLARIS) && !defined(NS_USE_NATIVE))
  1191.   // g++
  1192.   newact.sa_handler = (void (*)(...))SIG_DFL;
  1193. #else
  1194.   // Native Solaris 2.5, IRIX, etc.
  1195.   newact.sa_handler = SIG_DFL;
  1196. #endif
  1197.  
  1198.       newact.sa_flags = 0;
  1199.       sigfillset(&newact.sa_mask);
  1200.       sigaction (SIGCHLD, &newact, NULL);
  1201.  
  1202.       errno = 0;
  1203.       switch (forked = fork ())
  1204.     {
  1205.     case -1:
  1206.       {
  1207.         while (--ac >= 0)
  1208.           XP_FREE (av [ac]);
  1209.         XP_FREE (av);
  1210.         /* fork() failed (errno is meaningful.) */
  1211.         fe_perror (context, XP_GetString( XFE_COULDNT_FORK_FOR_DELIVERY ));
  1212.         /* Reset SIGCHLD signal hander before returning */
  1213.         sigaction(SIGCHLD, &oldact, NULL);
  1214.         return -1;
  1215.       }
  1216.     case 0:
  1217.       {
  1218.         execvp (av[0], av);
  1219.         exit (-1);    /* execvp() failed (this exits the child fork.) */
  1220.         return -1; // not reached, but needed to shut the IRIX 6.2 compiler up
  1221.       }
  1222.     default:
  1223.       {
  1224.         /* This is the "old" process (subproc pid is in `forked'.) */
  1225.         char buf [2048];
  1226.         int status = 0;
  1227.         pid_t waited_pid;
  1228.         
  1229.         while (--ac >= 0)
  1230.           XP_FREE (av [ac]);
  1231.         XP_FREE (av);
  1232.  
  1233.         /* wait for the other process to terminate. */
  1234.         waited_pid = waitpid (forked, &status, 0);
  1235.  
  1236.         /* Reset SIG CHILD signal handler */
  1237.         sigaction(SIGCHLD, &oldact, NULL);
  1238.  
  1239.         if (waited_pid <= 0 || waited_pid != forked)
  1240.           {
  1241.         /* We didn't fork properly, or something.  Let's hope errno
  1242.            has a meaningful value... (can it?) */
  1243.         PR_snprintf (buf, sizeof (buf),
  1244.                  XP_GetString( XFE_PROBLEMS_EXECUTING ),
  1245.                  cmd);
  1246.         fe_perror (context, buf);
  1247.         return -1;
  1248.           }
  1249.  
  1250.         if (!WIFEXITED (status))
  1251.           {
  1252.         /* Dumped core or was killed or something.  Let's hope errno
  1253.            has a meaningful value... (can it?) */
  1254.         PR_snprintf (buf, sizeof (buf),
  1255.                  XP_GetString( XFE_TERMINATED_ABNORMALLY ),
  1256.                  cmd);
  1257.         fe_perror (context, buf);
  1258.         return -1;
  1259.           }
  1260.  
  1261.         if (WEXITSTATUS (status) != 0)
  1262.           {
  1263.         PR_snprintf (buf, sizeof (buf),
  1264.                  XP_GetString( XFE_APP_EXITED_WITH_STATUS ),
  1265.                  cmd,
  1266.                  WEXITSTATUS (status));
  1267.         FE_Alert (context, buf);
  1268.         return -1;
  1269.           }
  1270.         /* Else, exited with code 0 */
  1271.         return 1;
  1272.       }
  1273.     }
  1274.     }
  1275. }
  1276.  
  1277. extern "C" XP_Bool 
  1278. FE_NewsDownloadPrompt(MWContext *context,
  1279.                       int32 numMessagesToDownload,
  1280.                       XP_Bool *downloadAll)
  1281. {
  1282.     XFE_Frame *f = ViewGlue_getFrame(XP_GetNonGridContext(context));
  1283.     XP_Bool ret_val;
  1284.     XFE_NewsPromptDialog *dialog;
  1285.     if (!f)
  1286.         return False;
  1287.  
  1288.     dialog = new XFE_NewsPromptDialog(f->getBaseWidget(), numMessagesToDownload);
  1289.  
  1290.     ret_val = dialog->post();
  1291.  
  1292.     *downloadAll = dialog->getDownloadAll();
  1293.  
  1294.     delete dialog;
  1295.  
  1296.     return ret_val;
  1297. }
  1298.  
  1299. extern "C" MSG_Master*
  1300. FE_GetMaster() {
  1301.     return fe_getMNMaster();
  1302. }
  1303.  
  1304. #endif  // MOZ_MAIL_NEWS
  1305.