home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / srchfrm.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  63.5 KB  |  2,503 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. // srchfrm.cpp : implementation file
  19. //
  20.  
  21. #include "stdafx.h"
  22. #include "srchfrm.h"
  23. #include "fldrfrm.h"
  24. #include "thrdfrm.h"
  25. #include "msgfrm.h"
  26. #include "abdefn.h"
  27. #include "addrbook.h"
  28. #include "wfemsg.h"
  29. #include "dirprefs.h"
  30. #include "xp_time.h"
  31. #include "xplocale.h"
  32. #include "template.h"
  33. #include "dateedit.h"
  34. #include "apimsg.h"
  35. #include "nethelp.h"
  36. #include "xp_help.h"
  37. #include "fegui.h"
  38. #include "intl_csi.h"
  39. #include "msg_srch.h"
  40. #include "advopdlg.h"
  41. #include "edhdrdlg.h"
  42. #include "srchobj.h"
  43. #include "shcut.h"
  44. #include "msgcom.h"
  45. #include "mailqf.h"
  46. #include "rdfglobal.h"
  47.  
  48. #define SEARCH_GROW_HEIGHT 200
  49.  
  50. #define SCOPE_SELECTED                  0
  51. #define SCOPE_ALL_MAIL                  1
  52. #define SCOPE_SUBSCRIBED_NEWS            2
  53. #define SCOPE_ALL_NEWS                  3
  54.  
  55. #define DEF_VISIBLE_COLUMNS                4
  56. #define LDAPSEARCH_SOURCETARGET_FORMAT "Netscape LDAP Search source-target"
  57. #define NETSCAPE_SEARCH_FORMAT "Netscape Search"
  58.  
  59. CSearchFrame            *g_pSearchWindow = NULL;
  60. CLDAPSearchFrame        *g_pLDAPSearchWindow = NULL;
  61.  
  62. #ifndef _AFXDLL
  63. #undef new
  64. #endif
  65. IMPLEMENT_DYNCREATE(CSearchView, COutlinerView)
  66. IMPLEMENT_DYNCREATE(CLDAPSearchView, COutlinerView)
  67. #ifndef _AFXDLL
  68. #define new DEBUG_NEW
  69. #endif
  70.  
  71. // Minor space saver
  72.  
  73. static _TCHAR szResultText[64];
  74.  
  75. /////////////////////////////////////////////////////////////////////////////
  76. // CSearchBar
  77.  
  78. static void SlideWindow( CWnd *pWnd, int dx, int dy )
  79. {
  80.     CRect rect;
  81.     CWnd *parent;
  82.  
  83.     pWnd->GetWindowRect(&rect);
  84.     if (parent = pWnd->GetParent())
  85.         parent->ScreenToClient(&rect);
  86.  
  87.     rect.top += dy;
  88.     rect.left += dx;
  89.     rect.bottom += dy;
  90.     rect.right += dx;
  91.  
  92.     pWnd->MoveWindow(&rect, TRUE);
  93. }
  94.  
  95. static void GrowWindow( CWnd *pWnd, int dx, int dy )
  96. {
  97.     CRect rect;
  98.     CWnd *parent;
  99.  
  100.     pWnd->GetWindowRect(&rect);
  101.     if (parent = pWnd->GetParent())
  102.         parent->ScreenToClient(&rect);
  103.  
  104.     rect.bottom += dy;
  105.     rect.right += dx;
  106.  
  107.     pWnd->MoveWindow(&rect, TRUE);
  108. }
  109.  
  110. CSearchBar::CSearchBar()
  111. {
  112.     m_iMoreCount = 0;
  113.     m_iHeight = 0;
  114.     m_iWidth = 0;
  115.     m_bLogicType = 0;
  116. }
  117.  
  118. CSearchBar::~CSearchBar()
  119. {
  120. }
  121.  
  122. int CSearchBar::GetHeightNeeded()
  123. {
  124.     CRect rect, rect2, rect3;
  125.     CWnd *widget = GetDlgItem(IDC_MORE);
  126.     ASSERT(widget);
  127.     GetWindowRect(&rect);
  128.     widget->GetWindowRect(&rect2);
  129.  
  130.     CWnd *widget2 = NULL;
  131.  
  132.     if(m_bLDAP)
  133.     {
  134.         widget2 = GetDlgItem(IDC_ADVANCED_SEARCH);
  135.     }
  136.     else
  137.     {
  138.         widget2 = GetDlgItem(IDC_SEARCHHELP);
  139.     }
  140.  
  141.     if (widget2)
  142.         widget2->GetWindowRect(&rect3);
  143.     else
  144.         return 0;
  145.  
  146.     //because of help button
  147.     int nHeight = (rect3.bottom > rect2.bottom) ? rect3.bottom : rect2.bottom;
  148.     return nHeight - rect.top + 8;
  149. }
  150.  
  151. MSG_ScopeAttribute CSearchBar::DetermineScope( DWORD dwItemData )
  152. {
  153.     MSG_Pane *pPane = NULL;
  154.     MSG_ScopeAttribute scope = scopeMailFolder;
  155.  
  156.     if ( m_bLDAP ) {
  157.         scope = scopeLdapDirectory;
  158.     } else {
  159.         MSG_FolderLine folderLine;
  160.         if (MSG_GetFolderLineById(WFE_MSGGetMaster(), (MSG_FolderInfo *) dwItemData, &folderLine)) {
  161.             if (folderLine.flags & MSG_FOLDER_FLAG_MAIL) {
  162.                 scope = scopeMailFolder;    // Yeah, it's redundant
  163.             } else if (folderLine.flags & (MSG_FOLDER_FLAG_NEWS_HOST|MSG_FOLDER_FLAG_NEWSGROUP)) {
  164.                 scope = scopeNewsgroup;
  165.             }
  166.         }
  167.     }
  168.     return scope;
  169. }
  170.  
  171. void CSearchBar::UpdateAttribList()
  172. {
  173.     CComboBox* combo;
  174.     int iScopeCurSel;
  175.  
  176.     combo = (CComboBox *) GetDlgItem( IDC_COMBO_SCOPE );
  177.     iScopeCurSel = combo->GetCurSel();
  178.     DWORD dwItemData = combo->GetItemData(iScopeCurSel);
  179.  
  180.     MSG_ScopeAttribute scope = DetermineScope( dwItemData );
  181.  
  182.     m_searchObj.UpdateAttribList (scope);
  183. }
  184.  
  185. void CSearchBar::InitializeAttributes (MSG_SearchValueWidget widgetValue, MSG_SearchAttribute attribValue)
  186. {
  187.     m_searchObj.InitializeAttributes (widgetValue, attribValue);
  188. }
  189.  
  190. void CSearchBar::UpdateOpList()
  191. {
  192.     CComboBox* combo;
  193.     int iScopeCurSel;
  194.  
  195.     combo = (CComboBox *) GetDlgItem( IDC_COMBO_SCOPE );
  196.     iScopeCurSel = combo->GetCurSel();
  197.     DWORD dwItemData = combo->GetItemData(iScopeCurSel);
  198.  
  199.     MSG_ScopeAttribute scope = DetermineScope( dwItemData );
  200.  
  201.     m_searchObj.UpdateOpList (scope);
  202. }
  203.  
  204.  
  205. void CSearchBar::UpdateOpList(int iRow)
  206. {
  207.     CComboBox* combo;
  208.     int iScopeCurSel;
  209.  
  210.     combo = (CComboBox *) GetDlgItem( IDC_COMBO_SCOPE );
  211.     iScopeCurSel = combo->GetCurSel();
  212.     DWORD dwItemData = combo->GetItemData(iScopeCurSel);
  213.  
  214.     MSG_ScopeAttribute scope = DetermineScope( dwItemData );
  215.  
  216.     m_searchObj.UpdateOpList (iRow, scope);
  217. }
  218.  
  219. int CSearchBar::More()
  220. {
  221.     int dy = 0;
  222.  
  223.     dy = m_searchObj.More (&m_iMoreCount, m_bLogicType);
  224.  
  225. #ifndef _WIN32
  226.     m_sizeFixedLayout.cy = GetHeightNeeded();
  227. #endif
  228.  
  229.     return dy;
  230. }
  231.  
  232. int CSearchBar::ChangeLogicText()
  233. {
  234.     m_searchObj.ChangeLogicText (m_iMoreCount, m_bLogicType);
  235.  
  236.     return 1;
  237. }
  238.  
  239.  
  240. int CSearchBar::Fewer()
  241. {
  242.     int dy = 0;
  243.  
  244.     dy = m_searchObj.Fewer(&m_iMoreCount, m_bLogicType);
  245.  
  246. #ifndef _WIN32
  247.     m_sizeFixedLayout.cy = GetHeightNeeded();
  248. #endif
  249.  
  250.     return dy;
  251. }
  252.  
  253. void CSearchBar::Advanced()
  254. {
  255. }
  256.  
  257. void CSearchBar::OnAndOr()
  258. {
  259.     m_searchObj.OnAndOr (m_iMoreCount, &m_bLogicType);
  260. }
  261.  
  262. int CSearchBar::ClearSearch(BOOL bIsLDAPSearch)
  263. {
  264.     int dy = 0, res = 0;
  265.  
  266.     res = m_searchObj.ClearSearch (&m_iMoreCount, bIsLDAPSearch);
  267.  
  268.     //We need to tell the frame to shrink
  269.     if ( !m_iMoreCount  && !res)
  270.     {
  271.         CRect rect;
  272.         GetParent()->GetWindowRect(&rect);
  273.         if (rect.Height() > m_iOrigFrameHeight)
  274.             res =  (m_iOrigFrameHeight - rect.Height());  //We need to tell the frame to shrink
  275.     }
  276.  
  277.     UpdateAttribList();
  278.     UpdateOpList();
  279.  
  280.     m_searchObj.ReInitializeWidgets();
  281.     
  282. #ifndef _WIN32
  283.     m_sizeFixedLayout.cy = GetHeightNeeded();
  284. #endif
  285.  
  286.     return res;
  287. }
  288.  
  289. void CSearchBar::BuildQuery(MSG_Pane* searchPane)
  290. {
  291.     m_searchObj.BuildQuery (searchPane, m_iMoreCount, m_bLogicType);
  292. }
  293.  
  294. /////////////////////////////////////////////////////////////////////////////
  295. // CSearchBar overloaded methods
  296.  
  297. BOOL CSearchBar::Create(CWnd* pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID)
  298. {
  299.     BOOL res = CDialogBar::Create(pParentWnd, nIDTemplate, nStyle, nID);
  300.  
  301.     CRect rect, rect2;
  302.     int dy = 0;
  303.  
  304.     dy = m_searchObj.New (this);
  305.                 
  306.     m_iHeight = m_sizeDefault.cy - dy;
  307. #ifndef _WIN32
  308.     m_sizeFixedLayout.cy = m_iHeight;
  309. #endif
  310.     m_iWidth = m_sizeDefault.cx;
  311.  
  312.     return res;
  313. }
  314.  
  315. CSize CSearchBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)    
  316. {
  317.     CSize size;
  318.     size.cx = (bStretch && bHorz ? 32767 : m_sizeDefault.cx );
  319.     size.cy = GetHeightNeeded ( );
  320.     return size;    
  321. }
  322.  
  323. /////////////////////////////////////////////////////////////////////////////
  324. // CSearchBar Message handlers
  325.  
  326. BEGIN_MESSAGE_MAP(CSearchBar, CDialogBar)
  327.     //{{AFX_MSG_MAP(CSearchFrame)
  328.     ON_WM_CREATE()
  329.     ON_WM_SIZE()
  330.     //}}AFX_MSG_MAP
  331. #ifndef _WIN32
  332.     ON_MESSAGE(WM_DLGSUBCLASS, OnDlgSubclass)
  333. #endif
  334. END_MESSAGE_MAP()
  335.  
  336. int CSearchBar::OnCreate( LPCREATESTRUCT lpCreateStruct )
  337. {
  338.     int retval =  CDialogBar::OnCreate( lpCreateStruct);
  339.  
  340.     CRect rect;
  341.     GetWindowRect(&rect);
  342.     m_sizeDefault = rect.Size();
  343.  
  344.     return retval;
  345. }
  346.  
  347. void CSearchBar::OnSize( UINT nType, int cx, int cy )
  348. {
  349.     CDialogBar::OnSize( nType, cx, cy );
  350.     if ( cx && m_iWidth && ( cx != m_iWidth ) ) {
  351.         CWnd *widget;
  352.         int dx = cx - m_iWidth;
  353.         
  354.         widget = GetDlgItem(IDC_FIND);
  355.         SlideWindow(widget, dx, 0);
  356.         widget = GetDlgItem(IDC_SAVE);
  357.         if (widget)
  358.             SlideWindow(widget, dx, 0);
  359.         widget = GetDlgItem(IDC_SEARCHHELP);
  360.         SlideWindow(widget, dx, 0);
  361.  
  362.         widget = GetDlgItem(IDC_ADVANCED_SEARCH);
  363.         SlideWindow(widget, dx, 0);
  364.  
  365.  
  366.         m_searchObj.OnSize (nType, cx, cy, dx);
  367.         m_iWidth = cx;
  368.     }
  369. }
  370.  
  371. #ifndef _WIN32
  372. LRESULT CSearchBar::OnDlgSubclass(WPARAM wParam, LPARAM lParam)
  373. {
  374.     *(int FAR*) lParam = 0;
  375.  
  376.     return 0;
  377. }
  378. #endif
  379.  
  380. /////////////////////////////////////////////////////////////////////////////
  381. // CNewsMsgList
  382.  
  383. class CSearchResultsList: public IMsgList {
  384.  
  385.     CSearchFrame *m_pControllingFrame;
  386.     unsigned long m_ulRefCount;
  387.  
  388. public:
  389. // IUnknown Interface
  390.     STDMETHODIMP                    QueryInterface(REFIID,LPVOID *);
  391.     STDMETHODIMP_(ULONG)    AddRef(void);
  392.     STDMETHODIMP_(ULONG)    Release(void);
  393.  
  394. // IMsgList Interface
  395.     virtual void ListChangeStarting( MSG_Pane* pane, XP_Bool asynchronous,
  396.                                      MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  397.                                      int32 num);
  398.     virtual void ListChangeFinished( MSG_Pane* pane, XP_Bool asynchronous,
  399.                                      MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  400.                                      int32 num);
  401.  
  402.     virtual void GetSelection( MSG_Pane* pane, MSG_ViewIndex **indices, int *count, 
  403.                                 int *focus);
  404.     virtual void SelectItem( MSG_Pane* pane, int item );
  405.     virtual void CopyMessagesInto( MSG_Pane *pane, MSG_ViewIndex *indices, int count,
  406.                                    MSG_FolderInfo *folderInfo);
  407.     virtual void MoveMessagesInto( MSG_Pane *pane, MSG_ViewIndex *indices, int count,
  408.                                    MSG_FolderInfo *folderInfo);
  409.  
  410.     CSearchResultsList( CSearchFrame *pControllingFrame ) {
  411.         m_ulRefCount = 0;
  412.         m_pControllingFrame = pControllingFrame;
  413.     }
  414. };
  415.  
  416. STDMETHODIMP CSearchResultsList::QueryInterface(REFIID refiid, LPVOID * ppv)
  417. {
  418.     *ppv = NULL;
  419.     if (IsEqualIID(refiid,IID_IUnknown))
  420.         *ppv = (LPUNKNOWN) this;
  421.     else if (IsEqualIID(refiid,IID_IMsgList))
  422.         *ppv = (LPMSGLIST) this;
  423.  
  424.     if (*ppv != NULL) {
  425.         ((LPUNKNOWN) *ppv)->AddRef();
  426.         return NOERROR;
  427.     }
  428.         
  429.     return ResultFromScode(E_NOINTERFACE);
  430. }
  431.  
  432. STDMETHODIMP_(ULONG) CSearchResultsList::AddRef(void)
  433. {
  434.     return ++m_ulRefCount;
  435. }
  436.  
  437. STDMETHODIMP_(ULONG) CSearchResultsList::Release(void)
  438. {
  439.     ULONG ulRef;
  440.     ulRef = --m_ulRefCount;
  441.     if (m_ulRefCount == 0) 
  442.         delete this;    
  443.     return ulRef;           
  444. }
  445.  
  446. void CSearchResultsList::ListChangeStarting( MSG_Pane* pane, XP_Bool asynchronous,
  447.                                        MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  448.                                        int32 num)
  449. {
  450.     if (m_pControllingFrame) {
  451.         m_pControllingFrame->ListChangeStarting( pane, asynchronous,
  452.                                                  notify, where, num );
  453.     }
  454. }
  455.  
  456. void CSearchResultsList::ListChangeFinished( MSG_Pane* pane, XP_Bool asynchronous,
  457.                                        MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  458.                                        int32 num)
  459. {
  460.     if (m_pControllingFrame) {
  461.         m_pControllingFrame->ListChangeFinished( pane, asynchronous,
  462.                                                  notify, where, num );
  463.     }
  464. }
  465.  
  466. void CSearchResultsList::GetSelection( MSG_Pane* pane, MSG_ViewIndex **indices, int *count, 
  467.                                 int *focus)
  468. {
  469. }
  470.  
  471. void CSearchResultsList::SelectItem( MSG_Pane* pane, int item )
  472. {
  473. }
  474.  
  475. void CSearchResultsList::MoveMessagesInto( MSG_Pane *pane, MSG_ViewIndex *indices, int count,
  476.                                    MSG_FolderInfo *folderInfo)
  477. {
  478.  
  479.  
  480.  
  481.     MSG_DragEffect  effect = MSG_DragMessagesIntoFolderStatus(pane,
  482.                                     indices,
  483.                                     count,
  484.                                     folderInfo,
  485.                                     MSG_Require_Move);
  486.     if (effect != MSG_Drag_Not_Allowed)
  487.         MSG_MoveMessagesIntoFolder(pane, indices, count, folderInfo);
  488.     
  489. }
  490.  
  491. void CSearchResultsList::CopyMessagesInto( MSG_Pane *pane, MSG_ViewIndex *indices, int count,
  492.                                    MSG_FolderInfo *folderInfo) 
  493. {
  494.     MSG_DragEffect  effect = MSG_DragMessagesIntoFolderStatus(pane,
  495.                                     indices,
  496.                                     count,
  497.                                     folderInfo,
  498.                                     MSG_Require_Copy);
  499.     if (effect != MSG_Drag_Not_Allowed)
  500.         MSG_CopyMessagesIntoFolder(pane, indices, count, folderInfo);
  501. }
  502.  
  503. /////////////////////////////////////////////////////////////////////////////
  504. // CSearchFrame
  505.  
  506. CSearchFrame::CSearchFrame()
  507. {
  508.     INTL_CharSetInfo csi = LO_GetDocumentCharacterSetInfo(GetContext());
  509.     m_cxType = SearchCX;
  510.  
  511.     GetContext()->type = MWContextSearch;
  512.     GetContext()->fancyFTP = TRUE;
  513.     GetContext()->fancyNews = TRUE;
  514.     GetContext()->intrupt = FALSE;
  515.     GetContext()->reSize = FALSE;
  516.     INTL_SetCSIWinCSID(csi, CIntlWin::GetSystemLocaleCsid());
  517.  
  518.     m_pMaster = WFE_MSGGetMaster();
  519.  
  520.     m_iHeight = 0;
  521.     m_iWidth = 0;
  522.     m_bResultsShowing = FALSE;
  523.     m_bSearching = FALSE;
  524.     m_bIsLDAPSearch = FALSE;
  525.     m_bDragCopying = FALSE;
  526.  
  527.     m_listSearch = XP_ListNew();
  528.     m_listResult = NULL;
  529.     m_pOutliner = NULL;
  530.     m_pAdvancedOptionsDlg = NULL;
  531.     m_pCustomHeadersDlg = NULL;
  532.  
  533.     CSearchResultsList *pInstance = new CSearchResultsList (this);
  534.     pInstance->QueryInterface (IID_IMsgList, (LPVOID *) &m_pIMsgList);
  535.  
  536.     m_pSearchPane = MSG_CreateSearchPane (GetContext(), WFE_MSGGetMaster());
  537.     MSG_SetFEData (m_pSearchPane, pInstance);
  538. }
  539.  
  540. CSearchFrame::~CSearchFrame()
  541. {
  542.     MSG_SearchFree (m_pSearchPane);
  543.     MSG_DestroyPane (m_pSearchPane);
  544.     m_pIMsgList->Release();
  545. }
  546.  
  547. #ifndef _WIN32
  548.  
  549. CWnd* CSearchFrame::CreateView(CCreateContext* pContext, UINT nID)
  550. {
  551.     ASSERT(m_hWnd != NULL);
  552.     ASSERT(::IsWindow(m_hWnd));
  553.     ASSERT(pContext != NULL);
  554.     ASSERT(pContext->m_pNewViewClass != NULL);
  555.  
  556.     // Note: can be a CWnd with PostNcDestroy self cleanup
  557.     CWnd* pView = (CWnd*)pContext->m_pNewViewClass->CreateObject();
  558.     if (pView == NULL)
  559.     {
  560.         TRACE1("Warning: Dynamic create of view type %hs failed.\n",
  561.             pContext->m_pNewViewClass->m_lpszClassName);
  562.         return NULL;
  563.     }
  564.     ASSERT(pView->IsKindOf( RUNTIME_CLASS( CWnd ) ));
  565.  
  566.     // views are always created with a border!
  567.     if (!pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
  568.         CRect(0,0,0,0), this, nID, pContext))
  569.     {
  570.         TRACE0("Warning: could not create view for frame.\n");
  571.         return NULL;        // can't continue without a view
  572.     }
  573.  
  574.     return pView;
  575. }
  576.  
  577. #endif
  578.  
  579. void CSearchFrame::AdjustHeight(int dy)
  580. {
  581.     CRect rect;
  582.     GetWindowRect(&rect);
  583.  
  584.     CSize size = rect.Size();
  585.     size.cy += dy; //plus fudge for group box bottom margin
  586.     m_iHeight = size.cy;
  587.  
  588.     SetWindowPos( NULL, 0, 0, size.cx, size.cy,
  589.                   SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  590. }
  591.  
  592. void CSearchFrame::ShowResults( BOOL bShow )
  593. {
  594.     if ( bShow != m_bResultsShowing ) {
  595.         if (bShow) {
  596.             CRect rect;
  597.             GetWindowRect(&rect);
  598.             CSize size = rect.Size();
  599.             m_iHeight += SEARCH_GROW_HEIGHT;
  600.             SetWindowPos( NULL, 0, 0, size.cx, m_iHeight,
  601.                           SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  602.  
  603.             m_barStatus.ShowWindow(SW_SHOW);        
  604.  
  605.             RecalcLayout();
  606.  
  607.         } else {
  608.  
  609.             CRect rect;
  610.             GetWindowRect(&rect);
  611.             CSize size = rect.Size();
  612.             m_iHeight -= SEARCH_GROW_HEIGHT;
  613.             SetWindowPos( NULL, 0, 0, size.cx, m_iHeight,
  614.                           SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  615.  
  616.             RecalcLayout();
  617.  
  618.             m_pOutliner->SetTotalLines(0);
  619.             m_pOutliner->SelectItem(0);
  620.         }
  621.         m_bResultsShowing = bShow;
  622.     }
  623. }
  624.  
  625. void CSearchFrame::ListChangeStarting( MSG_Pane* pane, XP_Bool asynchronous,
  626.                              MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  627.                              int32 num)
  628. {
  629.     if ( pane == (MSG_Pane*) m_pSearchPane ) 
  630.     {
  631.         if ( m_pOutliner ) 
  632.         {
  633.             m_pOutliner->MysticStuffStarting( asynchronous, notify,where, num );
  634.         }
  635.     }
  636. }
  637.  
  638. void CSearchFrame::ListChangeFinished( MSG_Pane* pane, XP_Bool asynchronous,
  639.                              MSG_NOTIFY_CODE notify, MSG_ViewIndex where,
  640.                              int32 num)
  641. {
  642.     if ( pane == (MSG_Pane*) m_pSearchPane ) 
  643.     {
  644.         if ( m_pOutliner ) 
  645.         {
  646.             m_pOutliner->MysticStuffFinishing( asynchronous, notify, where, num );
  647.         }
  648.     }
  649. }
  650.  
  651. void CSearchFrame::Progress(MWContext *pContext, const char *pMessage)
  652. {
  653.     m_barStatus.SetPaneText( m_barStatus.CommandToIndex( ID_SEPARATOR), pMessage );
  654. }
  655.  
  656. void CSearchFrame::SetProgressBarPercent(MWContext *pContext, int32 lPercent)
  657. {
  658.     m_barStatus.SetPercentDone(lPercent);
  659. }
  660.  
  661. void CSearchFrame::AllConnectionsComplete( MWContext *pContext )
  662. {
  663.     CStubsCX::AllConnectionsComplete( pContext );
  664.  
  665.     // If we were performing a search as view operation, we want to turn the progress bar cylon 
  666.     // off when the connections are complete because this implies that the search as view op is done!
  667.     if (!m_bSearching) 
  668.         SetProgressBarPercent(pContext, 0); 
  669.  
  670.     m_bSearching = FALSE;
  671.  
  672.     int total = m_pOutliner->GetTotalLines();
  673.     CString csStatus;
  674.     if ( total > 1) {
  675.         csStatus.Format( szLoadString(IDS_SEARCHHITS), total );
  676.     } else if ( total > 0 ) {
  677.         csStatus.LoadString( IDS_SEARCHONEHIT );
  678.     } else {
  679.         csStatus.LoadString( IDS_SEARCHNOHITS );
  680.     }
  681.     m_barStatus.SetPaneText( m_barStatus.CommandToIndex( ID_SEPARATOR), csStatus );
  682.     SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  683. }
  684.  
  685. void CSearchFrame::UpdateScopes( CMailNewsFrame *pFrame )
  686. {
  687.     m_barSearch.m_wndScopes.Populate(WFE_MSGGetMaster(), NULL);
  688.     
  689.     MSG_FolderInfo *folderInfo = pFrame ? pFrame->GetCurFolder() : NULL;
  690.  
  691.     m_barSearch.m_wndScopes.SetCurSel(0);
  692.     if (folderInfo) {
  693.         MSG_FolderLine folderLine;
  694.         MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
  695.         if (folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) {
  696.             folderInfo = MSG_GetCategoryContainerForCategory(folderInfo);
  697.         }
  698.         for ( int i = 0; i < m_barSearch.m_wndScopes.GetCount(); i++ ) {
  699.             DWORD dwItemData = m_barSearch.m_wndScopes.GetItemData(i);
  700.             if (dwItemData == (DWORD) folderInfo) {
  701.                 m_barSearch.m_wndScopes.SetCurSel(i);
  702.                 break;
  703.             }
  704.         }
  705.     }
  706.     m_barSearch.UpdateAttribList();
  707.     m_barSearch.UpdateOpList();
  708. }
  709.  
  710. /////////////////////////////////////////////////////////////////////////////
  711. // CSearchFrame Overloaded methods
  712.  
  713. void CSearchFrame::Create()
  714. {
  715.     DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
  716.     CString strFullString, strTitle;
  717.     strFullString.LoadString( IDR_SEARCHFRAME );
  718.     AfxExtractSubString( strTitle, strFullString, 0 );
  719.  
  720.     LPCTSTR lpszClass = GetIconWndClass( dwDefaultStyle, IDR_SEARCHFRAME );
  721.     LPCTSTR lpszTitle = strTitle;
  722.     CFrameWnd::Create(lpszClass, lpszTitle, dwDefaultStyle);
  723.  
  724.     ActivateFrame();
  725. }
  726.  
  727. BOOL CSearchFrame::PreCreateWindow(CREATESTRUCT& cs) 
  728. {
  729.     cs.hwndParent = NULL;
  730.     return CFrameWnd::PreCreateWindow(cs);
  731. }
  732.  
  733. BOOL CSearchFrame::OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext )
  734. {
  735.     CWnd *pWnd;
  736.     CCreateContext Context;
  737.     Context.m_pNewViewClass = RUNTIME_CLASS(CSearchView);
  738.     
  739.     if ( pWnd = CreateView(&Context) ) {
  740.         COutlinerView *pView = (COutlinerView *) pWnd;
  741.         pView->CreateColumns ( );
  742.         m_pOutliner = (CSearchOutliner *) pView->m_pOutlinerParent->m_pOutliner;
  743.         m_pOutliner->SetContext( GetContext() );
  744.         m_pOutliner->SetPane (m_pSearchPane);
  745.     } else {
  746.         return FALSE;
  747.     }
  748.  
  749.  
  750.     return TRUE;
  751. }
  752.  
  753. /////////////////////////////////////////////////////////////////////////////
  754. // CSearchFrame message handlers
  755.  
  756. BEGIN_MESSAGE_MAP(CSearchFrame, CFrameWnd)
  757.     ON_WM_CREATE()
  758.     ON_WM_CLOSE()
  759.     ON_WM_DESTROY()
  760.     ON_WM_GETMINMAXINFO()
  761.     ON_BN_CLICKED(IDC_MORE, OnMore)
  762.     ON_UPDATE_COMMAND_UI( IDC_MORE, OnUpdateMore )
  763.     ON_BN_CLICKED(IDC_FEWER, OnFewer)
  764.     ON_UPDATE_COMMAND_UI( IDC_FEWER, OnUpdateFewer )
  765.     ON_BN_CLICKED(IDC_FIND, OnFind)
  766.     ON_UPDATE_COMMAND_UI( IDC_FIND, OnUpdateFind )
  767.     ON_BN_CLICKED(IDC_TO, OnTo)
  768.     ON_UPDATE_COMMAND_UI( IDC_TO, OnUpdateTo )
  769.     ON_BN_CLICKED(IDC_BUTTON_FILE_MESSAGE, OnFileButton)
  770.     ON_UPDATE_COMMAND_UI( IDC_BUTTON_FILE_MESSAGE, OnUpdateFileButton )
  771.  
  772.     ON_BN_CLICKED(IDC_NEW, OnNew)
  773.     ON_UPDATE_COMMAND_UI(IDC_NEW, OnUpdateQuery)
  774.     ON_BN_CLICKED(IDC_SAVE, OnSave)
  775.     ON_UPDATE_COMMAND_UI( IDC_SAVE, OnUpdateSave )
  776.     ON_BN_CLICKED(IDC_SEARCHHELP, OnHelp)
  777.     ON_UPDATE_COMMAND_UI( IDC_SEARCHHELP, OnUpdateHelp )
  778.     ON_BN_CLICKED(IDC_ADVANCED_SEARCH, OnAdvanced)
  779.     ON_UPDATE_COMMAND_UI( IDC_ADVANCED_SEARCH, OnUpdateAdvanced )
  780.     ON_CBN_SELCHANGE(IDC_COMBO_SCOPE, OnScope)
  781.     ON_CBN_SELCHANGE(IDC_COMBO_ATTRIB1, OnAttrib1)
  782.     ON_CBN_SELCHANGE(IDC_COMBO_ATTRIB2, OnAttrib2)
  783.     ON_CBN_SELCHANGE(IDC_COMBO_ATTRIB3, OnAttrib3)
  784.     ON_CBN_SELCHANGE(IDC_COMBO_ATTRIB4, OnAttrib4)
  785.     ON_CBN_SELCHANGE(IDC_COMBO_ATTRIB5, OnAttrib5)
  786.     ON_CBN_SELCHANGE(IDC_COMBO_AND_OR, OnAndOr)
  787.     ON_UPDATE_COMMAND_UI(IDC_COMBO_AND_OR, OnUpdateAndOr)
  788.     ON_MESSAGE(WM_ADVANCED_OPTIONS_DONE, OnFinishedAdvanced)
  789.     ON_MESSAGE(WM_EDIT_CUSTOM_DONE, OnFinishedHeaders)
  790.  
  791.     ON_COMMAND(ID_EDIT_DELETEMESSAGE, OnDeleteMessage)
  792.     ON_UPDATE_COMMAND_UI(ID_EDIT_DELETEMESSAGE, OnUpdateDeleteMessage)
  793.  
  794.     ON_COMMAND(ID_FILE_OPENMESSAGE, OnOpenMessage)
  795.     ON_UPDATE_COMMAND_UI(ID_FILE_OPENMESSAGE, OnUpdateOpenMessage)
  796.  
  797. #ifdef ON_COMMAND_RANGE
  798.     ON_COMMAND_RANGE(FIRST_MOVE_MENU_ID, LAST_MOVE_MENU_ID, OnFileMessage )
  799. #endif
  800.  
  801. #ifdef ON_UPDATE_COMMAND_UI_RANGE
  802.     ON_UPDATE_COMMAND_UI_RANGE( IDC_COMBO_ATTRIB1, IDC_EDIT_VALUE5, OnUpdateQuery )
  803.     ON_UPDATE_COMMAND_UI_RANGE( FIRST_MOVE_MENU_ID, LAST_MOVE_MENU_ID, OnUpdateFile )
  804.  
  805. #endif
  806.     ON_UPDATE_COMMAND_UI( ID_MESSAGE_FILE, OnUpdateFile )
  807.     ON_UPDATE_COMMAND_UI( IDC_COMBO_SCOPE, OnUpdateQuery )
  808.  
  809. END_MESSAGE_MAP()
  810.  
  811. #ifndef ON_COMMAND_RANGE
  812.  
  813. BOOL CSearchFrame::OnCommand( WPARAM wParam, LPARAM lParam )
  814. {
  815.     UINT nID = wParam;
  816.  
  817.     if ( nID >= FIRST_MOVE_MENU_ID && nID <= LAST_MOVE_MENU_ID ) {
  818.         OnFileMessage( nID );
  819.         return TRUE;
  820.     }
  821.     return CSearchFrame::OnCommand( wParam, lParam );
  822. }
  823.  
  824. #endif
  825.  
  826.  
  827. #ifndef ON_UPDATE_COMMAND_UI_RANGE
  828.  
  829. BOOL CSearchFrame::OnCmdMsg( UINT nID, int nCode, void* pExtra, 
  830.                              AFX_CMDHANDLERINFO* pHandlerInfo ) 
  831. {
  832.     if ((nID >= IDC_COMBO_ATTRIB1) && (nID <= IDC_EDIT_VALUE5) && 
  833.         ( nCode == CN_UPDATE_COMMAND_UI) ) {
  834.         OnUpdateQuery( (CCmdUI *) pExtra );
  835.         return TRUE;
  836.     }
  837.     else if (nCode == CN_UPDATE_COMMAND_UI) 
  838.     {
  839.         CCmdUI* pCmdUI = (CCmdUI*)pExtra;
  840.         if ( nID >= FIRST_MOVE_MENU_ID && nID <= LAST_MOVE_MENU_ID ) {
  841.             OnUpdateFile( pCmdUI );
  842.             return TRUE;
  843.         }
  844.         if ( nID >= FIRST_COPY_MENU_ID && nID <= LAST_COPY_MENU_ID ) {
  845.             OnUpdateFile( pCmdUI );
  846.             return TRUE;
  847.         }
  848.     }
  849.     return CFrameWnd::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
  850. }
  851.  
  852. #endif
  853.  
  854.  
  855. void CSearchFrame::OnFileButton()
  856. {
  857.     int nTotalLines = m_pOutliner->GetTotalLines();
  858.     MSG_ViewIndex *indices;
  859.     int iSel;
  860.     m_pOutliner->GetSelection(indices, iSel);
  861.     HMENU hFileMenu = CreatePopupMenu();
  862.     if (!hFileMenu)
  863.         return;  //Bail!!!
  864.  
  865.     if ( iSel < nTotalLines ) 
  866.     {
  867.         UINT nID = FIRST_MOVE_MENU_ID;
  868.         CMailNewsFrame::UpdateMenu( NULL, hFileMenu, nID );
  869.     }
  870.  
  871.  
  872.     CRect rect;
  873.     CWnd *pWidget = (CWnd*) m_barAction.GetDlgItem(IDC_BUTTON_FILE_MESSAGE);
  874.     if (pWidget)
  875.     {   //convert this bad boy to Screen units
  876.         pWidget->GetWindowRect(&rect);
  877.         ::MapDialogRect(pWidget->GetSafeHwnd(), &rect);
  878.         pWidget->EnableWindow(FALSE);
  879.     }
  880.     else
  881.     {
  882.         return;//Bail!!
  883.     }
  884.  
  885.     //    Track the popup now.        
  886.        DWORD dwError = ::TrackPopupMenu( hFileMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, rect.left, rect.bottom, 0,
  887.                       GetSafeHwnd(), NULL);
  888.  
  889.     pWidget->EnableWindow(TRUE);
  890.  
  891.  
  892.     //  Cleanup handled in CMailNewsFrame
  893.     //VERIFY(::DestroyMenu( hFileMenu ));
  894. }
  895.  
  896.  
  897. void CSearchFrame::OnUpdateFileButton(CCmdUI *pCmdUI)
  898. {
  899.     MSG_ViewIndex *indices;
  900.     int count;
  901.     m_pOutliner->GetSelection(indices, count);
  902.     int nLines = m_pOutliner->GetTotalLines();
  903.  
  904.     pCmdUI->Enable( ((nLines > 0) && count));
  905. }
  906.  
  907. void CSearchFrame::OnFileMessage(UINT nID)
  908. {
  909.     if ( m_pSearchPane ) 
  910.     {
  911.         MSG_ViewIndex *indices;
  912.         int count;
  913.         m_pOutliner->GetSelection(indices, count);
  914.         MSG_FolderInfo *folderInfo = FolderInfoFromMenuID( nID );
  915.  
  916.         ASSERT(folderInfo);
  917.         if (folderInfo) 
  918.         {
  919.             // We want to make file behave for newsgroups
  920.             if ( MSG_GetFolderFlags(folderInfo) & MSG_FOLDER_FLAG_NEWSGROUP ) 
  921.             {
  922.                 MSG_CopyMessagesIntoFolder( m_pSearchPane, indices, count, folderInfo);
  923.             } 
  924.             else 
  925.             {
  926.                 MSG_MoveMessagesIntoFolder( m_pSearchPane, indices, count, folderInfo);
  927.             }
  928.             ModalStatusBegin( MODAL_DELAY );
  929.         }
  930.     }
  931.  
  932. }
  933.  
  934. void CSearchFrame::OnOpenMessage()
  935. {
  936.     BOOL bReuse = g_MsgPrefs.m_bMessageReuse;
  937.     if (GetKeyState(VK_MENU) & 0x8000)
  938.         bReuse = !bReuse;
  939.  
  940.     MSG_ViewIndex *indices;
  941.     int i, count;
  942.     
  943.     m_pOutliner->GetSelection(indices, count);
  944.  
  945.     for ( i = 0; i < count; i++ ) {
  946.         MSG_ResultElement *elem = NULL;
  947.         MSG_GetResultElement(m_pSearchPane, indices[i], &elem);
  948.  
  949.         ASSERT(elem);
  950.  
  951.         if ( !elem )
  952.             continue;
  953.  
  954.         MWContextType cxType = MSG_GetResultElementType( elem );
  955.  
  956.         if ( cxType == MWContextMail || cxType == MWContextMailMsg || 
  957.              cxType == MWContextNews || cxType == MWContextNewsMsg ) {
  958.             CMessageFrame *frame = CMessageFrame::Open ();
  959.             MSG_OpenResultElement (elem, frame->GetPane());
  960.         } else if ( cxType == MWContextBrowser ) {
  961.             MWContext *pContext = NULL;
  962.             VERIFY(pContext = CFE_CreateNewDocWindow( NULL, NULL ));
  963.             if (pContext) {
  964.                 MSG_OpenResultElement( elem, (MSG_Pane *) pContext );
  965.             }
  966.         } else { 
  967.             ASSERT(0); // What on earth are you passing me?
  968.         }
  969.     }
  970. }
  971.  
  972. void CSearchFrame::OnUpdateOpenMessage(CCmdUI *pCmdUI )
  973. {
  974.     pCmdUI->Enable(TRUE);
  975. }
  976.  
  977.  
  978. MSG_FolderInfo *CSearchFrame::FolderInfoFromMenuID( MSG_FolderInfo *mailRoot, 
  979.                                                       UINT &nBase, UINT nID )
  980. {
  981.     int i, iCount;
  982.     MSG_FolderInfo **folderInfos;
  983.     MSG_FolderInfo *res = NULL;
  984.     MSG_FolderLine folderLine;
  985.  
  986.     if (mailRoot == NULL ) {
  987.         // Loop through top level folderInfos, looking for mail trees.
  988.  
  989.         iCount = MSG_GetFolderChildren(m_pMaster, NULL, NULL, NULL);
  990.         folderInfos = new MSG_FolderInfo*[iCount];
  991.         if (folderInfos) {
  992.             MSG_GetFolderChildren(m_pMaster, NULL, folderInfos, iCount);
  993.  
  994.             for (i = 0; i < iCount && !res; i++) {
  995.                 if (MSG_GetFolderLineById(m_pMaster, folderInfos[i], &folderLine)) {
  996.                     if (folderLine.flags & MSG_FOLDER_FLAG_MAIL) {
  997.                         res = FolderInfoFromMenuID( folderInfos[i], nBase, nID);
  998.                     }
  999.                 }
  1000.             }
  1001.             delete [] folderInfos;
  1002.         }
  1003.         return res;
  1004.     }
  1005.  
  1006.     MSG_GetFolderLineById( m_pMaster, mailRoot, &folderLine );
  1007.     if (folderLine.level > 1) { // We've a subfolder
  1008.         if ( nID == nBase ) {
  1009.             return mailRoot;
  1010.         }
  1011.         nBase++;
  1012.     }
  1013.  
  1014.     iCount = MSG_GetFolderChildren( m_pMaster, mailRoot, NULL, NULL );
  1015.  
  1016.     folderInfos = new MSG_FolderInfo*[iCount];
  1017.     ASSERT( folderInfos );
  1018.     if (folderInfos) {
  1019.         MSG_GetFolderChildren( m_pMaster, mailRoot, folderInfos, iCount );
  1020.  
  1021.         for ( i = 0; i < iCount && !res; i++ ) {
  1022.             if ( MSG_GetFolderLineById( m_pMaster, folderInfos[ i ], &folderLine ) ) {
  1023.                 if ( folderLine.numChildren > 0 ) {
  1024.                     res = FolderInfoFromMenuID( folderInfos[ i ], nBase, nID );
  1025.                 } else {
  1026.                     if ( nID == nBase ) {
  1027.                         res = folderInfos[ i ];
  1028.                     } else {
  1029.                         nBase++;
  1030.                     }
  1031.                 }
  1032.             }
  1033.         }
  1034.         delete [] folderInfos;
  1035.     }
  1036.  
  1037.     return res;
  1038. }
  1039.  
  1040. MSG_FolderInfo *CSearchFrame::FolderInfoFromMenuID( UINT nID )
  1041. {
  1042.     UINT nBase = 0;
  1043.     if ( nID >= FIRST_MOVE_MENU_ID && nID <= LAST_MOVE_MENU_ID ) 
  1044.     {
  1045.         nBase = FIRST_MOVE_MENU_ID;
  1046.     }
  1047.     else 
  1048.     {
  1049.         ASSERT(0);
  1050.         return NULL;
  1051.     }
  1052.     return FolderInfoFromMenuID( NULL, nBase, nID );
  1053. }
  1054.  
  1055.  
  1056.  
  1057. void CSearchFrame::OnUpdateFile( CCmdUI *pCmdUI )
  1058. {
  1059.     MSG_ViewIndex *indices = NULL;
  1060.     int count;
  1061.     MSG_ResultElement *elem = NULL;
  1062.  
  1063.     m_pOutliner->GetSelection(indices, count);
  1064.     MSG_GetResultElement(m_pSearchPane, indices[0], &elem);
  1065.  
  1066.     ASSERT(elem);
  1067.  
  1068.     if ( !elem )
  1069.         return;
  1070.  
  1071.     MSG_SearchValue *value;
  1072.     MSG_GetResultAttribute(elem, attribMessageKey, &value);
  1073.  
  1074.     BOOL bEnable = value->u.key != MSG_MESSAGEKEYNONE;
  1075.     if (pCmdUI->m_pSubMenu)
  1076.     {
  1077.         pCmdUI->m_pMenu->EnableMenuItem(pCmdUI->m_nIndex,
  1078.                                         MF_BYPOSITION |(bEnable ? MF_ENABLED : MF_GRAYED));
  1079.     } 
  1080.     else
  1081.     {
  1082.         pCmdUI->Enable( bEnable );
  1083.     }
  1084. }
  1085.  
  1086. BOOL CSearchFrame::PreTranslateMessage( MSG* pMsg )
  1087. {
  1088.     if ( (GetKeyState(VK_CONTROL) & 0x8000) || (GetKeyState(VK_MENU) & 0x8000))
  1089.         return CFrameWnd::PreTranslateMessage(pMsg);
  1090.  
  1091.     if (pMsg->message == WM_KEYDOWN && (int) pMsg->wParam == VK_ESCAPE)
  1092.         PostMessage(WM_CLOSE);
  1093.  
  1094.     if (pMsg->message == WM_KEYDOWN && (int) pMsg->wParam == VK_TAB) {
  1095.         HWND hwndNext = NULL;
  1096.         HWND hwndFocus = ::GetFocus();
  1097.  
  1098.         HWND hwndSearchFirst = ::GetNextDlgTabItem( m_barSearch.m_hWnd, NULL, FALSE );
  1099.         HWND hwndActionFirst = ::GetNextDlgTabItem( m_barAction.m_hWnd, NULL, FALSE );
  1100.  
  1101.         HWND hwndSearchLast = ::GetNextDlgTabItem( m_barSearch.m_hWnd, hwndSearchFirst, TRUE );
  1102.         HWND hwndActionLast = ::GetNextDlgTabItem( m_barAction.m_hWnd, hwndActionFirst, TRUE );
  1103.  
  1104.         if ( GetKeyState(VK_SHIFT) & 0x8000 ) {
  1105.  
  1106.             // Tab backward
  1107.  
  1108.             if ( hwndFocus == hwndSearchFirst ) {
  1109.                 // Handle tabbing into action bar
  1110.                 if ( m_bResultsShowing ) {
  1111.                     hwndNext = hwndActionLast;
  1112.                     if ( !hwndNext || GetWindowLong( hwndNext, GWL_STYLE) & WS_DISABLED ) {
  1113.                         // Nothing active in the action bar
  1114.                         // we can head for the outliner instead
  1115.                         hwndNext = m_pOutliner->m_hWnd;
  1116.                     }
  1117.                 }
  1118.             } else if (hwndFocus == m_pOutliner->m_hWnd) {
  1119.                 // Handle tabbing out of outliner
  1120.                 hwndNext = hwndSearchLast;
  1121.             } else if ( hwndFocus == hwndActionFirst ) {
  1122.                 // Handle tabbing into the outliner
  1123.                 hwndNext = m_pOutliner->m_hWnd;
  1124.             }
  1125.  
  1126.         } else {
  1127.  
  1128.             // Tab forward
  1129.  
  1130.             if (hwndFocus == m_pOutliner->m_hWnd) {
  1131.                 // Handle tabbing out of outliner
  1132.                 hwndNext = hwndActionFirst;
  1133.                 if ( !hwndNext || GetWindowLong( hwndNext, GWL_STYLE) & WS_DISABLED ) {
  1134.                     // nothing active in action bar
  1135.                     hwndNext = hwndSearchFirst;
  1136.                 }
  1137.             } else if ( hwndFocus == hwndSearchLast ) {
  1138.                 // Handle tabbing into outliner
  1139.                 if ( m_bResultsShowing ) {
  1140.                     // we can head for the outliner instead
  1141.                     hwndNext = m_pOutliner->m_hWnd;
  1142.                 }
  1143.             } else if (hwndFocus == hwndActionLast) {
  1144.                 // Handle tabbing out of the action bar
  1145.                 hwndNext = hwndSearchFirst;
  1146.             }
  1147.  
  1148.         }
  1149.         if ( hwndNext ) {
  1150.             ::SetFocus( hwndNext );
  1151.             return TRUE;
  1152.         }
  1153.     }
  1154.  
  1155.     return CFrameWnd::PreTranslateMessage(pMsg);
  1156. }
  1157.  
  1158. int CSearchFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  1159. {
  1160.     UINT aIDArray[] = { IDS_TRANSFER_STATUS, ID_SEPARATOR };
  1161.     int res = CFrameWnd::OnCreate(lpCreateStruct);
  1162.  
  1163.     SetWindowText(szLoadString(IDS_SEARCHMESSAGES));
  1164.  
  1165.     m_barSearch.m_bLDAP = FALSE;
  1166.  
  1167.     m_helpString = HELP_SEARCH_MAILNEWS;
  1168.  
  1169. #ifdef _WIN32
  1170.     m_barSearch.Create( this, IDD_SEARCH, WS_CHILD|CBRS_ALIGN_TOP, 1 );
  1171. #else
  1172.     m_barSearch.Create( this, IDD_SEARCH, WS_CHILD|CBRS_TOP, 1 );
  1173. #endif
  1174.     m_barStatus.Create( this, FALSE, FALSE );
  1175.     m_barAction.Create( this, IDD_MSGSRCHACTION, WS_CHILD|CBRS_BOTTOM, 2);
  1176.  
  1177.     RecalcLayout( );
  1178.     
  1179.     m_barSearch.InitializeAttributes (widgetText, attribSender);
  1180.  
  1181.     m_barSearch.m_wndScopes.SubclassDlgItem(IDC_COMBO_SCOPE, &m_barSearch);
  1182.     UpdateScopes( NULL );
  1183.  
  1184.     // Initially size window to only dialog + title bar.
  1185.  
  1186.     CRect rect, rect2;
  1187.     int BorderX = GetSystemMetrics(SM_CXFRAME);
  1188.     int BorderY = GetSystemMetrics(SM_CYFRAME);
  1189.  
  1190.     GetWindowRect(&rect);
  1191.     m_barSearch.GetWindowRect(&rect2);
  1192.     CSize size = m_barSearch.CalcFixedLayout(FALSE, FALSE);
  1193.     // Figure height of title bar + bottom border
  1194.     size.cy += rect2.top - rect.top + BorderY;
  1195.     size.cx += BorderX * 2;
  1196.     SetWindowPos( NULL, 0, 0, size.cx, size.cy,
  1197.                   SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  1198.  
  1199.     m_iHeight = size.cy;
  1200.     m_iWidth = size.cx;
  1201.  
  1202.     m_barSearch.m_iOrigFrameHeight = m_iOrigFrameHeight = m_iHeight;
  1203.     m_barSearch.m_searchObj.SetOrigFrameHeight(m_barSearch.m_iOrigFrameHeight);
  1204.  
  1205.     OnNew();
  1206.     
  1207.  
  1208. #ifndef _WIN32
  1209.     SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1210. #endif
  1211.  
  1212.     return res;
  1213. }
  1214.  
  1215. void CSearchFrame::OnSize( UINT nType, int cx, int cy )
  1216. {
  1217.     CFrameWnd::OnSize( nType, cx, cy );
  1218. }
  1219.  
  1220. void CSearchFrame::OnClose()
  1221. {
  1222.     CFrameWnd::OnClose();
  1223.     g_pSearchWindow = NULL;
  1224. }
  1225.  
  1226. void CSearchFrame::OnDestroy()
  1227. {
  1228.     CFrameWnd::OnDestroy();
  1229.  
  1230.     if(!IsDestroyed()) {
  1231.         DestroyContext();
  1232.     }
  1233. }
  1234.  
  1235. void CSearchFrame::OnUpdateDeleteMessage(CCmdUI* pCmdUI)
  1236. {
  1237.     pCmdUI->Enable(TRUE);
  1238. }
  1239.  
  1240. void CSearchFrame::OnDeleteMessage()
  1241. {
  1242.     ModalStatusBegin( MODAL_DELAY );
  1243.  
  1244.     MSG_ViewIndex *indices = NULL;
  1245.     int count = 0;
  1246.     m_pOutliner->GetSelection(indices, count);
  1247.  
  1248.     MSG_Command(m_pSearchPane, MSG_DeleteMessage, indices, count);
  1249.  
  1250.     ModalStatusEnd();
  1251. }
  1252.  
  1253. void CSearchFrame::ModalStatusBegin( int iModalDelay )
  1254. {
  1255.     if ( iModalDelay > -1 ) {
  1256.     }
  1257. }
  1258.  
  1259. void CSearchFrame::ModalStatusEnd()
  1260. {
  1261.  
  1262. }
  1263.  
  1264.  
  1265. LONG CSearchFrame::OnFinishedHeaders(WPARAM wParam, LPARAM lParam )
  1266. {
  1267.     MSG_Master *master = WFE_MSGGetMaster();
  1268.     CComboBox *pCombo = (CComboBox *) m_barSearch.m_searchObj.GetColumnOneAttributeWidget(m_iRowSelected);
  1269.     if (lParam == IDOK )
  1270.     {
  1271.         m_barSearch.m_searchObj.UpdateColumn1Attributes();
  1272.     }
  1273.     else
  1274.     {
  1275.         pCombo->SetCurSel(0);
  1276.     }
  1277.     MSG_ReleaseEditHeadersSemaphore(master, this);
  1278.     m_pCustomHeadersDlg = NULL;
  1279.     return 0;
  1280. }
  1281.  
  1282.  
  1283. LONG CSearchFrame::OnFinishedAdvanced(WPARAM wParam, LPARAM lParam )
  1284. {
  1285.     m_barSearch.UpdateAttribList();
  1286.     m_barSearch.UpdateOpList();
  1287.     m_barSearch.m_searchObj.ReInitializeWidgets();    
  1288.     m_pAdvancedOptionsDlg = NULL;
  1289.     return 0;
  1290. }
  1291.  
  1292. void CSearchFrame::OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI )
  1293. {
  1294.     CFrameWnd::OnGetMinMaxInfo( lpMMI );
  1295.  
  1296.     if (m_iHeight) {
  1297.         if (!m_bResultsShowing) {
  1298.             lpMMI->ptMaxSize.y = m_iHeight;
  1299.             lpMMI->ptMaxTrackSize.y = m_iHeight;
  1300.         }
  1301.         lpMMI->ptMinTrackSize.y = m_iHeight;
  1302.     }
  1303.     if (m_iWidth) {
  1304.         lpMMI->ptMinTrackSize.x = m_iWidth;
  1305.     }
  1306. }
  1307.  
  1308. void CSearchFrame::OnAndOr()
  1309. {
  1310.     m_barSearch.OnAndOr();
  1311. }
  1312.  
  1313. void CSearchFrame::OnAdvanced()
  1314. {
  1315.     m_pAdvancedOptionsDlg = new CAdvSearchOptionsDlg(this);
  1316.     if(m_pAdvancedOptionsDlg)
  1317.         m_pAdvancedOptionsDlg->ShowWindow(SW_SHOW);
  1318.  
  1319. }
  1320.  
  1321. void CSearchFrame::OnUpdateAdvanced( CCmdUI *pCmdUI)
  1322. {
  1323.     pCmdUI->Enable( !m_bSearching );
  1324. }
  1325.  
  1326.  
  1327. void CSearchFrame::OnMore()
  1328. {
  1329.     AdjustHeight(m_barSearch.More());
  1330.     RecalcLayout( );
  1331. #ifndef _WIN32
  1332.     SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1333. #endif
  1334. }
  1335.  
  1336. void CSearchFrame::OnUpdateMore( CCmdUI *pCmdUI )
  1337. {
  1338.     pCmdUI->Enable( (m_barSearch.m_iMoreCount < 4) && !m_bSearching );
  1339. }
  1340.  
  1341. void CSearchFrame::OnFewer()
  1342. {
  1343.     AdjustHeight(m_barSearch.Fewer());
  1344.     RecalcLayout( );
  1345. #ifndef _WIN32
  1346.     SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1347. #endif
  1348. }
  1349.  
  1350. void CSearchFrame::OnUpdateFewer( CCmdUI *pCmdUI )
  1351. {
  1352.     pCmdUI->Enable( (m_barSearch.m_iMoreCount > 0) && !m_bSearching );
  1353. }
  1354.  
  1355. void CSearchFrame::OnNew()
  1356. {
  1357.     if (m_bSearching) {
  1358.         XP_InterruptContext( GetContext() );
  1359.         m_bSearching = FALSE;
  1360.     }
  1361.     MSG_SearchFree(m_pSearchPane);    /* free memory in context   */
  1362.  
  1363.     ShowResults( FALSE );
  1364.  
  1365.     m_pOutliner->SelectItem(0);
  1366.     int dy = m_barSearch.ClearSearch(m_bIsLDAPSearch);
  1367.  
  1368.  
  1369.     AdjustHeight(dy);
  1370.  
  1371. #ifndef _WIN32
  1372.     SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1373. #endif
  1374. }
  1375.  
  1376. void CSearchFrame::OnSave()
  1377. {
  1378.     char *name = FE_PromptWithCaption(GetContext(), 
  1379.                                       szLoadString(IDS_VIRTUALNEWSGROUP),
  1380.                                       szLoadString(IDS_VIRTUALNEWSGROUPDESC),
  1381.                                       NULL);
  1382.     MSG_SaveProfile(m_pSearchPane, name);
  1383. }
  1384.  
  1385. void CSearchFrame::OnUpdateSave( CCmdUI *pCmdUI )
  1386. {
  1387.     XP_Bool fEnable = FALSE;
  1388.     MSG_SaveProfileStatus (m_pSearchPane, &fEnable);
  1389.     pCmdUI->Enable( fEnable );
  1390. }
  1391.  
  1392. void CSearchFrame::OnHelp()
  1393. {
  1394.     NetHelp(m_helpString);
  1395. }
  1396.  
  1397. void CSearchFrame::OnUpdateHelp( CCmdUI *pCmdUI )
  1398. {
  1399.         pCmdUI->Enable( TRUE );
  1400. }
  1401.  
  1402. void CSearchFrame::OnFind()
  1403. {
  1404.     if ( m_bSearching ) {
  1405.         // We've turned into stop button
  1406.         XP_InterruptContext( GetContext() );
  1407.         return;
  1408.     }
  1409.  
  1410.     // Build Search
  1411.  
  1412.     ShowResults( FALSE );
  1413.  
  1414.     MSG_SearchFree (m_pSearchPane);
  1415.     MSG_SearchAlloc (m_pSearchPane);
  1416.  
  1417.     ASSERT(m_pOutliner);
  1418.     m_pOutliner->Invalidate();
  1419.                        
  1420.     CComboBox *combo;
  1421.  
  1422.     int iCurSel;
  1423.     MSG_ScopeAttribute scope;
  1424.     
  1425.     MSG_Master *master = WFE_MSGGetMaster();
  1426.  
  1427.     combo = (CComboBox *) m_barSearch.GetDlgItem( IDC_COMBO_SCOPE );
  1428.     iCurSel = combo->GetCurSel();
  1429.  
  1430.     DWORD dwData = combo->GetItemData(iCurSel);
  1431.     scope = m_barSearch.DetermineScope(dwData);
  1432.     
  1433.     MSG_AddScopeTerm( m_pSearchPane, scope, (MSG_FolderInfo *) dwData );
  1434.  
  1435.     m_barSearch.BuildQuery (m_pSearchPane);
  1436.  
  1437.     if (MSG_Search(m_pSearchPane) == SearchError_Success) {
  1438.         m_bSearching = TRUE;
  1439.         ShowResults( TRUE );
  1440.         SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1441.         m_barStatus.SetPaneText( m_barStatus.CommandToIndex( ID_SEPARATOR), 
  1442.                                  szLoadString( IDS_SEARCHING ) );
  1443.     }
  1444. }
  1445.  
  1446. void CSearchFrame::OnUpdateFind( CCmdUI *pCmdUI )
  1447. {
  1448.     CString cs;
  1449.     if ( m_bSearching || CanAllInterrupt()) {
  1450.         cs.LoadString( IDS_STOP );
  1451.     } else {
  1452.         cs.LoadString( IDS_SEARCH );
  1453.     }
  1454.  
  1455.     pCmdUI->SetText( cs );
  1456. }
  1457.  
  1458. void CSearchFrame::OnUpdateAndOr(CCmdUI *pCmdUI)
  1459. {
  1460.  
  1461.     if ( m_bSearching || CanAllInterrupt()) {     
  1462.         pCmdUI->Enable(FALSE);        
  1463.     }else {
  1464.         pCmdUI->Enable(TRUE); 
  1465.     }
  1466. }
  1467.  
  1468. void CSearchFrame::OnTo()
  1469. {
  1470.     MSG_ViewIndex *indices;
  1471.     int count;
  1472.     m_pOutliner->GetSelection(indices, count);
  1473.  
  1474.     if (count == 1) {
  1475.         MSG_ResultElement *elem = NULL;
  1476.         MSG_GetResultElement(m_pSearchPane, indices[0], &elem);
  1477.  
  1478.         ASSERT(elem);
  1479.  
  1480.         if ( !elem )
  1481.             return;
  1482.  
  1483.         MSG_SearchValue *value;
  1484.         MSG_GetResultAttribute(elem, attribMessageKey, &value);
  1485.         MessageKey key = value->u.key;
  1486.         MSG_GetResultAttribute(elem, attribFolderInfo, &value);
  1487.         MSG_FolderInfo *folderInfo = value->u.folder;
  1488.  
  1489.         if (folderInfo)
  1490.         {
  1491.             C3PaneMailFrame::Open(folderInfo, key);
  1492.         }
  1493.     }
  1494. }
  1495.  
  1496. void CSearchFrame::OnUpdateTo( CCmdUI *pCmdUI )
  1497. {
  1498.     MSG_ViewIndex *indices;
  1499.     int count;
  1500.     m_pOutliner->GetSelection(indices, count);
  1501.     int nLines = m_pOutliner->GetTotalLines();
  1502.     pCmdUI->Enable( ((nLines > 0) && count) && MSG_GoToFolderStatus (m_pSearchPane, indices, count));
  1503. }
  1504.  
  1505. void CSearchFrame::OnUpdateQuery( CCmdUI *pCmdUI )
  1506. {
  1507.     pCmdUI->Enable( !m_bSearching );
  1508. }
  1509.  
  1510. void CSearchFrame::OnScope()
  1511. {
  1512.     m_barSearch.UpdateAttribList();
  1513.     m_barSearch.UpdateOpList();
  1514. }
  1515.  
  1516. void CSearchFrame::OnAttrib1()
  1517. {
  1518.     EditHeader(0);
  1519.     m_barSearch.UpdateOpList();
  1520.  
  1521. }
  1522.  
  1523. void CSearchFrame::OnAttrib2()
  1524. {
  1525.     EditHeader(1);
  1526.     m_barSearch.UpdateOpList();
  1527. }
  1528.  
  1529. void CSearchFrame::OnAttrib3()
  1530. {
  1531.     EditHeader(2);
  1532.     m_barSearch.UpdateOpList();
  1533. }
  1534.  
  1535. void CSearchFrame::OnAttrib4()
  1536. {
  1537.     EditHeader(3);
  1538.     m_barSearch.UpdateOpList();
  1539. }
  1540.  
  1541. void CSearchFrame::OnAttrib5()
  1542. {
  1543.     EditHeader(4);
  1544.     m_barSearch.UpdateOpList();
  1545. }
  1546.  
  1547.  
  1548. void CSearchFrame::EditHeader(int iRow)
  1549. {
  1550.     //We are being asked to modify custom headers
  1551.     CComboBox *combo;    
  1552.     int iCurSel;
  1553.     MSG_SearchAttribute attrib;
  1554.     m_iRowSelected = iRow;
  1555.     combo = (CComboBox *) m_barSearch.m_searchObj.GetColumnOneAttributeWidget(iRow);
  1556.     iCurSel = combo->GetCurSel();
  1557.     attrib = (MSG_SearchAttribute) combo->GetItemData(iCurSel);
  1558.  
  1559.     if (attrib == -1)
  1560.     {
  1561.         MSG_Master *master = WFE_MSGGetMaster();
  1562.         //find out if we are the only ones trying to edit headers.
  1563.         if (master)
  1564.         {
  1565.             if (!MSG_AcquireEditHeadersSemaphore(master, this))
  1566.             {
  1567.                 ::MessageBox(FEU_GetLastActiveFrame()->GetSafeHwnd(),
  1568.                          szLoadString(IDS_EDIT_HEADER_IN_USE), 
  1569.                          szLoadString(IDS_CUSTOM_HEADER_ERROR), 
  1570.                          MB_OK|MB_ICONSTOP);
  1571.                 combo->SetCurSel(0);
  1572.                 return;
  1573.                 //We can't edit anything since another window already has the semaphore.
  1574.             }
  1575.         }
  1576.         else
  1577.         {    //Something is hosed!
  1578.             return;
  1579.         }
  1580.  
  1581.         m_pCustomHeadersDlg = new CCustomHeadersDlg(this);
  1582.         if (m_pCustomHeadersDlg)
  1583.         {
  1584.             m_pCustomHeadersDlg->ShowWindow(SW_SHOW);
  1585.         }
  1586.     }
  1587. }
  1588.  
  1589. //////////////////////////////////////////////////////////////////////////////
  1590. // CSearchOutliner
  1591.  
  1592. CSearchOutliner::CSearchOutliner ( )
  1593. {
  1594.     m_attribSortBy = attribDate;
  1595.     m_bSortDescending = FALSE;
  1596.     m_iMysticPlane = 0;
  1597.  
  1598.     ApiApiPtr(api);
  1599.     m_pUnkUserImage = api->CreateClassInstance(APICLASS_IMAGEMAP);
  1600.     if (m_pUnkUserImage) {
  1601.         m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
  1602.         ASSERT(m_pIUserImage);
  1603.         m_pIUserImage->Initialize(IDB_MAILNEWS,16,16);
  1604.     }
  1605.     m_hFont = NULL;
  1606. }
  1607.  
  1608. CSearchOutliner::~CSearchOutliner ( )
  1609. {
  1610.     if (m_pUnkUserImage) {
  1611.         if (m_pIUserImage)
  1612.             m_pUnkUserImage->Release();
  1613.     }
  1614.     if (m_hFont) {
  1615.         theApp.ReleaseAppFont(m_hFont);
  1616.     }
  1617. }
  1618.  
  1619. BEGIN_MESSAGE_MAP(CSearchOutliner, CMSelectOutliner )
  1620.     //{{AFX_MSG_MAP(CSearchOutliner)
  1621.     ON_WM_CREATE()
  1622.     //}}AFX_MSG_MAP
  1623. END_MESSAGE_MAP()
  1624.  
  1625. int CSearchOutliner::OnCreate ( LPCREATESTRUCT lpCreateStruct )
  1626. {
  1627.     int iRetVal = COutliner::OnCreate ( lpCreateStruct );
  1628.     
  1629.     InitializeClipFormats ( );
  1630.  
  1631.     return iRetVal;
  1632. }
  1633.  
  1634.  
  1635. void CSearchOutliner::PropertyMenu ( int iSel, UINT flags )    
  1636. {
  1637.     HMENU hmenu = CreatePopupMenu();
  1638.  
  1639.     if ( !hmenu )
  1640.         return; // Bail
  1641.  
  1642.     if ( iSel < m_iTotalLines ) 
  1643.     {
  1644.         ::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
  1645.         ::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
  1646.  
  1647.         HMENU hFileMenu = CreatePopupMenu();
  1648.         UINT nID = FIRST_MOVE_MENU_ID;
  1649.         CMailNewsFrame::UpdateMenu( NULL, hFileMenu, nID );
  1650.         ::AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT) hFileMenu, szLoadString( IDS_POPUP_FILE ) );
  1651.         ::AppendMenu( hmenu, MF_STRING, CASTUINT(ID_EDIT_DELETEMESSAGE), szLoadString( IDS_POPUP_DELETEMESSAGE ) );
  1652.     }
  1653.  
  1654.     //    Track the popup now.
  1655.     POINT pt = m_ptHit;
  1656.     ClientToScreen(&pt);
  1657.  
  1658.        ::TrackPopupMenu( hmenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0,
  1659.                       GetParentFrame()->GetSafeHwnd(), NULL);
  1660.  
  1661.     //  Cleanup
  1662.     VERIFY(::DestroyMenu( hmenu ));
  1663. }
  1664.  
  1665.  
  1666. void CSearchOutliner::InitializeClipFormats(void)
  1667. {
  1668.     m_cfSearchMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_SEARCH_FORMAT);
  1669. }
  1670.  
  1671.  
  1672.  
  1673.  
  1674. CLIPFORMAT * CSearchOutliner::GetClipFormatList(void)
  1675. {
  1676.     static CLIPFORMAT cfFormatList[2];
  1677.     cfFormatList[0] = m_cfSearchMessages;
  1678.     cfFormatList[1] = 0;
  1679.  
  1680.     return cfFormatList;
  1681. }
  1682.  
  1683. COleDataSource * CSearchOutliner::GetDataSource(void)
  1684. {
  1685.     MSG_ViewIndex *indices;
  1686.     int count;
  1687.     GetSelection(indices, count);
  1688.  
  1689.     HANDLE hContent = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(MailNewsDragData));
  1690.     MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock (hContent);
  1691.  
  1692.     pDragData->m_pane = m_pSearchPane;
  1693.     pDragData->m_indices = indices;
  1694.     pDragData->m_count = count;
  1695.  
  1696.     GlobalUnlock(hContent);
  1697.  
  1698.     COleDataSource * pDataSource = new COleDataSource;  
  1699.     pDataSource->CacheGlobalData(m_cfSearchMessages,hContent);
  1700.  
  1701.     if ( count == 1 ) {
  1702.         MSG_ResultElement *elem = NULL;
  1703.         MSG_GetResultElement(m_pSearchPane, indices[0], &elem);
  1704.         MSG_SearchValue *value;
  1705.         MSG_GetResultAttribute(elem, attribMessageKey, &value);
  1706.         MessageKey key = value->u.key;
  1707.         MSG_GetResultAttribute(elem, attribSubject, &value);
  1708.         URL_Struct *url = MSG_ConstructUrlForMessage( m_pSearchPane, key );
  1709.  
  1710.         if ( url ) {            
  1711.             RDFGLOBAL_DragTitleAndURL( pDataSource, value->u.string, url->address );
  1712.             NET_FreeURLStruct( url );
  1713.         }
  1714.     }
  1715.  
  1716.     return pDataSource;
  1717. }
  1718.  
  1719.  
  1720. BOOL CSearchOutliner::DeleteItem ( int iLine )
  1721. {
  1722. #ifndef DEBUG_phil
  1723.     // Delete? Are you kidding?
  1724.     MessageBeep(0);
  1725.     return FALSE;
  1726. #else
  1727.     MSG_ResultElement *elem = NULL;
  1728.     MSG_GetResultElement (m_pSearchPane, iLine, &elem);
  1729.     char *fileName = wfe_GetExistingFileName(m_hWnd, szLoadString(IDS_FILETOATTACH), ALL, TRUE);
  1730.     if (fileName)
  1731.     {
  1732.         CString cs;
  1733.         WFE_ConvertFile2Url(cs,(const char *)fileName);
  1734.         MSG_SearchValue value;
  1735.         value.attribute = attribJpegFile;
  1736.         value.u.string = XP_STRDUP(cs);
  1737.         MSG_ModifyLdapResult (elem, &value);
  1738.  
  1739.         XP_FREE (fileName);
  1740.         XP_FREE(value.u.string);
  1741.     }
  1742.     return TRUE;
  1743. #endif
  1744. }
  1745.  
  1746. void CSearchOutliner::ChangeResults (int num)
  1747. {
  1748.     int iOldTotal = m_iTotalLines;
  1749.     m_iTotalLines += num;
  1750.     EnableScrollBars();
  1751.     if (num > 0)
  1752.         HandleInsert(iOldTotal, num);
  1753.     else
  1754.         HandleDelete(iOldTotal, -num);
  1755. }
  1756.  
  1757. HFONT CSearchOutliner::GetLineFont(void *pLineData)
  1758. {
  1759.     MSG_SearchValue *folderInfoResult;
  1760.     MSG_GetResultAttribute( (MSG_ResultElement *) pLineData, attribFolderInfo, 
  1761.                             &folderInfoResult ); 
  1762.     int16 doc_csid = 0;
  1763.     if (folderInfoResult)
  1764.         doc_csid = MSG_GetFolderCSID( folderInfoResult->u.folder );
  1765.     if (!doc_csid)
  1766.         doc_csid = INTL_DefaultWinCharSetID(0);
  1767.     int16 win_csid = INTL_DocToWinCharSetID(doc_csid);
  1768.  
  1769.     if ( win_csid != m_iCSID ) {
  1770.         m_iCSID = win_csid;
  1771.         CClientDC dc( this );
  1772.  
  1773.          if (m_hFont) {
  1774.             theApp.ReleaseAppFont(m_hFont);
  1775.         }
  1776.  
  1777.         LOGFONT lf;
  1778.         memset(&lf, 0, sizeof(LOGFONT));
  1779.         lf.lfPitchAndFamily = FF_SWISS;
  1780.         lf.lfCharSet = IntlGetLfCharset(win_csid);
  1781.         if (win_csid == CS_LATIN1)
  1782.              _tcscpy(lf.lfFaceName, "MS Sans Serif");
  1783.         else
  1784.              _tcscpy(lf.lfFaceName, IntlGetUIPropFaceName(win_csid));
  1785.            lf.lfHeight = -MulDiv(9, dc.GetDeviceCaps(LOGPIXELSY), 72);
  1786.         m_hFont = theApp.CreateAppFont( lf );
  1787.     }
  1788.     return m_hFont ? m_hFont : m_hRegFont;
  1789. }
  1790.  
  1791. int CSearchOutliner::TranslateIcon (void * pData)
  1792. {
  1793.     // Do something smart to differentiate between mail and news
  1794.     int idxImage = IDX_MAILMESSAGE;
  1795.     return idxImage;
  1796. }
  1797.  
  1798. int CSearchOutliner::TranslateIconFolder (void * pData)
  1799. {
  1800.     // We're a flat list, so we're never a folder
  1801.     return ( OUTLINER_ITEM );
  1802. }
  1803.  
  1804. void * CSearchOutliner::AcquireLineData ( int line )
  1805. {
  1806.     MSG_ResultElement *elem = NULL;
  1807.     MSG_GetResultElement (m_pSearchPane, line, &elem);
  1808.     return elem;
  1809. }
  1810.  
  1811. void CSearchOutliner::GetTreeInfo ( int iLine, uint32 * pFlags, int * pDepth, 
  1812.                                     OutlinerAncestorInfo ** pAncestor )
  1813. {
  1814.     if ( pFlags ) *pFlags = 0; // Flags? 
  1815.     if ( pDepth ) *pDepth = 0; // We're flat, remember?
  1816. }
  1817.  
  1818. void CSearchOutliner::ReleaseLineData ( void * )
  1819. {
  1820. }
  1821.  
  1822. LPCTSTR CSearchOutliner::GetColumnText ( UINT iColumn, void * pLineData )
  1823. {
  1824.     MSG_SearchValue *result;
  1825.     MSG_SearchAttribute attrib = (MSG_SearchAttribute) iColumn;
  1826.     CString cs;
  1827.  
  1828.     szResultText[0] = '\0'; // default to empty string
  1829.     szResultText[63] = '\0';
  1830.  
  1831.     if (MSG_GetResultAttribute( (MSG_ResultElement *) pLineData, attrib, &result) == 
  1832.         SearchError_Success) {
  1833.  
  1834.         switch (result->attribute) {
  1835.         case attribDate:
  1836.             _tcsncpy(szResultText, MSG_FormatDate(m_pSearchPane, result->u.date), 63);
  1837.             break;
  1838.         case attribPriority:
  1839.             MSG_GetPriorityName( result->u.priority, szResultText, 64);
  1840.             break;
  1841.         case attribMsgStatus:
  1842.             MSG_GetStatusName( result->u.msgStatus, szResultText, 64);
  1843.             break;
  1844.         case attribSender:
  1845.         case attribSubject:
  1846.             {
  1847.                 char *buf = IntlDecodeMimePartIIStr(result->u.string, INTL_DocToWinCharSetID(m_iCSID), FALSE);
  1848.                 if (buf) {
  1849.                     _tcsncpy(szResultText, buf, 63);
  1850.                     XP_FREE(buf);
  1851.                     break;
  1852.                 }
  1853.             }
  1854.         default:
  1855.             _tcsncpy(szResultText, result->u.string, 63);
  1856.             break;
  1857.         }
  1858.         MSG_DestroySearchValue (result);
  1859.     }
  1860.     return szResultText;
  1861. }
  1862.  
  1863. void CSearchOutliner::OnSelDblClk()
  1864. {
  1865.     BOOL bReuse = g_MsgPrefs.m_bMessageReuse;
  1866.     if (GetKeyState(VK_MENU) & 0x8000)
  1867.         bReuse = !bReuse;
  1868.  
  1869.     MSG_ViewIndex *indices;
  1870.     int i, count;
  1871.     
  1872.     GetSelection(indices, count);
  1873.  
  1874.     for ( i = 0; i < count; i++ ) {
  1875.         MSG_ResultElement *elem = NULL;
  1876.         MSG_GetResultElement(m_pSearchPane, indices[i], &elem);
  1877.  
  1878.         ASSERT(elem);
  1879.  
  1880.         if ( !elem )
  1881.             continue;
  1882.  
  1883.         MWContextType cxType = MSG_GetResultElementType( elem );
  1884.  
  1885.         if ( cxType == MWContextMail || cxType == MWContextMailMsg || 
  1886.              cxType == MWContextNews || cxType == MWContextNewsMsg ) {
  1887.             CMessageFrame *frame = CMessageFrame::Open ();
  1888.             MSG_OpenResultElement (elem, frame->GetPane());
  1889.         } else if ( cxType == MWContextBrowser ) {
  1890.             MWContext *pContext = NULL;
  1891.             VERIFY(pContext = CFE_CreateNewDocWindow( NULL, NULL ));
  1892.             if (pContext) {
  1893.                 MSG_OpenResultElement( elem, (MSG_Pane *) pContext );
  1894.             }
  1895.         } else { 
  1896.             ASSERT(0); // What on earth are you passing me?
  1897.         }
  1898.     }
  1899. }
  1900.  
  1901. void CSearchOutliner::OnSelChanged()
  1902. {
  1903. #ifndef _WIN32 // Force update on Win16
  1904.     GetParentFrame()->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  1905. #endif
  1906. }
  1907.  
  1908.  
  1909. void CSearchOutliner::MysticStuffStarting( XP_Bool asynchronous,
  1910.                                             MSG_NOTIFY_CODE notify, 
  1911.                                             MSG_ViewIndex where,
  1912.                                             int32 num )
  1913. {
  1914.     ++m_iMysticPlane;
  1915. }
  1916.  
  1917. void CSearchOutliner::MysticStuffFinishing( XP_Bool asynchronous,
  1918.                                              MSG_NOTIFY_CODE notify, 
  1919.                                              MSG_ViewIndex where,
  1920.                                              int32 num )
  1921. {
  1922.     if (notify == MSG_NotifyInsertOrDelete)
  1923.     {
  1924.         if (num > 0)
  1925.             HandleInsert(where, num);
  1926.         else
  1927.             HandleDelete(where, -num);
  1928.         ((CSearchFrame*)GetParentFrame())->ModalStatusEnd();
  1929.     }    
  1930. }
  1931.  
  1932.  
  1933. /////////////////////////////////////////////////////////////////////////////
  1934. // CSearchOutlinerParent
  1935.  
  1936. BOOL CSearchOutlinerParent::RenderData ( int idColumn, CRect & rect, CDC &dc, LPCTSTR text )
  1937. {
  1938.     MSG_SearchAttribute attrib = (MSG_SearchAttribute) idColumn;
  1939.     CSearchOutliner *pOutliner = (CSearchOutliner *) m_pOutliner;
  1940.     
  1941.     // Draw Sort Indicator
  1942.     MSG_COMMAND_CHECK_STATE sortType = pOutliner->m_attribSortBy == attrib ? MSG_Checked : MSG_Unchecked;
  1943.  
  1944.     if (sortType != MSG_Checked)
  1945.         return FALSE;
  1946.  
  1947.     int idxImage = pOutliner->m_bSortDescending ? IDX_SORTINDICATORUP : IDX_SORTINDICATORDOWN;
  1948.  
  1949.     UINT dwDTFormat = DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER;
  1950.     RECT rectText = rect;
  1951.     rectText.left += 4;
  1952.     rectText.right -= 5;
  1953.  
  1954.     rectText.right -= 14;
  1955.     m_pIImage->DrawTransImage( idxImage,
  1956.                                rectText.right + 4,
  1957.                                (rect.top + rect.bottom) / 2 - 4,
  1958.                                &dc );
  1959.  
  1960.     WFE_DrawTextEx( 0, dc.m_hDC, (LPTSTR) text, -1, 
  1961.                     &rectText, dwDTFormat, WFE_DT_CROPRIGHT );
  1962.  
  1963.     return TRUE;
  1964. }
  1965.  
  1966. COutliner * CSearchOutlinerParent::GetOutliner ( void )
  1967. {
  1968.     return new CSearchOutliner;
  1969. }
  1970.  
  1971. void CSearchOutlinerParent::CreateColumns ( void )
  1972. {
  1973.     CString cs;
  1974.  
  1975.     cs.LoadString(IDS_MAIL_SUBJECT);
  1976.     m_pOutliner->AddColumn ( cs, attribSubject,  20, 0, ColumnVariable, 3500 ); 
  1977.     cs.LoadString(IDS_MAIL_SENDER);
  1978.     m_pOutliner->AddColumn ( cs, attribSender,   20, 0, ColumnVariable, 2500 ); 
  1979.     cs.LoadString(IDS_MAIL_DATE);
  1980.     m_pOutliner->AddColumn ( cs, attribDate,     20, 0, ColumnVariable, 1000 );
  1981.     cs.LoadString(IDS_MAIL_PRIORITY);
  1982.     m_pOutliner->AddColumn ( cs, attribPriority, 20, 0, ColumnVariable, 1000 );
  1983.     cs.LoadString(IDS_MAIL_LOCATION);
  1984.     m_pOutliner->AddColumn ( cs, attribLocation, 20, 0, ColumnVariable, 2000 );
  1985.     m_pOutliner->SetImageColumn( attribSubject );
  1986.     m_pOutliner->SetHasPipes( FALSE );
  1987. }
  1988.  
  1989. BOOL CSearchOutlinerParent::ColumnCommand ( int idColumn )
  1990. {
  1991.     MSG_SearchAttribute attrib = (MSG_SearchAttribute) idColumn;
  1992.     CSearchOutliner *pOutliner = (CSearchOutliner *) m_pOutliner;
  1993.     
  1994.     if (attrib == pOutliner->m_attribSortBy) {
  1995.         pOutliner->m_bSortDescending = !pOutliner->m_bSortDescending; 
  1996.     } else {
  1997.         pOutliner->m_attribSortBy = attrib;
  1998.     }
  1999.     MSG_SortResultList(pOutliner->m_pSearchPane, pOutliner->m_attribSortBy, pOutliner->m_bSortDescending);
  2000.     Invalidate();
  2001.     pOutliner->Invalidate();
  2002.  
  2003.     return TRUE;
  2004. }
  2005.  
  2006. void CSearchFrame::Open()
  2007. {
  2008.     if (!g_pSearchWindow) {
  2009.         g_pSearchWindow = new CSearchFrame();
  2010.         g_pSearchWindow->Create();
  2011.     } else {
  2012.         g_pSearchWindow->ActivateFrame( g_pSearchWindow->IsIconic() ? SW_RESTORE : SW_SHOW );
  2013.     }       
  2014. }
  2015.  
  2016. void CSearchFrame::Open( CMailNewsFrame *pFrame )
  2017. {
  2018.     CSearchFrame::Open();
  2019.     if ( g_pSearchWindow ) {
  2020.         g_pSearchWindow->UpdateScopes( pFrame );
  2021.     }
  2022. }
  2023.  
  2024. void CSearchFrame::Close()
  2025. {
  2026.     if (g_pSearchWindow) {
  2027.         g_pSearchWindow->PostMessage(WM_CLOSE);
  2028.     }       
  2029. }
  2030.  
  2031. /////////////////////////////////////////////////////////////////////////////
  2032. // CLDAPSearchFrame
  2033.  
  2034. void CLDAPSearchFrame::Create()
  2035. {
  2036.     m_bIsLDAPSearch = TRUE;
  2037.  
  2038.     DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN;
  2039.     CString strFullString, strTitle;
  2040.     strFullString.LoadString( IDR_SEARCHFRAME );
  2041.     AfxExtractSubString( strTitle, strFullString, 0 );
  2042.  
  2043.     LPCTSTR lpszClass = GetIconWndClass( dwDefaultStyle, IDR_SEARCHFRAME );
  2044.     LPCTSTR lpszTitle = strTitle;
  2045.     CFrameWnd::Create(lpszClass, lpszTitle, dwDefaultStyle);
  2046.  
  2047.     ActivateFrame();
  2048. }
  2049.  
  2050. BOOL CLDAPSearchFrame::OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext )
  2051. {
  2052.     CWnd *pWnd;
  2053.     CCreateContext Context;
  2054.     Context.m_pNewViewClass = RUNTIME_CLASS(CLDAPSearchView);
  2055.     
  2056.     if ( pWnd = CreateView(&Context) ) {
  2057.         COutlinerView *pView = (COutlinerView *) pWnd;
  2058.         pView->CreateColumns ( );
  2059.         m_pOutliner = (CLDAPSearchOutliner *) pView->m_pOutlinerParent->m_pOutliner;
  2060.         m_pOutliner->SetContext( GetContext() );
  2061.         m_pOutliner->SetPane (m_pSearchPane);
  2062.     } else {
  2063.         return FALSE;
  2064.     }
  2065.     return TRUE;
  2066. }
  2067.  
  2068. BEGIN_MESSAGE_MAP(CLDAPSearchFrame, CSearchFrame)
  2069.     ON_WM_CREATE()
  2070.     ON_WM_CLOSE()
  2071.     ON_CBN_SELCHANGE(IDC_COMBO_SCOPE, OnScope)
  2072.     ON_BN_CLICKED(IDC_FIND, OnFind)
  2073.     ON_BN_CLICKED(IDC_ADD, OnAdd)
  2074.     ON_UPDATE_COMMAND_UI(IDC_ADD, OnUpdateAdd)
  2075.     ON_BN_CLICKED(IDC_TO, OnTo)
  2076.     ON_UPDATE_COMMAND_UI(IDC_TO, OnUpdateTo)
  2077. END_MESSAGE_MAP()
  2078.  
  2079. int CLDAPSearchFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  2080. {
  2081.     UINT aIDArray[] = { ID_SEPARATOR, IDS_TRANSFER_STATUS };
  2082.     int res = CFrameWnd::OnCreate(lpCreateStruct);
  2083.  
  2084.     m_barSearch.m_bLDAP = TRUE;
  2085.  
  2086.     m_helpString = HELP_SEARCH_LDAP;
  2087.  
  2088. #ifdef _WIN32
  2089.     m_barSearch.Create( this, IDD_SEARCHLDAP, WS_CHILD|CBRS_ALIGN_TOP, 1 );
  2090. #else
  2091.     m_barSearch.Create( this, IDD_SEARCHLDAP, WS_CHILD|CBRS_TOP, 1 );
  2092. #endif
  2093.     m_barStatus.Create( this, FALSE, FALSE );
  2094.     m_barAction.Create( this, IDD_LDAPSEARCH, WS_CHILD|CBRS_BOTTOM, 2);
  2095.  
  2096.     m_barStatus.SetPaneText(m_barStatus.CommandToIndex( ID_SEPARATOR), 
  2097.                             szLoadString(IDS_SEARCHLDAP));
  2098.  
  2099.     RecalcLayout( );
  2100.     
  2101.     m_barSearch.InitializeAttributes (widgetText, attribCommonName);
  2102.  
  2103.     CComboBox *combo;
  2104.     combo = (CComboBox *) m_barSearch.GetDlgItem(IDC_COMBO_SCOPE);
  2105.     combo->ResetContent();
  2106.  
  2107.     XP_List *ldapDirectories = XP_ListNew();
  2108.     if (ldapDirectories) {
  2109.         DIR_GetLdapServers (theApp.m_directories, ldapDirectories);
  2110.         if (XP_ListCount(ldapDirectories)) {
  2111.             for (int i = 1; i <= XP_ListCount(ldapDirectories); i++) {
  2112.                 DIR_Server *server = (DIR_Server*) XP_ListGetObjectNum (ldapDirectories, i);
  2113.                 XP_ASSERT(server);
  2114.                 if (server)     {
  2115.                     if (server->description && server->description[0])
  2116.                         combo->AddString (server->description);
  2117.                     else
  2118.                         combo->AddString (server->serverName);
  2119.                     combo->SetItemData (i-1, scopeLdapDirectory * 2);
  2120.                 }
  2121.             }
  2122.             XP_ListDestroy (ldapDirectories);
  2123.         }
  2124.         else {
  2125.             combo->AddString("");
  2126.             combo->SetItemData (0, scopeLdapDirectory * 2);
  2127.         }
  2128.     }
  2129.     else {
  2130.         combo->AddString("");
  2131.         combo->SetItemData (0, scopeLdapDirectory * 2);
  2132.     }
  2133.  
  2134.     combo->SetCurSel(0);
  2135.     OnScope();
  2136.  
  2137.     // Initially size window to only dialog + title bar.
  2138.  
  2139.     CRect rect, rect2;
  2140.     int BorderX = GetSystemMetrics(SM_CXFRAME);
  2141.     int BorderY = GetSystemMetrics(SM_CYFRAME);
  2142.  
  2143.     GetWindowRect(&rect);
  2144.     m_barSearch.GetWindowRect(&rect2);
  2145.     CSize size = m_barSearch.CalcFixedLayout(FALSE, FALSE);
  2146.     // Figure height of title bar + bottom border
  2147.     size.cy += rect2.top - rect.top + BorderY;
  2148.     size.cx += BorderX * 2;
  2149.     SetWindowPos( NULL, 0, 0, size.cx, size.cy,
  2150.                   SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  2151.  
  2152.     m_iHeight = size.cy;
  2153.     m_iWidth = size.cx;
  2154.  
  2155.     OnNew();
  2156.  
  2157.     ShowResults( TRUE );
  2158.  
  2159.     return res;
  2160. }
  2161.  
  2162. void CLDAPSearchFrame::OnClose()
  2163. {
  2164.     if (m_pOutliner)
  2165.         m_pOutliner->SaveXPPrefs("mailnews.ldapsearch_columns_win");
  2166.     CFrameWnd::OnClose();
  2167.     g_pLDAPSearchWindow = NULL;
  2168. }
  2169.  
  2170. void CLDAPSearchFrame::OnScope()
  2171. {
  2172.     CSearchFrame::OnScope();
  2173.  
  2174.     CComboBox *combo = (CComboBox *) m_barSearch.GetDlgItem(IDC_COMBO_SCOPE);
  2175.     int iCurSel = combo->GetCurSel();
  2176.  
  2177.     XP_List *ldapDirectories = XP_ListNew();
  2178.     if (!ldapDirectories)
  2179.         return;
  2180.  
  2181.     DIR_GetLdapServers(theApp.m_directories, ldapDirectories);
  2182.     DIR_Server *pServer = (DIR_Server*) XP_ListGetObjectNum(ldapDirectories, iCurSel + 1);
  2183.     XP_ListDestroy (ldapDirectories);
  2184.  
  2185.     if (!pServer)
  2186.         return;
  2187.  
  2188.     int iCount = m_pOutliner->GetNumColumns();
  2189.     for (int i = 0; i < iCount; i++) {
  2190.         MSG_SearchAttribute attrib = (MSG_SearchAttribute) m_pOutliner->GetColumnAtPos(i);
  2191.         DIR_AttributeId id;
  2192.         MSG_SearchAttribToDirAttrib(attrib, &id);
  2193.         const char *text = DIR_GetAttributeName(pServer, id);
  2194.         m_pOutliner->SetColumnName(attrib, text);
  2195.     }
  2196.     m_pOutliner->GetParent()->Invalidate();
  2197. }
  2198.  
  2199. void CLDAPSearchFrame::OnFind()
  2200. {
  2201.     if ( m_bSearching ) {
  2202.         // We've turned into stop button
  2203.         XP_InterruptContext( GetContext() );
  2204.         m_bSearching = FALSE;
  2205.         return;
  2206.     } else if (CanAllInterrupt()) {
  2207.         AllInterrupt();
  2208.     }
  2209.  
  2210.     // Build Search
  2211.  
  2212.     ShowResults( FALSE );
  2213.  
  2214.     MSG_SearchFree (m_pSearchPane);
  2215.     MSG_SearchAlloc (m_pSearchPane);
  2216.  
  2217.     ASSERT(m_pOutliner);
  2218.     m_pOutliner->Invalidate();
  2219.                        
  2220.     CComboBox *combo;
  2221.  
  2222.     int iCurSel;
  2223.     
  2224.     combo = (CComboBox *) m_barSearch.GetDlgItem( IDC_COMBO_SCOPE );
  2225.     iCurSel = combo->GetCurSel();
  2226.  
  2227.     XP_List *ldapDirectories = XP_ListNew();
  2228.     if (!ldapDirectories)
  2229.         return;
  2230.     DIR_GetLdapServers (theApp.m_directories, ldapDirectories);
  2231.     DIR_Server *pServer = (DIR_Server*) XP_ListGetObjectNum (ldapDirectories, iCurSel + 1);
  2232.     XP_ListDestroy (ldapDirectories);
  2233.     if (!pServer)
  2234.         return;
  2235.  
  2236.     MSG_AddLdapScope( m_pSearchPane, pServer);
  2237.  
  2238.     m_barSearch.BuildQuery (m_pSearchPane);
  2239.  
  2240.     if (MSG_Search(m_pSearchPane) == SearchError_Success) {
  2241.         m_bSearching = TRUE;
  2242.         ShowResults( TRUE );
  2243.         SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0);
  2244.         m_barStatus.SetPaneText(m_barStatus.CommandToIndex( ID_SEPARATOR), 
  2245.                                 szLoadString( IDS_SEARCHING ) );
  2246.     }
  2247. }
  2248.  
  2249. void CLDAPSearchFrame::OnAdd()
  2250. {
  2251.     MSG_ViewIndex *indices;
  2252.     int count;
  2253.     m_pOutliner->GetSelection( indices, count );
  2254.     MSG_AddLdapResultsToAddressBook( m_pSearchPane, indices, count );
  2255. }
  2256.  
  2257. void CLDAPSearchFrame::OnUpdateAdd( CCmdUI *pCmdUI )
  2258. {
  2259.     MSG_ViewIndex *indices;
  2260.     int count;
  2261.     m_pOutliner->GetSelection( indices, count );
  2262.     pCmdUI->Enable( count > 0 && !m_bSearching);
  2263. }
  2264.  
  2265. void CLDAPSearchFrame::OnTo()
  2266. {
  2267.     MSG_ViewIndex *indices;
  2268.     int count;
  2269.     m_pOutliner->GetSelection( indices, count );
  2270.     MSG_ComposeFromLdapResults( m_pSearchPane, indices, count);
  2271. }
  2272.  
  2273. void CLDAPSearchFrame::OnUpdateTo( CCmdUI *pCmdUI )
  2274. {
  2275.     MSG_ViewIndex *indices;
  2276.     int count;
  2277.     m_pOutliner->GetSelection( indices, count );
  2278.     pCmdUI->Enable( count > 0 && !m_bSearching);
  2279. }
  2280.  
  2281. /////////////////////////////////////////////////////////////////////////////
  2282. // CLDAPSearchOutliner
  2283.  
  2284. BEGIN_MESSAGE_MAP(CLDAPSearchOutliner, CSearchOutliner)
  2285.     //{{AFX_MSG_MAP(CLDAPSearchOutliner)
  2286.     ON_WM_CREATE()
  2287.     //}}AFX_MSG_MAP
  2288. END_MESSAGE_MAP()
  2289.  
  2290. int CLDAPSearchOutliner::OnCreate ( LPCREATESTRUCT lpCreateStruct )
  2291. {
  2292.     int iRetVal = CSearchOutliner::OnCreate ( lpCreateStruct );
  2293.     
  2294.     InitializeClipFormats ( );
  2295.  
  2296.     return iRetVal;
  2297. }
  2298.  
  2299. HFONT CLDAPSearchOutliner::GetLineFont( void *pData )
  2300. {
  2301.     return m_hRegFont;
  2302. }
  2303.  
  2304. int CLDAPSearchOutliner::TranslateIcon (void * pData)
  2305. {
  2306.     // Do something smart
  2307.     int idxImage = IDX_MAILMESSAGE;
  2308.     return idxImage;
  2309. }
  2310.  
  2311. void CLDAPSearchOutliner::InitializeClipFormats(void)
  2312. {
  2313.      m_cfAddresses = (CLIPFORMAT)RegisterClipboardFormat(vCardClipboardFormat);
  2314.      m_cfSourceTarget = (CLIPFORMAT)RegisterClipboardFormat(LDAPSEARCH_SOURCETARGET_FORMAT);
  2315. }
  2316.  
  2317. CLIPFORMAT * CLDAPSearchOutliner::GetClipFormatList(void)
  2318. {
  2319.     static CLIPFORMAT cfFormatList[3];
  2320.     cfFormatList[0] = m_cfAddresses;
  2321.     cfFormatList[1] = m_cfSourceTarget;
  2322.     cfFormatList[2] = 0;
  2323.     return cfFormatList;
  2324. }
  2325.  
  2326. COleDataSource * CLDAPSearchOutliner::GetDataSource(void)
  2327. {
  2328.     COleDataSource * pDataSource = new COleDataSource;
  2329.     char* pVcard = NULL;
  2330.     char* pVcards = XP_STRDUP("");
  2331.     HANDLE hString = 0;
  2332.     PersonEntry person;
  2333.     char szFirstNameText[130] = "\0";
  2334.     char szLastNameText[130] = "\0";
  2335.     char szEmailText[130] = "\0";
  2336.     char szOrganizationText[130] = "\0";
  2337.     char szLocalityText[130] = "\0";
  2338.     char szWorkPhoneText[130] = "\0";
  2339.     MSG_ResultElement* elem = NULL;
  2340.     MSG_SearchValue *result = NULL;
  2341.     MSG_ViewIndex *indices;
  2342.     int count;
  2343.  
  2344.     GetSelection( indices, count );
  2345.  
  2346.     for (int i = 0; i < count; i++){
  2347.  
  2348.         szFirstNameText[0] = '\0';
  2349.         szLastNameText[0] = '\0';
  2350.         szEmailText[0] = '\0';
  2351.         szOrganizationText[0] = '\0';
  2352.         szLocalityText[0] = '\0';
  2353.         szWorkPhoneText[0] = '\0';
  2354.  
  2355.         if (MSG_GetResultElement (m_pSearchPane, indices[i], &elem) == SearchError_Success) {
  2356.             if (MSG_GetResultAttribute( elem, attribGivenName, &result) == SearchError_Success) {
  2357.                 XP_STRNCPY_SAFE (szFirstNameText, result->u.string, sizeof (szFirstNameText));
  2358.                 MSG_DestroySearchValue (result);
  2359.             }
  2360.             if (MSG_GetResultAttribute( elem, attribSurname, &result) == SearchError_Success) {
  2361.                 XP_STRNCPY_SAFE (szLastNameText, result->u.string, sizeof (szLastNameText));
  2362.                 MSG_DestroySearchValue (result);
  2363.             }
  2364.             if (MSG_GetResultAttribute( elem, attrib822Address, &result) == SearchError_Success)  {
  2365.                 XP_STRNCPY_SAFE (szEmailText, result->u.string, sizeof (szEmailText));
  2366.                 MSG_DestroySearchValue (result);
  2367.             }
  2368.             if (MSG_GetResultAttribute( elem, attribOrganization, &result) == SearchError_Success) {
  2369.                 XP_STRNCPY_SAFE (szOrganizationText, result->u.string, sizeof (szOrganizationText));
  2370.                 MSG_DestroySearchValue (result);
  2371.             }
  2372.             if (MSG_GetResultAttribute( elem, attribLocality, &result) == SearchError_Success) {
  2373.                 XP_STRNCPY_SAFE (szLocalityText, result->u.string, sizeof (szLocalityText));
  2374.                 MSG_DestroySearchValue (result);
  2375.             }
  2376.             if (MSG_GetResultAttribute( elem, attribPhoneNumber, &result) == SearchError_Success) {
  2377.                 XP_STRNCPY_SAFE (szWorkPhoneText, result->u.string, sizeof (szLocalityText));
  2378.                 MSG_DestroySearchValue (result);
  2379.             }
  2380.  
  2381.             if ((XP_STRLEN (szFirstNameText) == 0) || (XP_STRLEN (szLastNameText) == 0))
  2382.             {
  2383.                 if (MSG_GetResultAttribute( elem, attribCommonName, &result) == SearchError_Success) {
  2384.                     XP_STRNCPY_SAFE (szFirstNameText, result->u.string, sizeof (szFirstNameText));
  2385.                     MSG_DestroySearchValue (result);
  2386.                     szLastNameText[0] = '\0';
  2387.                 }
  2388.             }
  2389.         }
  2390.         person.Initialize();
  2391.         if (szFirstNameText[0] != '\0')
  2392.             person.pGivenName = szFirstNameText;
  2393.         if (szLastNameText[0] != '\0')
  2394.             person.pFamilyName = szLastNameText;
  2395.         if (szOrganizationText[0] != '\0')
  2396.             person.pCompanyName = szOrganizationText;
  2397.         if (szLocalityText[0] != '\0')
  2398.             person.pLocality = szLocalityText;
  2399.         if (szEmailText[0] != '\0')
  2400.             person.pEmailAddress = szEmailText;
  2401.         if (szWorkPhoneText[0] != '\0')
  2402.             person.pWorkPhone = szWorkPhoneText;
  2403.  
  2404.         AB_ExportToVCardFromPerson(theApp.m_pABook, &person, &pVcard);
  2405.         pVcards = StrAllocCat(pVcards, pVcard);
  2406.         XP_FREE(pVcard);
  2407.         pVcard = NULL;
  2408.  
  2409.     }
  2410.  
  2411.     if (pVcards) {
  2412.         hString = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT,strlen(pVcards)+1);
  2413.         LPSTR lpszString = (LPSTR)GlobalLock(hString);
  2414.         strcpy(lpszString,pVcards);
  2415.         XP_FREE (pVcards);
  2416.         GlobalUnlock(hString);
  2417.         pDataSource->CacheGlobalData(m_cfAddresses, hString);
  2418.         pDataSource->CacheGlobalData(m_cfSourceTarget, hString);
  2419.         pDataSource->CacheGlobalData(CF_TEXT, hString);
  2420.     }
  2421.  
  2422.     return pDataSource;
  2423. }
  2424.  
  2425. /////////////////////////////////////////////////////////////////////////////
  2426. // CSearchOutlinerParent
  2427.  
  2428. COutliner * CLDAPSearchOutlinerParent::GetOutliner ( void )
  2429. {
  2430.     return new CLDAPSearchOutliner;
  2431. }
  2432.  
  2433. void CLDAPSearchOutlinerParent::CreateColumns ( void )
  2434. {
  2435.     CString cs;
  2436.  
  2437.     cs.LoadString(IDS_USERNAME);
  2438.     m_pOutliner->AddColumn (cs,            attribCommonName,        20, 0, ColumnVariable, 2500 );
  2439.     cs.LoadString(IDS_EMAILADDRESS);
  2440.     m_pOutliner->AddColumn (cs,            attrib822Address,        20, 0, ColumnVariable, 2000 ); 
  2441.     cs.LoadString(IDS_COMPANYNAME);
  2442.     m_pOutliner->AddColumn (cs,            attribOrganization,        20, 0, ColumnVariable, 2000 ); 
  2443.     cs.LoadString(IDS_PHONE);
  2444.     m_pOutliner->AddColumn (cs,            attribPhoneNumber,        20, 0, ColumnVariable, 2000, FALSE);
  2445.     cs.LoadString(IDS_LOCALITY);
  2446.     m_pOutliner->AddColumn (cs,            attribLocality,            20, 0, ColumnVariable, 1500 );
  2447.     m_pOutliner->SetImageColumn( attribSubject );
  2448.     m_pOutliner->SetHasPipes( FALSE );
  2449.  
  2450.     m_pOutliner->SetVisibleColumns(DEF_VISIBLE_COLUMNS);
  2451.     m_pOutliner->LoadXPPrefs("mailnews.ldapsearch_columns_win");
  2452. }
  2453.  
  2454. void CLDAPSearchFrame::Open()
  2455. {
  2456.     XP_List *ldapDirectories = XP_ListNew();
  2457.     if (!ldapDirectories)
  2458.         return;
  2459.  
  2460.     DIR_GetLdapServers(theApp.m_directories, ldapDirectories);
  2461.     if (XP_ListCount(ldapDirectories)) {
  2462.         if (!g_pLDAPSearchWindow) {
  2463.             g_pLDAPSearchWindow = new CLDAPSearchFrame();
  2464.             g_pLDAPSearchWindow->Create();
  2465.         } else {
  2466.             g_pLDAPSearchWindow->ActivateFrame( g_pLDAPSearchWindow->IsIconic() ? SW_RESTORE : SW_SHOW );
  2467.         }
  2468.     } else {
  2469.         ::MessageBox(FEU_GetLastActiveFrame()->GetSafeHwnd(),
  2470.                      szLoadString(IDS_NOLDAPSERVERS), 
  2471.                      szLoadString(IDS_TITLE_ERROR), 
  2472.                      MB_OK|MB_ICONSTOP);
  2473.     }
  2474.     XP_ListDestroy (ldapDirectories);
  2475. }
  2476.  
  2477. void CLDAPSearchFrame::Close()
  2478. {
  2479.     if (g_pLDAPSearchWindow) {
  2480.         g_pLDAPSearchWindow->PostMessage(WM_CLOSE);
  2481.     }       
  2482. }
  2483.  
  2484. void WFE_MSGOpenSearch()
  2485. {
  2486.     CSearchFrame::Open();
  2487. }
  2488.  
  2489. void WFE_MSGSearchClose()
  2490. {
  2491.     CSearchFrame::Close();
  2492. }
  2493.     
  2494. void WFE_MSGOpenLDAPSearch()
  2495. {
  2496.     CLDAPSearchFrame::Open();
  2497. }
  2498.  
  2499. void WFE_MSGLDAPSearchClose()
  2500. {
  2501.     CLDAPSearchFrame::Close();
  2502. }
  2503.