home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / mailmisc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  108.3 KB  |  3,966 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. #include "stdafx.h"
  20. #include "shcut.h"
  21. #include "msgcom.h"
  22. #include "msg_srch.h"
  23. #include "prefapi.h"
  24. #include "msgtmpl.h"
  25. #include "netsdoc.h"
  26. #include "mailmisc.h"
  27. #include "mailpriv.h"
  28. #include "msgview.h"
  29. #include "fldrfrm.h"
  30. #include "thrdfrm.h"
  31. #include "msgfrm.h"
  32. #include "wfemsg.h"
  33. #include "intl_csi.h"
  34. #include "fegui.h"
  35. #include "rdfglobal.h"
  36.  
  37. #ifndef _AFXDLL
  38. #undef new
  39. #endif
  40. IMPLEMENT_DYNCREATE(CFolderView, COutlinerView)
  41. #ifndef _AFXDLL
  42. #define new DEBUG_NEW
  43. #endif
  44.  
  45. #define COL_LEFT_MARGIN    ((m_cxChar+1)/2)
  46. #define EXTRATEXT_SIZE    128
  47.  
  48. extern "C" const char* FE_GetFolderDirectory(MWContext *pContext);
  49.  
  50. int WFE_MSGTranslateFolderIcon( uint8 level, int32 iFlags, BOOL bOpen )
  51. {
  52.     int folderTable[] = { IDX_MAILFOLDERCLOSED, IDX_MAILFOLDEROPEN,
  53.                           IDX_MAILFOLDERCLOSEDNEW, IDX_MAILFOLDEROPENNEW,
  54.                         // 4
  55.                           IDX_NEWSGROUP, IDX_NEWSGROUP,
  56.                           IDX_NEWSGROUP, IDX_NEWSGROUP,
  57.                         // 8
  58.                             IDX_LOCALMAIL, IDX_LOCALMAIL,
  59.                             IDX_LOCALMAIL, IDX_LOCALMAIL,
  60.                         // 12
  61.                           IDX_REMOTEMAIL, IDX_REMOTEMAIL,
  62.                           IDX_REMOTEMAIL, IDX_REMOTEMAIL,
  63.                         // 16
  64.                           IDX_NEWSHOST, IDX_NEWSHOST,
  65.                           IDX_NEWSHOST, IDX_NEWSHOST,
  66.                         // 20
  67.                           IDX_INBOXCLOSED, IDX_INBOXOPEN,
  68.                           IDX_INBOXCLOSEDNEW, IDX_INBOXOPENNEW,
  69.                         // 24
  70.                           IDX_OUTBOXCLOSED, IDX_OUTBOXOPEN,
  71.                           IDX_OUTBOXCLOSED, IDX_OUTBOXOPEN,
  72.                         // 28
  73.                           IDX_SENTCLOSED, IDX_SENTOPEN,
  74.                           IDX_SENTCLOSED, IDX_SENTOPEN,
  75.                         // 32
  76.                           IDX_DRAFTSCLOSED, IDX_DRAFTSOPEN,
  77.                           IDX_DRAFTSCLOSED, IDX_DRAFTSOPEN,
  78.                         // 36
  79.                           IDX_TRASH, IDX_TRASHOPEN,
  80.                           IDX_TRASH, IDX_TRASHOPEN,
  81.                         // 40
  82.                            IDX_TEMPLATE, IDX_TEMPLATEOPEN,
  83.                            IDX_TEMPLATE, IDX_TEMPLATEOPEN,
  84.                         };
  85.  
  86.     int idx = 0;
  87.  
  88.     if (iFlags & MSG_FOLDER_FLAG_NEWSGROUP)
  89.         idx = 4;
  90.     else if (level < 2)
  91.         if (iFlags & MSG_FOLDER_FLAG_NEWS_HOST)
  92.             idx = 16;
  93.         else if (iFlags & MSG_FOLDER_FLAG_IMAPBOX)
  94.             idx = 12;
  95.         else
  96.             idx = 8;
  97.     else
  98.         if (iFlags & MSG_FOLDER_FLAG_INBOX)
  99.             idx = 20;
  100.         else if (iFlags & MSG_FOLDER_FLAG_QUEUE)
  101.             idx = 24;
  102.         else if (iFlags & MSG_FOLDER_FLAG_DRAFTS)
  103.             idx = 32;
  104.         else if (iFlags & MSG_FOLDER_FLAG_TRASH )
  105.             idx = 36;
  106.         else if (iFlags & MSG_FOLDER_FLAG_SENTMAIL )
  107.             idx = 28;
  108.         else if (iFlags & MSG_FOLDER_FLAG_TEMPLATES )
  109.             idx = 40;
  110.         
  111.     idx += bOpen ? 1 : 0;
  112.     idx += iFlags & MSG_FOLDER_FLAG_GOT_NEW ? 2 : 0;
  113.  
  114.     return folderTable[idx];
  115. }
  116.  
  117. void WFE_MSGBuildMessagePopup( HMENU hmenu, BOOL bNews, BOOL bInHeaders )
  118. {
  119.     ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_REPLY, szLoadString( IDS_MENU_REPLY ) );
  120.     if ( bNews ) {
  121.         ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_POSTREPLY, szLoadString( IDS_MENU_POSTREPLY ) );
  122.         ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_POSTANDREPLY, szLoadString( IDS_MENU_POSTMAILREPLY ) );
  123.     } else {
  124.         ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_REPLYALL, szLoadString( IDS_MENU_REPLYALL ) );
  125.     }
  126.     ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_FORWARD, szLoadString( IDS_MENU_FORWARD ) );
  127.     ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_FORWARDQUOTED, szLoadString( IDS_MENU_FORWARDQUOTED ) );
  128.     ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  129.      
  130.     HMENU hAddMenu = ::CreatePopupMenu();
  131.     ::AppendMenu( hAddMenu, MF_STRING, ID_MESSAGE_ADDSENDER, szLoadString( IDS_POPUP_ADDSENDER ) );
  132.     ::AppendMenu( hAddMenu, MF_STRING, ID_MESSAGE_ADDALL, szLoadString( IDS_POPUP_ADDALL ) );
  133.     ::AppendMenu( hmenu, MF_STRING|MF_POPUP, (UINT) hAddMenu, szLoadString( IDS_POPUP_ADDTOADDRESSBOOK ) );
  134.     ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  135.  
  136.     if (bInHeaders) {
  137.         ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_KILL, szLoadString( IDS_POPUP_IGNORETHREAD ) );
  138.         ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_WATCH, szLoadString( IDS_POPUP_WATCHTHREAD ) );
  139.         ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  140.         if (!bNews) {
  141.              
  142.             HMENU hPriorityMenu = ::CreatePopupMenu();
  143.             ::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_LOWEST, szLoadString( IDS_POPUP_LOWEST ) );
  144.             ::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_LOW, szLoadString( IDS_POPUP_LOW ) );
  145.             ::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_NORMAL, szLoadString( IDS_POPUP_NORMAL ) );
  146.             ::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_HIGH, szLoadString( IDS_POPUP_HIGH ) );
  147.             ::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_HIGHEST, szLoadString( IDS_POPUP_HIGHEST ) );
  148.             ::AppendMenu( hmenu, MF_STRING|MF_POPUP, (UINT) hPriorityMenu, szLoadString( IDS_POPUP_PRIORITY ) );
  149.             ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  150.         }
  151.     }
  152.  
  153.     UINT nID = FIRST_MOVE_MENU_ID;
  154.     HMENU hFileMenu = CreatePopupMenu();
  155.     CMailNewsFrame::UpdateMenu( NULL, hFileMenu, nID );
  156.     ::AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT) hFileMenu, szLoadString( IDS_POPUP_FILE ) );
  157.     ::AppendMenu( hmenu, MF_STRING, CASTUINT(ID_EDIT_DELETEMESSAGE), 
  158.                   szLoadString( CASTUINT(bNews ? IDS_POPUP_CANCELMESSAGE : IDS_POPUP_DELETEMESSAGE )) );
  159.     ::AppendMenu( hmenu, MF_STRING, ID_FILE_SAVEMESSAGES, szLoadString( IDS_POPUP_SAVEMESSAGE ) );
  160.     ::AppendMenu( hmenu, MF_STRING, ID_FILE_PRINT, szLoadString( IDS_POPUP_PRINTMESSAGE ) );
  161. }
  162.  
  163. //////////////////////////////////////////////////////////////////////////////
  164. // CBiffCX
  165.  
  166. class CBiffCX: public CStubsCX
  167. {
  168. public:
  169.     CBiffCX(): CStubsCX(Network, MWContextBiff) {};
  170.     
  171.     virtual void DestroyContext();
  172. };
  173.  
  174. void CBiffCX::DestroyContext()
  175. {
  176.     MSG_BiffCleanupContext(GetContext());
  177.  
  178.     CStubsCX::DestroyContext();
  179. }
  180.  
  181. //////////////////////////////////////////////////////////////////////////////
  182. // CMessagePrefs
  183.  
  184. CMsgPrefs g_MsgPrefs;
  185.  
  186. #ifdef _WIN32
  187. static TCHAR lpszEventMailBeep[] = _T("AppEvents\\EventLabels\\MailBeep");
  188. static TCHAR lpszSchemeMailBeep[] = _T("AppEvents\\Schemes\\Apps\\.Default\\MailBeep");
  189. static TCHAR lpszCurrent[] = _T(".current");
  190. static TCHAR lpszChord[] = _T("chord.wav");
  191. #endif
  192. static char lpszSounds[] = "Sounds";
  193. static char lpszMailBeep[] = "MailBeep";
  194.  
  195. void WFE_MSGInit()
  196. {
  197. #ifdef _WIN32
  198.     if (sysInfo.m_bWin4) {
  199.         TCHAR szBuf[_MAX_PATH];
  200.         LONG lBufSize = _MAX_PATH;
  201.  
  202.         if ( ::RegQueryValue(HKEY_CURRENT_USER, lpszEventMailBeep, szBuf, &lBufSize) !=
  203.              ERROR_SUCCESS ) {
  204.             ::RegSetValue(HKEY_CURRENT_USER, lpszEventMailBeep, REG_SZ,
  205.                           szLoadString(IDS_MAILSOUND), _tcslen(szLoadString(IDS_MAILSOUND)));
  206.         }
  207.  
  208.         HKEY hkey;
  209.         if ( ::RegCreateKey(HKEY_CURRENT_USER, lpszSchemeMailBeep, &hkey) == 
  210.              ERROR_SUCCESS ) {
  211.             
  212.             lBufSize = _MAX_PATH;
  213.             if ( ::RegQueryValue(hkey, lpszCurrent, szBuf, &lBufSize) !=
  214.                  ERROR_SUCCESS ) {
  215.                 ::RegSetValue(hkey, lpszCurrent, REG_SZ,
  216.                               lpszChord, _tcslen(lpszChord));
  217.             }
  218.             ::RegCloseKey(hkey);
  219.         }
  220.     }
  221.     else
  222. #endif
  223.     {
  224.         char szBuf[_MAX_PATH * 2];
  225.         LONG lBufSize = _MAX_PATH * 2;
  226.         ::GetProfileString(lpszSounds, lpszMailBeep, szLoadString(IDS_MAILSOUND16), szBuf, lBufSize );
  227.         ::WriteProfileString(lpszSounds, lpszMailBeep, szBuf);
  228.     }    
  229.     g_MsgPrefs.Init();
  230. }
  231.  
  232. void WFE_MSGShutdown()
  233. {
  234.     MSG_DestroyMaster(WFE_MSGGetMaster());
  235.      MSG_ShutdownMsgLib();
  236.     g_MsgPrefs.Shutdown();
  237. }
  238.  
  239. MSG_Master* WFE_MSGGetMaster()
  240. {
  241.     return g_MsgPrefs.GetMaster();
  242. }
  243.  
  244. CMsgPrefs::CMsgPrefs()
  245. {
  246.     m_pMaster = NULL;
  247. }
  248.  
  249. PR_CALLBACK cbMsgPrefs(const char *prefName, void *pData)
  250. {
  251.     XP_Bool bPref;
  252.     char *pszPref = NULL;
  253.  
  254.     switch ((int) pData) {
  255.     case 0:
  256.         bPref= TRUE;
  257.         PREF_GetBoolPref("mailnews.reuse_thread_window", &bPref);
  258.         g_MsgPrefs.m_bThreadReuse = bPref;
  259.         break;
  260.  
  261.     case 1:
  262.         bPref= TRUE;
  263.         PREF_GetBoolPref("mailnews.reuse_message_window", &bPref);
  264.         g_MsgPrefs.m_bMessageReuse = bPref;
  265.         break;
  266.  
  267.     case 2:
  268.         bPref= TRUE;
  269.         PREF_GetBoolPref("mailnews.message_in_thread_window", &bPref);
  270.         g_MsgPrefs.m_bThreadPaneMaxed = !bPref;
  271.         break;
  272.  
  273.     case 3:
  274.         PREF_CopyCharPref("mail.directory", &pszPref);
  275.         if (pszPref)
  276.             g_MsgPrefs.m_csMailDir = pszPref;
  277.         break;
  278.  
  279.     case 4:
  280.         PREF_CopyCharPref("network.hosts.pop_server", &pszPref);
  281.         if (pszPref) {
  282.             g_MsgPrefs.m_csMailHost = pszPref;
  283.         }
  284.         break;
  285.  
  286.     case 5:
  287.         PREF_CopyCharPref("news.directory", &pszPref);
  288.         if (pszPref)
  289.             g_MsgPrefs.m_csNewsDir = pszPref;
  290.         break;
  291.  
  292.     case 6:
  293.         PREF_CopyCharPref("network.hosts.nntp_server", &pszPref);
  294.         if (pszPref) {
  295.             NET_SetNewsHost(pszPref);
  296.             g_MsgPrefs.m_csNewsHost = pszPref;
  297.         }
  298.         break;
  299.  
  300.     case 7:
  301.         PREF_CopyCharPref("mail.identity.useremail", &pszPref);
  302.         if (pszPref)
  303.             g_MsgPrefs.m_csUsersEmailAddr = pszPref;
  304.         break;
  305.  
  306.     case 8:
  307.         PREF_CopyCharPref("mail.identity.username", &pszPref);
  308.         if (pszPref)
  309.             g_MsgPrefs.m_csUsersFullName = pszPref;
  310.         break;
  311.  
  312.     case 9:
  313.         PREF_CopyCharPref("mail.identity.organization", &pszPref);
  314.         if (pszPref)
  315.             g_MsgPrefs.m_csUsersOrganization = pszPref;
  316.         break;
  317.  
  318.     case 10:
  319.         PREF_CopyCharPref("mail.signature_file", &pszPref);
  320.         if (pszPref) {
  321.             XP_FREEIF(g_MsgPrefs.m_pszUserSig);
  322.             g_MsgPrefs.m_pszUserSig = wfe_ReadUserSig(pszPref);
  323.         }
  324.         break;
  325.     case 11:
  326.         break;
  327.  
  328.     case 12:
  329.         {
  330.             for(CGenericFrame * f = theApp.m_pFrameList; f; f = f->m_pNext)
  331.                 f->PostMessage(WM_COMMAND, (WPARAM) ID_DONEGOINGOFFLINE, (LPARAM) 0);
  332.         }
  333.         break;
  334.  
  335.     default:
  336.         ASSERT(0);
  337.     }
  338.  
  339.     XP_FREEIF(pszPref);
  340.  
  341.     return PREF_NOERROR;
  342. }
  343.  
  344. void CMsgPrefs::Init()
  345. {
  346.     m_pFolderTemplate = new CFolderTemplate(IDR_MAILFRAME,  
  347.             RUNTIME_CLASS(CNetscapeDoc),
  348.             RUNTIME_CLASS(CFolderFrame),     // mail window
  349.             RUNTIME_CLASS(CFolderView));
  350.     m_pThreadTemplate = new CThreadTemplate(IDR_MAILTHREAD,  
  351.             RUNTIME_CLASS(CNetscapeDoc),
  352.             RUNTIME_CLASS(C3PaneMailFrame),  // 3 pane mail window
  353.             RUNTIME_CLASS(CMailNewsSplitter));
  354.     m_pMsgTemplate = new CMessageTemplate(IDR_MESSAGEFRAME,  
  355.             RUNTIME_CLASS(CNetscapeDoc),
  356.             RUNTIME_CLASS(CMessageFrame),     // mail message window
  357.             RUNTIME_CLASS(CMessageView));
  358.  
  359.     theApp.AddDocTemplate(m_pFolderTemplate);
  360.     theApp.AddDocTemplate(m_pThreadTemplate);
  361.     theApp.AddDocTemplate(m_pMsgTemplate);
  362.  
  363.     int32 prefInt = 0;
  364.     char *prefStr = NULL;
  365.     
  366.     // Set up mail directory (must be before creation of msg prefs)
  367.     CString msg = theApp.m_UserDirectory;
  368.     msg += "\\mail";
  369.     PREF_SetDefaultCharPref("mail.directory", msg);
  370.     PREF_CopyCharPref("mail.directory", &prefStr);
  371.     if (prefStr)
  372.         m_csMailDir = prefStr;
  373.     XP_FREEIF(prefStr);
  374.  
  375.     // Initialize the message library 
  376.     MSG_InitMsgLib();
  377.  
  378.     // Create the MSG lib pref structure
  379.     m_pMsgPrefs = MSG_CreatePrefs();
  380.  
  381.     //
  382.     // Read in user identity stuff
  383.     //
  384.  
  385.     PREF_CopyCharPref("mail.identity.username",&prefStr);
  386.     m_csUsersFullName = prefStr;
  387.     XP_FREEIF(prefStr);        
  388.     
  389.     PREF_CopyCharPref("mail.identity.useremail",&prefStr);
  390.     m_csUsersEmailAddr = prefStr;
  391.     XP_FREEIF(prefStr);        
  392.     
  393.     PREF_CopyCharPref("mail.identity.organization",&prefStr);
  394.     m_csUsersOrganization = prefStr;
  395.     XP_FREEIF(prefStr);        
  396.  
  397.     PREF_CopyCharPref("mail.signature_file", &prefStr);
  398.     m_pszUserSig = wfe_ReadUserSig(prefStr);
  399.     XP_FREEIF(prefStr);        
  400.  
  401.     //
  402.     // Set up the POP3 server
  403.     //
  404.  
  405.     PREF_CopyCharPref("network.hosts.pop_server", &prefStr);
  406.     if (prefStr) {
  407.         g_MsgPrefs.m_csMailHost = prefStr;
  408.     }
  409.     XP_FREEIF(prefStr);
  410.  
  411.     XP_Bool prefBool= FALSE;
  412.     PREF_GetBoolPref("mail.remember_password",&prefBool);
  413.     prefStr = NULL;
  414.     PREF_CopyCharPref("mail.pop_password",&prefStr);
  415.     if(prefStr && prefBool) {
  416.         NET_SetPopPassword(prefStr);
  417.     }
  418.     XP_FREEIF(prefStr);
  419.  
  420.     //
  421.     // Set up the SMTP server
  422.     //
  423.  
  424.     PREF_CopyCharPref("network.hosts.smtp_server", &prefStr);
  425.     NET_SetMailRelayHost(prefStr);
  426.     XP_FREEIF(prefStr);    
  427.  
  428.     PREF_SetBoolPref("news.show_pretty_names", TRUE);
  429.  
  430.     //
  431.     // Set up the NNTP server
  432.     //
  433.  
  434.     PREF_CopyCharPref("network.hosts.nntp_server", &prefStr);
  435.     NET_SetNewsHost(prefStr);
  436.     m_csNewsHost = prefStr;
  437.     XP_FREEIF(prefStr);
  438.  
  439.     // Set up news directory
  440.     msg = theApp.m_UserDirectory;
  441.     msg += "\\news";
  442.     PREF_SetDefaultCharPref("news.directory",msg);
  443.     PREF_CopyCharPref("news.directory",&prefStr);
  444.     m_csNewsDir = prefStr;
  445.     XP_FREEIF(prefStr);    
  446.  
  447.     // Check that the news directory exists
  448.     // Don't show error messagebox according bug#37398
  449.     if(FEU_SanityCheckDir(m_csNewsDir)) 
  450.     {
  451.         NET_ReadNewsrcFileMappings();
  452.     }
  453.  
  454.     //
  455.     // Compose prefs
  456.     //
  457.  
  458.     prefBool = TRUE;
  459.     PREF_GetBoolPref("mail.strictly_mime", &prefBool);
  460.     MIME_ConformToStandard(prefBool); 
  461.  
  462.     //
  463.     // Set up window prefs
  464.     //
  465.     prefBool= TRUE;
  466.     PREF_GetBoolPref("mailnews.reuse_thread_window", &prefBool);
  467.     m_bThreadReuse = prefBool;
  468.  
  469.     prefBool= TRUE;
  470.     PREF_GetBoolPref("mailnews.reuse_message_window", &prefBool);
  471.     m_bMessageReuse = prefBool;
  472.  
  473.     prefBool= TRUE;
  474.     PREF_GetBoolPref("mailnews.message_in_thread_window", &prefBool);
  475.     m_bThreadPaneMaxed = !prefBool;
  476.  
  477.     PREF_RegisterCallback("mailnews.reuse_thread_window", cbMsgPrefs, (void *) 0);
  478.     PREF_RegisterCallback("mailnews.reuse_message_window", cbMsgPrefs, (void *) 1);
  479.     PREF_RegisterCallback("mailnews.message_in_thread_window", cbMsgPrefs, (void *) 2);
  480.     // The BE should probably be handling most of these
  481.     PREF_RegisterCallback("mail.directory", cbMsgPrefs, (void *) 3);
  482.     PREF_RegisterCallback("network.hosts.pop_server", cbMsgPrefs, (void *) 4);
  483.     PREF_RegisterCallback("news.directory", cbMsgPrefs, (void *) 5);
  484.     PREF_RegisterCallback("network.hosts.nntp_server", cbMsgPrefs, (void *) 6);
  485.     PREF_RegisterCallback("mail.identity.useremail", cbMsgPrefs, (void *) 7);
  486.     PREF_RegisterCallback("mail.identity.username", cbMsgPrefs, (void *) 8);
  487.     PREF_RegisterCallback("mail.identity.organization", cbMsgPrefs, (void *) 9);
  488.     PREF_RegisterCallback("mail.signature_file", cbMsgPrefs, (void *) 10);
  489.     PREF_RegisterCallback("mail.leave_on_server", cbMsgPrefs, (void *) 11);
  490.     PREF_RegisterCallback("network.online", cbMsgPrefs, (void *) 12);
  491.  
  492.     // START THE BIFF CONTEXT
  493.     CBiffCX *pCX = new CBiffCX();
  494.     m_pBiffContext = pCX->GetContext();
  495.  
  496.     MSG_BiffInit(m_pBiffContext, m_pMsgPrefs);
  497. }
  498.  
  499. void CMsgPrefs::Shutdown()
  500. {
  501. }
  502.  
  503. CMsgPrefs::~CMsgPrefs()
  504. {
  505.     XP_FREEIF(m_pszUserSig);
  506. }
  507.  
  508. BOOL CMsgPrefs::IsValid() const
  509. {
  510.     char buffer[256];
  511.     int nLen = 255;
  512.  
  513.     buffer[0] = '\0';
  514.     if (PREF_NOERROR == PREF_GetCharPref("mail.pop_name", buffer, &nLen))
  515.     {
  516.         if (strlen(buffer) && !m_csMailHost.IsEmpty())
  517.             return TRUE;
  518.         else
  519.             return FALSE;
  520.     }
  521.     else
  522.         return FALSE;
  523. }
  524.  
  525. MSG_Master *CMsgPrefs::GetMaster()
  526. {
  527.     // Lazy loading of the one-and-only master object for news
  528.     // * Must be lazy loaded so theApp.m_pMsgPrefs is initialized
  529.  
  530.     if (!m_pMaster)
  531.     {
  532.         if (!m_pMsgPrefs)
  533.             m_pMsgPrefs = MSG_CreatePrefs();
  534.         m_pMaster = MSG_InitializeMail(m_pMsgPrefs);
  535.     }
  536.     return m_pMaster;
  537. }
  538.  
  539. //////////////////////////////////////////////////////////////////////////////
  540. // CMailNewsOutliner
  541.  
  542. CMailNewsOutliner::CMailNewsOutliner()
  543. {
  544.     m_iSelBlock = 0;
  545.     m_bSelChanged = FALSE;
  546.     m_bExpandOrCollapse = FALSE;
  547.     m_pPane = NULL;
  548.     m_iMysticPlane = 0;
  549. }
  550.  
  551. CMailNewsOutliner::~CMailNewsOutliner()
  552. {
  553. }
  554.  
  555. void CMailNewsOutliner::SetPane(MSG_Pane *pane)
  556. {
  557.     m_pPane = pane;
  558.  
  559.     if (m_pPane) {
  560.         SetTotalLines( (int) MSG_GetNumLines(m_pPane));
  561.         Invalidate();
  562.         UpdateWindow();
  563.     }
  564. }
  565.  
  566. const char *aszNotifications[] = {
  567.     "None",
  568.     "InsOrDel",
  569.     "Changed",
  570.     "Scramble",
  571.     "All"
  572. };
  573.      
  574. void CMailNewsOutliner::MysticStuffStarting( XP_Bool asynchronous,
  575.                                             MSG_NOTIFY_CODE notify, 
  576.                                             MSG_ViewIndex where,
  577.                                             int32 num )
  578. {
  579.     TipHide();
  580.  
  581.     if ( 0 == m_iMysticPlane++  ) {
  582.         m_bSelChanged = FALSE;
  583.     }
  584.  
  585.     if ( notify == MSG_NotifyInsertOrDelete && m_bExpandOrCollapse ) {
  586.     }
  587. }
  588.  
  589. void CMailNewsOutliner::MysticStuffFinishing( XP_Bool asynchronous,
  590.                                              MSG_NOTIFY_CODE notify, 
  591.                                              MSG_ViewIndex where,
  592.                                              int32 num )
  593. {
  594.     switch ( notify ) {
  595.     case MSG_NotifyNone:
  596.         break;
  597.     case MSG_NotifyAll:
  598.         ClearSelection();
  599.         m_iSelection = -1;
  600.         m_iTopLine = 0;
  601.         m_bSelChanged = TRUE;
  602.         Invalidate();
  603.         break;
  604.     case MSG_NotifyInsertOrDelete:
  605.         if ( m_bExpandOrCollapse && where > 0 && num < 0 ) {
  606.             // We're collapsing, so if our primary selection is
  607.             // in the collapsing area, we need to select the
  608.             // parent
  609.             // Assume that where - 1 is the parent
  610.  
  611.             if ( m_iSelection >= (int32) where && 
  612.                  m_iSelection < (int32) (where - num) ) {
  613.                 m_iSelection = CASTINT(where - 1);
  614.                 m_iFocus = CASTINT(where - 1);
  615.                 AddSelection( m_iSelection );
  616.                 m_bSelChanged = TRUE;
  617.             }
  618.             if ( m_iShiftAnchor >= (int32) where &&
  619.                  m_iShiftAnchor < (int32) (where - num ) ) {
  620.                 m_iShiftAnchor = CASTINT(where - 1);
  621.             }
  622.         }
  623.  
  624.         if ( num < 0 ) {
  625.             m_bSelChanged |= HandleDelete( where, -num );
  626.         } else if (num > 0) {
  627.             m_bSelChanged |= HandleInsert( where, num );
  628.         } else {
  629.             m_bSelChanged = TRUE;
  630.         }
  631.         break;
  632.     case MSG_NotifyChanged:
  633.         InvalidateLines( (int) where, (int) num );
  634.         break;
  635.     case MSG_NotifyScramble:
  636.         ScrollIntoView(m_iFocus);
  637.         Invalidate();
  638.         break;
  639.     }
  640.  
  641.     if ( !--m_iMysticPlane && m_pPane ) {
  642.         SetTotalLines( (int) MSG_GetNumLines( m_pPane ) );
  643.         UpdateWindow();
  644.  
  645.         if (m_bSelChanged) {
  646.             m_bSelChanged = FALSE;
  647.             OnSelChanged();
  648.         }
  649.     }
  650. }
  651.  
  652. int CMailNewsOutliner::ToggleExpansion( int iLine )
  653. {
  654.     int32 numChanged;
  655.  
  656.     m_bExpandOrCollapse = TRUE;
  657.     MSG_ToggleExpansion( m_pPane, iLine, &numChanged );
  658.     m_bExpandOrCollapse = FALSE;
  659.  
  660.     return (int) numChanged;
  661. }
  662.  
  663. int CMailNewsOutliner::Expand( int iLine )
  664. {
  665.     if (MSG_ExpansionDelta( m_pPane, iLine ) > 0) {
  666.         return ToggleExpansion( iLine );
  667.     }
  668.     return 0;
  669. }
  670.  
  671. int CMailNewsOutliner::Collapse( int iLine )
  672. {
  673.     if (MSG_ExpansionDelta( m_pPane, iLine ) < 0) {
  674.         return ToggleExpansion( iLine );
  675.     }
  676.     return 0;
  677. }
  678.  
  679. BEGIN_MESSAGE_MAP( CMailNewsOutliner, CMSelectOutliner )
  680.     ON_WM_SETCURSOR()
  681.     ON_WM_LBUTTONDOWN()
  682.     ON_WM_RBUTTONDOWN()
  683.     ON_WM_KEYDOWN()
  684.     ON_WM_KEYUP()
  685. END_MESSAGE_MAP()
  686.  
  687. BOOL CMailNewsOutliner::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
  688. {
  689.  
  690.     if ( (nHitTest == HTCLIENT) && (m_iSelBlock > 0)) {
  691.         ::SetCursor( ::LoadCursor( NULL, IDC_WAIT ) );
  692.         return TRUE;
  693.     }
  694.  
  695.     return CMSelectOutliner::OnSetCursor( pWnd, nHitTest, message );
  696. }
  697.  
  698. void CMailNewsOutliner::OnLButtonDown( UINT nFlags, CPoint point )
  699. {
  700.     if (m_iSelBlock <= 0)
  701.         COutliner::OnLButtonDown(nFlags, point);
  702.     else 
  703.         MessageBeep((UINT) -1);
  704. }
  705.  
  706. void CMailNewsOutliner::OnRButtonDown( UINT nFlags, CPoint point )
  707. {
  708.     if (m_iSelBlock <= 0)
  709.         COutliner::OnRButtonDown(nFlags, point);
  710.     else 
  711.         MessageBeep((UINT) -1);
  712. }
  713.  
  714. void CMailNewsOutliner::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  715. {
  716.     if (m_iSelBlock <= 0)
  717.         COutliner::OnKeyDown(nChar, nRepCnt, nFlags);
  718.     else 
  719.         MessageBeep((UINT) -1);
  720. }
  721.  
  722. void CMailNewsOutliner::OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags )
  723. {
  724.     if (m_iSelection != m_iLastSelected) {
  725.         if (m_iIndicesCount == 1) {
  726.             COutliner::OnKeyUp(nChar, nRepCnt, nFlags);
  727.         } else {
  728.             int flags = 0;
  729.             if (GetKeyState(VK_SHIFT)&0x8000)
  730.                 flags |= MK_SHIFT;
  731.             if (GetKeyState(VK_CONTROL)&0x8000)
  732.                 flags |= MK_CONTROL;
  733.             SelectItem(m_iSelection, OUTLINER_TIMER, flags);
  734.         }
  735.     }
  736. }
  737.  
  738.  
  739. //////////////////////////////////////////////////////////////////////////////
  740. // CFolderOutliner
  741.  
  742. #define DOUBLE_CLICK_TIMER   9999
  743.  
  744. CFolderOutliner::CFolderOutliner ( )
  745. {
  746.     m_pUnkUserImage = NULL;
  747.     ApiApiPtr(api);
  748.     m_pUnkUserImage = api->CreateClassInstance(
  749.       APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILNEWS);
  750.     m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
  751.     ASSERT(m_pIUserImage);
  752.     if (!m_pIUserImage->GetResourceID())
  753.       m_pIUserImage->Initialize(IDB_MAILNEWS,16,16);
  754.  
  755.     m_pszExtraText = new _TCHAR[EXTRATEXT_SIZE];
  756.     m_pMysticStuff = NULL;
  757.     m_pAncestor = NULL;
  758.  
  759.     m_uTimer = 0;
  760.     m_dwPrevTime = 0;
  761.     m_bLButtonDown = FALSE;
  762.     m_bDoubleClicked = FALSE;
  763.     m_b3PaneParent = FALSE;
  764.     m_nCurrentSelected = -1;
  765. }
  766.  
  767. CFolderOutliner::~CFolderOutliner ( )
  768. {
  769.     if (m_pUnkUserImage) {
  770.         if (m_pIUserImage)
  771.             m_pUnkUserImage->Release();
  772.     }
  773.  
  774.     delete [] m_pszExtraText;
  775.     delete [] m_pMysticStuff;
  776. }
  777.  
  778. void CFolderOutliner::MysticStuffStarting( XP_Bool asynchronous,
  779.                                           MSG_NOTIFY_CODE notify, 
  780.                                           MSG_ViewIndex where,
  781.                                           int32 num )
  782. {
  783.     CMailNewsOutliner::MysticStuffStarting( asynchronous, notify,
  784.                                            where, num );
  785.  
  786.     if ( notify == MSG_NotifyScramble && m_pPane ) {
  787.         MSG_ViewIndex *indices;
  788.         int i, count;
  789.         GetSelection(indices, count);
  790.  
  791.         m_pMysticStuff = new MSG_FolderInfo*[count];
  792.  
  793.         for (i = 0; i < count; i++) {
  794.             m_pMysticStuff[i] = MSG_GetFolderInfo(m_pPane, indices[i]);
  795.         }
  796.  
  797.         m_MysticFocus = MSG_GetFolderInfo( m_pPane, m_iFocus );
  798.         m_MysticSelection = MSG_GetFolderInfo( m_pPane, m_iSelection );
  799.     }
  800. }
  801.  
  802. void CFolderOutliner::MysticStuffFinishing( XP_Bool asynchronous,
  803.                                            MSG_NOTIFY_CODE notify, 
  804.                                            MSG_ViewIndex where,
  805.                                            int32 num )
  806. {
  807.     if ( notify == MSG_NotifyScramble && m_pPane ) {
  808.         MSG_ViewIndex *indices;
  809.         int i, count;
  810.         GetSelection(indices, count);
  811.  
  812.         ClearSelection();
  813.  
  814.         for ( i = 0; i < count; i++ ) {
  815.             int index = (int) MSG_GetFolderIndex(m_pPane, m_pMysticStuff[i]);
  816.             if ( index != MSG_VIEWINDEXNONE ) {
  817.                 AddSelection(index);
  818.             } else {
  819.                 m_bSelChanged = TRUE;
  820.             }
  821.         }
  822.  
  823.         delete [] m_pMysticStuff;
  824.         m_pMysticStuff = NULL;
  825.  
  826.         if ( m_MysticSelection == NULL ) {
  827.             m_iSelection = -1;
  828.         } else {
  829.             int iSelection = (int) MSG_GetFolderIndex(m_pPane, m_MysticSelection);
  830.             if (iSelection == -1 ) {
  831.                 iSelection = GetTotalLines() > 0 ? 0 : -1;
  832.                 if (iSelection != -1)
  833.                     AddSelection( iSelection );
  834.             }
  835.             m_iSelection = iSelection;
  836.         }
  837.  
  838.         if ( m_MysticFocus == NULL ) {
  839.             m_iFocus = m_iSelection;
  840.         } else {
  841.             int iFocus = (int) MSG_GetFolderIndex(m_pPane, m_MysticFocus);
  842.             if ( iFocus == -1 ) {
  843.                 iFocus = m_iSelection > 0 ? m_iSelection : 0;
  844.             }
  845.             m_iFocus = iFocus;
  846.         }
  847.         m_iShiftAnchor = m_iFocus;
  848.     }
  849.  
  850.     CMailNewsOutliner::MysticStuffFinishing( asynchronous, notify,
  851.                                             where, num );
  852. }
  853.  
  854. // Tree Info stuff
  855. int CFolderOutliner::GetDepth( int iLine )
  856. {
  857.     MSG_FolderLine folderLine;
  858.     MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
  859.     return folderLine.level - 1;
  860. }
  861.  
  862. int CFolderOutliner::GetNumChildren( int iLine )
  863. {
  864.     MSG_FolderLine folderLine;
  865.     MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
  866.     return folderLine.numChildren;
  867. }
  868.  
  869. BOOL CFolderOutliner::IsCollapsed( int iLine )
  870. {
  871.     MSG_FolderLine folderLine;
  872.     MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
  873.     return folderLine.flags & MSG_FOLDER_FLAG_ELIDED ? TRUE : FALSE;
  874. }
  875.  
  876. void CFolderOutliner::PropertyMenu ( int iSel, UINT flags )    
  877. {
  878.     HMENU hmenu = CreatePopupMenu();
  879.     
  880.     if ( !hmenu )
  881.         return;  
  882.  
  883.     MSG_ViewIndex *indices;
  884.     int count;
  885.     GetSelection( indices, count );
  886.  
  887.     if ( iSel < m_iTotalLines && count == 1 ) {
  888.         MSG_FolderLine folderLine;
  889.         MSG_GetFolderLineByIndex( m_pPane, indices[0], 1, &folderLine );
  890.  
  891.         BOOL bReuse = g_MsgPrefs.m_bThreadReuse;
  892.         if (GetKeyState(VK_MENU) & 0x8000)
  893.             bReuse = !bReuse;
  894.  
  895.         if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) { 
  896.             if (folderLine.level > 1) {
  897.                 if (bReuse) {
  898.                     ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENFOLDER ) );
  899.                     ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENFOLDERNEWWINDOW ) );
  900.                 } else {
  901.                     ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENFOLDERNEWWINDOW ) );
  902.                     ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENFOLDER ) );
  903.                 }
  904.                 ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  905.                  
  906.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWFOLDER, szLoadString( IDS_POPUP_NEWSUBFOLDER ) );
  907.                 ::AppendMenu( hmenu, MF_STRING, ID_EDIT_DELETEFOLDER, szLoadString( IDS_POPUP_DELETEFOLDER ) );
  908.                 ::AppendMenu( hmenu, MF_STRING, ID_FOLDER_RENAME, szLoadString( IDS_POPUP_RENAMEFOLDER ) );
  909.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_COMPRESSTHISFOLDER, szLoadString( IDS_POPUP_COMPRESSFOLDER ) );
  910.                 ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  911.              
  912.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWMESSAGE, szLoadString( IDS_POPUP_NEWMESSAGE ) );
  913.                 ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  914.              
  915.                 ::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
  916.                 ::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_FOLDERPROP ) );
  917.             } else {
  918.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWFOLDER, szLoadString( IDS_POPUP_NEWFOLDER ) );
  919.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_UPDATECOUNTS, szLoadString( IDS_POPUP_UPDATEMESSAGECOUNT ) );
  920.                 ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  921.              
  922.                 ::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
  923.                 ::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_MAILSERVERPROP) );
  924.             }
  925.         } else if ( folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ) {
  926.             BOOL bReuse = g_MsgPrefs.m_bThreadReuse;
  927.             if (bReuse) {
  928.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENNEWSGROUP ) );
  929.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENNEWSGROUPNEWWINDOW ) );
  930.             } else {
  931.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENNEWSGROUPNEWWINDOW ) );
  932.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENNEWSGROUP ) );
  933.             }
  934.             ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  935.          
  936.             ::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWMESSAGE, szLoadString( IDS_POPUP_NEWMESSAGE ) );
  937.             ::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_MARKALLREAD, szLoadString( IDS_POPUP_MARKNEWSGROUPREAD ) );
  938.             ::AppendMenu( hmenu, MF_STRING, ID_POPUP_DELETEFOLDER, szLoadString( IDS_POPUP_REMOVENEWSGROUP ) );
  939.             ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  940.          
  941.             ::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
  942.             ::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_NEWSGROUPPROP ) );
  943.         } else if ( folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST ) {
  944.             ::AppendMenu( hmenu, MF_STRING, ID_FILE_SUBSCRIBE, szLoadString( IDS_POPUP_JOINNEWSGROUP ) );
  945.             ::AppendMenu( hmenu, MF_STRING, ID_FILE_UPDATECOUNTS, szLoadString( IDS_POPUP_UPDATEMESSAGECOUNT ) );
  946.             ::AppendMenu( hmenu, MF_STRING, ID_POPUP_DELETEFOLDER, szLoadString( IDS_POPUP_REMOVENEWSHOST ) );
  947.             ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  948.          
  949.             ::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
  950.             ::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_NEWSHOSTPROP) );
  951.         }
  952.     }
  953.     //    Track the popup now.
  954.     POINT pt = m_ptHit;
  955.     ClientToScreen(&pt);
  956.  
  957.     ::TrackPopupMenu( hmenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0,
  958.                       GetParentFrame()->GetSafeHwnd(), NULL);
  959.  
  960.     VERIFY(::DestroyMenu( hmenu ));
  961. }
  962.  
  963. DROPEFFECT CFolderOutliner::DropSelect( int iLineNo, COleDataObject *pDataObject )
  964. {
  965.     DROPEFFECT res = DROPEFFECT_NONE;
  966.     MSG_DragEffect requireEffect = MSG_Default_Drag;
  967.     MSG_DragEffect effect = MSG_Drag_Not_Allowed;
  968.     HGLOBAL hContent = NULL;
  969.     MailNewsDragData *pDragData = NULL;
  970.  
  971.     if ((GetKeyState(VK_SHIFT) & 0x8000) && (GetKeyState(VK_CONTROL) & 0x8000))
  972.         requireEffect = MSG_Default_Drag;
  973.     else if (GetKeyState(VK_SHIFT) & 0x8000)
  974.         requireEffect = MSG_Require_Move;
  975.     else if (GetKeyState(VK_CONTROL) & 0x8000)
  976.         requireEffect = MSG_Require_Copy;
  977.  
  978. // The commented out code has the effect of always doing a move, if we get called
  979. // with the same iLineNo as last time!
  980. //    if (iLineNo != m_iDragSelection)
  981.     {
  982.         if ( m_iDragSelection != -1 )
  983.             InvalidateLine (m_iDragSelection);
  984.  
  985.         m_iDragSelection = -1;
  986.  
  987.         MSG_FolderLine folderLine;
  988.  
  989.         if (MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLineNo, 1, &folderLine )) 
  990.         {
  991.             if ( pDataObject->IsDataAvailable( m_cfMessages ) ) 
  992.             {
  993.                 hContent = pDataObject->GetGlobalData (m_cfMessages);
  994.                 pDragData = (MailNewsDragData *) GlobalLock(hContent);
  995.                 effect = MSG_DragMessagesIntoFolderStatus
  996.                         (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  997.                         folderLine.id, requireEffect);
  998.                 GlobalUnlock (hContent); //do we have to GlobalFree it too?
  999.             }
  1000.             else if ( pDataObject->IsDataAvailable( m_cfFolders ) ) 
  1001.             {
  1002.                 hContent = pDataObject->GetGlobalData (m_cfFolders);
  1003.                 pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1004.                 effect = MSG_DragFoldersIntoStatus
  1005.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1006.                     folderLine.id, requireEffect);
  1007.                 GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1008.             }
  1009.             else if ( pDataObject->IsDataAvailable( m_cfSearchMessages ) ) 
  1010.             {
  1011.                 hContent = pDataObject->GetGlobalData (m_cfSearchMessages);
  1012.                 pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1013.                 effect = MSG_DragMessagesIntoFolderStatus
  1014.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1015.                     folderLine.id, requireEffect);
  1016.                 GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1017.             }
  1018.             if (MSG_Drag_Not_Allowed != effect) 
  1019.             {
  1020.                 InvalidateLine (iLineNo);
  1021.                 m_iDragSelection = iLineNo;
  1022.                 if (effect == MSG_Require_Copy)
  1023.                     res = DROPEFFECT_COPY;
  1024.                 else
  1025.                     res = DROPEFFECT_MOVE;
  1026.             } 
  1027.         }
  1028.     }
  1029. //    else  
  1030. //        res = DROPEFFECT_MOVE;
  1031.  
  1032.     return res;
  1033. }
  1034.  
  1035. void CFolderOutliner::AcceptDrop( int iLineNo, COleDataObject *pDataObject,
  1036.                                  DROPEFFECT dropEffect )
  1037. {
  1038.     if (iLineNo != -1) {
  1039.         MSG_FolderInfo *pFolder = MSG_GetFolderInfo(m_pPane,iLineNo);
  1040.         ASSERT(pFolder);
  1041.  
  1042.         MSG_DragEffect requireEffect = MSG_Default_Drag;
  1043.         if (dropEffect & DROPEFFECT_MOVE)
  1044.             requireEffect = MSG_Require_Move;
  1045.         else if (dropEffect & DROPEFFECT_COPY)
  1046.             requireEffect = MSG_Require_Copy;
  1047.  
  1048.         if ( pDataObject->IsDataAvailable( m_cfMessages ) && pFolder ) 
  1049.         {
  1050.             HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
  1051.             MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1052.  
  1053.             MSG_DragEffect effect =  MSG_DragMessagesIntoFolderStatus
  1054.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1055.                     pFolder, requireEffect);
  1056.  
  1057.             LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
  1058.             if (pUnk) {
  1059.                 LPMSGLIST pInterface = NULL;
  1060.                 pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
  1061.                 if ( pInterface ) {
  1062.                     switch (effect) {
  1063.                     case MSG_Require_Move:
  1064.                         pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1065.                                                       pDragData->m_count, pFolder);
  1066.                         break;
  1067.                     case MSG_Require_Copy:
  1068.                         pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1069.                                                       pDragData->m_count, pFolder);
  1070.                         break;
  1071.                     default:
  1072.                         ASSERT(0);
  1073.                         break;
  1074.                     }
  1075.                     pInterface->Release();
  1076.                 }
  1077.             }
  1078.             GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1079.         }
  1080.  
  1081.         if ( pDataObject->IsDataAvailable( m_cfSearchMessages ) && pFolder ) 
  1082.         {
  1083.             HGLOBAL hContent = pDataObject->GetGlobalData (m_cfSearchMessages);
  1084.             MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1085.  
  1086.             MSG_DragEffect effect =  MSG_DragMessagesIntoFolderStatus
  1087.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1088.                     pFolder, requireEffect);
  1089.  
  1090.             LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
  1091.             if (pUnk) {
  1092.                 LPMSGLIST pInterface = NULL;
  1093.                 pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
  1094.                 if ( pInterface ) {
  1095.                     switch (effect) {
  1096.                     case MSG_Require_Move:
  1097.                         pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1098.                                                       pDragData->m_count, pFolder);
  1099.                         break;
  1100.                     case MSG_Require_Copy:
  1101.                         pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1102.                                                       pDragData->m_count, pFolder);
  1103.                         break;
  1104.                     default:
  1105.                         ASSERT(0);
  1106.                         break;
  1107.                     }
  1108.                     pInterface->Release();
  1109.                 }
  1110.             }
  1111.             GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1112.         }
  1113.  
  1114.  
  1115.          if ( pDataObject->IsDataAvailable( m_cfFolders ) && pFolder ) 
  1116.         {
  1117.             HGLOBAL hContent = pDataObject->GetGlobalData (m_cfFolders);
  1118.             MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1119.  
  1120.             MSG_DragEffect effect = MSG_DragFoldersIntoStatus
  1121.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1122.                     pFolder, MSG_Default_Drag);
  1123.  
  1124.             if (effect == MSG_Require_Copy || effect == MSG_Require_Move)
  1125.             {
  1126.                 MSG_MoveFoldersInto( pDragData->m_pane, pDragData->m_indices, 
  1127.                                      pDragData->m_count, pFolder);
  1128.                 if (IsParent3PaneFrame())
  1129.                 {
  1130.                     C3PaneMailFrame* pFrame = C3PaneMailFrame::FindFrame(pFolder);;
  1131.                     if (pFrame) 
  1132.                         pFrame->ActivateFrame();
  1133. #if 0    // this interrupts the move - why are we doing it?
  1134.                     else
  1135.                         GetParentFrame()->SendMessage(WM_COMMAND, 
  1136.                                                     ID_FOLDER_SELECT, 0);
  1137. #endif
  1138.                 }
  1139.             }
  1140.             GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1141.         }
  1142.     }
  1143. }
  1144.  
  1145. COleDataSource * CFolderOutliner::GetDataSource(void)
  1146. {
  1147.     MSG_ViewIndex *indices;
  1148.     int count;
  1149.     GetSelection(indices, count);
  1150.  
  1151.     HANDLE hContent = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(MailNewsDragData));
  1152.     MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock (hContent);
  1153.  
  1154.     pDragData->m_pane = m_pPane;
  1155.     pDragData->m_indices = indices;
  1156.     pDragData->m_count = count;
  1157.  
  1158.     GlobalUnlock(hContent);
  1159.  
  1160.     COleDataSource * pDataSource = new COleDataSource;  
  1161.     pDataSource->CacheGlobalData(m_cfFolders,hContent);
  1162.  
  1163.     if ( count == 1 ) {
  1164.         MSG_FolderLine folderLine;
  1165.         MSG_GetFolderLineByIndex( m_pPane, indices[0], 1, &folderLine );
  1166.         URL_Struct *url = MSG_ConstructUrlForFolder( m_pPane, folderLine.id );
  1167.  
  1168.         if ( url ) {            
  1169.             const char *name = (folderLine.prettyName && folderLine.prettyName[0]) ?
  1170.                                folderLine.prettyName : folderLine.name;
  1171.             RDFGLOBAL_DragTitleAndURL( pDataSource, name, url->address );
  1172.             NET_FreeURLStruct( url );
  1173.         }
  1174.     }
  1175.  
  1176.     return pDataSource;
  1177. }
  1178.  
  1179. void CFolderOutliner::InitializeClipFormats(void)
  1180. {
  1181.     m_cfMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_MESSAGE_FORMAT);
  1182.     m_cfFolders = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_FOLDER_FORMAT);
  1183.     m_cfSearchMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_SEARCH_FORMAT);
  1184. }
  1185.  
  1186. CLIPFORMAT * CFolderOutliner::GetClipFormatList(void)
  1187. {
  1188.     static CLIPFORMAT cfFormatList[4];
  1189.     cfFormatList[0] = m_cfMessages;
  1190.     cfFormatList[1] = m_cfFolders;
  1191.     cfFormatList[2] = m_cfSearchMessages;
  1192.     cfFormatList[3] =     0;
  1193.     return cfFormatList;
  1194. }
  1195.  
  1196. int CFolderOutliner::TranslateIcon (void * pData)
  1197. {
  1198.     ASSERT(pData);
  1199.     MSG_FolderLine * pFolder = (MSG_FolderLine*)pData;
  1200.  
  1201.     BOOL bOpen = pFolder->numChildren <= 0 ||
  1202.                  pFolder->flags & MSG_FOLDER_FLAG_ELIDED ? FALSE : TRUE;
  1203.  
  1204.     return WFE_MSGTranslateFolderIcon( pFolder->level, pFolder->flags, bOpen );
  1205. }
  1206.  
  1207. int CFolderOutliner::TranslateIconFolder (void * pData)
  1208. {
  1209.     ASSERT(pData);
  1210.     MSG_FolderLine * pFolder = (MSG_FolderLine*)pData;
  1211.  
  1212.     if (pFolder->numChildren > 0) {
  1213.         if (pFolder->flags & MSG_FOLDER_FLAG_ELIDED) {
  1214.             return(OUTLINER_CLOSEDFOLDER);
  1215.         } else {
  1216.             return(OUTLINER_OPENFOLDER);
  1217.         }
  1218.     }
  1219.     return (OUTLINER_ITEM);
  1220. }
  1221.  
  1222. void * CFolderOutliner::AcquireLineData ( int line )
  1223. {
  1224.     delete [] m_pAncestor;
  1225.     m_pAncestor = NULL;
  1226.  
  1227.     m_pszExtraText[ 0 ] = '\0';
  1228.     if ( line >= m_iTotalLines)
  1229.         return NULL;
  1230.     if ( !MSG_GetFolderLineByIndex(m_pPane, line, 1, &m_FolderLine ))
  1231.         return NULL;
  1232.  
  1233.     return &m_FolderLine;
  1234. }
  1235.  
  1236. void CFolderOutliner::GetTreeInfo ( int line, uint32 * pFlags, int * pDepth, 
  1237.                                     OutlinerAncestorInfo ** pAncestor )
  1238. {
  1239.     delete [] m_pAncestor;
  1240.     m_pAncestor = NULL;
  1241.  
  1242.     if (pAncestor) {
  1243.         if ( m_FolderLine.level > 0 ) {
  1244.             m_pAncestor = new OutlinerAncestorInfo[m_FolderLine.level];
  1245.         } else {
  1246.             m_pAncestor = new OutlinerAncestorInfo[1];
  1247.         }
  1248.  
  1249.         int i = m_FolderLine.level - 1;
  1250.         int idx = line + 1;
  1251.         while ( i > 0 ) {
  1252.             int level;
  1253.             if ( idx < m_iTotalLines ) {
  1254.                 level = MSG_GetFolderLevelByIndex( m_pPane, idx );
  1255.                 if ( (level - 1) == i ) {
  1256.                     m_pAncestor[i].has_prev = TRUE;
  1257.                     m_pAncestor[i].has_next = TRUE;
  1258.                     i--;
  1259.                     idx++;
  1260.                 } else if ( (level - 1) < i ) {
  1261.                     m_pAncestor[i].has_prev = FALSE;
  1262.                     m_pAncestor[i].has_next = FALSE;
  1263.                     i--;
  1264.                 } else {
  1265.                     idx++;
  1266.                 }
  1267.             } else {
  1268.                 m_pAncestor[i].has_prev = FALSE;
  1269.                 m_pAncestor[i].has_next = FALSE;
  1270.                 i--;
  1271.             }
  1272.         }
  1273.         m_pAncestor[0].has_prev = FALSE;
  1274.         m_pAncestor[0].has_next = FALSE;
  1275.  
  1276.         *pAncestor = m_pAncestor;
  1277.     }
  1278.  
  1279.     if ( pFlags ) *pFlags = m_FolderLine.flags;
  1280.     if ( pDepth ) *pDepth = m_FolderLine.level - 1;
  1281. }
  1282.  
  1283. void CFolderOutliner::ReleaseLineData ( void * )
  1284. {
  1285.     delete [] m_pAncestor;
  1286.     m_pAncestor = NULL;
  1287. }
  1288.  
  1289. int CFolderOutliner::OnCreate(LPCREATESTRUCT lpcs)
  1290. {
  1291.     m_b3PaneParent = GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame));
  1292.     
  1293.     return CMailNewsOutliner::OnCreate(lpcs);
  1294. }
  1295.  
  1296. void CFolderOutliner::OnDestroy()
  1297. {
  1298.     if (m_uTimer)
  1299.     {
  1300.         KillTimer(m_uTimer);
  1301.         m_uTimer = 0;
  1302.     }
  1303.     CMailNewsOutliner::OnDestroy();
  1304. }
  1305.  
  1306. void CFolderOutliner::OnLButtonDown(UINT nFlags, CPoint point)
  1307. {
  1308.     m_bLButtonDown = TRUE;
  1309.     CMailNewsOutliner::OnLButtonDown(nFlags, point);
  1310. }
  1311.  
  1312. void CFolderOutliner::OnTimer(UINT nIDEvent)
  1313. {
  1314.     if (m_uTimer == nIDEvent)
  1315.     {
  1316.         if (m_bDoubleClicked)
  1317.         {
  1318.             m_bDoubleClicked = FALSE;
  1319.             KillTimer(m_uTimer);
  1320.             m_uTimer = 0;
  1321.         }
  1322.         else
  1323.         {
  1324.             UINT delta = GetTickCount() - m_dwPrevTime;
  1325.             if (delta > GetDoubleClickTime())
  1326.             {    // single click
  1327.                 m_bSelChanged = FALSE;
  1328.                 if (GetCurrentSelected() != m_iSelection)
  1329.                 {
  1330.                     if (!m_iSelBlock)
  1331.                         GetParentFrame()->SendMessage(WM_COMMAND, 
  1332.                                                     ID_FOLDER_SELECT, 0);
  1333.                 }
  1334.                 KillTimer(m_uTimer);
  1335.                 m_uTimer = 0;
  1336.             }
  1337.         }
  1338.         m_bLButtonDown = FALSE;
  1339.     }
  1340.     else
  1341.         CMailNewsOutliner::OnTimer(nIDEvent);
  1342. }
  1343.  
  1344. void CFolderOutliner::OnSelChanged()
  1345. {
  1346.     if (IsParent3PaneFrame())
  1347.     {
  1348.         SetCurrentSelected(m_iLastSelected);
  1349.         if (m_uTimer == 0 && m_bLButtonDown && !m_bDoubleClicked)
  1350.         {
  1351.             m_dwPrevTime = GetTickCount();
  1352.             UINT uElapse = GetDoubleClickTime() / 5;
  1353.             m_uTimer = SetTimer(DOUBLE_CLICK_TIMER, uElapse, NULL);
  1354.             return;
  1355.         } 
  1356.     }
  1357.      m_bSelChanged = FALSE;
  1358.     if (!m_iSelBlock)
  1359.         GetParentFrame()->SendMessage(WM_COMMAND, ID_FOLDER_SELECT, 0);
  1360. }
  1361.  
  1362. void CFolderOutliner::OnSelDblClk()
  1363. {
  1364.     m_bDoubleClicked = TRUE;
  1365.  
  1366.     MSG_FolderLine folderLine;
  1367.     if (MSG_GetFolderLineByIndex(m_pPane, m_iFocus, 1, &folderLine)) {
  1368.         if (folderLine.level < 2) {
  1369.             DoToggleExpansion(m_iFocus);
  1370.         }
  1371.     }
  1372.     GetParentFrame()->SendMessage(WM_COMMAND, ID_FILE_OPENFOLDER, 0);
  1373. }
  1374.  
  1375. HFONT CFolderOutliner::GetLineFont ( void *pLineData )
  1376. {
  1377.     MSG_FolderLine *pFolderLine = (MSG_FolderLine *) pLineData;
  1378.  
  1379.     if (((pFolderLine->deepUnseen > 0) && (pFolderLine->flags & MSG_FOLDER_FLAG_ELIDED)) ||
  1380.         (pFolderLine->unseen > 0) ||
  1381.         (pFolderLine->level < 2) )
  1382.         return m_hBoldFont;
  1383.     else
  1384.         return m_hRegFont;
  1385. }
  1386.  
  1387. LPCTSTR CFolderOutliner::GetColumnText( UINT iColumn, void * pLineData )
  1388. {
  1389.     m_pszExtraText[0] = '\0';
  1390.     LPCTSTR name;
  1391.  
  1392.     switch ( iColumn )
  1393.     {
  1394.         case ID_COLUMN_FOLDER:
  1395.             name = (LPCTSTR) m_FolderLine.prettyName;
  1396.             if ( !name || !name[0] )
  1397.                 name = m_FolderLine.name;
  1398.             return name;
  1399.  
  1400.         case ID_COLUMN_UNREAD:
  1401.             if( m_FolderLine.unseen > 0 )
  1402.                 sprintf( m_pszExtraText, "%ld", m_FolderLine.unseen );
  1403.             else if (m_FolderLine.unseen < 0)
  1404.                 sprintf( m_pszExtraText, "???" );
  1405.             return m_pszExtraText;
  1406.             
  1407.         case ID_COLUMN_COUNT:
  1408.             if( m_FolderLine.total > 0 )
  1409.                 sprintf( m_pszExtraText, "%ld", m_FolderLine.total );
  1410.             else if(m_FolderLine.total < 0)
  1411.                 sprintf( m_pszExtraText, "???" );
  1412.             return m_pszExtraText;
  1413.  
  1414.     }
  1415.     return m_pszExtraText;
  1416. }
  1417.  
  1418. LPCTSTR CFolderOutliner::GetColumnTip( UINT iColumn, void * pLineData )
  1419. {
  1420.     switch ( iColumn ) {
  1421.     case ID_COLUMN_UNREAD:
  1422.         if ( m_FolderLine.deepUnseen != m_FolderLine.unseen ) {
  1423.             if( m_FolderLine.unseen > 0 ) { 
  1424.                 sprintf( m_pszExtraText, "(%ld) %ld", 
  1425.                          m_FolderLine.deepUnseen, m_FolderLine.unseen );
  1426.                 return m_pszExtraText;
  1427.             } else if (m_FolderLine.unseen == 0) {
  1428.                 sprintf( m_pszExtraText, "(%ld)", m_FolderLine.deepUnseen );
  1429.                 return m_pszExtraText;
  1430.             }
  1431.         }
  1432.         break;
  1433.  
  1434.     case ID_COLUMN_COUNT:
  1435.         if ( m_FolderLine.deepTotal != m_FolderLine.total ) {
  1436.             if( m_FolderLine.total > 0 ) { 
  1437.                 sprintf( m_pszExtraText, "(%ld) %ld", 
  1438.                          m_FolderLine.deepTotal, m_FolderLine.total );
  1439.                 return m_pszExtraText;
  1440.             } else if (m_FolderLine.total == 0) {
  1441.                 sprintf( m_pszExtraText, "(%ld)", m_FolderLine.deepTotal );
  1442.                 return m_pszExtraText;
  1443.             }
  1444.         }
  1445.         break;
  1446.     }
  1447.     return NULL;
  1448. }
  1449.  
  1450. BEGIN_MESSAGE_MAP(CFolderOutliner, CMailNewsOutliner)
  1451.     ON_WM_CREATE()
  1452.     ON_WM_LBUTTONDOWN()
  1453.     ON_WM_TIMER()
  1454.     ON_WM_DESTROY()
  1455. END_MESSAGE_MAP()
  1456.  
  1457. //////////////////////////////////////////////////////////////////////////////
  1458. // CMessageOutliner
  1459.  
  1460.  
  1461. CMessageOutliner::CMessageOutliner ( )
  1462. {
  1463.     m_pszExtraText = new _TCHAR[EXTRATEXT_SIZE];
  1464.     m_pAncestor = NULL;
  1465.     m_bNews = FALSE;
  1466.     m_bDrafts = FALSE;
  1467.  
  1468.     m_uTimer = 0;
  1469.     m_dwPrevTime = 0;
  1470.     m_bLButtonDown = FALSE;
  1471.     m_bDoubleClicked = FALSE;
  1472.     m_nCurrentSelected = -1;
  1473.  
  1474.     m_pUnkUserImage = NULL;
  1475.     ApiApiPtr(api);
  1476.     m_pUnkUserImage = api->CreateClassInstance(
  1477.       APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILNEWS);
  1478.     m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
  1479.     ASSERT(m_pIUserImage);
  1480.     if (!m_pIUserImage->GetResourceID())
  1481.       m_pIUserImage->Initialize(IDB_MAILNEWS,16,16);
  1482.  
  1483.     m_pMysticStuff = NULL;
  1484. }
  1485.  
  1486. CMessageOutliner::~CMessageOutliner ( )
  1487. {
  1488.     if (m_pUnkUserImage) {
  1489.         if (m_pIUserImage)
  1490.             m_pUnkUserImage->Release();
  1491.     }
  1492.  
  1493.     delete [] m_pszExtraText;
  1494.     delete [] m_pMysticStuff;
  1495. }
  1496.  
  1497. void CMessageOutliner::MysticStuffStarting( XP_Bool asynchronous,
  1498.                                            MSG_NOTIFY_CODE notify, 
  1499.                                            MSG_ViewIndex where,
  1500.                                            int32 num )
  1501. {
  1502.     CMailNewsOutliner::MysticStuffStarting( asynchronous, notify,
  1503.                                            where, num);
  1504.     if ( notify == MSG_NotifyScramble ) {
  1505.         MSG_ViewIndex *indices;
  1506.         int i, count;
  1507.         GetSelection(indices, count);
  1508.  
  1509.         m_pMysticStuff = new MessageKey[count];
  1510.  
  1511.         for (i = 0; i < count; i++) {
  1512.             m_pMysticStuff[i] = MSG_GetMessageKey(m_pPane, indices[i]);
  1513.         }
  1514.  
  1515.         m_MysticFocus = MSG_MESSAGEKEYNONE;
  1516.         m_MysticSelection = MSG_MESSAGEKEYNONE;
  1517.  
  1518.         if ( m_iSelection != -1 && m_iSelection < m_iTotalLines) {
  1519.             m_MysticSelection = MSG_GetMessageKey( m_pPane, m_iSelection );
  1520.         }
  1521.         if ( m_iFocus != -1 && m_iFocus < m_iTotalLines) {
  1522.             m_MysticFocus = MSG_GetMessageKey( m_pPane, m_iFocus );
  1523.         }
  1524.     }
  1525. }
  1526.  
  1527. void CMessageOutliner::MysticStuffFinishing( XP_Bool asynchronous,
  1528.                                             MSG_NOTIFY_CODE notify, 
  1529.                                             MSG_ViewIndex where,
  1530.                                             int32 num )
  1531. {
  1532.     if ( notify == MSG_NotifyScramble ) {
  1533.         MSG_ViewIndex *indices;
  1534.         int i, count;
  1535.         GetSelection(indices, count);
  1536.  
  1537.         ClearSelection();
  1538.  
  1539.         for ( i = 0; i < count; i++ ) {
  1540.             MSG_ViewIndex index = MSG_GetMessageIndexForKey(m_pPane, m_pMysticStuff[i], TRUE);
  1541.             if ( index != MSG_VIEWINDEXNONE ) {
  1542.                 AddSelection(index);
  1543.             } else {
  1544.                 m_bSelChanged = TRUE;
  1545.             }
  1546.         }
  1547.  
  1548.         delete [] m_pMysticStuff;
  1549.         m_pMysticStuff = NULL;
  1550.  
  1551.         if ( m_MysticSelection == MSG_MESSAGEKEYNONE ) {
  1552.             m_iSelection = -1;
  1553.         } else {
  1554.             int iSelection = CASTINT(MSG_GetMessageIndexForKey(m_pPane, m_MysticSelection, TRUE));
  1555.             if (iSelection == -1 ) {
  1556.                 iSelection = MSG_GetNumLines( m_pPane ) > 0 ? 0 : -1;
  1557.                 if (iSelection != -1)
  1558.                     AddSelection( iSelection );
  1559.             }
  1560.             m_iSelection = iSelection;
  1561.         }
  1562.  
  1563.         if ( m_MysticFocus == MSG_MESSAGEKEYNONE ) {
  1564.             m_iFocus = m_iSelection;
  1565.         } else {
  1566.             int iFocus = CASTINT(MSG_GetMessageIndexForKey(m_pPane, m_MysticFocus, TRUE));
  1567.             if ( iFocus == -1 ) {
  1568.                 iFocus = m_iSelection > 0 ? m_iSelection : 0;
  1569.             }
  1570.             m_iFocus = iFocus;
  1571.         }
  1572.         m_iShiftAnchor = m_iFocus;
  1573.     }
  1574.  
  1575.     if ( notify == MSG_NotifyAll ) {
  1576.         MSG_FolderInfo *folderInfo = MSG_GetCurFolder( m_pPane );
  1577.         MSG_FolderLine folderLine;
  1578.         MSG_GetFolderLineById( WFE_MSGGetMaster(),
  1579.                                folderInfo, &folderLine );
  1580.         if ( m_bNews ) {
  1581.             SaveXPPrefs("news.thread_columns_win");
  1582.         } else {
  1583.             SaveXPPrefs("mail.thread_columns_win");
  1584.         }
  1585.  
  1586.         m_bNews = folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ? TRUE : FALSE;
  1587.         m_bDrafts = folderLine.flags & MSG_FOLDER_FLAG_DRAFTS ? TRUE : FALSE;
  1588.  
  1589.         if( m_bNews ) {
  1590.             LoadXPPrefs("news.thread_columns_win");
  1591.         } else {
  1592.             LoadXPPrefs("mail.thread_columns_win");
  1593.         }
  1594.     }
  1595.  
  1596.     CMailNewsOutliner::MysticStuffFinishing( asynchronous, notify,
  1597.                                             where, num);
  1598. }
  1599.  
  1600. // Tree Info stuff
  1601. int CMessageOutliner::GetDepth( int iLine )
  1602. {
  1603.     MSG_MessageLine messageLine;
  1604.     MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
  1605.     return messageLine.level - 1;
  1606. }
  1607.  
  1608. int CMessageOutliner::GetNumChildren( int iLine )
  1609. {
  1610.     MSG_MessageLine messageLine;
  1611.     MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
  1612.     return messageLine.numChildren;
  1613. }
  1614.  
  1615. int CMessageOutliner::GetParentIndex( int iLine )
  1616. {
  1617.     MessageKey key = MSG_GetMessageKey( m_pPane, (MSG_ViewIndex) iLine );
  1618.     return CASTINT(MSG_ThreadIndexOfMsg( m_pPane, key ));
  1619. }
  1620.  
  1621. BOOL CMessageOutliner::IsCollapsed( int iLine )
  1622. {
  1623.     MSG_MessageLine messageLine;
  1624.     MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
  1625.     return messageLine.flags & MSG_FLAG_ELIDED ? TRUE : FALSE;
  1626. }
  1627.  
  1628. int CMessageOutliner::ExpandAll( int iLine )
  1629. {
  1630.     int iDelta = 0;
  1631.     for (int i = GetTotalLines() - 1; i >= 0; i--) {
  1632.         iDelta += Expand(i);
  1633.     }
  1634.     ScrollIntoView(m_iFocus);
  1635.  
  1636.     return iDelta;
  1637. }
  1638.  
  1639. int CMessageOutliner::CollapseAll( int iLine )
  1640. {
  1641.     int iDelta = 0;
  1642.     for (int i = 0; i < GetTotalLines(); i++) {
  1643.         iDelta += Collapse(i);
  1644.     }
  1645.     ScrollIntoView(m_iFocus);
  1646.  
  1647.     return iDelta;
  1648. }
  1649.  
  1650. void CMessageOutliner::SelectThread( int iLine, UINT flags )
  1651. {
  1652.     if ( MSG_GetToggleStatus( m_pPane, MSG_SortByThread, NULL, 0) != MSG_Checked )
  1653.         return;
  1654.  
  1655.     MysticStuffStarting( FALSE, MSG_NotifyNone, 0, 0 );
  1656.     theApp.DoWaitCursor(1);
  1657.  
  1658.     m_bSelChanged = TRUE;
  1659.  
  1660.     MessageKey *keys;
  1661.     MSG_ViewIndex *indices;
  1662.     int i, count;
  1663.     if ( iLine >= 0 ) {
  1664.         if (!(flags & MK_CONTROL )) {
  1665.             ClearSelection();
  1666.         }
  1667.  
  1668.         InvalidateLine(m_iFocus);
  1669.         m_iFocus = m_iSelection = iLine;
  1670.         InvalidateLine(m_iFocus);
  1671.  
  1672.         if ( flags & MK_SHIFT ) {
  1673.             GetSelection( indices, count );
  1674.             if ( count <= 0 )
  1675.                 return;
  1676.  
  1677.             keys = new MessageKey[count];
  1678.  
  1679.             for ( i = 0; i < count; i++ ) {
  1680.                 keys[ i ] = MSG_GetMessageKey( m_pPane, indices[ i ] );
  1681.             }
  1682.         } else {
  1683.             count = 1;
  1684.             keys = new MessageKey[1];
  1685.             keys[0] = MSG_GetMessageKey( m_pPane, (MSG_ViewIndex) iLine );
  1686.         }
  1687.     } else {
  1688.         GetSelection( indices, count );
  1689.         if ( count <= 0 )
  1690.             return;
  1691.  
  1692.         keys = new MessageKey[count];
  1693.  
  1694.         for ( i = 0; i < count; i++ ) {
  1695.             keys[ i ] = MSG_GetMessageKey( m_pPane, indices[ i ] );
  1696.         }
  1697.         ClearSelection();
  1698.     }
  1699.  
  1700.     for ( i = 0; i < count; i++ ) {
  1701.         MSG_ViewIndex index = MSG_ThreadIndexOfMsg( m_pPane, keys[ i ] );
  1702.         int delta = CASTINT(MSG_ExpansionDelta( m_pPane, index ));
  1703.         if ( delta > 0) {
  1704.             MSG_ToggleExpansion( m_pPane, index, NULL );
  1705.         } else {
  1706.             delta = -delta;
  1707.         }    
  1708.         SelectRange( index, index + delta );
  1709.     }
  1710.  
  1711.     delete [] keys;
  1712.  
  1713.     theApp.DoWaitCursor(-1);
  1714.     MysticStuffFinishing( FALSE, MSG_NotifyNone, 0, 0 );
  1715. }
  1716.  
  1717. void CMessageOutliner::SelectFlagged()
  1718. {
  1719.     MSG_MessageLine messageLine;
  1720.  
  1721.     ClearSelection();
  1722.     for (int i = 0; i < m_iTotalLines; i++ ) {
  1723.         if ( MSG_GetThreadLineByIndex( m_pPane, i, 1, &messageLine ) ) {
  1724.             if ( messageLine.flags & MSG_FLAG_MARKED ) {
  1725.                 AddSelection(i);
  1726.             }
  1727.         }
  1728.     }
  1729.     OnSelChanged();
  1730. }
  1731.  
  1732. void CMessageOutliner::EnsureFlagsVisible()
  1733. {
  1734.     int iPos = GetColumnPos(ID_COLUMN_MARK);
  1735.     int iVis = CASTINT(GetVisibleColumns());
  1736.     if (iPos >= iVis) {
  1737.         SetColumnPos(ID_COLUMN_MARK, iVis);
  1738.         SetVisibleColumns(CASTUINT(iVis + 1));
  1739.  
  1740.         RECT rc;
  1741.         GetClientRect(&rc);
  1742.         OnSize(0, rc.right, rc.bottom);
  1743.         Invalidate();
  1744.         GetParent()->Invalidate();
  1745.     }
  1746. }
  1747.  
  1748. void CMessageOutliner::PropertyMenu ( int iSel, UINT flags )    
  1749. {
  1750.     HMENU hmenu = CreatePopupMenu();
  1751.  
  1752.     if ( !hmenu )
  1753.         return;  
  1754.  
  1755.     if ( iSel < m_iTotalLines ) {
  1756.         if (!m_bDrafts) {
  1757.             BOOL bReuse = g_MsgPrefs.m_bMessageReuse;
  1758.             if (GetKeyState(VK_MENU) & 0x8000)
  1759.                 bReuse = !bReuse;
  1760.  
  1761.             if (bReuse) {
  1762.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGEREUSE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
  1763.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGENEW, szLoadString( IDS_POPUP_OPENMESSAGENEWWINDOW ) );
  1764.             } else {
  1765.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGENEW, szLoadString( IDS_POPUP_OPENMESSAGENEWWINDOW ) );
  1766.                 ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGEREUSE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
  1767.             }
  1768.         } else {
  1769.             ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
  1770.         }
  1771.         ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  1772.         //
  1773.         WFE_MSGBuildMessagePopup( hmenu, m_bNews, TRUE );
  1774.     }
  1775.  
  1776.     //    Track the popup now.
  1777.     POINT pt = m_ptHit;
  1778.     ClientToScreen(&pt);
  1779.  
  1780.        ::TrackPopupMenu( hmenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0,
  1781.                       GetParentFrame()->GetSafeHwnd(), NULL);
  1782.  
  1783.     //  Cleanup
  1784.     VERIFY(::DestroyMenu( hmenu ));
  1785. }
  1786.  
  1787. COleDataSource * CMessageOutliner::GetDataSource(void)
  1788. {
  1789.     MSG_ViewIndex *indices;
  1790.     int count;
  1791.  
  1792.     GetSelection( indices, count );
  1793.  
  1794.     HANDLE hContent = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(MailNewsDragData));
  1795.     MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock (hContent);
  1796.     pDragData->m_pane = m_pPane;
  1797.     pDragData->m_indices = indices;
  1798.     pDragData->m_count = count;
  1799.     GlobalUnlock(hContent);
  1800.  
  1801.     COleDataSource * pDataSource = new COleDataSource;  
  1802.     pDataSource->CacheGlobalData(m_cfMessages,hContent);
  1803.  
  1804.     if ( count == 1 ) {
  1805.         MSG_MessageLine messageLine;
  1806.         MSG_GetThreadLineByIndex( m_pPane, indices[0], 1, &messageLine );
  1807.         URL_Struct *url = MSG_ConstructUrlForMessage( m_pPane, messageLine.messageKey );
  1808.  
  1809.         if ( url ) {            
  1810.             RDFGLOBAL_DragTitleAndURL( pDataSource, messageLine.subject, url->address );
  1811.             NET_FreeURLStruct( url );
  1812.         }
  1813.     }
  1814.  
  1815.     return pDataSource;
  1816. }
  1817.  
  1818. void CMessageOutliner::InitializeClipFormats(void)
  1819. {
  1820.     m_cfMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_MESSAGE_FORMAT);
  1821. }
  1822.  
  1823. CLIPFORMAT * CMessageOutliner::GetClipFormatList(void)
  1824. {
  1825.     static CLIPFORMAT cfFormatList[2];
  1826.     cfFormatList[0] = m_cfMessages;
  1827.     cfFormatList[1] = 0;
  1828.  
  1829.     return cfFormatList;
  1830. }
  1831.  
  1832. DROPEFFECT CMessageOutliner::DropSelect( int iLineNo, COleDataObject *pDataObject )
  1833. {
  1834.     DROPEFFECT res = DROPEFFECT_NONE;
  1835.  
  1836.     if ( !m_bNews && pDataObject->IsDataAvailable( m_cfMessages ) )  
  1837.     {
  1838.         MSG_FolderInfo *pFolderInfo = MSG_GetCurFolder( m_pPane );
  1839.         HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
  1840.         MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1841.  
  1842.         MSG_DragEffect requireEffect = MSG_Default_Drag;
  1843.         if ((GetKeyState(VK_SHIFT) & 0x8000) && (GetKeyState(VK_CONTROL) & 0x8000))
  1844.             requireEffect = MSG_Default_Drag;
  1845.         else if (GetKeyState(VK_SHIFT) & 0x8000)
  1846.             requireEffect = MSG_Require_Move;
  1847.         else if (GetKeyState(VK_CONTROL) & 0x8000)
  1848.             requireEffect = MSG_Require_Copy;
  1849.  
  1850.         MSG_DragEffect effect = MSG_DragMessagesIntoFolderStatus
  1851.                 (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1852.                 pFolderInfo, requireEffect);
  1853.  
  1854.         if (effect == MSG_Require_Copy)
  1855.             res = DROPEFFECT_COPY;
  1856.         else
  1857.             res = DROPEFFECT_MOVE;
  1858.  
  1859.         GlobalUnlock (hContent); //do we have to GlobalFree it too?
  1860.     }   
  1861.     return res;
  1862. }
  1863.  
  1864. void CMessageOutliner::AcceptDrop( int iLineNo, COleDataObject *pDataObject,
  1865.                                    DROPEFFECT dropEffect )
  1866. {
  1867.     if ( !m_bNews ) {
  1868.         MSG_FolderInfo *pFolder = MSG_GetCurFolder( m_pPane );
  1869.         ASSERT(pFolder);
  1870.  
  1871.         if ( pDataObject->IsDataAvailable( m_cfMessages ) && pFolder ) {
  1872.             HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
  1873.             MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
  1874.             
  1875.             MSG_DragEffect requireEffect = MSG_Default_Drag;
  1876.             if (dropEffect & DROPEFFECT_MOVE)
  1877.                 requireEffect = MSG_Require_Move;
  1878.             else if (dropEffect & DROPEFFECT_COPY)
  1879.                 requireEffect = MSG_Require_Copy;
  1880.  
  1881.             MSG_DragEffect effect = MSG_DragMessagesIntoFolderStatus
  1882.                     (pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
  1883.                     pFolder, requireEffect);
  1884.             //  need to code this way to make it work 
  1885.             LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
  1886.             if (pUnk) {
  1887.                 LPMSGLIST pInterface = NULL;
  1888.                 pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
  1889.                 if ( pInterface ) {
  1890.                     switch (effect ) {
  1891.                     case MSG_Require_Move:
  1892.                         pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1893.                                                       pDragData->m_count, pFolder);
  1894.                         break;
  1895.                     case MSG_Require_Copy:
  1896.                         pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
  1897.                                                       pDragData->m_count, pFolder);
  1898.                         break;
  1899.                     default:
  1900.                         ASSERT(0);
  1901.                         break;
  1902.                     }
  1903.                 }
  1904.             }  
  1905.             GlobalUnlock(hContent); //do we have to GlobalFree it too?
  1906.         }
  1907.     }
  1908. }
  1909.  
  1910. BOOL CMessageOutliner::RenderData( UINT iColumn, CRect &rect, CDC &dc, LPCTSTR text )
  1911. {
  1912.     switch ( iColumn )
  1913.     {
  1914.     case ID_COLUMN_THREAD:
  1915.         if ((m_MessageLine.level == 0 && m_MessageLine.numChildren > 0) ||
  1916.             (m_MessageLine.flags & (MSG_FLAG_WATCHED|MSG_FLAG_IGNORED))) {
  1917.             int idxImage[] = { IDX_THREADCLOSED, 
  1918.                                 IDX_THREADOPEN,
  1919.                                 IDX_THREADCLOSEDNEW,
  1920.                                 IDX_THREADOPENNEW,
  1921.                                 IDX_THREADWATCHED,
  1922.                                 IDX_THREADWATCHED,
  1923.                                 IDX_THREADWATCHEDNEW,
  1924.                                 IDX_THREADWATCHEDNEW,
  1925.                                 IDX_THREADIGNOREDCLOSED,
  1926.                                 IDX_THREADIGNOREDOPEN,
  1927.                                 IDX_THREADIGNOREDCLOSED,
  1928.                                 IDX_THREADIGNOREDOPEN };
  1929.             int idx = 0;
  1930.             idx += m_MessageLine.flags & MSG_FLAG_ELIDED ? 0 : 1;
  1931.             idx += m_MessageLine.numNewChildren ? 2 : 0;
  1932.             idx += m_MessageLine.flags & MSG_FLAG_WATCHED ? 4 : 0;
  1933.             idx += m_MessageLine.flags & MSG_FLAG_IGNORED ? 8 : 0;
  1934.  
  1935.             m_pIUserImage->DrawImage ( idxImage[idx],
  1936.                 rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), rect.top, &dc, FALSE );
  1937.         }
  1938.         return TRUE;
  1939.  
  1940.     case ID_COLUMN_MARK:
  1941.         {
  1942.             int idxImage = m_MessageLine.flags & MSG_FLAG_MARKED ?
  1943.                            IDX_MARKED : IDX_READ;
  1944.             m_pIUserImage->DrawImage ( idxImage,
  1945.                                        rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), 
  1946.                                        rect.top, &dc, FALSE );
  1947.         }
  1948.         return TRUE;
  1949.  
  1950.     case ID_COLUMN_READ:
  1951.         if (!(m_MessageLine.flags & MSG_FLAG_EXPIRED)) {
  1952.             int idxImage;
  1953.             if (m_MessageLine.flags & MSG_FLAG_READ)
  1954.                 idxImage = IDX_READ;
  1955.             else
  1956.                 idxImage = IDX_UNREAD;
  1957.  
  1958.             m_pIUserImage->DrawImage ( idxImage,
  1959.                 rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), rect.top, &dc, FALSE );
  1960.  
  1961.         }
  1962.         return TRUE;  
  1963.         
  1964.     case ID_COLUMN_PRIORITY: 
  1965.         {
  1966.             CRect rectText(rect);
  1967.             rectText.left += COL_LEFT_MARGIN;
  1968.             rectText.right -= COL_LEFT_MARGIN;
  1969.  
  1970.             COLORREF colorPriority[] = { RGB(0x00,0x00,0x00),
  1971.                                           RGB(0x00,0x00,0x00), 
  1972.                                           RGB(0xaa,0xaa,0xaa),
  1973.                                           RGB(0x55,0x55,0x55),
  1974.                                           RGB(0x00,0x00,0x00),
  1975.                                           RGB(0x80,0x00,0x00),
  1976.                                           RGB(0xff,0x00,0x00) };
  1977.  
  1978.             UINT dwDTFormat = DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER;
  1979.             COLORREF colorOld = dc.GetTextColor();
  1980.  
  1981.             if ( colorOld != GetSysColor( COLOR_HIGHLIGHTTEXT )) { 
  1982.                 dc.SetTextColor( colorPriority[ m_MessageLine.priority ] );
  1983.             }
  1984.  
  1985.             DrawColumnText( dc.m_hDC, rectText, text, CropRight, AlignLeft );
  1986.  
  1987.             dc.SetTextColor( colorOld );
  1988.             return TRUE;
  1989.         }
  1990.         break;
  1991.     }
  1992.     return FALSE;
  1993. }
  1994.  
  1995. int CMessageOutliner::TranslateIcon (void * pData)
  1996. {
  1997.     int messageTable[] = { IDX_MAILMESSAGE,       IDX_MAILNEW,           IDX_MAILREAD,
  1998.                            IDX_MAILMSGOFFLINE, IDX_MAILMSGOFFLINE, IDX_MAILREADOFFLINE,
  1999.                            IDX_NEWSARTICLE,       IDX_NEWSNEW,           IDX_NEWSREAD,
  2000.                            IDX_NEWSMSGOFFLINE, IDX_NEWSMSGOFFLINE, IDX_NEWSREADOFFLINE,
  2001.                            IDX_DRAFT,           IDX_DRAFT,           IDX_DRAFT,
  2002.                            IDX_DRAFT,           IDX_DRAFT,           IDX_DRAFT };
  2003.     ASSERT(pData);
  2004.     MSG_MessageLine * pMessage = (MSG_MessageLine *)pData;
  2005.  
  2006.     if (pMessage->flags & MSG_FLAG_IMAP_DELETED)
  2007.         return IDX_IMAPMSGDELETED;
  2008.  
  2009.     int idx = 0;
  2010.  
  2011.     if (m_bNews)
  2012.         idx = 6;
  2013.     else if (m_bDrafts)
  2014.         idx = 12;
  2015.  
  2016.     if ( pMessage->flags & MSG_FLAG_OFFLINE )
  2017.         idx += 3;
  2018.  
  2019.     if ( pMessage->flags & MSG_FLAG_READ )
  2020.         idx += 2;
  2021.     else if ( pMessage->flags & MSG_FLAG_NEW )
  2022.         idx += 1;
  2023.  
  2024.     return messageTable[idx];
  2025. }
  2026.  
  2027. int CMessageOutliner::TranslateIconFolder (void * pData)
  2028. {
  2029.     ASSERT(pData);
  2030.     MSG_MessageLine * pMessage = (MSG_MessageLine *)pData;
  2031.     
  2032.     if (pMessage->numChildren > 0) {
  2033.         if (pMessage->flags & MSG_FLAG_ELIDED) {
  2034.             return ( OUTLINER_CLOSEDFOLDER );
  2035.         } else {
  2036.             return ( OUTLINER_OPENFOLDER );
  2037.         }
  2038.     } else {
  2039.         return (OUTLINER_ITEM);
  2040.     }
  2041. }
  2042.  
  2043.  
  2044. BOOL CMessageOutliner::ColumnCommand ( int iColumn, int iLine )
  2045. {
  2046.     MSG_ViewIndex indices[1];
  2047.     indices[0] = iLine;
  2048.     
  2049.     switch ( iColumn )
  2050.     {
  2051.     case ID_COLUMN_THREAD:
  2052.         if ( MSG_GetToggleStatus( m_pPane, MSG_SortByThread, NULL, 0) == MSG_Checked ) {
  2053.             SelectThread( iLine );
  2054.             return TRUE;
  2055.         } else {
  2056.             return FALSE;
  2057.         }
  2058.  
  2059.     case ID_COLUMN_READ:
  2060.         if (!(m_MessageLine.flags & MSG_FLAG_EXPIRED)) 
  2061.             MSG_Command(m_pPane, MSG_ToggleMessageRead, indices, 1);
  2062.         return TRUE;
  2063.     case ID_COLUMN_MARK:
  2064.         {
  2065.             MSG_MessageLine messageLine;
  2066.             MSG_ViewIndex index = iLine;
  2067.  
  2068.             MSG_GetThreadLineByIndex( m_pPane, index, 1, &messageLine );
  2069.  
  2070.             MSG_Command( m_pPane, 
  2071.                          ( messageLine.flags & MSG_FLAG_MARKED) ? 
  2072.                          MSG_UnmarkMessages : MSG_MarkMessages,
  2073.                          &index, 1 );
  2074.  
  2075.             return TRUE;
  2076.         }
  2077.     }
  2078.  
  2079.     return FALSE;
  2080. }
  2081.  
  2082. void * CMessageOutliner::AcquireLineData ( int line )
  2083. {
  2084.     if ( line >= m_iTotalLines)
  2085.         return NULL;
  2086.  
  2087.     if ( !MSG_GetThreadLineByIndex(m_pPane, line, 1, &m_MessageLine ) )
  2088.         return NULL;
  2089.  
  2090.     return &m_MessageLine; 
  2091. }
  2092.  
  2093. void CMessageOutliner::GetTreeInfo ( int iLine, uint32 * pFlags, int * pDepth, 
  2094.                                      OutlinerAncestorInfo ** pAncestor )
  2095. {
  2096.     delete [] m_pAncestor;
  2097.     m_pAncestor = NULL;
  2098.  
  2099.     if ( pAncestor ) {
  2100.         m_pAncestor = new OutlinerAncestorInfo[m_MessageLine.level + 1];
  2101.  
  2102.         int i = m_MessageLine.level;
  2103.         int idx = iLine + 1;
  2104.         while ( i > 0 ) {
  2105.             if ( idx < m_iTotalLines ) {
  2106.                 int level = MSG_GetThreadLevelByIndex( m_pPane, idx );
  2107.                 if ( level == i ) {
  2108.                     m_pAncestor[i].has_prev = TRUE;
  2109.                     m_pAncestor[i].has_next = TRUE;
  2110.                     i--;
  2111.                     idx++;
  2112.                 } else if ( level < i ) {
  2113.                     m_pAncestor[i].has_prev = FALSE;
  2114.                     m_pAncestor[i].has_next = FALSE;
  2115.                     i--;
  2116.                 } else {
  2117.                     idx++;
  2118.                 }
  2119.             } else {
  2120.                 m_pAncestor[i].has_prev = FALSE;
  2121.                 m_pAncestor[i].has_next = FALSE;
  2122.                 i--;
  2123.             }
  2124.         }
  2125.         m_pAncestor[0].has_prev = FALSE;
  2126.         m_pAncestor[0].has_next = FALSE;
  2127.         *pAncestor = m_pAncestor;
  2128.     }
  2129.  
  2130.     if ( pFlags ) *pFlags = m_MessageLine.flags;
  2131.     if ( pDepth ) *pDepth = m_MessageLine.level;
  2132. }
  2133.  
  2134. HFONT CMessageOutliner::GetLineFont ( void * )
  2135. {
  2136.     if ( m_MessageLine.flags & MSG_FLAG_EXPIRED )
  2137.         return m_hRegFont;
  2138.  
  2139.     return (!(m_MessageLine.flags & MSG_FLAG_READ) ? m_hBoldFont : m_hRegFont);
  2140. }
  2141.  
  2142. void CMessageOutliner::ReleaseLineData ( void * )
  2143. {
  2144.     delete [] m_pAncestor;
  2145.     m_pAncestor = NULL;
  2146. }
  2147.  
  2148. LPCTSTR CMessageOutliner::GetColumnText ( UINT iColumn, void * pLineData )
  2149. {
  2150.     LPTSTR buf;   // temporary buffer for mail header conversion (I18N)
  2151.     m_pszExtraText[ 0 ] = _T('\0');
  2152.     m_pszExtraText[ EXTRATEXT_SIZE - 1 ] = _T('\0');
  2153.  
  2154.     switch ( iColumn )
  2155.     {
  2156.         case ID_COLUMN_FROM:
  2157.             {
  2158.                 buf = IntlDecodeMimePartIIStr(m_MessageLine.author, INTL_DocToWinCharSetID(m_iCSID), FALSE);
  2159.                 if (buf)
  2160.                 {
  2161.                     _tcsncpy(m_pszExtraText, buf, EXTRATEXT_SIZE - 1);
  2162.                     XP_FREE(buf);
  2163.                     return m_pszExtraText;
  2164.                 }
  2165.                 return m_MessageLine.author;
  2166.             }
  2167.         case ID_COLUMN_SUBJECT:
  2168.               { 
  2169.                 CString cs = _T("");
  2170.                 if ( m_MessageLine.flags & MSG_FLAG_HAS_RE ) {
  2171.                     cs.LoadString(IDS_MAIL_RE);
  2172.                 }
  2173.                 _tcscpy ( m_pszExtraText, cs );
  2174.                 buf = IntlDecodeMimePartIIStr(m_MessageLine.subject, INTL_DocToWinCharSetID(m_iCSID), FALSE);
  2175.                 if (buf) {
  2176.                     _tcsncat ( m_pszExtraText, buf, 
  2177.                                EXTRATEXT_SIZE - cs.GetLength() - 1);
  2178.                     XP_FREE(buf);
  2179.                 } else {
  2180.                     _tcsncat ( m_pszExtraText, m_MessageLine.subject,
  2181.                                EXTRATEXT_SIZE - cs.GetLength() - 1);
  2182.                 }
  2183.                 return m_pszExtraText;
  2184.             }
  2185.         case ID_COLUMN_DATE:
  2186.             {
  2187.                 if ( m_MessageLine.flags & MSG_FLAG_EXPIRED )
  2188.                     return _T("");
  2189.                 _tcscpy ( m_pszExtraText, MSG_FormatDate(m_pPane,m_MessageLine.date));
  2190.                 return m_pszExtraText;
  2191.             }
  2192.         case ID_COLUMN_PRIORITY:
  2193.             if ( m_MessageLine.priority != MSG_NoPriority && 
  2194.                  m_MessageLine.priority != MSG_PriorityNotSet &&
  2195.                  m_MessageLine.priority != MSG_NormalPriority) {
  2196.                 MSG_GetPriorityName( m_MessageLine.priority, m_pszExtraText, MSG_FLAG_EXPIRED);
  2197.             }
  2198.             return m_pszExtraText;
  2199.         case ID_COLUMN_STATUS:
  2200.             if (m_MessageLine.flags & MSG_FLAG_NEW) {
  2201.                 MSG_GetStatusName( MSG_FLAG_NEW,
  2202.                                    m_pszExtraText, EXTRATEXT_SIZE);
  2203.                 return m_pszExtraText;
  2204.             }
  2205.             if ( m_MessageLine.flags & MSG_FLAG_REPLIED &&
  2206.                  m_MessageLine.flags & MSG_FLAG_FORWARDED ) {
  2207.                 MSG_GetStatusName( MSG_FLAG_REPLIED|MSG_FLAG_FORWARDED,
  2208.                                    m_pszExtraText, EXTRATEXT_SIZE);
  2209.                 return m_pszExtraText;
  2210.             }
  2211.             else if ( m_MessageLine.flags & MSG_FLAG_FORWARDED ) {
  2212.                 MSG_GetStatusName( MSG_FLAG_FORWARDED,
  2213.                                    m_pszExtraText, EXTRATEXT_SIZE);
  2214.                 return m_pszExtraText;
  2215.             }
  2216.             else if ( m_MessageLine.flags & MSG_FLAG_REPLIED ) {
  2217.                 MSG_GetStatusName( MSG_FLAG_REPLIED,
  2218.                                    m_pszExtraText, EXTRATEXT_SIZE);
  2219.                 return m_pszExtraText;
  2220.             }
  2221.             
  2222.             break;
  2223.         case ID_COLUMN_LENGTH:
  2224.             if (m_bNews) {
  2225.                 _stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.messageLines );
  2226.             } else {
  2227.                 _TCHAR cSuffix = _T(' ');
  2228.                 int32 iSize = m_MessageLine.messageLines;
  2229.                 if ( iSize > 1L<<30 ) {
  2230.                     iSize /= 1L<<30;
  2231.                     cSuffix = _T('G');
  2232.                 } else if ( iSize > 1L<<20 ) {
  2233.                     iSize /= 1L<<20;
  2234.                     cSuffix = _T('M');
  2235.                 } else if ( iSize > 1L<<10 ) {
  2236.                     iSize /= 1L<<10;
  2237.                     cSuffix = _T('K');
  2238.                 } else {
  2239.                     iSize = 1;
  2240.                     cSuffix = _T('K');
  2241.                 }
  2242.                 _stprintf( m_pszExtraText, _T("%d%cB"), (int) iSize, cSuffix );
  2243.             }
  2244.             return m_pszExtraText;
  2245.  
  2246.         case ID_COLUMN_UNREAD:
  2247.             if (m_MessageLine.numNewChildren) {
  2248.                 _stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.numNewChildren );
  2249.                 return m_pszExtraText;
  2250.             }
  2251.             break;
  2252.         case ID_COLUMN_COUNT:
  2253.             if (m_MessageLine.numChildren) {
  2254.                 _stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.numChildren + 1 );
  2255.                 return m_pszExtraText;
  2256.             }
  2257.             break;
  2258.     }
  2259.     return ("");
  2260. }
  2261.  
  2262. void CMessageOutliner::OnDestroy()
  2263. {
  2264.     if (m_uTimer)
  2265.     {
  2266.         KillTimer(m_uTimer);
  2267.         m_uTimer = 0;
  2268.     }
  2269.     CMailNewsOutliner::OnDestroy();
  2270. }
  2271.  
  2272. void CMessageOutliner::OnLButtonDown(UINT nFlags, CPoint point)
  2273. {
  2274.     m_bLButtonDown = TRUE;
  2275.     CMailNewsOutliner::OnLButtonDown(nFlags, point);
  2276. }
  2277.  
  2278. void CMessageOutliner::OnTimer(UINT nIDEvent)
  2279. {
  2280.     if (m_uTimer == nIDEvent)
  2281.     {
  2282.         if (m_bDoubleClicked)
  2283.         {
  2284.             m_bDoubleClicked = FALSE;
  2285.             KillTimer(m_uTimer);
  2286.             m_uTimer = 0;
  2287.         }
  2288.         else
  2289.         {
  2290.             UINT delta = GetTickCount() - m_dwPrevTime;
  2291.             if (delta > GetDoubleClickTime())
  2292.             {    // single click
  2293.                 m_bSelChanged = FALSE;
  2294.                 if (GetCurrentSelected() != m_iSelection)
  2295.                 {
  2296.                     if (!m_iSelBlock)
  2297.                         GetParentFrame()->PostMessage(WM_COMMAND, ID_MESSAGE_SELECT, 0);
  2298.                 }
  2299.                 KillTimer(m_uTimer);
  2300.                 m_uTimer = 0;
  2301.             }
  2302.         }
  2303.         m_bLButtonDown = FALSE;
  2304.     }
  2305.     else
  2306.         CMailNewsOutliner::OnTimer(nIDEvent);
  2307. }
  2308.  
  2309. void CMessageOutliner::OnSelChanged()
  2310. {
  2311.     SetCurrentSelected(m_iLastSelected);
  2312.     if (m_bLButtonDown && m_uTimer == 0 && !m_bDoubleClicked)
  2313.     {
  2314.         m_dwPrevTime = GetTickCount();
  2315.         UINT uElapse = GetDoubleClickTime() / 5;
  2316.         m_uTimer = SetTimer(DOUBLE_CLICK_TIMER, uElapse, NULL);
  2317.     }
  2318.     else
  2319.     {
  2320.         if (!m_bDoubleClicked)
  2321.         {
  2322.             m_bSelChanged = FALSE;   
  2323.             if (!m_iSelBlock)
  2324.                 GetParentFrame()->PostMessage(WM_COMMAND, ID_MESSAGE_SELECT, 0);
  2325.         }
  2326.     }
  2327. }
  2328.  
  2329. void CMessageOutliner::OnSelDblClk()
  2330. {
  2331.     if (m_bLButtonDown && m_uTimer != 0)
  2332.         m_bDoubleClicked = TRUE;
  2333.  
  2334.     GetParentFrame()->PostMessage(WM_COMMAND, ID_FILE_OPENMESSAGE, 0);
  2335. }
  2336.  
  2337. BEGIN_MESSAGE_MAP(CMessageOutliner, CMailNewsOutliner)
  2338.     ON_WM_LBUTTONDOWN()
  2339.     ON_WM_TIMER()
  2340.     ON_WM_DESTROY()
  2341. END_MESSAGE_MAP()
  2342.  
  2343. /////////////////////////////////////////////////////////////////////////////
  2344. // CFolderOutlinerParent
  2345.  
  2346. CFolderOutlinerParent::CFolderOutlinerParent()
  2347. {
  2348.     m_pUnkUserImage = NULL;
  2349.     ApiApiPtr(api);
  2350.     m_pUnkUserImage = api->CreateClassInstance(
  2351.         APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILCOL);
  2352.     m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
  2353.     ASSERT(m_pIUserImage);
  2354.     if (!m_pIUserImage->GetResourceID())
  2355.         m_pIUserImage->Initialize(IDB_MAILCOL,16,16);
  2356. }
  2357.  
  2358. CFolderOutlinerParent::~CFolderOutlinerParent()
  2359. {
  2360.     if (m_pUnkUserImage) {
  2361.         if (m_pIUserImage)
  2362.             m_pUnkUserImage->Release();
  2363.     }
  2364. }
  2365.  
  2366. COutliner * CFolderOutlinerParent::GetOutliner ( void )
  2367. {
  2368.     return new CFolderOutliner;
  2369. }
  2370.  
  2371. typedef struct COLUMNDESC {
  2372.     UINT idCol;
  2373.     UINT idTitle;
  2374.     int nWidth;
  2375.     BOOL bButton;
  2376.     Column_t styleColumn;
  2377.     CropType_t styleCrop;
  2378.     AlignType_t styleAlign;
  2379. } ColumnDesc_t;
  2380.  
  2381. static ColumnDesc_t aidFolderColumns[] = 
  2382.     { { ID_COLUMN_FOLDER, IDS_MAIL_NAME,   6000, FALSE, ColumnVariable, CropRight, AlignLeft },
  2383.       { ID_COLUMN_UNREAD, IDS_MAIL_UNREAD, 2000, FALSE, ColumnVariable, CropRight, AlignRight },
  2384.       { ID_COLUMN_COUNT,  IDS_MAIL_TOTAL,  2000, FALSE, ColumnVariable, CropRight, AlignRight } };
  2385.  
  2386. void CFolderOutlinerParent::CreateColumns ( void )
  2387. {
  2388.     ColumnDesc_t *pColumns;
  2389.     int nColumns;
  2390.     int i;
  2391.  
  2392.     nColumns = sizeof( aidFolderColumns ) / sizeof ( ColumnDesc_t );
  2393.     pColumns = aidFolderColumns;
  2394.  
  2395.     CString cs;
  2396.     
  2397.     for ( i = 0; i < nColumns; i++ ) {
  2398.         int nMin = pColumns[i].styleColumn == ColumnFixed ? 20 : pColumns[i].nWidth;
  2399.         int nDefault = pColumns[i].nWidth;
  2400.  
  2401.         if ( pColumns[i].idTitle ) {
  2402.             cs.LoadString(pColumns[i].idTitle);
  2403.         } else {
  2404.             cs = _T("");
  2405.         }
  2406.         m_pOutliner->AddColumn ( cs, 
  2407.                                  pColumns[i].idCol, 
  2408.                                  nMin, 0, 
  2409.                                  pColumns[i].styleColumn,
  2410.                                  nDefault, 
  2411.                                  pColumns[i].bButton, 
  2412.                                  pColumns[i].styleCrop,
  2413.                                  pColumns[i].styleAlign );
  2414.     }
  2415.  
  2416.     m_pOutliner->SetImageColumn( ID_COLUMN_FOLDER );
  2417.  
  2418.     if (((CFolderOutliner*)m_pOutliner)->IsParent3PaneFrame())
  2419.         m_pOutliner->LoadXPPrefs("mailnews.3Pane_folder_columns_win");
  2420.     else
  2421.         m_pOutliner->LoadXPPrefs("mailnews.folder_columns_win");
  2422. }
  2423.  
  2424. BEGIN_MESSAGE_MAP(CFolderOutlinerParent,COutlinerParent)
  2425.     ON_WM_DESTROY()
  2426. END_MESSAGE_MAP()
  2427.  
  2428. void CFolderOutlinerParent::OnDestroy()
  2429. {
  2430.     if (((CFolderOutliner*)m_pOutliner)->IsParent3PaneFrame())
  2431.         m_pOutliner->SaveXPPrefs("mailnews.3Pane_folder_columns_win");
  2432.     else
  2433.         m_pOutliner->SaveXPPrefs( "mailnews.folder_columns_win" );
  2434.  
  2435.     COutlinerParent::OnDestroy();
  2436. }
  2437.  
  2438. /////////////////////////////////////////////////////////////////////////////
  2439. // CMessageOutlinerParent
  2440.  
  2441. CMessageOutlinerParent::CMessageOutlinerParent()
  2442. {
  2443.     m_pUnkUserImage = NULL;
  2444.     ApiApiPtr(api);
  2445.     m_pUnkUserImage = api->CreateClassInstance(
  2446.         APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILCOL);
  2447.     m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
  2448.     ASSERT(m_pIUserImage);
  2449.     if (!m_pIUserImage->GetResourceID())
  2450.         m_pIUserImage->Initialize(IDB_MAILCOL,16,16);
  2451. }
  2452.  
  2453. CMessageOutlinerParent::~CMessageOutlinerParent()
  2454. {
  2455.     if (m_pUnkUserImage) {
  2456.         if (m_pIUserImage)
  2457.             m_pUnkUserImage->Release();
  2458.     }
  2459. }
  2460.  
  2461. BOOL CMessageOutlinerParent::RenderData ( int idColumn, CRect & rect, CDC &dc, LPCTSTR text )
  2462. {
  2463.     MSG_Pane *pPane = ((CMailNewsOutliner *) m_pOutliner)->GetPane();
  2464.     ASSERT(pPane);
  2465.     MSG_COMMAND_CHECK_STATE sortType = MSG_Unchecked;
  2466.  
  2467.     switch (idColumn) {
  2468.         case ID_COLUMN_READ:
  2469.         case ID_COLUMN_THREAD:
  2470.         case ID_COLUMN_MARK:
  2471.             {
  2472.                 int idxImage;
  2473.                 switch (idColumn) {
  2474.                 case ID_COLUMN_READ:
  2475.                     idxImage = IDX_MAILUNREAD;
  2476.                     break;
  2477.                 case ID_COLUMN_THREAD:
  2478.                     if (MSG_GetToggleStatus(pPane, MSG_SortByThread, NULL, 0) == MSG_Checked) {
  2479.                         idxImage = IDX_THREAD;
  2480.                     } else {
  2481.                         idxImage = IDX_UNTHREAD;
  2482.                     }
  2483.                     break;
  2484.                 case ID_COLUMN_MARK:
  2485.                     idxImage = IDX_MAILMARKED;
  2486.                     break;
  2487.                 }
  2488.                 m_pIUserImage->DrawTransImage( idxImage,
  2489.                                                (rect.left + rect.right + 1) / 2 - 8,
  2490.                                                (rect.top + rect.bottom + 1) / 2 - 8, &dc );
  2491.             }
  2492.         return TRUE;
  2493.         case ID_COLUMN_DATE:
  2494.             sortType = MSG_GetToggleStatus(pPane, MSG_SortByDate, NULL, 0);
  2495.             break;
  2496.         case ID_COLUMN_SUBJECT:
  2497.             sortType = MSG_GetToggleStatus(pPane, MSG_SortBySubject, NULL, 0);
  2498.             break;
  2499.         case ID_COLUMN_FROM:
  2500.             sortType = MSG_GetToggleStatus(pPane, MSG_SortBySender, NULL, 0);
  2501.             break;
  2502.         case ID_COLUMN_PRIORITY:
  2503.             sortType = MSG_GetToggleStatus(pPane, MSG_SortByPriority, NULL, 0);
  2504.             break;
  2505.         case ID_COLUMN_STATUS:
  2506.             sortType = MSG_GetToggleStatus(pPane, MSG_SortByStatus, NULL, 0);
  2507.             break;
  2508.         case ID_COLUMN_LENGTH:
  2509.             sortType = MSG_GetToggleStatus(pPane, MSG_SortBySize, NULL, 0);
  2510.             break;
  2511.         default:
  2512.             return FALSE;
  2513.     }
  2514.  
  2515.     UINT dwDTFormat = DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER;
  2516.  
  2517.  
  2518.     CString csTitle = text;
  2519.     if ( MSG_DisplayingRecipients( pPane ) && idColumn == ID_COLUMN_FROM ) {
  2520.         csTitle.LoadString( IDS_MAIL_RECIPIENT );
  2521.     }
  2522.     if ( idColumn == ID_COLUMN_LENGTH ) {
  2523.         dwDTFormat |= DT_RIGHT;
  2524.         if (!((CMessageOutliner *)m_pOutliner)->IsNews())
  2525.             csTitle.LoadString( IDS_SIZE );
  2526.     }
  2527.  
  2528.     RECT rectText = rect;
  2529.     rectText.left += COL_LEFT_MARGIN;
  2530.     rectText.right -= COL_LEFT_MARGIN + 1;
  2531.  
  2532.     if (sortType == MSG_Checked) {
  2533.         rectText.right -= 14;
  2534.         int idxImage;
  2535.         if (MSG_GetToggleStatus( pPane,MSG_SortBackward, NULL, 0) == MSG_Checked )
  2536.             idxImage = IDX_SORTINDICATORUP;
  2537.         else
  2538.             idxImage = IDX_SORTINDICATORDOWN;
  2539.         m_pIImage->DrawTransImage( idxImage,
  2540.                                    rectText.right + 4,
  2541.                                    (rect.top + rect.bottom) / 2 - 4,
  2542.                                    &dc );
  2543.     }
  2544.  
  2545.     WFE_DrawTextEx( 0, dc.m_hDC, (LPTSTR) (LPCTSTR) csTitle, -1, 
  2546.                     &rectText, dwDTFormat, WFE_DT_CROPRIGHT );
  2547.  
  2548.     return TRUE;
  2549. }
  2550.  
  2551. COutliner * CMessageOutlinerParent::GetOutliner ( void )
  2552. {
  2553.     return new CMessageOutliner;
  2554. }
  2555.  
  2556. static ColumnDesc_t aidMessageColumns[] = 
  2557.     { { ID_COLUMN_THREAD,    0,                   24,   TRUE, ColumnFixed,    CropRight, AlignLeft },
  2558.       { ID_COLUMN_SUBJECT,    IDS_MAIL_SUBJECT,  2500, TRUE, ColumnVariable, CropRight, AlignLeft },
  2559.       { ID_COLUMN_READ,        0,                   24,   TRUE, ColumnFixed,       CropRight, AlignLeft },
  2560.       { ID_COLUMN_FROM,        IDS_MAIL_SENDER,   2500, TRUE, ColumnVariable, CropRight, AlignLeft },
  2561.       { ID_COLUMN_DATE,        IDS_MAIL_DATE,       1500, TRUE, ColumnVariable, CropRight, AlignLeft },
  2562.       { ID_COLUMN_PRIORITY, IDS_MAIL_PRIORITY, 1000, TRUE, ColumnVariable, CropRight, AlignLeft },
  2563.       { ID_COLUMN_MARK,        0,                   24,   TRUE, ColumnFixed,       CropRight, AlignLeft },
  2564.       { ID_COLUMN_STATUS,    IDS_MAIL_STATUS,   750,  TRUE, ColumnVariable, CropRight, AlignLeft },
  2565.       { ID_COLUMN_LENGTH,    IDS_MAIL_LENGTH,   750,  TRUE, ColumnVariable, CropRight, AlignRight },
  2566.       { ID_COLUMN_UNREAD,    IDS_MAIL_UNREAD,   500,  FALSE, ColumnVariable, CropRight, AlignRight },
  2567.       { ID_COLUMN_COUNT,    IDS_MAIL_TOTAL,    500,  FALSE, ColumnVariable, CropRight, AlignRight } };
  2568.  
  2569. void CMessageOutlinerParent::CreateColumns ( void )
  2570. {
  2571.     ColumnDesc_t *pColumns;
  2572.     int nColumns;
  2573.     int i;
  2574.  
  2575.     nColumns = sizeof( aidMessageColumns ) / sizeof ( ColumnDesc_t );
  2576.     pColumns = aidMessageColumns;
  2577.  
  2578.     CString cs;
  2579.     
  2580.     for ( i = 0; i < nColumns; i++ ) {
  2581.         int nMin = pColumns[i].styleColumn == ColumnFixed ? 20 : pColumns[i].nWidth;
  2582.         int nDefault = pColumns[i].nWidth;
  2583.  
  2584.         if ( pColumns[i].idTitle ) {
  2585.             cs.LoadString(pColumns[i].idTitle);
  2586.         } else {
  2587.             cs = _T("");
  2588.         }
  2589.         m_pOutliner->AddColumn ( cs, 
  2590.                                  pColumns[i].idCol, 
  2591.                                  nMin, 0, 
  2592.                                  pColumns[i].styleColumn,
  2593.                                  nDefault, 
  2594.                                  pColumns[i].bButton, 
  2595.                                  pColumns[i].styleCrop,
  2596.                                  pColumns[i].styleAlign );
  2597.     }
  2598.  
  2599.     m_pOutliner->SetVisibleColumns( 6 );
  2600.     m_pOutliner->SetImageColumn( ID_COLUMN_SUBJECT );
  2601.  
  2602.     if ( ((CMessageOutliner *) m_pOutliner)->IsNews() ) {
  2603.         m_pOutliner->LoadXPPrefs("news.thread_columns_win");
  2604.     } else {
  2605.         m_pOutliner->LoadXPPrefs("mail.thread_columns_win");
  2606.     }
  2607.  }
  2608.  
  2609. BOOL CMessageOutlinerParent::ColumnCommand ( int nColumn )
  2610. {
  2611.     UINT iCommand = 0;
  2612.  
  2613.     switch ( nColumn ) {
  2614.     case ID_COLUMN_FROM:
  2615.         iCommand = ID_SORT_BYSENDER;
  2616.         break;
  2617.  
  2618.     case ID_COLUMN_SUBJECT:
  2619.         iCommand = ID_SORT_BYSUBJECT;
  2620.         break;
  2621.  
  2622.     case ID_COLUMN_DATE:
  2623.         iCommand = ID_SORT_BYDATE;
  2624.         break;
  2625.  
  2626.     case ID_COLUMN_THREAD:
  2627.         iCommand = ID_SORT_BYTHREAD;
  2628.         break;
  2629.  
  2630.     case ID_COLUMN_PRIORITY:
  2631.         iCommand = ID_SORT_BYPRIORITY;
  2632.         break;
  2633.  
  2634.     case ID_COLUMN_STATUS:
  2635.         iCommand = ID_SORT_BYSTATUS;
  2636.         break;
  2637.  
  2638.     case ID_COLUMN_LENGTH:
  2639.         iCommand = ID_SORT_BYSIZE;
  2640.         break;
  2641.  
  2642.     case ID_COLUMN_MARK:
  2643.         iCommand = ID_SORT_BYFLAG;
  2644.         break;
  2645.  
  2646.     case ID_COLUMN_READ:
  2647.         iCommand = ID_SORT_BYUNREAD;
  2648.         break;
  2649.     }
  2650.  
  2651.     if ( iCommand ) {
  2652.         SetCursor ( theApp.LoadStandardCursor ( IDC_WAIT ) );
  2653.         GetParentFrame()->SendMessage(WM_COMMAND, iCommand, 0 );
  2654.         SetCursor ( theApp.LoadStandardCursor ( IDC_ARROW ) );
  2655.     }
  2656.  
  2657.     return 0;
  2658. }
  2659.  
  2660. BEGIN_MESSAGE_MAP(CMessageOutlinerParent,COutlinerParent)
  2661.     ON_WM_DESTROY()
  2662. END_MESSAGE_MAP()
  2663.  
  2664.  
  2665. void CMessageOutlinerParent::OnDestroy()
  2666. {
  2667.     if ( ((CMessageOutliner *) m_pOutliner)->IsNews() )
  2668.         m_pOutliner->SaveXPPrefs("news.thread_columns_win");
  2669.     else
  2670.         m_pOutliner->SaveXPPrefs("mail.thread_columns_win");
  2671.  
  2672.     COutlinerParent::OnDestroy();
  2673. }
  2674.  
  2675. //////////////////////////////////////////////////////////////////////////////
  2676. // CMarkReadDateDlg
  2677.  
  2678. BOOL CMarkReadDateDlg::OnInitDialog( )
  2679. {
  2680.     BOOL res = CDialog::OnInitDialog();
  2681.  
  2682.     wndDateTo.SubclassDlgItem(IDC_STATIC1, this);
  2683.  
  2684.     CTime timeTmp = CTime::GetCurrentTime();
  2685.     wndDateTo.SetDate( timeTmp );
  2686.  
  2687.     return res;
  2688. }
  2689.  
  2690. void CMarkReadDateDlg::OnOK()
  2691. {
  2692.     wndDateTo.GetDate(dateTo);
  2693.     CDialog::OnOK();
  2694. }
  2695.  
  2696.  
  2697. /////////////////////////////////////////////////////////////////////////////
  2698. // C function shared by CMailFolderHelper and preference
  2699.  
  2700. extern "C" void HelperInitFonts( HDC hdc , HFONT *phFont, HFONT *phBoldFont)
  2701. {
  2702.     uint16 csid = INTL_CharSetNameToID(INTL_ResourceCharSet());
  2703.  
  2704.     LOGFONT lf;                               
  2705.     memset(&lf,0,sizeof(LOGFONT));
  2706.  
  2707.     lf.lfPitchAndFamily = FF_SWISS;
  2708.     lf.lfCharSet = IntlGetLfCharset( csid );
  2709.     if ( csid == CS_LATIN1 )
  2710.          _tcscpy( lf.lfFaceName, "MS Sans Serif" );
  2711.     else
  2712.          _tcscpy( lf.lfFaceName, IntlGetUIPropFaceName( csid ) );
  2713.        lf.lfHeight = -MulDiv( 9, ::GetDeviceCaps( hdc, LOGPIXELSY ), 72);
  2714.     *phFont = theApp.CreateAppFont( lf );
  2715.     lf.lfWeight = 700;
  2716.     *phBoldFont = theApp.CreateAppFont( lf );
  2717. }
  2718.  
  2719. extern "C" void HelperDoMeasureItem( HWND hWnd, LPMEASUREITEMSTRUCT lpMeasureItemStruct )
  2720. {
  2721.     lpMeasureItemStruct->itemHeight = 16;
  2722. }
  2723.  
  2724. extern "C" void HelperDoDrawItem
  2725. ( HWND hWnd, LPDRAWITEMSTRUCT lpDrawItemStruct, HFONT *phFont, HFONT *phBoldFont,
  2726.   MSG_Master *pMaster, BOOL bStaticCtl, int iInitialDepth, LPIMAGEMAP pIImageMap, 
  2727.   BOOL bNoPrettyName)
  2728. {
  2729.     HDC hDC = lpDrawItemStruct->hDC;
  2730.     RECT rcItem = lpDrawItemStruct->rcItem;
  2731.     RECT rcTemp = rcItem;
  2732.     RECT rcText;
  2733.     DWORD dwItemData = lpDrawItemStruct->itemData;
  2734.     HBRUSH hBrushWindow = ::CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
  2735.     HBRUSH hBrushHigh = ::CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) );
  2736.     HBRUSH hBrushFill = NULL;
  2737.  
  2738.     if ( !*phFont ) {
  2739.         HelperInitFonts( hDC, phFont, phBoldFont);
  2740.     }
  2741.  
  2742.     HFONT hOldFont = NULL;
  2743.     if ( *phFont ) {
  2744.         hOldFont = (HFONT) ::SelectObject( hDC, *phFont );
  2745.     }
  2746.  
  2747.     if ( lpDrawItemStruct->itemState & ODS_SELECTED ) {
  2748.         hBrushFill = hBrushHigh;
  2749.         ::SetBkColor( hDC, GetSysColor( COLOR_HIGHLIGHT ) );
  2750.         ::SetTextColor( hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
  2751.     } else {
  2752.         hBrushFill = hBrushWindow;
  2753.         ::SetBkColor( hDC, GetSysColor( COLOR_WINDOW ) );
  2754.         ::SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );
  2755.     }
  2756.  
  2757.     VERIFY(::FillRect( hDC, &rcItem, hBrushWindow ));
  2758.  
  2759.     if ( lpDrawItemStruct->itemID != -1 &&  dwItemData ) {
  2760.         MSG_FolderInfo *folderInfo = (MSG_FolderInfo *) dwItemData;
  2761.         MSG_FolderLine folderLine;
  2762.         MSG_GetFolderLineById( pMaster, folderInfo, &folderLine);
  2763.  
  2764.         int idxImage = WFE_MSGTranslateFolderIcon( folderLine.level,
  2765.                                                    folderLine.flags, 
  2766.                                                    folderLine.numChildren );
  2767.  
  2768.         if ( *phBoldFont && folderLine.unseen > 0 ) {
  2769.             ::SelectObject( hDC, *phBoldFont );
  2770.         }
  2771.         int iIndent = 4;
  2772.  
  2773.         BOOL bStatic = FALSE;
  2774. #ifdef _WIN32
  2775.     if ( sysInfo.m_bWin4 )
  2776.         bStatic = ( lpDrawItemStruct->itemState & ODS_COMBOBOXEDIT ) ? TRUE : FALSE;
  2777.     else 
  2778. #endif
  2779.         bStatic = bStaticCtl;
  2780.  
  2781.         if (!bStatic)
  2782.             iIndent += (folderLine.level - iInitialDepth) * 8;
  2783.  
  2784.         pIImageMap->DrawImage( idxImage, iIndent, rcItem.top, hDC, FALSE );
  2785.  
  2786.         LPCTSTR name;
  2787.         if (bNoPrettyName)
  2788.             name = folderLine.name;
  2789.         else
  2790.         {
  2791.             name = (LPCTSTR) folderLine.prettyName;
  2792.             if ( !name || !name[0] )
  2793.                 name = folderLine.name;
  2794.         }
  2795.  
  2796.         ::DrawText( hDC, name, -1, &rcTemp, DT_SINGLELINE|DT_CALCRECT|DT_NOPREFIX );
  2797.         int iWidth = rcTemp.right - rcTemp.left;
  2798.  
  2799.         rcTemp = rcItem;
  2800.         rcText = rcItem;
  2801.         rcTemp.left = iIndent + 20;
  2802.         rcTemp.right = rcTemp.left + iWidth + 4;
  2803.         if (rcTemp.right > rcItem.right)
  2804.             rcTemp.right = rcItem.right;
  2805.  
  2806.         VERIFY(::FillRect( hDC, &rcTemp, hBrushFill ));
  2807.         rcText.left = rcTemp.left + 2;
  2808.         rcText.right = rcTemp.right - 2;
  2809.         ::DrawText( hDC, name, -1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX );
  2810.  
  2811.         if ( lpDrawItemStruct->itemAction & ODA_FOCUS && 
  2812.              lpDrawItemStruct->itemState & ODS_SELECTED ) {
  2813.             ::DrawFocusRect( hDC, &rcTemp );
  2814.         }
  2815.     }
  2816.     if ( hBrushHigh ) 
  2817.         VERIFY( ::DeleteObject( hBrushHigh ));
  2818.     if ( hBrushWindow ) 
  2819.         VERIFY( ::DeleteObject( hBrushWindow ));
  2820.  
  2821.     if ( hOldFont )
  2822.         ::SelectObject( hDC, hOldFont );
  2823. }
  2824.  
  2825. extern "C" void HelperSubPopulate
  2826. ( HWND hWnd, int *pIndex, MSG_FolderInfo *folder, MSG_Master *pMaster, 
  2827.   UINT nAddString, UINT nSetItemData)
  2828. {
  2829.     int32 iLines = MSG_GetFolderChildren (pMaster, folder, NULL, 0);
  2830.     MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
  2831.     ASSERT(ppFolderInfo);
  2832.     if (ppFolderInfo)
  2833.     {
  2834.         MSG_GetFolderChildren (pMaster, folder, ppFolderInfo, iLines);
  2835.         for (int i = 0; i < iLines; i++)
  2836.         {
  2837.             MSG_FolderLine folderLine;
  2838.             if (MSG_GetFolderLineById (pMaster, ppFolderInfo[i], &folderLine)) {
  2839.                 if ( !(folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) ||
  2840.                       (folderLine.flags & MSG_FOLDER_FLAG_CAT_CONTAINER)) {
  2841.                     SendMessage( hWnd, nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
  2842.                     SendMessage( hWnd, nSetItemData, (WPARAM) *pIndex, (LPARAM) folderLine.id );
  2843.                     (*pIndex)++;
  2844.                     if ( folderLine.numChildren > 0 ) {
  2845.                         HelperSubPopulate( hWnd, pIndex, folderLine.id ,pMaster, nAddString, nSetItemData);
  2846.                     }
  2847.                 }
  2848.             }
  2849.         }
  2850.         delete [] ppFolderInfo;
  2851.     }
  2852. }
  2853.  
  2854. extern "C" int HelperPopulate
  2855. ( HWND hWnd, MSG_Master *master, MSG_FolderInfo *mailRoot, MSG_Master **hMaster, 
  2856.   UINT nResetContent, int* piInitialDepth, UINT nAddString, UINT nSetItemData)
  2857. {
  2858.     *hMaster = master;
  2859.     int index = 0;
  2860.  
  2861.     *piInitialDepth = 1;
  2862.  
  2863.     SendMessage( hWnd, nResetContent, (WPARAM) 0, (LPARAM) 0 );
  2864.  
  2865.     if ( mailRoot ) {
  2866.         MSG_FolderLine folderLine;
  2867.         MSG_GetFolderLineById( master, mailRoot, &folderLine );
  2868.         *piInitialDepth = folderLine.level;
  2869.     }
  2870.  
  2871.     HelperSubPopulate( hWnd, &index, mailRoot, master, nAddString, nSetItemData);
  2872.  
  2873.     return 1;    
  2874. }
  2875.  
  2876.  
  2877. /////////////////////////////////////////////////////////////////////////////
  2878. // CMailFolderCombo, CMailFolderList
  2879.  
  2880. CMailFolderHelper::CMailFolderHelper( UINT nAddString, UINT nSetItemData, 
  2881.                                       UINT nResetContent)
  2882. {
  2883.     m_bStaticCtl = FALSE;
  2884.  
  2885.     m_hFont = NULL;
  2886.     m_hBoldFont = NULL;
  2887.  
  2888.     m_nAddString = nAddString;
  2889.     m_nSetItemData = nSetItemData;
  2890.     m_nResetContent = nResetContent;
  2891.  
  2892.     ApiApiPtr(api);
  2893.     m_pIImageUnk = api->CreateClassInstance(APICLASS_IMAGEMAP);
  2894.     ASSERT(m_pIImageUnk);
  2895.     if (m_pIImageUnk) {
  2896.         m_pIImageUnk->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIImageMap);
  2897.         ASSERT(m_pIImageMap);
  2898.         m_pIImageMap->Initialize(IDB_MAILNEWS,16,16);
  2899.     }
  2900. }
  2901.  
  2902. CMailFolderHelper::~CMailFolderHelper()
  2903. {
  2904.     if (m_pIImageUnk && m_pIImageMap ) {
  2905.         m_pIImageUnk->Release();
  2906.     }
  2907.     if (m_hFont)
  2908.         theApp.ReleaseAppFont(m_hFont);
  2909.     if (m_hBoldFont)
  2910.         theApp.ReleaseAppFont(m_hBoldFont);
  2911. }
  2912.  
  2913. void CMailFolderHelper::InitFonts( HDC hdc )
  2914. {
  2915.     ::HelperInitFonts(hdc, &m_hFont, &m_hBoldFont);
  2916. }
  2917.  
  2918. void CMailFolderHelper::DoMeasureItem( HWND hWnd, LPMEASUREITEMSTRUCT lpMeasureItemStruct )
  2919. {
  2920.     ::HelperDoMeasureItem( hWnd, lpMeasureItemStruct );
  2921. }
  2922.  
  2923. void CMailFolderHelper::DoDrawItem( HWND hWnd, LPDRAWITEMSTRUCT lpDrawItemStruct, BOOL bNoPrettyName)
  2924. {
  2925.     ::HelperDoDrawItem( hWnd, lpDrawItemStruct, &m_hFont, &m_hBoldFont,
  2926.                         m_pMaster, m_bStaticCtl, m_iInitialDepth, m_pIImageMap, bNoPrettyName);
  2927. }
  2928.  
  2929. void CMailFolderHelper::SubPopulate( HWND hWnd, int &index, MSG_FolderInfo *folder )
  2930. {
  2931.     HelperSubPopulate( hWnd, &index, folder, m_pMaster, m_nAddString, m_nSetItemData);
  2932. }
  2933.  
  2934. int CMailFolderHelper::Populate( HWND hWnd, MSG_Master *master, MSG_FolderInfo *mailRoot )
  2935. {
  2936.     return HelperPopulate( hWnd, master, mailRoot, &m_pMaster, m_nResetContent, 
  2937.                            &m_iInitialDepth, m_nAddString, m_nSetItemData);
  2938. }
  2939.  
  2940. int CMailFolderHelper::PopulateMailServer( HWND hWnd, MSG_Master *master, BOOL bRoots)
  2941. {
  2942.     m_pMaster = master;
  2943.     int index = 0;
  2944.  
  2945.     m_iInitialDepth = 1;
  2946.  
  2947.     SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );
  2948.  
  2949.     int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
  2950.     MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
  2951.     ASSERT(ppFolderInfo);
  2952.     if (ppFolderInfo)
  2953.     {
  2954.         MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
  2955.         for (int i = 0; i < iLines; i++)
  2956.         {
  2957.             MSG_FolderLine folderLine;
  2958.             if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
  2959.                 if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) {
  2960.                     if ( bRoots ) {
  2961.                         SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
  2962.                         SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
  2963.                         index++;
  2964.                     }
  2965.                 }
  2966.             }
  2967.         }
  2968.         delete [] ppFolderInfo;
  2969.     }
  2970.  
  2971.     return 1;    
  2972. }
  2973.  
  2974. int CMailFolderHelper::PopulateMail( HWND hWnd, MSG_Master *master, BOOL bRoots)
  2975. {
  2976.     m_pMaster = master;
  2977.     int index = 0;
  2978.  
  2979.     m_iInitialDepth = 1;
  2980.  
  2981.     SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );
  2982.  
  2983.     int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
  2984.     MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
  2985.     ASSERT(ppFolderInfo);
  2986.     if (ppFolderInfo)
  2987.     {
  2988.         MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
  2989.         for (int i = 0; i < iLines; i++)
  2990.         {
  2991.             MSG_FolderLine folderLine;
  2992.             if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
  2993.                 if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) {
  2994.                     if ( bRoots ) {
  2995.                         SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
  2996.                         SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
  2997.                         index++;
  2998.                     }
  2999.                     if ( folderLine.numChildren > 0 ) {
  3000.                         SubPopulate( hWnd, index, ppFolderInfo[i] );
  3001.                     }
  3002.                 }
  3003.             }
  3004.         }
  3005.         delete [] ppFolderInfo;
  3006.     }
  3007.  
  3008.     return 1;    
  3009. }
  3010.  
  3011. int CMailFolderHelper::PopulateNews( HWND hWnd, MSG_Master *master, BOOL bRoots )
  3012. {
  3013.     m_pMaster = master;
  3014.     int index = 0;
  3015.  
  3016.     m_iInitialDepth = 1;
  3017.  
  3018.     SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );
  3019.  
  3020.     int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
  3021.     MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
  3022.     ASSERT(ppFolderInfo);
  3023.     if (ppFolderInfo)
  3024.     {
  3025.         MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
  3026.         for (int i = 0; i < iLines; i++)
  3027.         {
  3028.             MSG_FolderLine folderLine;
  3029.             if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
  3030.                 if ( folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ||
  3031.                      folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST) 
  3032.                 {
  3033.                     if ( bRoots ) {
  3034.                         SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
  3035.                         SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
  3036.                         index++;
  3037.                     }
  3038.                     if ( folderLine.numChildren > 0 ) {
  3039.                         SubPopulate( hWnd, index, ppFolderInfo[i] );
  3040.                     }
  3041.                 }
  3042.             }
  3043.         }
  3044.         delete ppFolderInfo;
  3045.     }
  3046.  
  3047.     return 1;    
  3048. }
  3049.  
  3050.  
  3051. #define NAV_BUTTONWIDTH        24
  3052. #define NAV_BUTTONHEIGHT    16
  3053.  
  3054. CNavCombo::CNavCombo()
  3055. {
  3056.     m_bFirst = TRUE;
  3057.     m_hFont = NULL;
  3058.     m_hBigFont = NULL;
  3059. }
  3060.  
  3061. CNavCombo::~CNavCombo()
  3062. {
  3063. }
  3064.  
  3065. void CNavCombo::SetFont( CFont *pFont, CFont *pBigFont )
  3066. {
  3067.     m_hFont = (HFONT) pFont->m_hObject;
  3068.     m_hBigFont = (HFONT) pBigFont->m_hObject;
  3069.  
  3070.     CMailFolderCombo::SetFont(pFont);
  3071. }
  3072.  
  3073. void CNavCombo::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
  3074. {
  3075.     BOOL bStatic = FALSE;
  3076.  
  3077. #ifdef _WIN32
  3078.     if ( sysInfo.m_bWin4 )
  3079.         bStatic = ( lpDrawItemStruct->itemState & ODS_COMBOBOXEDIT ) ? TRUE : FALSE;
  3080.     else 
  3081. #endif
  3082.         bStatic = m_bStaticCtl;
  3083.  
  3084.     if ( bStatic ) {
  3085.         HDC hdc = lpDrawItemStruct->hDC;
  3086.         RECT rect = lpDrawItemStruct->rcItem; 
  3087.  
  3088.         COLORREF oldText;
  3089.         COLORREF oldBk;
  3090.         if ( lpDrawItemStruct->itemState & ODS_SELECTED ) {
  3091.             oldText = ::SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
  3092.             oldBk = ::SetBkColor( hdc, GetSysColor(COLOR_HIGHLIGHT));
  3093.         } else {
  3094.             oldText = ::SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) );
  3095.             oldBk = ::SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  3096.         }
  3097.         HFONT hOldFont = (HFONT) ::SelectObject( hdc, m_hBigFont );
  3098.  
  3099.         MSG_FolderInfo *itemData = (MSG_FolderInfo *) lpDrawItemStruct->itemData;
  3100.  
  3101.         if ( (lpDrawItemStruct->itemID != (UINT) -1) && itemData ) {
  3102.             MSG_FolderLine folderLine;
  3103.             MSG_GetFolderLineById( m_pMaster, itemData, &folderLine);
  3104.             
  3105.             rect.left += 4;
  3106.  
  3107.             LPCTSTR name = (LPCTSTR) folderLine.prettyName;
  3108.             if ( !name || !name[0] )
  3109.                 name = folderLine.name;
  3110.  
  3111.             CIntlWin::DrawText( 0, hdc, (LPSTR) name, -1, &rect,
  3112.                                   DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX );
  3113.         }
  3114.  
  3115.         if ( hOldFont )
  3116.             ::SelectObject( hdc, hOldFont );
  3117.  
  3118.         ::SetTextColor( hdc, oldText );
  3119.         ::SetBkColor(hdc, oldText);
  3120.     } else {
  3121.         CMailFolderCombo::DrawItem( lpDrawItemStruct );
  3122.     }
  3123. }
  3124.  
  3125. BEGIN_MESSAGE_MAP( CNavCombo, CMailFolderCombo )
  3126.     ON_WM_CTLCOLOR()
  3127.     ON_WM_PAINT()
  3128. END_MESSAGE_MAP()
  3129.  
  3130. void CNavCombo::OnPaint()
  3131. {
  3132.     m_bStaticCtl = TRUE;
  3133.     CMailFolderCombo::OnPaint();
  3134.     m_bFirst = TRUE;
  3135. }
  3136.  
  3137. HBRUSH CNavCombo::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor )
  3138. {
  3139.     if (nCtlColor == CTLCOLOR_LISTBOX) {
  3140.         if (m_bFirst) {
  3141.             RECT rcParent;
  3142.             GetWindowRect( &rcParent );
  3143.             pWnd->GetWindowRect(&m_rcList);
  3144.             m_bFirst = FALSE;
  3145.             int height = m_rcList.bottom - m_rcList.top;
  3146.             if ( (rcParent.bottom + height) > GetSystemMetrics( SM_CYFULLSCREEN ) ) {
  3147.                 height = GetSystemMetrics( SM_CYFULLSCREEN ) - rcParent.bottom;
  3148.             }
  3149.             pWnd->MoveWindow( m_rcList.left, rcParent.bottom,
  3150.                               m_rcList.right - m_rcList.left, height );
  3151.         }
  3152.     }
  3153.  
  3154.     m_bStaticCtl = (nCtlColor == CTLCOLOR_EDIT);
  3155.  
  3156.     return CMailFolderCombo::OnCtlColor( pDC, pWnd, nCtlColor );
  3157. }
  3158.  
  3159. ///////////////////////////////////////////////////////////////////////
  3160. // CLinkDropSource
  3161.  
  3162. class CLinkDropSource: public COleDropSource
  3163. {
  3164. protected:
  3165.     virtual SCODE GiveFeedback( DROPEFFECT dropEffect );
  3166. };
  3167.  
  3168. SCODE CLinkDropSource::GiveFeedback( DROPEFFECT dropEffect )
  3169. {
  3170.     if ( !(dropEffect & (DROPEFFECT_COPY|DROPEFFECT_MOVE)) ) {
  3171.         return COleDropSource::GiveFeedback( dropEffect );
  3172.     } else {
  3173.         ::SetCursor( ::LoadCursor( AfxGetResourceHandle(), 
  3174.                                    MAKEINTRESOURCE( dropEffect & DROPEFFECT_COPY ?
  3175.                                                     IDC_LINK_COPY : IDC_LINK_MOVE ) ) );
  3176.         return NOERROR;
  3177.     }
  3178. }
  3179.  
  3180. ///////////////////////////////////////////////////////////////////////
  3181. // CMailInfoBar
  3182.  
  3183. CMailInfoBar::CMailInfoBar()
  3184. {
  3185.     m_bEraseBackground = TRUE;
  3186.  
  3187.     m_idxImage = 0;
  3188.     m_pUnkImage = NULL;
  3189.  
  3190.     ApiApiPtr(api);
  3191.     m_pUnkImage = api->CreateClassInstance( APICLASS_IMAGEMAP,
  3192.                                             NULL, 
  3193.                                             (APISIGNATURE)IDB_MAILNEWS);
  3194.     m_pUnkImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIImage);
  3195.     ASSERT(m_pIImage);
  3196.     if (!m_pIImage->GetResourceID())
  3197.         m_pIImage->Initialize(IDB_MAILNEWS,16,16);
  3198.  
  3199.     m_hbmBanner = NULL;
  3200.     m_hFont = NULL;
  3201.     m_hBoldFont = NULL;
  3202.     m_hIntlFont = NULL;
  3203.     m_hBoldIntlFont = NULL;
  3204. }
  3205.  
  3206. CMailInfoBar::~CMailInfoBar()
  3207. {
  3208.     if (m_pUnkImage) {
  3209.         if (m_pIImage)
  3210.             m_pUnkImage->Release();
  3211.     }
  3212.     if (m_hbmBanner)
  3213.         VERIFY(::DeleteObject( m_hbmBanner ));
  3214.  
  3215.     if (m_hFont) {
  3216.         theApp.ReleaseAppFont(m_hFont);
  3217.     }
  3218.     if (m_hBoldFont) {
  3219.         theApp.ReleaseAppFont(m_hBoldFont);
  3220.     }
  3221.     if (m_hIntlFont) {
  3222.         theApp.ReleaseAppFont(m_hIntlFont);
  3223.     }
  3224.     if (m_hBoldIntlFont) {
  3225.         theApp.ReleaseAppFont(m_hBoldIntlFont);
  3226.     }
  3227. }
  3228.  
  3229. void CMailInfoBar::SetCSID( int csid )
  3230. {
  3231.  
  3232.     if (m_hFont) {
  3233.         theApp.ReleaseAppFont(m_hFont);
  3234.     }
  3235.     if (m_hBoldFont) {
  3236.         theApp.ReleaseAppFont(m_hBoldFont);
  3237.     }
  3238.     if (m_hIntlFont) {
  3239.         theApp.ReleaseAppFont(m_hIntlFont);
  3240.     }
  3241.     if (m_hBoldIntlFont) {
  3242.         theApp.ReleaseAppFont(m_hBoldIntlFont);
  3243.     }
  3244.  
  3245.     CClientDC dc(this);
  3246.     m_iCSID = csid;
  3247.     int16 defCSID = INTL_CharSetNameToID(INTL_ResourceCharSet());
  3248.  
  3249.     LOGFONT lf;
  3250.     memset( &lf, 0, sizeof(LOGFONT) );
  3251.  
  3252.     lf.lfPitchAndFamily = FF_SWISS;
  3253.     lf.lfCharSet = IntlGetLfCharset(defCSID);
  3254.     if (defCSID == CS_LATIN1)
  3255.          _tcscpy(lf.lfFaceName, "MS Sans Serif");
  3256.     else
  3257.          _tcscpy(lf.lfFaceName, IntlGetUIPropFaceName(defCSID));
  3258.  
  3259.        lf.lfHeight = -MulDiv( 9, dc.GetDeviceCaps(LOGPIXELSY), 72 );
  3260.     lf.lfWeight = 0;
  3261.     m_hFont = theApp.CreateAppFont( lf );
  3262.        lf.lfHeight = -MulDiv( 10, dc.GetDeviceCaps(LOGPIXELSY), 72 );
  3263.     lf.lfWeight = 700;
  3264.     m_hBoldFont = theApp.CreateAppFont( lf );
  3265.     lf.lfCharSet = IntlGetLfCharset(csid);
  3266.     if (csid == CS_LATIN1)
  3267.          _tcscpy(lf.lfFaceName, "MS Sans Serif");
  3268.     else
  3269.          _tcscpy(lf.lfFaceName, IntlGetUIPropFaceName(csid));
  3270.  
  3271.        lf.lfHeight = -MulDiv( 9, dc.GetDeviceCaps(LOGPIXELSY), 72 );
  3272.     lf.lfWeight = 0;
  3273.     m_hIntlFont = theApp.CreateAppFont( lf );
  3274.        lf.lfHeight = -MulDiv( 10, dc.GetDeviceCaps(LOGPIXELSY), 72 );
  3275.     lf.lfWeight = 700;
  3276.     m_hBoldIntlFont = theApp.CreateAppFont( lf );
  3277.  
  3278.     Invalidate();
  3279. }
  3280.  
  3281. BOOL CMailInfoBar::Create( CWnd *pWnd, MSG_Pane *pPane )
  3282. {
  3283.     m_pPane = pPane;
  3284.  
  3285.     ASSERT( pWnd && pWnd->IsKindOf( RUNTIME_CLASS(CFrameWnd) ));
  3286.  
  3287.     DWORD dwStyle = WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|CBRS_TOP;
  3288.     UINT nID = AFX_IDW_CONTROLBAR_FIRST + 0x7e;
  3289.     
  3290.     LPCTSTR lpszClass = AfxRegisterWndClass( 0, ::LoadCursor( NULL, IDC_ARROW) );
  3291.  
  3292. #ifdef _WIN32
  3293.     m_dwStyle = dwStyle;
  3294. #endif
  3295.  
  3296.     BOOL res = CControlBar::Create( lpszClass, _T("InfoBar"), dwStyle, 
  3297.                                     CRect(0,0,0,0), pWnd, nID);
  3298.  
  3299.     if (res) {
  3300.         SetCSID( INTL_DefaultWinCharSetID(0) );
  3301. #ifndef _WIN32
  3302.         m_sizeFixedLayout = CalcFixedLayout(TRUE, TRUE);
  3303. #endif
  3304.     }
  3305.     return res;
  3306. }
  3307.  
  3308. void CMailInfoBar::OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler )
  3309. {
  3310. }
  3311.  
  3312. CSize CMailInfoBar::CalcFixedLayout( BOOL bStretch, BOOL bHorz )
  3313. {
  3314.     ASSERT( bHorz ); // No vertical, No way
  3315.  
  3316.     HDC hDC = ::GetDC( m_hWnd );
  3317.     HFONT hOldFont = (HFONT) ::SelectObject( hDC, m_hBoldFont);
  3318.  
  3319.     TEXTMETRIC tm;
  3320.     GetTextMetrics( hDC, &tm);
  3321.     
  3322.     ::SelectObject( hDC, hOldFont );
  3323.     ::ReleaseDC( m_hWnd, hDC );
  3324.  
  3325.     int iHeight = (tm.tmHeight > 20 ? tm.tmHeight : 20 ) + 4;
  3326.  
  3327.     return CSize( 32767, iHeight );
  3328. }
  3329.  
  3330. BOOL CMailInfoBar::PreTranslateMessage( MSG *pMsg )
  3331. {
  3332.     if (pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
  3333.         m_wndToolTip.RelayEvent( pMsg );
  3334.  
  3335.     return CControlBar::PreTranslateMessage( pMsg );
  3336. }
  3337.  
  3338. void CMailInfoBar::PaintBackground( HDC hDC )
  3339. {
  3340.     RECT rect;
  3341.     GetClientRect( &rect );
  3342.  
  3343.     ::FillRect( hDC, &rect, sysInfo.m_hbrBtnFace );
  3344. }
  3345.  
  3346. void CMailInfoBar::DrawInfoText( int iCSID, HDC hDC, LPCSTR lpszText, LPRECT lpRect )
  3347. {
  3348.     WFE_DrawTextEx( iCSID, hDC, (LPSTR) lpszText, -1, lpRect,
  3349.                     DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX,
  3350.                     WFE_DT_CROPRIGHT );
  3351. }
  3352.  
  3353. void CMailInfoBar::DrawInfoText( HDC hDC, LPCSTR lpszText, LPRECT lpRect )
  3354. {
  3355.     int16 resCsid = INTL_CharSetNameToID(INTL_ResourceCharSet());
  3356.     DrawInfoText( resCsid, hDC, lpszText, lpRect );
  3357. }
  3358.  
  3359. void CMailInfoBar::MeasureInfoText( int iCSID, HDC hDC, LPCSTR lpszText, LPRECT lpRect )
  3360. {
  3361.     CIntlWin::DrawText( iCSID, hDC, (LPSTR) lpszText, -1, lpRect, DT_LEFT|DT_SINGLELINE|DT_CALCRECT );
  3362. }
  3363.  
  3364. void CMailInfoBar::MeasureInfoText( HDC hDC, LPCSTR lpszText, LPRECT lpRect )
  3365. {
  3366.     int16 resCsid = INTL_CharSetNameToID(INTL_ResourceCharSet());
  3367.     MeasureInfoText( resCsid, hDC, lpszText, lpRect );
  3368. }
  3369.  
  3370. void CMailInfoBar::DragProxie()
  3371. {
  3372. }
  3373.  
  3374. BEGIN_MESSAGE_MAP( CMailInfoBar, CControlBar )
  3375.     ON_WM_CREATE()
  3376.     ON_WM_LBUTTONDOWN()
  3377.     ON_WM_LBUTTONUP()
  3378.     ON_WM_MOUSEMOVE()
  3379.     ON_WM_SHOWWINDOW()
  3380.     ON_WM_ERASEBKGND()
  3381.     ON_WM_SETCURSOR()
  3382. END_MESSAGE_MAP()
  3383.  
  3384. int CMailInfoBar::OnCreate(LPCREATESTRUCT lpcs)
  3385. {
  3386.     int res = CControlBar::OnCreate(lpcs);
  3387.     if (res != -1) {
  3388.         m_wndToolTip.Create(this, TTS_ALWAYSTIP);
  3389.         m_wndToolTip.Activate(TRUE);
  3390.     }
  3391.     return res;
  3392. }
  3393. void CMailInfoBar::OnLButtonDown( UINT nFlags, CPoint point )
  3394. {
  3395.     RECT rect;
  3396.     GetClientRect(&rect);
  3397.     rect.right = 22;
  3398.  
  3399.     if (PtInRect(&rect, point)) {
  3400.         DragProxie();
  3401.     }
  3402.     else{
  3403.         // Send this message to the customizable toolbar for dragging
  3404.         MapWindowPoints(GetParent(), &point, 1);
  3405.         GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
  3406.     }
  3407.  
  3408. }
  3409.  
  3410. void CMailInfoBar::OnLButtonUp( UINT nFlags, CPoint point )
  3411. {
  3412.     RECT rect;
  3413.     GetClientRect(&rect);
  3414.     rect.right = 22;
  3415.  
  3416.     if (!PtInRect(&rect, point)) {
  3417.         // Send this message to the customizable toolbar for dragging
  3418.         MapWindowPoints(GetParent(), &point, 1);
  3419.         GetParent()->SendMessage(WM_LBUTTONUP, nFlags, MAKELPARAM(point.x, point.y));
  3420.  
  3421.     }
  3422.     
  3423. }
  3424.  
  3425. void CMailInfoBar::OnMouseMove( UINT nFlags, CPoint point )
  3426. {
  3427.     RECT rect;
  3428.     GetClientRect(&rect);
  3429.     rect.right = 22;
  3430.  
  3431.     if (!PtInRect(&rect, point)) {
  3432.         // Send this message to the customizable toolbar for dragging
  3433.         MapWindowPoints(GetParent(), &point, 1);
  3434.         GetParent()->SendMessage(WM_MOUSEMOVE, nFlags, MAKELPARAM(point.x, point.y));
  3435.     }
  3436.  
  3437. }
  3438.  
  3439. void CMailInfoBar::OnShowWindow( BOOL bShow, UINT nStatus )
  3440. {
  3441.     m_bEraseBackground |= bShow;
  3442. }
  3443.  
  3444. BOOL CMailInfoBar::OnEraseBkgnd( CDC* pDC )
  3445. {
  3446.     if ( m_bEraseBackground ) {
  3447.         PaintBackground( pDC->m_hDC );
  3448.         m_bEraseBackground = FALSE;
  3449.     }
  3450.  
  3451.     return TRUE;
  3452. }
  3453.  
  3454. BOOL CMailInfoBar::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
  3455. {
  3456.     POINT pt;
  3457.     RECT rect;
  3458.     GetWindowRect(&rect);
  3459.     if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
  3460.         rect.left += 30;
  3461.     rect.right = rect.left + 22;
  3462.     GetCursorPos( &pt );
  3463.  
  3464.     if ( nHitTest == HTCLIENT && ::PtInRect( &rect, pt ) ) {
  3465.         ::SetCursor( ::LoadCursor( AfxGetResourceHandle(), MAKEINTRESOURCE(IDC_HANDOPEN) ) );
  3466.         return TRUE;
  3467.     }
  3468.  
  3469.     return CControlBar::OnSetCursor( pWnd, nHitTest, message );
  3470. }
  3471.  
  3472. /////////////////////////////////////////////////////////////////////
  3473. //
  3474. // CContainerInfoBar
  3475. //
  3476. // Info Bar for the Folder Window
  3477.  
  3478. void CContainerInfoBar::Update()
  3479. {
  3480.     LPCSTR szUser = FE_UsersFullName();
  3481.     if ( szUser ) {
  3482.         m_csBanner.Format( szLoadString( IDS_MAIL_MYCONTAINERS ), szUser);
  3483.     } else {
  3484.         m_csBanner.LoadString(IDS_MAIL_CONTAINERS);
  3485.     }
  3486. }
  3487.  
  3488. void CContainerInfoBar::DragProxie()
  3489. {
  3490.     URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );
  3491.     if ( url ) {
  3492.         COleDataSource *pDataSource = new COleDataSource;
  3493.         RDFGLOBAL_DragTitleAndURL( pDataSource, m_csBanner, url->address );
  3494.         COleDropSource *pDropSource = new CLinkDropSource;
  3495.         DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
  3496.                                                   DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
  3497.                                                   CRect( 0, 0, 0, 0),
  3498.                                                   pDropSource );
  3499.         pDataSource->Empty();
  3500.         delete pDataSource;
  3501.         delete pDropSource;
  3502.         NET_FreeURLStruct( url );
  3503.     }
  3504. }
  3505.  
  3506. BEGIN_MESSAGE_MAP( CContainerInfoBar, CMailInfoBar )
  3507.     ON_WM_CREATE()
  3508.     ON_WM_PAINT()
  3509. END_MESSAGE_MAP()
  3510.  
  3511. int CContainerInfoBar::OnCreate(LPCREATESTRUCT lpcs)
  3512. {
  3513.     int res = CMailInfoBar::OnCreate(lpcs);
  3514.     if (res != -1) {
  3515.         RECT rect;
  3516.         SetRectEmpty(&rect);
  3517.         m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
  3518.     }
  3519.     return res;
  3520. }
  3521. void CContainerInfoBar::OnPaint( )
  3522. {
  3523.     CPaintDC dc(this);
  3524.     CRect rect;
  3525.     GetClientRect( &rect );
  3526.  
  3527.     PaintBackground( dc.m_hDC );
  3528.  
  3529.     m_pIImage->DrawTransImage( IDX_COLLECTION,
  3530.                                2,
  3531.                                rect.bottom / 2 - 8,
  3532.                                &dc );
  3533.  
  3534.     RECT rcTool;
  3535.     ::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
  3536.     m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);
  3537.  
  3538.     int oldMode = dc.SetBkMode( TRANSPARENT );
  3539.     HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldFont );
  3540.  
  3541.     int iWidth = rect.right - rect.left;
  3542.     rect.left += 22;
  3543.  
  3544.     DrawInfoText( dc.m_hDC, m_csBanner, &rect );
  3545.  
  3546.     dc.SetBkMode( oldMode );
  3547.     dc.SelectObject( hOldFont );
  3548. }
  3549.  
  3550. ///////////////////////////////////////////////////////////////////////
  3551. //
  3552. // CFolderInfoBar
  3553. //
  3554. // Info Bar for the Thread Window
  3555.  
  3556. CFolderInfoBar::CFolderInfoBar()
  3557. {
  3558.     m_folderOld = NULL;
  3559. }
  3560.  
  3561. CFolderInfoBar::~CFolderInfoBar()
  3562. {
  3563. }
  3564.  
  3565. void CFolderInfoBar::SetCSID( int csid )
  3566. {
  3567.     CMailInfoBar::SetCSID( csid );
  3568.     m_wndNavButton.SetFont( CFont::FromHandle( m_hFont ), CFont::FromHandle( m_hBoldFont ) );
  3569. }
  3570.  
  3571. void CFolderInfoBar::Update()
  3572. {
  3573.     if (m_pPane) {
  3574.         MSG_FolderLine folderLine;
  3575.         MSG_FolderInfo *folderInfo = NULL;
  3576.  
  3577.         if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
  3578.         {
  3579.             if (((C3PaneMailFrame*)GetParentFrame())->GetSelectedFolder(&folderLine))
  3580.                 folderInfo = folderLine.id;
  3581.         }
  3582.         if (!folderInfo)
  3583.             folderInfo = MSG_GetCurFolder( m_pPane );
  3584.         if (folderInfo) {
  3585.             MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
  3586.             if (folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) {
  3587.                 folderInfo = MSG_GetCategoryContainerForCategory(folderInfo);
  3588.                 MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
  3589.             }
  3590.  
  3591.             if ( folderInfo != m_folderOld ) {
  3592.                 m_wndNavButton.Populate( WFE_MSGGetMaster(), NULL );
  3593.                 m_wndNavButton.SetCurSel(0);
  3594.                 for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
  3595.                     if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == folderInfo ) {
  3596.                         m_wndNavButton.SetCurSel(i);
  3597.                         break;
  3598.                     }
  3599.                 }
  3600.             }
  3601.  
  3602.             m_csFolderName = folderLine.prettyName && folderLine.prettyName[0] ?
  3603.                              folderLine.prettyName : folderLine.name;
  3604.  
  3605.             if (folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) {
  3606.                 if (folderLine.deepUnseen >= 0) {
  3607.                     m_csFolderCounts.Format(szLoadString(IDS_FOLDERCOUNTS),
  3608.                                             (int32) folderLine.deepTotal, 
  3609.                                             (int32) folderLine.deepUnseen);
  3610.                 } else {
  3611.                     m_csFolderCounts.LoadString(IDS_FOLDERUNKNOWNCOUNTS);
  3612.                 }
  3613.             } else {
  3614.                 if (folderLine.unseen >= 0) {
  3615.                     m_csFolderCounts.Format(szLoadString(IDS_FOLDERCOUNTS),
  3616.                                             (int32) folderLine.total, 
  3617.                                             (int32) folderLine.unseen);
  3618.                 } else {
  3619.                     m_csFolderCounts.LoadString(IDS_FOLDERUNKNOWNCOUNTS);
  3620.                 }
  3621.             }
  3622.  
  3623.             m_idxImage = WFE_MSGTranslateFolderIcon( folderLine.level, 
  3624.                                                      folderLine.flags,
  3625.                                                      FALSE );
  3626.             m_folderOld = folderInfo;
  3627.         } else {
  3628.             m_csFolderName = "";
  3629.             m_csFolderCounts = "";
  3630.         }
  3631.     }
  3632.     Invalidate();
  3633.     UpdateWindow();
  3634. }
  3635.  
  3636. void CFolderInfoBar::DragProxie()
  3637. {
  3638.     URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );
  3639.     if ( url ) {
  3640.         
  3641.         COleDataSource *pDataSource = new COleDataSource;
  3642.         RDFGLOBAL_DragTitleAndURL( pDataSource, m_csFolderName, url->address );
  3643.         COleDropSource *pDropSource = new CLinkDropSource;
  3644.         DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
  3645.                                                   DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
  3646.                                                   CRect( 0, 0, 0, 0),
  3647.                                                   pDropSource );
  3648.         pDataSource->Empty();
  3649.         delete pDataSource;
  3650.         delete pDropSource;
  3651.         NET_FreeURLStruct( url );
  3652.     }
  3653. }
  3654.  
  3655. BEGIN_MESSAGE_MAP( CFolderInfoBar, CMailInfoBar )
  3656.     ON_WM_CREATE()
  3657.     ON_WM_SIZE()
  3658.     ON_WM_PAINT()
  3659.     ON_CBN_DROPDOWN(101, OnDropDown)
  3660.     ON_CBN_SELENDOK(101, OnCloseUp)
  3661.     ON_BN_CLICKED(102, OnContainer )
  3662.     ON_COMMAND( ID_BUTTON_CONTAINER, OnContainer )
  3663. END_MESSAGE_MAP()
  3664.  
  3665. int CFolderInfoBar::OnCreate( LPCREATESTRUCT lpCreateStruct )
  3666. {
  3667.     int res = CMailInfoBar::OnCreate( lpCreateStruct );
  3668.  
  3669.     if ( res != -1 ) {
  3670.         DWORD dwStyle = 0;
  3671.  
  3672.         dwStyle = WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_OWNERDRAWFIXED|CBS_DROPDOWNLIST;
  3673.  
  3674.         m_wndNavButton.Create( dwStyle, CRect(22,3,250,480), this, 101 );
  3675.         
  3676.         CString csFull, csLabel, csTip, csStatus;
  3677.         WFE_ParseButtonString( ID_NAVIGATE_CONTAINER, csStatus, csTip, csLabel );
  3678.  
  3679.         m_wndBackButton.Create( this, FALSE, CSize(20,20), CSize(20,20), 
  3680.                                 csLabel, csTip, csStatus,
  3681.                                 IDB_BACK, 0, CSize(16,16), 
  3682.                                 ID_BUTTON_CONTAINER, 0, 0 );
  3683.  
  3684.         m_wndBackButton.SetActionMessageOwner(this);
  3685.         RECT rect;
  3686.         SetRectEmpty(&rect);
  3687.         m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
  3688.     }
  3689.     return res;
  3690. }    
  3691.  
  3692. void CFolderInfoBar::OnSize( UINT nType, int cx, int cy )
  3693. {
  3694.     if ( nType != SIZE_MINIMIZED ) {
  3695.         m_wndBackButton.MoveWindow( cx - 22, 3, 22, cy - 6 );
  3696.     }
  3697. }
  3698.  
  3699. void CFolderInfoBar::OnDropDown()
  3700. {
  3701.     // Folder Structure might have changed, rebuild.
  3702.     m_wndNavButton.Populate( WFE_MSGGetMaster(), NULL );
  3703.     m_wndNavButton.SetCurSel(0);
  3704.     for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
  3705.         if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == m_folderOld ) {
  3706.             m_wndNavButton.SetCurSel(i);
  3707.             break;
  3708.         }
  3709.     }
  3710. }
  3711.  
  3712. void CFolderInfoBar::OnCloseUp()
  3713. {
  3714.     int iCurSel = m_wndNavButton.GetCurSel();
  3715.     m_wndNavButton.m_bFirst = TRUE;
  3716.  
  3717.     MSG_FolderInfo *folderInfo = (MSG_FolderInfo *) m_wndNavButton.GetItemData(iCurSel);
  3718.     MSG_FolderLine folderLine;
  3719.     if ( m_folderOld != folderInfo ) {
  3720.  
  3721.         CMsgListFrame* pFrame = C3PaneMailFrame::FindFrame( folderInfo );
  3722.         if ( pFrame ) {
  3723.             pFrame->ActivateFrame();
  3724.         } else {
  3725.             if ( !MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine ) ) {
  3726.                 ASSERT(0); // Shouldn't happen
  3727.                 return;
  3728.             }
  3729.  
  3730.             // User selected a folder
  3731.             pFrame = (CMsgListFrame *) GetParentFrame();
  3732.             ASSERT(pFrame && pFrame->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)));
  3733.             if (pFrame->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
  3734.             {
  3735.                 // bounce focus back to frame
  3736.                 ((C3PaneMailFrame*)pFrame)->UpdateFolderPane(folderInfo);
  3737.                 pFrame->SetFocus();
  3738.                 return;
  3739.             } 
  3740.             else 
  3741.             {
  3742.                 if ( folderLine.level > 1 )  
  3743.                     CFolderFrame::Open( folderInfo );
  3744.             }
  3745.         }
  3746.  
  3747.         // Since we didn't change, reselect our folder
  3748.         m_wndNavButton.SetCurSel(0);
  3749.         for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
  3750.             if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == m_folderOld ) {
  3751.                 m_wndNavButton.SetCurSel(i);
  3752.                 break;
  3753.             }
  3754.         }
  3755.     }
  3756. }
  3757.  
  3758. void CFolderInfoBar::OnContainer()
  3759. {
  3760.     GetParentFrame()->PostMessage( WM_COMMAND, (WPARAM) ID_NAVIGATE_CONTAINER );
  3761. }
  3762.  
  3763. void CFolderInfoBar::OnPaint( )
  3764. {
  3765.     CPaintDC dc(this);
  3766.     CRect rect;
  3767.     GetClientRect( &rect );
  3768.  
  3769.     PaintBackground( dc.m_hDC );
  3770.  
  3771.     m_pIImage->DrawTransImage( m_idxImage,
  3772.                                2,
  3773.                                rect.bottom / 2 - 8,
  3774.                                &dc );
  3775.  
  3776.     RECT rcTool;
  3777.     ::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
  3778.     m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);
  3779.  
  3780.     int oldMode = dc.SetBkMode( TRANSPARENT );
  3781.     HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldFont );
  3782.  
  3783.     dc.SelectObject( m_hFont );
  3784.  
  3785.     RECT rcText;
  3786.     MeasureInfoText( dc.m_hDC, m_csFolderCounts, &rcText);
  3787.     int iCountsWidth = rcText.right - rcText.left;
  3788.  
  3789.     rect.left = rect.right - iCountsWidth - 32;
  3790.     rect.right -= 32;
  3791.  
  3792.     DrawInfoText( dc.m_hDC, m_csFolderCounts, &rect );
  3793.  
  3794.     dc.SetBkMode( oldMode );
  3795.     dc.SelectObject( hOldFont );
  3796.  
  3797.     m_wndNavButton.UpdateWindow();
  3798. }
  3799.  
  3800. ///////////////////////////////////////////////////////////////////////
  3801. //
  3802. // CMessageInfoBar
  3803. //
  3804. // Info Bar for the Message Window
  3805.  
  3806. CMessageInfoBar::CMessageInfoBar()
  3807. {
  3808.     m_csFolderTip = "";
  3809.     m_csFolderStatus = "";
  3810. }
  3811.  
  3812. CMessageInfoBar::~CMessageInfoBar()
  3813. {
  3814. }
  3815.  
  3816. void CMessageInfoBar::SetCSID( int csid )
  3817. {
  3818.     CMailInfoBar::SetCSID( csid );
  3819.     Update();
  3820. }
  3821.  
  3822. void CMessageInfoBar::Update()
  3823. {
  3824.     if (m_pPane) {
  3825.         MSG_FolderInfo *folderInfo;
  3826.         MessageKey key;
  3827.         MSG_ViewIndex index;
  3828.         MSG_GetCurMessage( m_pPane, &folderInfo, &key, &index);
  3829.         if (folderInfo) {
  3830.             MSG_FolderLine folderLine;
  3831.             MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
  3832.             m_idxImage = folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ? 
  3833.                          IDX_NEWSARTICLE :
  3834.                          IDX_MAILREAD;
  3835.             m_csFolderTip = folderLine.name;
  3836.             m_csFolderStatus.Format(szLoadString(IDS_OPEN_STRING), folderLine.name);
  3837.         } else {
  3838.             m_idxImage = 0;
  3839.         }
  3840.         if ( key != MSG_MESSAGEKEYNONE ) {
  3841.             LPTSTR buf; 
  3842.             MSG_MessageLine messageLine;
  3843.             MSG_GetThreadLineById( m_pPane, key, &messageLine );
  3844.             buf = IntlDecodeMimePartIIStr( messageLine.subject, INTL_DocToWinCharSetID(m_iCSID), FALSE );
  3845.             if ( buf ) {
  3846.                 m_csMessageName = buf;
  3847.                 XP_FREE(buf);
  3848.             } else {
  3849.                 m_csMessageName = messageLine.subject;
  3850.             }
  3851.             buf = IntlDecodeMimePartIIStr( messageLine.author, INTL_DocToWinCharSetID(m_iCSID), FALSE );
  3852.             if ( buf ) {
  3853.                 m_csMessageAuthor = buf;
  3854.                 XP_FREE(buf);
  3855.             } else {
  3856.                 m_csMessageAuthor = messageLine.author;
  3857.             }
  3858.         } else {
  3859.             m_csMessageName = "";
  3860.             m_csMessageAuthor = "";
  3861.         }
  3862.     }
  3863.     Invalidate();
  3864. }
  3865.  
  3866. void CMessageInfoBar::DragProxie()
  3867. {
  3868.     URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );
  3869.  
  3870.     if ( url ) {
  3871.         
  3872.         COleDataSource *pDataSource = new COleDataSource;
  3873.         RDFGLOBAL_DragTitleAndURL( pDataSource, m_csMessageName, url->address );
  3874.         COleDropSource *pDropSource = new CLinkDropSource;
  3875.         DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
  3876.                                                   DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
  3877.                                                   CRect( 0, 0, 0, 0),
  3878.                                                   pDropSource );
  3879.         pDataSource->Empty();
  3880.         delete pDataSource;
  3881.         delete pDropSource;
  3882.  
  3883.         NET_FreeURLStruct( url );
  3884.     }
  3885. }
  3886.  
  3887. BEGIN_MESSAGE_MAP( CMessageInfoBar, CMailInfoBar )
  3888.     ON_WM_CREATE()
  3889.     ON_WM_SIZE()
  3890.     ON_WM_PAINT()
  3891.     ON_BN_CLICKED( 102, OnContainer )
  3892.     ON_COMMAND( ID_BUTTON_CONTAINER, OnContainer )
  3893. END_MESSAGE_MAP()
  3894.  
  3895. int CMessageInfoBar::OnCreate( LPCREATESTRUCT lpCreateStruct )
  3896. {
  3897.     int res = CMailInfoBar::OnCreate( lpCreateStruct );
  3898.     if ( res != -1 ) {
  3899.         CString csFull, csLabel, csTip, csStatus;
  3900.         WFE_ParseButtonString( ID_NAVIGATE_MSGCONTAINER, csStatus, csTip, csLabel );
  3901.         m_wndBackButton.Create( this, FALSE, CSize(20,20), CSize(20,20), 
  3902.                                 csLabel, csTip, csStatus,
  3903.                                 IDB_BACK, 0, CSize(16,16), 
  3904.                                 ID_BUTTON_CONTAINER, 0, TB_DYNAMIC_TOOLTIP );
  3905.  
  3906.         m_wndBackButton.SetActionMessageOwner(this);
  3907.  
  3908.         RECT rect;
  3909.         SetRectEmpty(&rect);
  3910.         m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
  3911.     }
  3912.  
  3913.     return res;
  3914. }
  3915.         
  3916. void CMessageInfoBar::OnSize( UINT nType, int cx, int cy )
  3917. {
  3918.     if ( nType != SIZE_MINIMIZED ) {
  3919.         m_wndBackButton.MoveWindow( cx - 22, 3, 22, cy - 6 );
  3920.     }
  3921. }
  3922.  
  3923. void CMessageInfoBar::OnPaint( )
  3924. {
  3925.     CPaintDC dc(this);
  3926.     CRect rect;
  3927.     GetClientRect( &rect );
  3928.  
  3929.     PaintBackground( dc.m_hDC );
  3930.  
  3931.     m_pIImage->DrawTransImage( m_idxImage,
  3932.                                2,
  3933.                                rect.bottom / 2 - 8,
  3934.                                &dc );
  3935.  
  3936.     RECT rcTool;
  3937.     ::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
  3938.     m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);
  3939.  
  3940.     int oldMode = dc.SetBkMode( TRANSPARENT );
  3941.     HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldIntlFont );
  3942.  
  3943.     int iWidth = rect.right - rect.left;
  3944.     rect.left += 22;
  3945.     rect.right = 22 + iWidth / 2;
  3946.  
  3947.     DrawInfoText( m_iCSID, dc.m_hDC, m_csMessageName, &rect );
  3948.  
  3949.     dc.SelectObject( m_hIntlFont );
  3950.     rect.left = rect.right;
  3951.     rect.right = iWidth;
  3952.  
  3953.     DrawInfoText( m_iCSID, dc.m_hDC, m_csMessageAuthor, &rect );
  3954.  
  3955.     dc.SetBkMode( oldMode );
  3956.     dc.SelectObject( hOldFont );
  3957. }
  3958.  
  3959. void CMessageInfoBar::OnContainer()
  3960. {
  3961.     GetParentFrame()->PostMessage( WM_COMMAND, (WPARAM) ID_NAVIGATE_CONTAINER );
  3962. }
  3963.  
  3964. ///////////////////////////////////////////////////////////////////////
  3965.  
  3966.