/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

#include "stdafx.h"
#include "shcut.h"
#include "msgcom.h"
#include "msg_srch.h"
#include "prefapi.h"
#include "msgtmpl.h"
#include "netsdoc.h"
#include "mailmisc.h"
#include "mailpriv.h"
#include "msgview.h"
#include "fldrfrm.h"
#include "thrdfrm.h"
#include "msgfrm.h"
#include "wfemsg.h"
#include "intl_csi.h"
#include "fegui.h"
#include "rdfglobal.h"

#ifndef _AFXDLL
#undef new
#endif
IMPLEMENT_DYNCREATE(CFolderView, COutlinerView)
#ifndef _AFXDLL
#define new DEBUG_NEW
#endif

#define COL_LEFT_MARGIN	((m_cxChar+1)/2)
#define EXTRATEXT_SIZE	128
 
extern "C" const char* FE_GetFolderDirectory(MWContext *pContext);

int WFE_MSGTranslateFolderIcon( uint8 level, int32 iFlags, BOOL bOpen )
{
	int folderTable[] = { IDX_MAILFOLDERCLOSED, IDX_MAILFOLDEROPEN,
						  IDX_MAILFOLDERCLOSEDNEW, IDX_MAILFOLDEROPENNEW,
						// 4
						  IDX_NEWSGROUP, IDX_NEWSGROUP,
						  IDX_NEWSGROUP, IDX_NEWSGROUP,
						// 8
  						  IDX_LOCALMAIL, IDX_LOCALMAIL,
  						  IDX_LOCALMAIL, IDX_LOCALMAIL,
						// 12
						  IDX_REMOTEMAIL, IDX_REMOTEMAIL,
						  IDX_REMOTEMAIL, IDX_REMOTEMAIL,
						// 16
						  IDX_NEWSHOST, IDX_NEWSHOST,
						  IDX_NEWSHOST, IDX_NEWSHOST,
						// 20
						  IDX_INBOXCLOSED, IDX_INBOXOPEN,
						  IDX_INBOXCLOSEDNEW, IDX_INBOXOPENNEW,
						// 24
						  IDX_OUTBOXCLOSED, IDX_OUTBOXOPEN,
						  IDX_OUTBOXCLOSED, IDX_OUTBOXOPEN,
						// 28
						  IDX_SENTCLOSED, IDX_SENTOPEN,
						  IDX_SENTCLOSED, IDX_SENTOPEN,
						// 32
						  IDX_DRAFTSCLOSED, IDX_DRAFTSOPEN,
						  IDX_DRAFTSCLOSED, IDX_DRAFTSOPEN,
						// 36
						  IDX_TRASH, IDX_TRASHOPEN,
						  IDX_TRASH, IDX_TRASHOPEN,
						// 40
						   IDX_TEMPLATE, IDX_TEMPLATEOPEN,
						   IDX_TEMPLATE, IDX_TEMPLATEOPEN,
						};

	int idx = 0;

	if (iFlags & MSG_FOLDER_FLAG_NEWSGROUP)
		idx = 4;
	else if (level < 2)
		if (iFlags & MSG_FOLDER_FLAG_NEWS_HOST)
			idx = 16;
		else if (iFlags & MSG_FOLDER_FLAG_IMAPBOX)
			idx = 12;
		else
			idx = 8;
	else
		if (iFlags & MSG_FOLDER_FLAG_INBOX)
			idx = 20;
		else if (iFlags & MSG_FOLDER_FLAG_QUEUE)
			idx = 24;
		else if (iFlags & MSG_FOLDER_FLAG_DRAFTS)
			idx = 32;
		else if (iFlags & MSG_FOLDER_FLAG_TRASH )
			idx = 36;
		else if (iFlags & MSG_FOLDER_FLAG_SENTMAIL )
			idx = 28;
		else if (iFlags & MSG_FOLDER_FLAG_TEMPLATES )
			idx = 40;
		
	idx += bOpen ? 1 : 0;
	idx += iFlags & MSG_FOLDER_FLAG_GOT_NEW ? 2 : 0;

	return folderTable[idx];
}

void WFE_MSGBuildMessagePopup( HMENU hmenu, BOOL bNews, BOOL bInHeaders )
{
	::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_REPLY, szLoadString( IDS_MENU_REPLY ) );
	if ( bNews ) {
		::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_POSTREPLY, szLoadString( IDS_MENU_POSTREPLY ) );
		::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_POSTANDREPLY, szLoadString( IDS_MENU_POSTMAILREPLY ) );
	} else {
		::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_REPLYALL, szLoadString( IDS_MENU_REPLYALL ) );
	}
	::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_FORWARD, szLoadString( IDS_MENU_FORWARD ) );
	::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_FORWARDQUOTED, szLoadString( IDS_MENU_FORWARDQUOTED ) );
	::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
	 
	HMENU hAddMenu = ::CreatePopupMenu();
	::AppendMenu( hAddMenu, MF_STRING, ID_MESSAGE_ADDSENDER, szLoadString( IDS_POPUP_ADDSENDER ) );
	::AppendMenu( hAddMenu, MF_STRING, ID_MESSAGE_ADDALL, szLoadString( IDS_POPUP_ADDALL ) );
	::AppendMenu( hmenu, MF_STRING|MF_POPUP, (UINT) hAddMenu, szLoadString( IDS_POPUP_ADDTOADDRESSBOOK ) );
	::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
 
	if (bInHeaders) {
		::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_KILL, szLoadString( IDS_POPUP_IGNORETHREAD ) );
		::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_WATCH, szLoadString( IDS_POPUP_WATCHTHREAD ) );
		::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		if (!bNews) {
			 
			HMENU hPriorityMenu = ::CreatePopupMenu();
			::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_LOWEST, szLoadString( IDS_POPUP_LOWEST ) );
			::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_LOW, szLoadString( IDS_POPUP_LOW ) );
			::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_NORMAL, szLoadString( IDS_POPUP_NORMAL ) );
			::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_HIGH, szLoadString( IDS_POPUP_HIGH ) );
			::AppendMenu( hPriorityMenu, MF_STRING, ID_PRIORITY_HIGHEST, szLoadString( IDS_POPUP_HIGHEST ) );
			::AppendMenu( hmenu, MF_STRING|MF_POPUP, (UINT) hPriorityMenu, szLoadString( IDS_POPUP_PRIORITY ) );
			::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		}
	}
 
	UINT nID = FIRST_MOVE_MENU_ID;
	HMENU hFileMenu = CreatePopupMenu();
	CMailNewsFrame::UpdateMenu( NULL, hFileMenu, nID );
	::AppendMenu( hmenu, MF_POPUP|MF_STRING, (UINT) hFileMenu, szLoadString( IDS_POPUP_FILE ) );
	::AppendMenu( hmenu, MF_STRING, CASTUINT(ID_EDIT_DELETEMESSAGE), 
				  szLoadString( CASTUINT(bNews ? IDS_POPUP_CANCELMESSAGE : IDS_POPUP_DELETEMESSAGE )) );
	::AppendMenu( hmenu, MF_STRING, ID_FILE_SAVEMESSAGES, szLoadString( IDS_POPUP_SAVEMESSAGE ) );
	::AppendMenu( hmenu, MF_STRING, ID_FILE_PRINT, szLoadString( IDS_POPUP_PRINTMESSAGE ) );
}

//////////////////////////////////////////////////////////////////////////////
// CBiffCX

class CBiffCX: public CStubsCX
{
public:
	CBiffCX(): CStubsCX(Network, MWContextBiff) {};
	
	virtual void DestroyContext();
};

void CBiffCX::DestroyContext()
{
	MSG_BiffCleanupContext(GetContext());

	CStubsCX::DestroyContext();
}

//////////////////////////////////////////////////////////////////////////////
// CMessagePrefs

CMsgPrefs g_MsgPrefs;

#ifdef _WIN32
static TCHAR lpszEventMailBeep[] = _T("AppEvents\\EventLabels\\MailBeep");
static TCHAR lpszSchemeMailBeep[] = _T("AppEvents\\Schemes\\Apps\\.Default\\MailBeep");
static TCHAR lpszCurrent[] = _T(".current");
static TCHAR lpszChord[] = _T("chord.wav");
#endif
static char lpszSounds[] = "Sounds";
static char lpszMailBeep[] = "MailBeep";

void WFE_MSGInit()
{
#ifdef _WIN32
	if (sysInfo.m_bWin4) {
		TCHAR szBuf[_MAX_PATH];
		LONG lBufSize = _MAX_PATH;

		if ( ::RegQueryValue(HKEY_CURRENT_USER, lpszEventMailBeep, szBuf, &lBufSize) !=
			 ERROR_SUCCESS ) {
			::RegSetValue(HKEY_CURRENT_USER, lpszEventMailBeep, REG_SZ,
						  szLoadString(IDS_MAILSOUND), _tcslen(szLoadString(IDS_MAILSOUND)));
		}

		HKEY hkey;
		if ( ::RegCreateKey(HKEY_CURRENT_USER, lpszSchemeMailBeep, &hkey) == 
			 ERROR_SUCCESS ) {
			
			lBufSize = _MAX_PATH;
			if ( ::RegQueryValue(hkey, lpszCurrent, szBuf, &lBufSize) !=
				 ERROR_SUCCESS ) {
				::RegSetValue(hkey, lpszCurrent, REG_SZ,
							  lpszChord, _tcslen(lpszChord));
			}
			::RegCloseKey(hkey);
		}
	}
	else
#endif
	{
		char szBuf[_MAX_PATH * 2];
		LONG lBufSize = _MAX_PATH * 2;
		::GetProfileString(lpszSounds, lpszMailBeep, szLoadString(IDS_MAILSOUND16), szBuf, lBufSize );
		::WriteProfileString(lpszSounds, lpszMailBeep, szBuf);
	}	
	g_MsgPrefs.Init();
}

void WFE_MSGShutdown()
{
	MSG_DestroyMaster(WFE_MSGGetMaster());
 	MSG_ShutdownMsgLib();
	g_MsgPrefs.Shutdown();
}

MSG_Master* WFE_MSGGetMaster()
{
	return g_MsgPrefs.GetMaster();
}

CMsgPrefs::CMsgPrefs()
{
	m_pMaster = NULL;
}

PR_CALLBACK cbMsgPrefs(const char *prefName, void *pData)
{
	XP_Bool bPref;
	char *pszPref = NULL;

	switch ((int) pData) {
	case 0:
		bPref= TRUE;
		PREF_GetBoolPref("mailnews.reuse_thread_window", &bPref);
		g_MsgPrefs.m_bThreadReuse = bPref;
		break;

	case 1:
		bPref= TRUE;
		PREF_GetBoolPref("mailnews.reuse_message_window", &bPref);
		g_MsgPrefs.m_bMessageReuse = bPref;
		break;

	case 2:
		bPref= TRUE;
		PREF_GetBoolPref("mailnews.message_in_thread_window", &bPref);
		g_MsgPrefs.m_bThreadPaneMaxed = !bPref;
		break;

	case 3:
		PREF_CopyCharPref("mail.directory", &pszPref);
		if (pszPref)
			g_MsgPrefs.m_csMailDir = pszPref;
		break;

	case 4:
		PREF_CopyCharPref("network.hosts.pop_server", &pszPref);
		if (pszPref) {
			g_MsgPrefs.m_csMailHost = pszPref;
		}
		break;

	case 5:
		PREF_CopyCharPref("news.directory", &pszPref);
		if (pszPref)
			g_MsgPrefs.m_csNewsDir = pszPref;
		break;

	case 6:
		PREF_CopyCharPref("network.hosts.nntp_server", &pszPref);
		if (pszPref) {
		    NET_SetNewsHost(pszPref);
			g_MsgPrefs.m_csNewsHost = pszPref;
		}
		break;

	case 7:
		PREF_CopyCharPref("mail.identity.useremail", &pszPref);
		if (pszPref)
			g_MsgPrefs.m_csUsersEmailAddr = pszPref;
		break;

	case 8:
		PREF_CopyCharPref("mail.identity.username", &pszPref);
		if (pszPref)
			g_MsgPrefs.m_csUsersFullName = pszPref;
		break;

	case 9:
		PREF_CopyCharPref("mail.identity.organization", &pszPref);
		if (pszPref)
			g_MsgPrefs.m_csUsersOrganization = pszPref;
		break;

	case 10:
		PREF_CopyCharPref("mail.signature_file", &pszPref);
		if (pszPref) {
			XP_FREEIF(g_MsgPrefs.m_pszUserSig);
			g_MsgPrefs.m_pszUserSig = wfe_ReadUserSig(pszPref);
		}
		break;
	case 11:
		break;

	case 12:
		{
			for(CGenericFrame * f = theApp.m_pFrameList; f; f = f->m_pNext)
				f->PostMessage(WM_COMMAND, (WPARAM) ID_DONEGOINGOFFLINE, (LPARAM) 0);
		}
		break;

	default:
		ASSERT(0);
	}

	XP_FREEIF(pszPref);

	return PREF_NOERROR;
}

void CMsgPrefs::Init()
{
    m_pFolderTemplate = new CFolderTemplate(IDR_MAILFRAME,  
            RUNTIME_CLASS(CNetscapeDoc),
            RUNTIME_CLASS(CFolderFrame),     // mail window
            RUNTIME_CLASS(CFolderView));
	m_pThreadTemplate = new CThreadTemplate(IDR_MAILTHREAD,  
			RUNTIME_CLASS(CNetscapeDoc),
			RUNTIME_CLASS(C3PaneMailFrame),  // 3 pane mail window
			RUNTIME_CLASS(CMailNewsSplitter));
    m_pMsgTemplate = new CMessageTemplate(IDR_MESSAGEFRAME,  
            RUNTIME_CLASS(CNetscapeDoc),
            RUNTIME_CLASS(CMessageFrame),     // mail message window
            RUNTIME_CLASS(CMessageView));

    theApp.AddDocTemplate(m_pFolderTemplate);
    theApp.AddDocTemplate(m_pThreadTemplate);
    theApp.AddDocTemplate(m_pMsgTemplate);

	int32 prefInt = 0;
	char *prefStr = NULL;
	
    // Set up mail directory (must be before creation of msg prefs)
	CString msg = theApp.m_UserDirectory;
    msg += "\\mail";
	PREF_SetDefaultCharPref("mail.directory", msg);
	PREF_CopyCharPref("mail.directory", &prefStr);
	if (prefStr)
		m_csMailDir = prefStr;
	XP_FREEIF(prefStr);

	// Initialize the message library 
	MSG_InitMsgLib();

	// Create the MSG lib pref structure
	m_pMsgPrefs = MSG_CreatePrefs();

	//
	// Read in user identity stuff
	//

	PREF_CopyCharPref("mail.identity.username",&prefStr);
	m_csUsersFullName = prefStr;
	XP_FREEIF(prefStr);        
    
	PREF_CopyCharPref("mail.identity.useremail",&prefStr);
	m_csUsersEmailAddr = prefStr;
	XP_FREEIF(prefStr);        
    
	PREF_CopyCharPref("mail.identity.organization",&prefStr);
	m_csUsersOrganization = prefStr;
	XP_FREEIF(prefStr);        

	PREF_CopyCharPref("mail.signature_file", &prefStr);
    m_pszUserSig = wfe_ReadUserSig(prefStr);
	XP_FREEIF(prefStr);        

	//
	// Set up the POP3 server
	//

	PREF_CopyCharPref("network.hosts.pop_server", &prefStr);
	if (prefStr) {
		g_MsgPrefs.m_csMailHost = prefStr;
	}
	XP_FREEIF(prefStr);

	XP_Bool prefBool= FALSE;
	PREF_GetBoolPref("mail.remember_password",&prefBool);
	prefStr = NULL;
	PREF_CopyCharPref("mail.pop_password",&prefStr);
    if(prefStr && prefBool) {
		NET_SetPopPassword(prefStr);
	}
	XP_FREEIF(prefStr);

	//
	// Set up the SMTP server
	//

	PREF_CopyCharPref("network.hosts.smtp_server", &prefStr);
    NET_SetMailRelayHost(prefStr);
	XP_FREEIF(prefStr);    

	PREF_SetBoolPref("news.show_pretty_names", TRUE);

	//
	// Set up the NNTP server
	//

	PREF_CopyCharPref("network.hosts.nntp_server", &prefStr);
    NET_SetNewsHost(prefStr);
	m_csNewsHost = prefStr;
	XP_FREEIF(prefStr);

	// Set up news directory
	msg = theApp.m_UserDirectory;
    msg += "\\news";
	PREF_SetDefaultCharPref("news.directory",msg);
	PREF_CopyCharPref("news.directory",&prefStr);
	m_csNewsDir = prefStr;
	XP_FREEIF(prefStr);    

    // Check that the news directory exists
	// Don't show error messagebox according bug#37398
    if(FEU_SanityCheckDir(m_csNewsDir)) 
	{
		NET_ReadNewsrcFileMappings();
	}

	//
	// Compose prefs
	//

	prefBool = TRUE;
	PREF_GetBoolPref("mail.strictly_mime", &prefBool);
    MIME_ConformToStandard(prefBool); 

	//
	// Set up window prefs
	//
	prefBool= TRUE;
	PREF_GetBoolPref("mailnews.reuse_thread_window", &prefBool);
	m_bThreadReuse = prefBool;

	prefBool= TRUE;
	PREF_GetBoolPref("mailnews.reuse_message_window", &prefBool);
	m_bMessageReuse = prefBool;

	prefBool= TRUE;
	PREF_GetBoolPref("mailnews.message_in_thread_window", &prefBool);
	m_bThreadPaneMaxed = !prefBool;

	PREF_RegisterCallback("mailnews.reuse_thread_window", cbMsgPrefs, (void *) 0);
	PREF_RegisterCallback("mailnews.reuse_message_window", cbMsgPrefs, (void *) 1);
	PREF_RegisterCallback("mailnews.message_in_thread_window", cbMsgPrefs, (void *) 2);
	// The BE should probably be handling most of these
	PREF_RegisterCallback("mail.directory", cbMsgPrefs, (void *) 3);
	PREF_RegisterCallback("network.hosts.pop_server", cbMsgPrefs, (void *) 4);
	PREF_RegisterCallback("news.directory", cbMsgPrefs, (void *) 5);
	PREF_RegisterCallback("network.hosts.nntp_server", cbMsgPrefs, (void *) 6);
	PREF_RegisterCallback("mail.identity.useremail", cbMsgPrefs, (void *) 7);
	PREF_RegisterCallback("mail.identity.username", cbMsgPrefs, (void *) 8);
	PREF_RegisterCallback("mail.identity.organization", cbMsgPrefs, (void *) 9);
	PREF_RegisterCallback("mail.signature_file", cbMsgPrefs, (void *) 10);
	PREF_RegisterCallback("mail.leave_on_server", cbMsgPrefs, (void *) 11);
	PREF_RegisterCallback("network.online", cbMsgPrefs, (void *) 12);

	// START THE BIFF CONTEXT
	CBiffCX *pCX = new CBiffCX();
    m_pBiffContext = pCX->GetContext();

    MSG_BiffInit(m_pBiffContext, m_pMsgPrefs);
}

void CMsgPrefs::Shutdown()
{
}

CMsgPrefs::~CMsgPrefs()
{
	XP_FREEIF(m_pszUserSig);
}

BOOL CMsgPrefs::IsValid() const
{
	char buffer[256];
	int nLen = 255;

	buffer[0] = '\0';
	if (PREF_NOERROR == PREF_GetCharPref("mail.pop_name", buffer, &nLen))
    {
		if (strlen(buffer) && !m_csMailHost.IsEmpty())
			return TRUE;
		else
			return FALSE;
	}
	else
		return FALSE;
}

MSG_Master *CMsgPrefs::GetMaster()
{
	// Lazy loading of the one-and-only master object for news
	// * Must be lazy loaded so theApp.m_pMsgPrefs is initialized

	if (!m_pMaster)
	{
		if (!m_pMsgPrefs)
			m_pMsgPrefs = MSG_CreatePrefs();
		m_pMaster = MSG_InitializeMail(m_pMsgPrefs);
	}
	return m_pMaster;
}

//////////////////////////////////////////////////////////////////////////////
// CMailNewsOutliner

CMailNewsOutliner::CMailNewsOutliner()
{
	m_iSelBlock = 0;
	m_bSelChanged = FALSE;
	m_bExpandOrCollapse = FALSE;
	m_pPane = NULL;
	m_iMysticPlane = 0;
}

CMailNewsOutliner::~CMailNewsOutliner()
{
}

void CMailNewsOutliner::SetPane(MSG_Pane *pane)
{
	m_pPane = pane;

	if (m_pPane) {
		SetTotalLines( (int) MSG_GetNumLines(m_pPane));
		Invalidate();
		UpdateWindow();
	}
}

const char *aszNotifications[] = {
	"None",
	"InsOrDel",
	"Changed",
	"Scramble",
	"All"
};
	 
void CMailNewsOutliner::MysticStuffStarting( XP_Bool asynchronous,
											MSG_NOTIFY_CODE notify, 
											MSG_ViewIndex where,
											int32 num )
{
	TipHide();

	if ( 0 == m_iMysticPlane++  ) {
		m_bSelChanged = FALSE;
	}

	if ( notify == MSG_NotifyInsertOrDelete && m_bExpandOrCollapse ) {
	}
}

void CMailNewsOutliner::MysticStuffFinishing( XP_Bool asynchronous,
											 MSG_NOTIFY_CODE notify, 
											 MSG_ViewIndex where,
											 int32 num )
{
	switch ( notify ) {
	case MSG_NotifyNone:
		break;
	case MSG_NotifyAll:
		ClearSelection();
		m_iSelection = -1;
		m_iTopLine = 0;
		m_bSelChanged = TRUE;
		Invalidate();
		break;
	case MSG_NotifyInsertOrDelete:
		if ( m_bExpandOrCollapse && where > 0 && num < 0 ) {
			// We're collapsing, so if our primary selection is
			// in the collapsing area, we need to select the
			// parent
			// Assume that where - 1 is the parent

			if ( m_iSelection >= (int32) where && 
				 m_iSelection < (int32) (where - num) ) {
				m_iSelection = CASTINT(where - 1);
				m_iFocus = CASTINT(where - 1);
				AddSelection( m_iSelection );
				m_bSelChanged = TRUE;
			}
			if ( m_iShiftAnchor >= (int32) where &&
				 m_iShiftAnchor < (int32) (where - num ) ) {
				m_iShiftAnchor = CASTINT(where - 1);
			}
		}

		if ( num < 0 ) {
			m_bSelChanged |= HandleDelete( where, -num );
		} else if (num > 0) {
			m_bSelChanged |= HandleInsert( where, num );
		} else {
			m_bSelChanged = TRUE;
		}
		break;
	case MSG_NotifyChanged:
		InvalidateLines( (int) where, (int) num );
		break;
	case MSG_NotifyScramble:
		ScrollIntoView(m_iFocus);
		Invalidate();
		break;
	}

	if ( !--m_iMysticPlane && m_pPane ) {
		SetTotalLines( (int) MSG_GetNumLines( m_pPane ) );
		UpdateWindow();

		if (m_bSelChanged) {
			m_bSelChanged = FALSE;
			OnSelChanged();
		}
	}
}

int CMailNewsOutliner::ToggleExpansion( int iLine )
{
	int32 numChanged;

	m_bExpandOrCollapse = TRUE;
    MSG_ToggleExpansion( m_pPane, iLine, &numChanged );
	m_bExpandOrCollapse = FALSE;

	return (int) numChanged;
}

int CMailNewsOutliner::Expand( int iLine )
{
	if (MSG_ExpansionDelta( m_pPane, iLine ) > 0) {
	    return ToggleExpansion( iLine );
	}
	return 0;
}

int CMailNewsOutliner::Collapse( int iLine )
{
	if (MSG_ExpansionDelta( m_pPane, iLine ) < 0) {
	    return ToggleExpansion( iLine );
	}
	return 0;
}

BEGIN_MESSAGE_MAP( CMailNewsOutliner, CMSelectOutliner )
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
END_MESSAGE_MAP()

BOOL CMailNewsOutliner::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
{

	if ( (nHitTest == HTCLIENT) && (m_iSelBlock > 0)) {
		::SetCursor( ::LoadCursor( NULL, IDC_WAIT ) );
		return TRUE;
	}

	return CMSelectOutliner::OnSetCursor( pWnd, nHitTest, message );
}

void CMailNewsOutliner::OnLButtonDown( UINT nFlags, CPoint point )
{
	if (m_iSelBlock <= 0)
		COutliner::OnLButtonDown(nFlags, point);
	else 
		MessageBeep((UINT) -1);
}

void CMailNewsOutliner::OnRButtonDown( UINT nFlags, CPoint point )
{
	if (m_iSelBlock <= 0)
		COutliner::OnRButtonDown(nFlags, point);
	else 
		MessageBeep((UINT) -1);
}

void CMailNewsOutliner::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
{
	if (m_iSelBlock <= 0)
		COutliner::OnKeyDown(nChar, nRepCnt, nFlags);
	else 
		MessageBeep((UINT) -1);
}

void CMailNewsOutliner::OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags )
{
    if (m_iSelection != m_iLastSelected) {
		if (m_iIndicesCount == 1) {
			COutliner::OnKeyUp(nChar, nRepCnt, nFlags);
		} else {
			int flags = 0;
			if (GetKeyState(VK_SHIFT)&0x8000)
				flags |= MK_SHIFT;
			if (GetKeyState(VK_CONTROL)&0x8000)
				flags |= MK_CONTROL;
			SelectItem(m_iSelection, OUTLINER_TIMER, flags);
		}
	}
}


//////////////////////////////////////////////////////////////////////////////
// CFolderOutliner

#define DOUBLE_CLICK_TIMER   9999

CFolderOutliner::CFolderOutliner ( )
{
	m_pUnkUserImage = NULL;
	ApiApiPtr(api);
	m_pUnkUserImage = api->CreateClassInstance(
	  APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILNEWS);
	m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
	ASSERT(m_pIUserImage);
	if (!m_pIUserImage->GetResourceID())
	  m_pIUserImage->Initialize(IDB_MAILNEWS,16,16);

    m_pszExtraText = new _TCHAR[EXTRATEXT_SIZE];
	m_pMysticStuff = NULL;
	m_pAncestor = NULL;

	m_uTimer = 0;
	m_dwPrevTime = 0;
	m_bLButtonDown = FALSE;
	m_bDoubleClicked = FALSE;
	m_b3PaneParent = FALSE;
	m_nCurrentSelected = -1;
}

CFolderOutliner::~CFolderOutliner ( )
{
    if (m_pUnkUserImage) {
        if (m_pIUserImage)
            m_pUnkUserImage->Release();
    }

    delete [] m_pszExtraText;
	delete [] m_pMysticStuff;
}

void CFolderOutliner::MysticStuffStarting( XP_Bool asynchronous,
										  MSG_NOTIFY_CODE notify, 
										  MSG_ViewIndex where,
										  int32 num )
{
	CMailNewsOutliner::MysticStuffStarting( asynchronous, notify,
										   where, num );

	if ( notify == MSG_NotifyScramble && m_pPane ) {
		MSG_ViewIndex *indices;
		int i, count;
		GetSelection(indices, count);

		m_pMysticStuff = new MSG_FolderInfo*[count];

		for (i = 0; i < count; i++) {
			m_pMysticStuff[i] = MSG_GetFolderInfo(m_pPane, indices[i]);
		}

		m_MysticFocus = MSG_GetFolderInfo( m_pPane, m_iFocus );
		m_MysticSelection = MSG_GetFolderInfo( m_pPane, m_iSelection );
	}
}

void CFolderOutliner::MysticStuffFinishing( XP_Bool asynchronous,
										   MSG_NOTIFY_CODE notify, 
										   MSG_ViewIndex where,
										   int32 num )
{
	if ( notify == MSG_NotifyScramble && m_pPane ) {
		MSG_ViewIndex *indices;
		int i, count;
		GetSelection(indices, count);

		ClearSelection();

		for ( i = 0; i < count; i++ ) {
			int index = (int) MSG_GetFolderIndex(m_pPane, m_pMysticStuff[i]);
			if ( index != MSG_VIEWINDEXNONE ) {
				AddSelection(index);
			} else {
				m_bSelChanged = TRUE;
			}
		}

		delete [] m_pMysticStuff;
		m_pMysticStuff = NULL;

		if ( m_MysticSelection == NULL ) {
			m_iSelection = -1;
		} else {
			int iSelection = (int) MSG_GetFolderIndex(m_pPane, m_MysticSelection);
			if (iSelection == -1 ) {
				iSelection = GetTotalLines() > 0 ? 0 : -1;
				if (iSelection != -1)
					AddSelection( iSelection );
			}
			m_iSelection = iSelection;
		}

		if ( m_MysticFocus == NULL ) {
			m_iFocus = m_iSelection;
		} else {
			int iFocus = (int) MSG_GetFolderIndex(m_pPane, m_MysticFocus);
			if ( iFocus == -1 ) {
				iFocus = m_iSelection > 0 ? m_iSelection : 0;
			}
			m_iFocus = iFocus;
		}
		m_iShiftAnchor = m_iFocus;
	}

	CMailNewsOutliner::MysticStuffFinishing( asynchronous, notify,
											where, num );
}

// Tree Info stuff
int CFolderOutliner::GetDepth( int iLine )
{
	MSG_FolderLine folderLine;
	MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
	return folderLine.level - 1;
}

int CFolderOutliner::GetNumChildren( int iLine )
{
	MSG_FolderLine folderLine;
	MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
	return folderLine.numChildren;
}

BOOL CFolderOutliner::IsCollapsed( int iLine )
{
	MSG_FolderLine folderLine;
	MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &folderLine );
	return folderLine.flags & MSG_FOLDER_FLAG_ELIDED ? TRUE : FALSE;
}

void CFolderOutliner::PropertyMenu ( int iSel, UINT flags )	
{
	HMENU hmenu = CreatePopupMenu();
	
	if ( !hmenu )
		return;  

	MSG_ViewIndex *indices;
	int count;
	GetSelection( indices, count );

    if ( iSel < m_iTotalLines && count == 1 ) {
		MSG_FolderLine folderLine;
		MSG_GetFolderLineByIndex( m_pPane, indices[0], 1, &folderLine );

		BOOL bReuse = g_MsgPrefs.m_bThreadReuse;
		if (GetKeyState(VK_MENU) & 0x8000)
			bReuse = !bReuse;

		if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) { 
			if (folderLine.level > 1) {
				if (bReuse) {
					::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENFOLDER ) );
					::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENFOLDERNEWWINDOW ) );
				} else {
					::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENFOLDERNEWWINDOW ) );
					::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENFOLDER ) );
				}
				::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
				 
				::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWFOLDER, szLoadString( IDS_POPUP_NEWSUBFOLDER ) );
				::AppendMenu( hmenu, MF_STRING, ID_EDIT_DELETEFOLDER, szLoadString( IDS_POPUP_DELETEFOLDER ) );
				::AppendMenu( hmenu, MF_STRING, ID_FOLDER_RENAME, szLoadString( IDS_POPUP_RENAMEFOLDER ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_COMPRESSTHISFOLDER, szLoadString( IDS_POPUP_COMPRESSFOLDER ) );
				::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
			 
				::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWMESSAGE, szLoadString( IDS_POPUP_NEWMESSAGE ) );
				::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
			 
				::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
				::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_FOLDERPROP ) );
			} else {
				::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWFOLDER, szLoadString( IDS_POPUP_NEWFOLDER ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_UPDATECOUNTS, szLoadString( IDS_POPUP_UPDATEMESSAGECOUNT ) );
				::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
			 
				::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
				::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_MAILSERVERPROP) );
			}
		} else if ( folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ) {
			BOOL bReuse = g_MsgPrefs.m_bThreadReuse;
			if (bReuse) {
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENNEWSGROUP ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENNEWSGROUPNEWWINDOW ) );
			} else {
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERNEW, szLoadString( IDS_POPUP_OPENNEWSGROUPNEWWINDOW ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENFOLDERREUSE, szLoadString( IDS_POPUP_OPENNEWSGROUP ) );
			}
			::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		 
			::AppendMenu( hmenu, MF_STRING, ID_FILE_NEWMESSAGE, szLoadString( IDS_POPUP_NEWMESSAGE ) );
			::AppendMenu( hmenu, MF_STRING, ID_MESSAGE_MARKALLREAD, szLoadString( IDS_POPUP_MARKNEWSGROUPREAD ) );
			::AppendMenu( hmenu, MF_STRING, ID_POPUP_DELETEFOLDER, szLoadString( IDS_POPUP_REMOVENEWSGROUP ) );
			::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		 
			::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
			::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_NEWSGROUPPROP ) );
		} else if ( folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST ) {
			::AppendMenu( hmenu, MF_STRING, ID_FILE_SUBSCRIBE, szLoadString( IDS_POPUP_JOINNEWSGROUP ) );
			::AppendMenu( hmenu, MF_STRING, ID_FILE_UPDATECOUNTS, szLoadString( IDS_POPUP_UPDATEMESSAGECOUNT ) );
			::AppendMenu( hmenu, MF_STRING, ID_POPUP_DELETEFOLDER, szLoadString( IDS_POPUP_REMOVENEWSHOST ) );
			::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		 
			::AppendMenu( hmenu, MF_STRING, ID_EDIT_SEARCH, szLoadString( IDS_POPUP_SEARCH ) );
			::AppendMenu( hmenu, MF_STRING, ID_VIEW_PROPERTIES, szLoadString( IDS_POPUP_NEWSHOSTPROP) );
		}
	}
	//	Track the popup now.
	POINT pt = m_ptHit;
	ClientToScreen(&pt);

	::TrackPopupMenu( hmenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0,
					  GetParentFrame()->GetSafeHwnd(), NULL);

	VERIFY(::DestroyMenu( hmenu ));
}

DROPEFFECT CFolderOutliner::DropSelect( int iLineNo, COleDataObject *pDataObject )
{
	DROPEFFECT res = DROPEFFECT_NONE;
	MSG_DragEffect requireEffect = MSG_Default_Drag;
	MSG_DragEffect effect = MSG_Drag_Not_Allowed;
	HGLOBAL hContent = NULL;
	MailNewsDragData *pDragData = NULL;

	if ((GetKeyState(VK_SHIFT) & 0x8000) && (GetKeyState(VK_CONTROL) & 0x8000))
		requireEffect = MSG_Default_Drag;
	else if (GetKeyState(VK_SHIFT) & 0x8000)
		requireEffect = MSG_Require_Move;
	else if (GetKeyState(VK_CONTROL) & 0x8000)
		requireEffect = MSG_Require_Copy;

// The commented out code has the effect of always doing a move, if we get called
// with the same iLineNo as last time!
//	if (iLineNo != m_iDragSelection)
	{
		if ( m_iDragSelection != -1 )
			InvalidateLine (m_iDragSelection);

		m_iDragSelection = -1;

		MSG_FolderLine folderLine;

		if (MSG_GetFolderLineByIndex( m_pPane, (MSG_ViewIndex) iLineNo, 1, &folderLine )) 
		{
			if ( pDataObject->IsDataAvailable( m_cfMessages ) ) 
			{
				hContent = pDataObject->GetGlobalData (m_cfMessages);
				pDragData = (MailNewsDragData *) GlobalLock(hContent);
				effect = MSG_DragMessagesIntoFolderStatus
						(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
						folderLine.id, requireEffect);
				GlobalUnlock (hContent); //do we have to GlobalFree it too?
			}
			else if ( pDataObject->IsDataAvailable( m_cfFolders ) ) 
			{
				hContent = pDataObject->GetGlobalData (m_cfFolders);
				pDragData = (MailNewsDragData *) GlobalLock(hContent);
				effect = MSG_DragFoldersIntoStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					folderLine.id, requireEffect);
				GlobalUnlock (hContent); //do we have to GlobalFree it too?
			}
			else if ( pDataObject->IsDataAvailable( m_cfSearchMessages ) ) 
			{
				hContent = pDataObject->GetGlobalData (m_cfSearchMessages);
				pDragData = (MailNewsDragData *) GlobalLock(hContent);
				effect = MSG_DragMessagesIntoFolderStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					folderLine.id, requireEffect);
				GlobalUnlock (hContent); //do we have to GlobalFree it too?
			}
			if (MSG_Drag_Not_Allowed != effect) 
			{
				InvalidateLine (iLineNo);
				m_iDragSelection = iLineNo;
				if (effect == MSG_Require_Copy)
					res = DROPEFFECT_COPY;
				else
					res = DROPEFFECT_MOVE;
			} 
		}
	}
//	else  
//		res = DROPEFFECT_MOVE;

	return res;
}

void CFolderOutliner::AcceptDrop( int iLineNo, COleDataObject *pDataObject,
								 DROPEFFECT dropEffect )
{
    if (iLineNo != -1) {
		MSG_FolderInfo *pFolder = MSG_GetFolderInfo(m_pPane,iLineNo);
		ASSERT(pFolder);

		MSG_DragEffect requireEffect = MSG_Default_Drag;
		if (dropEffect & DROPEFFECT_MOVE)
			requireEffect = MSG_Require_Move;
		else if (dropEffect & DROPEFFECT_COPY)
			requireEffect = MSG_Require_Copy;

		if ( pDataObject->IsDataAvailable( m_cfMessages ) && pFolder ) 
		{
			HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
			MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);

			MSG_DragEffect effect =  MSG_DragMessagesIntoFolderStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					pFolder, requireEffect);

			LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
			if (pUnk) {
				LPMSGLIST pInterface = NULL;
				pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
				if ( pInterface ) {
					switch (effect) {
					case MSG_Require_Move:
						pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					case MSG_Require_Copy:
						pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					default:
						ASSERT(0);
						break;
					}
					pInterface->Release();
				}
			}
			GlobalUnlock (hContent); //do we have to GlobalFree it too?
		}

		if ( pDataObject->IsDataAvailable( m_cfSearchMessages ) && pFolder ) 
		{
			HGLOBAL hContent = pDataObject->GetGlobalData (m_cfSearchMessages);
			MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);

			MSG_DragEffect effect =  MSG_DragMessagesIntoFolderStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					pFolder, requireEffect);

			LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
			if (pUnk) {
				LPMSGLIST pInterface = NULL;
				pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
				if ( pInterface ) {
					switch (effect) {
					case MSG_Require_Move:
						pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					case MSG_Require_Copy:
						pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					default:
						ASSERT(0);
						break;
					}
					pInterface->Release();
				}
			}
			GlobalUnlock (hContent); //do we have to GlobalFree it too?
		}


 		if ( pDataObject->IsDataAvailable( m_cfFolders ) && pFolder ) 
		{
			HGLOBAL hContent = pDataObject->GetGlobalData (m_cfFolders);
			MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);

			MSG_DragEffect effect = MSG_DragFoldersIntoStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					pFolder, MSG_Default_Drag);

			if (effect == MSG_Require_Copy || effect == MSG_Require_Move)
			{
				MSG_MoveFoldersInto( pDragData->m_pane, pDragData->m_indices, 
									 pDragData->m_count, pFolder);
				if (IsParent3PaneFrame())
				{
					C3PaneMailFrame* pFrame = C3PaneMailFrame::FindFrame(pFolder);;
					if (pFrame) 
						pFrame->ActivateFrame();
#if 0	// this interrupts the move - why are we doing it?
					else
						GetParentFrame()->SendMessage(WM_COMMAND, 
													ID_FOLDER_SELECT, 0);
#endif
				}
			}
			GlobalUnlock (hContent); //do we have to GlobalFree it too?
		}
	}
}

COleDataSource * CFolderOutliner::GetDataSource(void)
{
	MSG_ViewIndex *indices;
	int count;
	GetSelection(indices, count);

    HANDLE hContent = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(MailNewsDragData));
	MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock (hContent);

	pDragData->m_pane = m_pPane;
	pDragData->m_indices = indices;
	pDragData->m_count = count;

    GlobalUnlock(hContent);

    COleDataSource * pDataSource = new COleDataSource;  
    pDataSource->CacheGlobalData(m_cfFolders,hContent);

	if ( count == 1 ) {
		MSG_FolderLine folderLine;
		MSG_GetFolderLineByIndex( m_pPane, indices[0], 1, &folderLine );
		URL_Struct *url = MSG_ConstructUrlForFolder( m_pPane, folderLine.id );

		if ( url ) {			
			const char *name = (folderLine.prettyName && folderLine.prettyName[0]) ?
							   folderLine.prettyName : folderLine.name;
			RDFGLOBAL_DragTitleAndURL( pDataSource, name, url->address );
			NET_FreeURLStruct( url );
		}
	}

    return pDataSource;
}

void CFolderOutliner::InitializeClipFormats(void)
{
    m_cfMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_MESSAGE_FORMAT);
	m_cfFolders = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_FOLDER_FORMAT);
	m_cfSearchMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_SEARCH_FORMAT);
}

CLIPFORMAT * CFolderOutliner::GetClipFormatList(void)
{
    static CLIPFORMAT cfFormatList[4];
    cfFormatList[0] = m_cfMessages;
	cfFormatList[1] = m_cfFolders;
    cfFormatList[2] = m_cfSearchMessages;
	cfFormatList[3] = 	0;
    return cfFormatList;
}

int CFolderOutliner::TranslateIcon (void * pData)
{
    ASSERT(pData);
    MSG_FolderLine * pFolder = (MSG_FolderLine*)pData;

	BOOL bOpen = pFolder->numChildren <= 0 ||
				 pFolder->flags & MSG_FOLDER_FLAG_ELIDED ? FALSE : TRUE;

	return WFE_MSGTranslateFolderIcon( pFolder->level, pFolder->flags, bOpen );
}

int CFolderOutliner::TranslateIconFolder (void * pData)
{
    ASSERT(pData);
    MSG_FolderLine * pFolder = (MSG_FolderLine*)pData;

	if (pFolder->numChildren > 0) {
		if (pFolder->flags & MSG_FOLDER_FLAG_ELIDED) {
            return(OUTLINER_CLOSEDFOLDER);
		} else {
            return(OUTLINER_OPENFOLDER);
		}
	}
    return (OUTLINER_ITEM);
}

void * CFolderOutliner::AcquireLineData ( int line )
{
	delete [] m_pAncestor;
	m_pAncestor = NULL;

    m_pszExtraText[ 0 ] = '\0';
	if ( line >= m_iTotalLines)
		return NULL;
	if ( !MSG_GetFolderLineByIndex(m_pPane, line, 1, &m_FolderLine ))
        return NULL;

	return &m_FolderLine;
}

void CFolderOutliner::GetTreeInfo ( int line, uint32 * pFlags, int * pDepth, 
									OutlinerAncestorInfo ** pAncestor )
{
	delete [] m_pAncestor;
	m_pAncestor = NULL;

	if (pAncestor) {
		if ( m_FolderLine.level > 0 ) {
			m_pAncestor = new OutlinerAncestorInfo[m_FolderLine.level];
		} else {
			m_pAncestor = new OutlinerAncestorInfo[1];
		}

		int i = m_FolderLine.level - 1;
		int idx = line + 1;
		while ( i > 0 ) {
			int level;
			if ( idx < m_iTotalLines ) {
				level = MSG_GetFolderLevelByIndex( m_pPane, idx );
				if ( (level - 1) == i ) {
					m_pAncestor[i].has_prev = TRUE;
					m_pAncestor[i].has_next = TRUE;
					i--;
					idx++;
				} else if ( (level - 1) < i ) {
					m_pAncestor[i].has_prev = FALSE;
					m_pAncestor[i].has_next = FALSE;
					i--;
				} else {
					idx++;
				}
			} else {
				m_pAncestor[i].has_prev = FALSE;
				m_pAncestor[i].has_next = FALSE;
				i--;
			}
		}
		m_pAncestor[0].has_prev = FALSE;
		m_pAncestor[0].has_next = FALSE;

        *pAncestor = m_pAncestor;
	}

    if ( pFlags ) *pFlags = m_FolderLine.flags;
    if ( pDepth ) *pDepth = m_FolderLine.level - 1;
}

void CFolderOutliner::ReleaseLineData ( void * )
{
	delete [] m_pAncestor;
	m_pAncestor = NULL;
}

int CFolderOutliner::OnCreate(LPCREATESTRUCT lpcs)
{
	m_b3PaneParent = GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame));
	
	return CMailNewsOutliner::OnCreate(lpcs);
}

void CFolderOutliner::OnDestroy()
{
	if (m_uTimer)
	{
		KillTimer(m_uTimer);
		m_uTimer = 0;
	}
	CMailNewsOutliner::OnDestroy();
}

void CFolderOutliner::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLButtonDown = TRUE;
	CMailNewsOutliner::OnLButtonDown(nFlags, point);
}

void CFolderOutliner::OnTimer(UINT nIDEvent)
{
	if (m_uTimer == nIDEvent)
	{
		if (m_bDoubleClicked)
		{
			m_bDoubleClicked = FALSE;
			KillTimer(m_uTimer);
			m_uTimer = 0;
		}
		else
		{
			UINT delta = GetTickCount() - m_dwPrevTime;
			if (delta > GetDoubleClickTime())
			{	// single click
				m_bSelChanged = FALSE;
				if (GetCurrentSelected() != m_iSelection)
				{
					if (!m_iSelBlock)
						GetParentFrame()->SendMessage(WM_COMMAND, 
													ID_FOLDER_SELECT, 0);
				}
				KillTimer(m_uTimer);
				m_uTimer = 0;
			}
		}
		m_bLButtonDown = FALSE;
	}
	else
		CMailNewsOutliner::OnTimer(nIDEvent);
}

void CFolderOutliner::OnSelChanged()
{
	if (IsParent3PaneFrame())
	{
		SetCurrentSelected(m_iLastSelected);
		if (m_uTimer == 0 && m_bLButtonDown && !m_bDoubleClicked)
		{
			m_dwPrevTime = GetTickCount();
			UINT uElapse = GetDoubleClickTime() / 5;
			m_uTimer = SetTimer(DOUBLE_CLICK_TIMER, uElapse, NULL);
			return;
		} 
	}
 	m_bSelChanged = FALSE;
	if (!m_iSelBlock)
		GetParentFrame()->SendMessage(WM_COMMAND, ID_FOLDER_SELECT, 0);
}

void CFolderOutliner::OnSelDblClk()
{
	m_bDoubleClicked = TRUE;

	MSG_FolderLine folderLine;
	if (MSG_GetFolderLineByIndex(m_pPane, m_iFocus, 1, &folderLine)) {
		if (folderLine.level < 2) {
			DoToggleExpansion(m_iFocus);
		}
	}
	GetParentFrame()->SendMessage(WM_COMMAND, ID_FILE_OPENFOLDER, 0);
}

HFONT CFolderOutliner::GetLineFont ( void *pLineData )
{
	MSG_FolderLine *pFolderLine = (MSG_FolderLine *) pLineData;

	if (((pFolderLine->deepUnseen > 0) && (pFolderLine->flags & MSG_FOLDER_FLAG_ELIDED)) ||
		(pFolderLine->unseen > 0) ||
		(pFolderLine->level < 2) )
		return m_hBoldFont;
	else
		return m_hRegFont;
}

LPCTSTR CFolderOutliner::GetColumnText( UINT iColumn, void * pLineData )
{
	m_pszExtraText[0] = '\0';
	LPCTSTR name;

    switch ( iColumn )
    {
        case ID_COLUMN_FOLDER:
			name = (LPCTSTR) m_FolderLine.prettyName;
			if ( !name || !name[0] )
				name = m_FolderLine.name;
            return name;

        case ID_COLUMN_UNREAD:
            if( m_FolderLine.unseen > 0 )
				sprintf( m_pszExtraText, "%ld", m_FolderLine.unseen );
            else if (m_FolderLine.unseen < 0)
                sprintf( m_pszExtraText, "???" );
            return m_pszExtraText;
            
        case ID_COLUMN_COUNT:
            if( m_FolderLine.total > 0 )
				sprintf( m_pszExtraText, "%ld", m_FolderLine.total );
            else if(m_FolderLine.total < 0)
                sprintf( m_pszExtraText, "???" );
            return m_pszExtraText;

    }
    return m_pszExtraText;
}

LPCTSTR CFolderOutliner::GetColumnTip( UINT iColumn, void * pLineData )
{
	switch ( iColumn ) {
	case ID_COLUMN_UNREAD:
		if ( m_FolderLine.deepUnseen != m_FolderLine.unseen ) {
            if( m_FolderLine.unseen > 0 ) { 
				sprintf( m_pszExtraText, "(%ld) %ld", 
						 m_FolderLine.deepUnseen, m_FolderLine.unseen );
				return m_pszExtraText;
			} else if (m_FolderLine.unseen == 0) {
                sprintf( m_pszExtraText, "(%ld)", m_FolderLine.deepUnseen );
				return m_pszExtraText;
			}
		}
		break;

	case ID_COLUMN_COUNT:
		if ( m_FolderLine.deepTotal != m_FolderLine.total ) {
            if( m_FolderLine.total > 0 ) { 
				sprintf( m_pszExtraText, "(%ld) %ld", 
						 m_FolderLine.deepTotal, m_FolderLine.total );
				return m_pszExtraText;
			} else if (m_FolderLine.total == 0) {
                sprintf( m_pszExtraText, "(%ld)", m_FolderLine.deepTotal );
				return m_pszExtraText;
			}
		}
		break;
	}
	return NULL;
}

BEGIN_MESSAGE_MAP(CFolderOutliner, CMailNewsOutliner)
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_TIMER()
	ON_WM_DESTROY()
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////////////
// CMessageOutliner


CMessageOutliner::CMessageOutliner ( )
{
    m_pszExtraText = new _TCHAR[EXTRATEXT_SIZE];
	m_pAncestor = NULL;
	m_bNews = FALSE;
	m_bDrafts = FALSE;

	m_uTimer = 0;
	m_dwPrevTime = 0;
	m_bLButtonDown = FALSE;
	m_bDoubleClicked = FALSE;
	m_nCurrentSelected = -1;

	m_pUnkUserImage = NULL;
	ApiApiPtr(api);
	m_pUnkUserImage = api->CreateClassInstance(
	  APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILNEWS);
	m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
	ASSERT(m_pIUserImage);
	if (!m_pIUserImage->GetResourceID())
	  m_pIUserImage->Initialize(IDB_MAILNEWS,16,16);

	m_pMysticStuff = NULL;
}

CMessageOutliner::~CMessageOutliner ( )
{
    if (m_pUnkUserImage) {
        if (m_pIUserImage)
            m_pUnkUserImage->Release();
    }

    delete [] m_pszExtraText;
	delete [] m_pMysticStuff;
}

void CMessageOutliner::MysticStuffStarting( XP_Bool asynchronous,
										   MSG_NOTIFY_CODE notify, 
										   MSG_ViewIndex where,
										   int32 num )
{
	CMailNewsOutliner::MysticStuffStarting( asynchronous, notify,
										   where, num);
	if ( notify == MSG_NotifyScramble ) {
		MSG_ViewIndex *indices;
		int i, count;
		GetSelection(indices, count);

		m_pMysticStuff = new MessageKey[count];

		for (i = 0; i < count; i++) {
			m_pMysticStuff[i] = MSG_GetMessageKey(m_pPane, indices[i]);
		}

		m_MysticFocus = MSG_MESSAGEKEYNONE;
		m_MysticSelection = MSG_MESSAGEKEYNONE;

		if ( m_iSelection != -1 && m_iSelection < m_iTotalLines) {
			m_MysticSelection = MSG_GetMessageKey( m_pPane, m_iSelection );
		}
		if ( m_iFocus != -1 && m_iFocus < m_iTotalLines) {
			m_MysticFocus = MSG_GetMessageKey( m_pPane, m_iFocus );
		}
	}
}

void CMessageOutliner::MysticStuffFinishing( XP_Bool asynchronous,
											MSG_NOTIFY_CODE notify, 
											MSG_ViewIndex where,
											int32 num )
{
	if ( notify == MSG_NotifyScramble ) {
		MSG_ViewIndex *indices;
		int i, count;
		GetSelection(indices, count);

		ClearSelection();

		for ( i = 0; i < count; i++ ) {
			MSG_ViewIndex index = MSG_GetMessageIndexForKey(m_pPane, m_pMysticStuff[i], TRUE);
			if ( index != MSG_VIEWINDEXNONE ) {
				AddSelection(index);
			} else {
				m_bSelChanged = TRUE;
			}
		}

		delete [] m_pMysticStuff;
		m_pMysticStuff = NULL;

		if ( m_MysticSelection == MSG_MESSAGEKEYNONE ) {
			m_iSelection = -1;
		} else {
			int iSelection = CASTINT(MSG_GetMessageIndexForKey(m_pPane, m_MysticSelection, TRUE));
			if (iSelection == -1 ) {
				iSelection = MSG_GetNumLines( m_pPane ) > 0 ? 0 : -1;
				if (iSelection != -1)
					AddSelection( iSelection );
			}
			m_iSelection = iSelection;
		}

		if ( m_MysticFocus == MSG_MESSAGEKEYNONE ) {
			m_iFocus = m_iSelection;
		} else {
			int iFocus = CASTINT(MSG_GetMessageIndexForKey(m_pPane, m_MysticFocus, TRUE));
			if ( iFocus == -1 ) {
				iFocus = m_iSelection > 0 ? m_iSelection : 0;
			}
			m_iFocus = iFocus;
		}
		m_iShiftAnchor = m_iFocus;
	}

	if ( notify == MSG_NotifyAll ) {
		MSG_FolderInfo *folderInfo = MSG_GetCurFolder( m_pPane );
		MSG_FolderLine folderLine;
		MSG_GetFolderLineById( WFE_MSGGetMaster(),
							   folderInfo, &folderLine );
		if ( m_bNews ) {
			SaveXPPrefs("news.thread_columns_win");
		} else {
			SaveXPPrefs("mail.thread_columns_win");
		}

		m_bNews = folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ? TRUE : FALSE;
		m_bDrafts = folderLine.flags & MSG_FOLDER_FLAG_DRAFTS ? TRUE : FALSE;

		if( m_bNews ) {
			LoadXPPrefs("news.thread_columns_win");
		} else {
			LoadXPPrefs("mail.thread_columns_win");
		}
	}

	CMailNewsOutliner::MysticStuffFinishing( asynchronous, notify,
											where, num);
}

// Tree Info stuff
int CMessageOutliner::GetDepth( int iLine )
{
	MSG_MessageLine messageLine;
	MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
	return messageLine.level - 1;
}

int CMessageOutliner::GetNumChildren( int iLine )
{
	MSG_MessageLine messageLine;
	MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
	return messageLine.numChildren;
}

int CMessageOutliner::GetParentIndex( int iLine )
{
	MessageKey key = MSG_GetMessageKey( m_pPane, (MSG_ViewIndex) iLine );
	return CASTINT(MSG_ThreadIndexOfMsg( m_pPane, key ));
}

BOOL CMessageOutliner::IsCollapsed( int iLine )
{
	MSG_MessageLine messageLine;
	MSG_GetThreadLineByIndex( m_pPane, (MSG_ViewIndex) iLine, 1, &messageLine );
	return messageLine.flags & MSG_FLAG_ELIDED ? TRUE : FALSE;
}

int CMessageOutliner::ExpandAll( int iLine )
{
	int iDelta = 0;
	for (int i = GetTotalLines() - 1; i >= 0; i--) {
		iDelta += Expand(i);
	}
	ScrollIntoView(m_iFocus);

	return iDelta;
}

int CMessageOutliner::CollapseAll( int iLine )
{
	int iDelta = 0;
	for (int i = 0; i < GetTotalLines(); i++) {
		iDelta += Collapse(i);
	}
	ScrollIntoView(m_iFocus);

	return iDelta;
}

void CMessageOutliner::SelectThread( int iLine, UINT flags )
{
	if ( MSG_GetToggleStatus( m_pPane, MSG_SortByThread, NULL, 0) != MSG_Checked )
		return;

	MysticStuffStarting( FALSE, MSG_NotifyNone, 0, 0 );
	theApp.DoWaitCursor(1);

	m_bSelChanged = TRUE;

	MessageKey *keys;
	MSG_ViewIndex *indices;
	int i, count;
	if ( iLine >= 0 ) {
		if (!(flags & MK_CONTROL )) {
			ClearSelection();
		}

		InvalidateLine(m_iFocus);
		m_iFocus = m_iSelection = iLine;
		InvalidateLine(m_iFocus);

		if ( flags & MK_SHIFT ) {
			GetSelection( indices, count );
			if ( count <= 0 )
				return;

			keys = new MessageKey[count];

			for ( i = 0; i < count; i++ ) {
				keys[ i ] = MSG_GetMessageKey( m_pPane, indices[ i ] );
			}
		} else {
			count = 1;
			keys = new MessageKey[1];
			keys[0] = MSG_GetMessageKey( m_pPane, (MSG_ViewIndex) iLine );
		}
	} else {
		GetSelection( indices, count );
		if ( count <= 0 )
			return;

		keys = new MessageKey[count];

		for ( i = 0; i < count; i++ ) {
			keys[ i ] = MSG_GetMessageKey( m_pPane, indices[ i ] );
		}
		ClearSelection();
	}

	for ( i = 0; i < count; i++ ) {
		MSG_ViewIndex index = MSG_ThreadIndexOfMsg( m_pPane, keys[ i ] );
		int delta = CASTINT(MSG_ExpansionDelta( m_pPane, index ));
		if ( delta > 0) {
			MSG_ToggleExpansion( m_pPane, index, NULL );
		} else {
			delta = -delta;
		}	
		SelectRange( index, index + delta );
	}

	delete [] keys;

	theApp.DoWaitCursor(-1);
	MysticStuffFinishing( FALSE, MSG_NotifyNone, 0, 0 );
}

void CMessageOutliner::SelectFlagged()
{
	MSG_MessageLine messageLine;

	ClearSelection();
	for (int i = 0; i < m_iTotalLines; i++ ) {
		if ( MSG_GetThreadLineByIndex( m_pPane, i, 1, &messageLine ) ) {
			if ( messageLine.flags & MSG_FLAG_MARKED ) {
				AddSelection(i);
			}
		}
	}
	OnSelChanged();
}

void CMessageOutliner::EnsureFlagsVisible()
{
	int iPos = GetColumnPos(ID_COLUMN_MARK);
	int iVis = CASTINT(GetVisibleColumns());
	if (iPos >= iVis) {
		SetColumnPos(ID_COLUMN_MARK, iVis);
		SetVisibleColumns(CASTUINT(iVis + 1));

		RECT rc;
		GetClientRect(&rc);
		OnSize(0, rc.right, rc.bottom);
		Invalidate();
		GetParent()->Invalidate();
	}
}

void CMessageOutliner::PropertyMenu ( int iSel, UINT flags )	
{
    HMENU hmenu = CreatePopupMenu();

	if ( !hmenu )
		return;  

	if ( iSel < m_iTotalLines ) {
		if (!m_bDrafts) {
			BOOL bReuse = g_MsgPrefs.m_bMessageReuse;
			if (GetKeyState(VK_MENU) & 0x8000)
				bReuse = !bReuse;

			if (bReuse) {
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGEREUSE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGENEW, szLoadString( IDS_POPUP_OPENMESSAGENEWWINDOW ) );
			} else {
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGENEW, szLoadString( IDS_POPUP_OPENMESSAGENEWWINDOW ) );
				::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGEREUSE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
			}
		} else {
			::AppendMenu( hmenu, MF_STRING, ID_FILE_OPENMESSAGE, szLoadString( IDS_POPUP_OPENMESSAGE ) );
		}
		::AppendMenu( hmenu, MF_SEPARATOR, 0, NULL );
		//
		WFE_MSGBuildMessagePopup( hmenu, m_bNews, TRUE );
    }

    //	Track the popup now.
    POINT pt = m_ptHit;
    ClientToScreen(&pt);

   	::TrackPopupMenu( hmenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0,
					  GetParentFrame()->GetSafeHwnd(), NULL);

    //  Cleanup
    VERIFY(::DestroyMenu( hmenu ));
}

COleDataSource * CMessageOutliner::GetDataSource(void)
{
	MSG_ViewIndex *indices;
	int count;

	GetSelection( indices, count );

    HANDLE hContent = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,sizeof(MailNewsDragData));
	MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock (hContent);
	pDragData->m_pane = m_pPane;
	pDragData->m_indices = indices;
	pDragData->m_count = count;
    GlobalUnlock(hContent);

    COleDataSource * pDataSource = new COleDataSource;  
    pDataSource->CacheGlobalData(m_cfMessages,hContent);

	if ( count == 1 ) {
		MSG_MessageLine messageLine;
		MSG_GetThreadLineByIndex( m_pPane, indices[0], 1, &messageLine );
		URL_Struct *url = MSG_ConstructUrlForMessage( m_pPane, messageLine.messageKey );

		if ( url ) {			
			RDFGLOBAL_DragTitleAndURL( pDataSource, messageLine.subject, url->address );
			NET_FreeURLStruct( url );
		}
	}

	return pDataSource;
}

void CMessageOutliner::InitializeClipFormats(void)
{
    m_cfMessages = (CLIPFORMAT)RegisterClipboardFormat(NETSCAPE_MESSAGE_FORMAT);
}

CLIPFORMAT * CMessageOutliner::GetClipFormatList(void)
{
    static CLIPFORMAT cfFormatList[2];
    cfFormatList[0] = m_cfMessages;
    cfFormatList[1] = 0;

    return cfFormatList;
}

DROPEFFECT CMessageOutliner::DropSelect( int iLineNo, COleDataObject *pDataObject )
{
	DROPEFFECT res = DROPEFFECT_NONE;

	if ( !m_bNews && pDataObject->IsDataAvailable( m_cfMessages ) )  
	{
		MSG_FolderInfo *pFolderInfo = MSG_GetCurFolder( m_pPane );
		HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
		MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);

		MSG_DragEffect requireEffect = MSG_Default_Drag;
		if ((GetKeyState(VK_SHIFT) & 0x8000) && (GetKeyState(VK_CONTROL) & 0x8000))
			requireEffect = MSG_Default_Drag;
		else if (GetKeyState(VK_SHIFT) & 0x8000)
			requireEffect = MSG_Require_Move;
		else if (GetKeyState(VK_CONTROL) & 0x8000)
			requireEffect = MSG_Require_Copy;

		MSG_DragEffect effect = MSG_DragMessagesIntoFolderStatus
				(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
				pFolderInfo, requireEffect);

		if (effect == MSG_Require_Copy)
			res = DROPEFFECT_COPY;
		else
			res = DROPEFFECT_MOVE;

		GlobalUnlock (hContent); //do we have to GlobalFree it too?
	}   
	return res;
}

void CMessageOutliner::AcceptDrop( int iLineNo, COleDataObject *pDataObject,
								   DROPEFFECT dropEffect )
{
    if ( !m_bNews ) {
		MSG_FolderInfo *pFolder = MSG_GetCurFolder( m_pPane );
		ASSERT(pFolder);

		if ( pDataObject->IsDataAvailable( m_cfMessages ) && pFolder ) {
			HGLOBAL hContent = pDataObject->GetGlobalData (m_cfMessages);
			MailNewsDragData *pDragData = (MailNewsDragData *) GlobalLock(hContent);
			
			MSG_DragEffect requireEffect = MSG_Default_Drag;
			if (dropEffect & DROPEFFECT_MOVE)
				requireEffect = MSG_Require_Move;
			else if (dropEffect & DROPEFFECT_COPY)
				requireEffect = MSG_Require_Copy;

			MSG_DragEffect effect = MSG_DragMessagesIntoFolderStatus
					(pDragData->m_pane, pDragData->m_indices, pDragData->m_count,
					pFolder, requireEffect);
			//  need to code this way to make it work 
			LPUNKNOWN pUnk = (LPUNKNOWN) MSG_GetFEData( pDragData->m_pane );
			if (pUnk) {
				LPMSGLIST pInterface = NULL;
				pUnk->QueryInterface( IID_IMsgList, (LPVOID *) &pInterface );
				if ( pInterface ) {
					switch (effect ) {
					case MSG_Require_Move:
						pInterface->MoveMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					case MSG_Require_Copy:
						pInterface->CopyMessagesInto( pDragData->m_pane, pDragData->m_indices, 
													  pDragData->m_count, pFolder);
						break;
					default:
						ASSERT(0);
						break;
					}
				}
			}  
			GlobalUnlock(hContent); //do we have to GlobalFree it too?
		}
	}
}

BOOL CMessageOutliner::RenderData( UINT iColumn, CRect &rect, CDC &dc, LPCTSTR text )
{
    switch ( iColumn )
    {
	case ID_COLUMN_THREAD:
		if ((m_MessageLine.level == 0 && m_MessageLine.numChildren > 0) ||
			(m_MessageLine.flags & (MSG_FLAG_WATCHED|MSG_FLAG_IGNORED))) {
			int idxImage[] = { IDX_THREADCLOSED, 
								IDX_THREADOPEN,
								IDX_THREADCLOSEDNEW,
								IDX_THREADOPENNEW,
								IDX_THREADWATCHED,
								IDX_THREADWATCHED,
								IDX_THREADWATCHEDNEW,
								IDX_THREADWATCHEDNEW,
								IDX_THREADIGNOREDCLOSED,
								IDX_THREADIGNOREDOPEN,
								IDX_THREADIGNOREDCLOSED,
								IDX_THREADIGNOREDOPEN };
			int idx = 0;
			idx += m_MessageLine.flags & MSG_FLAG_ELIDED ? 0 : 1;
			idx += m_MessageLine.numNewChildren ? 2 : 0;
			idx += m_MessageLine.flags & MSG_FLAG_WATCHED ? 4 : 0;
			idx += m_MessageLine.flags & MSG_FLAG_IGNORED ? 8 : 0;

            m_pIUserImage->DrawImage ( idxImage[idx],
                rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), rect.top, &dc, FALSE );
		}
		return TRUE;

	case ID_COLUMN_MARK:
		{
			int idxImage = m_MessageLine.flags & MSG_FLAG_MARKED ?
						   IDX_MARKED : IDX_READ;
            m_pIUserImage->DrawImage ( idxImage,
									   rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), 
									   rect.top, &dc, FALSE );
		}
		return TRUE;

    case ID_COLUMN_READ:
        if (!(m_MessageLine.flags & MSG_FLAG_EXPIRED)) {
            int idxImage;
            if (m_MessageLine.flags & MSG_FLAG_READ)
                idxImage = IDX_READ;
            else
                idxImage = IDX_UNREAD;

            m_pIUserImage->DrawImage ( idxImage,
                rect.left + ( ( rect.Width ( ) - 16 ) / 2 ), rect.top, &dc, FALSE );

        }
        return TRUE;  
		
	case ID_COLUMN_PRIORITY: 
		{
			CRect rectText(rect);
			rectText.left += COL_LEFT_MARGIN;
			rectText.right -= COL_LEFT_MARGIN;

			COLORREF colorPriority[] = { RGB(0x00,0x00,0x00),
										  RGB(0x00,0x00,0x00), 
										  RGB(0xaa,0xaa,0xaa),
										  RGB(0x55,0x55,0x55),
										  RGB(0x00,0x00,0x00),
										  RGB(0x80,0x00,0x00),
										  RGB(0xff,0x00,0x00) };

			UINT dwDTFormat = DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER;
			COLORREF colorOld = dc.GetTextColor();

			if ( colorOld != GetSysColor( COLOR_HIGHLIGHTTEXT )) { 
				dc.SetTextColor( colorPriority[ m_MessageLine.priority ] );
			}

			DrawColumnText( dc.m_hDC, rectText, text, CropRight, AlignLeft );

			dc.SetTextColor( colorOld );
			return TRUE;
		}
		break;
    }
    return FALSE;
}

int CMessageOutliner::TranslateIcon (void * pData)
{
	int messageTable[] = { IDX_MAILMESSAGE,	   IDX_MAILNEW,		   IDX_MAILREAD,
						   IDX_MAILMSGOFFLINE, IDX_MAILMSGOFFLINE, IDX_MAILREADOFFLINE,
						   IDX_NEWSARTICLE,	   IDX_NEWSNEW,		   IDX_NEWSREAD,
						   IDX_NEWSMSGOFFLINE, IDX_NEWSMSGOFFLINE, IDX_NEWSREADOFFLINE,
						   IDX_DRAFT,		   IDX_DRAFT,		   IDX_DRAFT,
						   IDX_DRAFT,		   IDX_DRAFT,		   IDX_DRAFT };
    ASSERT(pData);
    MSG_MessageLine * pMessage = (MSG_MessageLine *)pData;

	if (pMessage->flags & MSG_FLAG_IMAP_DELETED)
		return IDX_IMAPMSGDELETED;

	int idx = 0;

	if (m_bNews)
		idx = 6;
	else if (m_bDrafts)
		idx = 12;

	if ( pMessage->flags & MSG_FLAG_OFFLINE )
		idx += 3;

	if ( pMessage->flags & MSG_FLAG_READ )
		idx += 2;
	else if ( pMessage->flags & MSG_FLAG_NEW )
		idx += 1;

	return messageTable[idx];
}

int CMessageOutliner::TranslateIconFolder (void * pData)
{
    ASSERT(pData);
    MSG_MessageLine * pMessage = (MSG_MessageLine *)pData;
    
	if (pMessage->numChildren > 0) {
		if (pMessage->flags & MSG_FLAG_ELIDED) {
            return ( OUTLINER_CLOSEDFOLDER );
        } else {
            return ( OUTLINER_OPENFOLDER );
		}
	} else {
		return (OUTLINER_ITEM);
    }
}


BOOL CMessageOutliner::ColumnCommand ( int iColumn, int iLine )
{
	MSG_ViewIndex indices[1];
	indices[0] = iLine;
	
	switch ( iColumn )
    {
	case ID_COLUMN_THREAD:
		if ( MSG_GetToggleStatus( m_pPane, MSG_SortByThread, NULL, 0) == MSG_Checked ) {
			SelectThread( iLine );
			return TRUE;
		} else {
			return FALSE;
		}

    case ID_COLUMN_READ:
        if (!(m_MessageLine.flags & MSG_FLAG_EXPIRED)) 
            MSG_Command(m_pPane, MSG_ToggleMessageRead, indices, 1);
        return TRUE;
	case ID_COLUMN_MARK:
		{
			MSG_MessageLine messageLine;
			MSG_ViewIndex index = iLine;

			MSG_GetThreadLineByIndex( m_pPane, index, 1, &messageLine );

			MSG_Command( m_pPane, 
						 ( messageLine.flags & MSG_FLAG_MARKED) ? 
						 MSG_UnmarkMessages : MSG_MarkMessages,
						 &index, 1 );

			return TRUE;
		}
    }

    return FALSE;
}

void * CMessageOutliner::AcquireLineData ( int line )
{
	if ( line >= m_iTotalLines)
		return NULL;

	if ( !MSG_GetThreadLineByIndex(m_pPane, line, 1, &m_MessageLine ) )
		return NULL;

	return &m_MessageLine; 
}

void CMessageOutliner::GetTreeInfo ( int iLine, uint32 * pFlags, int * pDepth, 
									 OutlinerAncestorInfo ** pAncestor )
{
	delete [] m_pAncestor;
	m_pAncestor = NULL;

	if ( pAncestor ) {
		m_pAncestor = new OutlinerAncestorInfo[m_MessageLine.level + 1];

		int i = m_MessageLine.level;
		int idx = iLine + 1;
		while ( i > 0 ) {
			if ( idx < m_iTotalLines ) {
				int level = MSG_GetThreadLevelByIndex( m_pPane, idx );
				if ( level == i ) {
					m_pAncestor[i].has_prev = TRUE;
					m_pAncestor[i].has_next = TRUE;
					i--;
					idx++;
				} else if ( level < i ) {
					m_pAncestor[i].has_prev = FALSE;
					m_pAncestor[i].has_next = FALSE;
					i--;
				} else {
					idx++;
				}
			} else {
				m_pAncestor[i].has_prev = FALSE;
				m_pAncestor[i].has_next = FALSE;
				i--;
			}
		}
		m_pAncestor[0].has_prev = FALSE;
		m_pAncestor[0].has_next = FALSE;
        *pAncestor = m_pAncestor;
	}

    if ( pFlags ) *pFlags = m_MessageLine.flags;
    if ( pDepth ) *pDepth = m_MessageLine.level;
}

HFONT CMessageOutliner::GetLineFont ( void * )
{
    if ( m_MessageLine.flags & MSG_FLAG_EXPIRED )
        return m_hRegFont;

    return (!(m_MessageLine.flags & MSG_FLAG_READ) ? m_hBoldFont : m_hRegFont);
}

void CMessageOutliner::ReleaseLineData ( void * )
{
	delete [] m_pAncestor;
	m_pAncestor = NULL;
}

LPCTSTR CMessageOutliner::GetColumnText ( UINT iColumn, void * pLineData )
{
	LPTSTR buf;   // temporary buffer for mail header conversion (I18N)
    m_pszExtraText[ 0 ] = _T('\0');
	m_pszExtraText[ EXTRATEXT_SIZE - 1 ] = _T('\0');

    switch ( iColumn )
    {
        case ID_COLUMN_FROM:
			{
				buf = IntlDecodeMimePartIIStr(m_MessageLine.author, INTL_DocToWinCharSetID(m_iCSID), FALSE);
				if (buf)
				{
					_tcsncpy(m_pszExtraText, buf, EXTRATEXT_SIZE - 1);
					XP_FREE(buf);
					return m_pszExtraText;
				}
				return m_MessageLine.author;
			}
        case ID_COLUMN_SUBJECT:
		  	{ 
				CString cs = _T("");
            	if ( m_MessageLine.flags & MSG_FLAG_HAS_RE ) {
                    cs.LoadString(IDS_MAIL_RE);
				}
                _tcscpy ( m_pszExtraText, cs );
				buf = IntlDecodeMimePartIIStr(m_MessageLine.subject, INTL_DocToWinCharSetID(m_iCSID), FALSE);
				if (buf) {
                	_tcsncat ( m_pszExtraText, buf, 
							   EXTRATEXT_SIZE - cs.GetLength() - 1);
					XP_FREE(buf);
				} else {
                	_tcsncat ( m_pszExtraText, m_MessageLine.subject,
							   EXTRATEXT_SIZE - cs.GetLength() - 1);
				}
				return m_pszExtraText;
			}
        case ID_COLUMN_DATE:
            {
                if ( m_MessageLine.flags & MSG_FLAG_EXPIRED )
                    return _T("");
                _tcscpy ( m_pszExtraText, MSG_FormatDate(m_pPane,m_MessageLine.date));
                return m_pszExtraText;
            }
		case ID_COLUMN_PRIORITY:
			if ( m_MessageLine.priority != MSG_NoPriority && 
				 m_MessageLine.priority != MSG_PriorityNotSet &&
				 m_MessageLine.priority != MSG_NormalPriority) {
				MSG_GetPriorityName( m_MessageLine.priority, m_pszExtraText, MSG_FLAG_EXPIRED);
			}
			return m_pszExtraText;
		case ID_COLUMN_STATUS:
			if (m_MessageLine.flags & MSG_FLAG_NEW) {
				MSG_GetStatusName( MSG_FLAG_NEW,
								   m_pszExtraText, EXTRATEXT_SIZE);
				return m_pszExtraText;
			}
			if ( m_MessageLine.flags & MSG_FLAG_REPLIED &&
				 m_MessageLine.flags & MSG_FLAG_FORWARDED ) {
				MSG_GetStatusName( MSG_FLAG_REPLIED|MSG_FLAG_FORWARDED,
								   m_pszExtraText, EXTRATEXT_SIZE);
				return m_pszExtraText;
			}
			else if ( m_MessageLine.flags & MSG_FLAG_FORWARDED ) {
				MSG_GetStatusName( MSG_FLAG_FORWARDED,
								   m_pszExtraText, EXTRATEXT_SIZE);
				return m_pszExtraText;
			}
			else if ( m_MessageLine.flags & MSG_FLAG_REPLIED ) {
				MSG_GetStatusName( MSG_FLAG_REPLIED,
								   m_pszExtraText, EXTRATEXT_SIZE);
				return m_pszExtraText;
			}
			
			break;
		case ID_COLUMN_LENGTH:
			if (m_bNews) {
				_stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.messageLines );
			} else {
				_TCHAR cSuffix = _T(' ');
				int32 iSize = m_MessageLine.messageLines;
				if ( iSize > 1L<<30 ) {
					iSize /= 1L<<30;
					cSuffix = _T('G');
				} else if ( iSize > 1L<<20 ) {
					iSize /= 1L<<20;
					cSuffix = _T('M');
				} else if ( iSize > 1L<<10 ) {
					iSize /= 1L<<10;
					cSuffix = _T('K');
				} else {
					iSize = 1;
					cSuffix = _T('K');
				}
				_stprintf( m_pszExtraText, _T("%d%cB"), (int) iSize, cSuffix );
			}
			return m_pszExtraText;

		case ID_COLUMN_UNREAD:
			if (m_MessageLine.numNewChildren) {
				_stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.numNewChildren );
				return m_pszExtraText;
			}
			break;
		case ID_COLUMN_COUNT:
			if (m_MessageLine.numChildren) {
				_stprintf( m_pszExtraText, _T("%d"), (int) m_MessageLine.numChildren + 1 );
				return m_pszExtraText;
			}
			break;
    }
    return ("");
}

void CMessageOutliner::OnDestroy()
{
	if (m_uTimer)
	{
		KillTimer(m_uTimer);
		m_uTimer = 0;
	}
	CMailNewsOutliner::OnDestroy();
}

void CMessageOutliner::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bLButtonDown = TRUE;
	CMailNewsOutliner::OnLButtonDown(nFlags, point);
}

void CMessageOutliner::OnTimer(UINT nIDEvent)
{
	if (m_uTimer == nIDEvent)
	{
		if (m_bDoubleClicked)
		{
			m_bDoubleClicked = FALSE;
			KillTimer(m_uTimer);
			m_uTimer = 0;
		}
		else
		{
			UINT delta = GetTickCount() - m_dwPrevTime;
			if (delta > GetDoubleClickTime())
			{	// single click
				m_bSelChanged = FALSE;
				if (GetCurrentSelected() != m_iSelection)
				{
					if (!m_iSelBlock)
						GetParentFrame()->PostMessage(WM_COMMAND, ID_MESSAGE_SELECT, 0);
				}
				KillTimer(m_uTimer);
				m_uTimer = 0;
			}
		}
		m_bLButtonDown = FALSE;
	}
	else
		CMailNewsOutliner::OnTimer(nIDEvent);
}

void CMessageOutliner::OnSelChanged()
{
	SetCurrentSelected(m_iLastSelected);
	if (m_bLButtonDown && m_uTimer == 0 && !m_bDoubleClicked)
	{
		m_dwPrevTime = GetTickCount();
		UINT uElapse = GetDoubleClickTime() / 5;
		m_uTimer = SetTimer(DOUBLE_CLICK_TIMER, uElapse, NULL);
	}
	else
	{
		if (!m_bDoubleClicked)
		{
			m_bSelChanged = FALSE;   
			if (!m_iSelBlock)
				GetParentFrame()->PostMessage(WM_COMMAND, ID_MESSAGE_SELECT, 0);
		}
	}
}

void CMessageOutliner::OnSelDblClk()
{
	if (m_bLButtonDown && m_uTimer != 0)
		m_bDoubleClicked = TRUE;

	GetParentFrame()->PostMessage(WM_COMMAND, ID_FILE_OPENMESSAGE, 0);
}

BEGIN_MESSAGE_MAP(CMessageOutliner, CMailNewsOutliner)
	ON_WM_LBUTTONDOWN()
	ON_WM_TIMER()
	ON_WM_DESTROY()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFolderOutlinerParent

CFolderOutlinerParent::CFolderOutlinerParent()
{
	m_pUnkUserImage = NULL;
	ApiApiPtr(api);
	m_pUnkUserImage = api->CreateClassInstance(
		APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILCOL);
	m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
	ASSERT(m_pIUserImage);
	if (!m_pIUserImage->GetResourceID())
		m_pIUserImage->Initialize(IDB_MAILCOL,16,16);
}

CFolderOutlinerParent::~CFolderOutlinerParent()
{
    if (m_pUnkUserImage) {
        if (m_pIUserImage)
            m_pUnkUserImage->Release();
    }
}

COutliner * CFolderOutlinerParent::GetOutliner ( void )
{
    return new CFolderOutliner;
}

typedef struct COLUMNDESC {
	UINT idCol;
	UINT idTitle;
	int nWidth;
	BOOL bButton;
    Column_t styleColumn;
    CropType_t styleCrop;
	AlignType_t styleAlign;
} ColumnDesc_t;

static ColumnDesc_t aidFolderColumns[] = 
	{ { ID_COLUMN_FOLDER, IDS_MAIL_NAME,   6000, FALSE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_UNREAD, IDS_MAIL_UNREAD, 2000, FALSE, ColumnVariable, CropRight, AlignRight },
	  { ID_COLUMN_COUNT,  IDS_MAIL_TOTAL,  2000, FALSE, ColumnVariable, CropRight, AlignRight } };

void CFolderOutlinerParent::CreateColumns ( void )
{
	ColumnDesc_t *pColumns;
	int nColumns;
	int i;

	nColumns = sizeof( aidFolderColumns ) / sizeof ( ColumnDesc_t );
	pColumns = aidFolderColumns;

    CString cs;
	
	for ( i = 0; i < nColumns; i++ ) {
		int nMin = pColumns[i].styleColumn == ColumnFixed ? 20 : pColumns[i].nWidth;
		int nDefault = pColumns[i].nWidth;

		if ( pColumns[i].idTitle ) {
			cs.LoadString(pColumns[i].idTitle);
		} else {
			cs = _T("");
		}
		m_pOutliner->AddColumn ( cs, 
								 pColumns[i].idCol, 
								 nMin, 0, 
								 pColumns[i].styleColumn,
								 nDefault, 
								 pColumns[i].bButton, 
								 pColumns[i].styleCrop,
								 pColumns[i].styleAlign );
	}

	m_pOutliner->SetImageColumn( ID_COLUMN_FOLDER );

	if (((CFolderOutliner*)m_pOutliner)->IsParent3PaneFrame())
		m_pOutliner->LoadXPPrefs("mailnews.3Pane_folder_columns_win");
	else
		m_pOutliner->LoadXPPrefs("mailnews.folder_columns_win");
}

BEGIN_MESSAGE_MAP(CFolderOutlinerParent,COutlinerParent)
    ON_WM_DESTROY()
END_MESSAGE_MAP()

void CFolderOutlinerParent::OnDestroy()
{
	if (((CFolderOutliner*)m_pOutliner)->IsParent3PaneFrame())
		m_pOutliner->SaveXPPrefs("mailnews.3Pane_folder_columns_win");
	else
		m_pOutliner->SaveXPPrefs( "mailnews.folder_columns_win" );

	COutlinerParent::OnDestroy();
}

/////////////////////////////////////////////////////////////////////////////
// CMessageOutlinerParent

CMessageOutlinerParent::CMessageOutlinerParent()
{
	m_pUnkUserImage = NULL;
	ApiApiPtr(api);
	m_pUnkUserImage = api->CreateClassInstance(
		APICLASS_IMAGEMAP,NULL,(APISIGNATURE)IDB_MAILCOL);
	m_pUnkUserImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIUserImage);
	ASSERT(m_pIUserImage);
	if (!m_pIUserImage->GetResourceID())
		m_pIUserImage->Initialize(IDB_MAILCOL,16,16);
}

CMessageOutlinerParent::~CMessageOutlinerParent()
{
    if (m_pUnkUserImage) {
        if (m_pIUserImage)
            m_pUnkUserImage->Release();
    }
}

BOOL CMessageOutlinerParent::RenderData ( int idColumn, CRect & rect, CDC &dc, LPCTSTR text )
{
	MSG_Pane *pPane = ((CMailNewsOutliner *) m_pOutliner)->GetPane();
	ASSERT(pPane);
	MSG_COMMAND_CHECK_STATE sortType = MSG_Unchecked;

    switch (idColumn) {
        case ID_COLUMN_READ:
		case ID_COLUMN_THREAD:
		case ID_COLUMN_MARK:
			{
				int idxImage;
				switch (idColumn) {
				case ID_COLUMN_READ:
					idxImage = IDX_MAILUNREAD;
					break;
				case ID_COLUMN_THREAD:
					if (MSG_GetToggleStatus(pPane, MSG_SortByThread, NULL, 0) == MSG_Checked) {
						idxImage = IDX_THREAD;
					} else {
						idxImage = IDX_UNTHREAD;
					}
					break;
				case ID_COLUMN_MARK:
					idxImage = IDX_MAILMARKED;
					break;
				}
				m_pIUserImage->DrawTransImage( idxImage,
											   (rect.left + rect.right + 1) / 2 - 8,
											   (rect.top + rect.bottom + 1) / 2 - 8, &dc );
			}
		return TRUE;
        case ID_COLUMN_DATE:
            sortType = MSG_GetToggleStatus(pPane, MSG_SortByDate, NULL, 0);
            break;
        case ID_COLUMN_SUBJECT:
            sortType = MSG_GetToggleStatus(pPane, MSG_SortBySubject, NULL, 0);
            break;
        case ID_COLUMN_FROM:
            sortType = MSG_GetToggleStatus(pPane, MSG_SortBySender, NULL, 0);
            break;
		case ID_COLUMN_PRIORITY:
            sortType = MSG_GetToggleStatus(pPane, MSG_SortByPriority, NULL, 0);
            break;
		case ID_COLUMN_STATUS:
			sortType = MSG_GetToggleStatus(pPane, MSG_SortByStatus, NULL, 0);
			break;
		case ID_COLUMN_LENGTH:
			sortType = MSG_GetToggleStatus(pPane, MSG_SortBySize, NULL, 0);
			break;
		default:
			return FALSE;
    }

	UINT dwDTFormat = DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER;


	CString csTitle = text;
	if ( MSG_DisplayingRecipients( pPane ) && idColumn == ID_COLUMN_FROM ) {
		csTitle.LoadString( IDS_MAIL_RECIPIENT );
	}
	if ( idColumn == ID_COLUMN_LENGTH ) {
		dwDTFormat |= DT_RIGHT;
		if (!((CMessageOutliner *)m_pOutliner)->IsNews())
			csTitle.LoadString( IDS_SIZE );
	}

	RECT rectText = rect;
	rectText.left += COL_LEFT_MARGIN;
	rectText.right -= COL_LEFT_MARGIN + 1;

    if (sortType == MSG_Checked) {
		rectText.right -= 14;
		int idxImage;
		if (MSG_GetToggleStatus( pPane,MSG_SortBackward, NULL, 0) == MSG_Checked )
			idxImage = IDX_SORTINDICATORUP;
		else
			idxImage = IDX_SORTINDICATORDOWN;
        m_pIImage->DrawTransImage( idxImage,
								   rectText.right + 4,
								   (rect.top + rect.bottom) / 2 - 4,
								   &dc );
	}

	WFE_DrawTextEx( 0, dc.m_hDC, (LPTSTR) (LPCTSTR) csTitle, -1, 
					&rectText, dwDTFormat, WFE_DT_CROPRIGHT );

    return TRUE;
}

COutliner * CMessageOutlinerParent::GetOutliner ( void )
{
    return new CMessageOutliner;
}

static ColumnDesc_t aidMessageColumns[] = 
	{ { ID_COLUMN_THREAD,	0,				   24,   TRUE, ColumnFixed,    CropRight, AlignLeft },
	  { ID_COLUMN_SUBJECT,	IDS_MAIL_SUBJECT,  2500, TRUE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_READ,		0,				   24,   TRUE, ColumnFixed,	   CropRight, AlignLeft },
	  { ID_COLUMN_FROM,		IDS_MAIL_SENDER,   2500, TRUE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_DATE,		IDS_MAIL_DATE,	   1500, TRUE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_PRIORITY, IDS_MAIL_PRIORITY, 1000, TRUE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_MARK,		0,				   24,   TRUE, ColumnFixed,	   CropRight, AlignLeft },
	  { ID_COLUMN_STATUS,	IDS_MAIL_STATUS,   750,  TRUE, ColumnVariable, CropRight, AlignLeft },
	  { ID_COLUMN_LENGTH,	IDS_MAIL_LENGTH,   750,  TRUE, ColumnVariable, CropRight, AlignRight },
	  { ID_COLUMN_UNREAD,	IDS_MAIL_UNREAD,   500,  FALSE, ColumnVariable, CropRight, AlignRight },
	  { ID_COLUMN_COUNT,	IDS_MAIL_TOTAL,    500,  FALSE, ColumnVariable, CropRight, AlignRight } };

void CMessageOutlinerParent::CreateColumns ( void )
{
	ColumnDesc_t *pColumns;
	int nColumns;
	int i;

	nColumns = sizeof( aidMessageColumns ) / sizeof ( ColumnDesc_t );
	pColumns = aidMessageColumns;

    CString cs;
	
	for ( i = 0; i < nColumns; i++ ) {
		int nMin = pColumns[i].styleColumn == ColumnFixed ? 20 : pColumns[i].nWidth;
		int nDefault = pColumns[i].nWidth;

		if ( pColumns[i].idTitle ) {
			cs.LoadString(pColumns[i].idTitle);
		} else {
			cs = _T("");
		}
		m_pOutliner->AddColumn ( cs, 
								 pColumns[i].idCol, 
								 nMin, 0, 
								 pColumns[i].styleColumn,
								 nDefault, 
								 pColumns[i].bButton, 
								 pColumns[i].styleCrop,
								 pColumns[i].styleAlign );
	}

	m_pOutliner->SetVisibleColumns( 6 );
	m_pOutliner->SetImageColumn( ID_COLUMN_SUBJECT );

    if ( ((CMessageOutliner *) m_pOutliner)->IsNews() ) {
		m_pOutliner->LoadXPPrefs("news.thread_columns_win");
	} else {
		m_pOutliner->LoadXPPrefs("mail.thread_columns_win");
	}
 }

BOOL CMessageOutlinerParent::ColumnCommand ( int nColumn )
{
	UINT iCommand = 0;

    switch ( nColumn ) {
    case ID_COLUMN_FROM:
		iCommand = ID_SORT_BYSENDER;
        break;

    case ID_COLUMN_SUBJECT:
		iCommand = ID_SORT_BYSUBJECT;
        break;

    case ID_COLUMN_DATE:
		iCommand = ID_SORT_BYDATE;
        break;

	case ID_COLUMN_THREAD:
		iCommand = ID_SORT_BYTHREAD;
		break;

	case ID_COLUMN_PRIORITY:
		iCommand = ID_SORT_BYPRIORITY;
		break;

	case ID_COLUMN_STATUS:
		iCommand = ID_SORT_BYSTATUS;
		break;

	case ID_COLUMN_LENGTH:
		iCommand = ID_SORT_BYSIZE;
		break;

	case ID_COLUMN_MARK:
		iCommand = ID_SORT_BYFLAG;
		break;

	case ID_COLUMN_READ:
		iCommand = ID_SORT_BYUNREAD;
		break;
    }

	if ( iCommand ) {
	    SetCursor ( theApp.LoadStandardCursor ( IDC_WAIT ) );
		GetParentFrame()->SendMessage(WM_COMMAND, iCommand, 0 );
	    SetCursor ( theApp.LoadStandardCursor ( IDC_ARROW ) );
	}

    return 0;
}

BEGIN_MESSAGE_MAP(CMessageOutlinerParent,COutlinerParent)
    ON_WM_DESTROY()
END_MESSAGE_MAP()


void CMessageOutlinerParent::OnDestroy()
{
    if ( ((CMessageOutliner *) m_pOutliner)->IsNews() )
		m_pOutliner->SaveXPPrefs("news.thread_columns_win");
    else
		m_pOutliner->SaveXPPrefs("mail.thread_columns_win");

	COutlinerParent::OnDestroy();
}

//////////////////////////////////////////////////////////////////////////////
// CMarkReadDateDlg

BOOL CMarkReadDateDlg::OnInitDialog( )
{
	BOOL res = CDialog::OnInitDialog();

	wndDateTo.SubclassDlgItem(IDC_STATIC1, this);

	CTime timeTmp = CTime::GetCurrentTime();
	wndDateTo.SetDate( timeTmp );

	return res;
}

void CMarkReadDateDlg::OnOK()
{
	wndDateTo.GetDate(dateTo);
	CDialog::OnOK();
}


/////////////////////////////////////////////////////////////////////////////
// C function shared by CMailFolderHelper and preference

extern "C" void HelperInitFonts( HDC hdc , HFONT *phFont, HFONT *phBoldFont)
{
	uint16 csid = INTL_CharSetNameToID(INTL_ResourceCharSet());

    LOGFONT lf;							   
    memset(&lf,0,sizeof(LOGFONT));

    lf.lfPitchAndFamily = FF_SWISS;
	lf.lfCharSet = IntlGetLfCharset( csid );
	if ( csid == CS_LATIN1 )
 		_tcscpy( lf.lfFaceName, "MS Sans Serif" );
	else
 		_tcscpy( lf.lfFaceName, IntlGetUIPropFaceName( csid ) );
   	lf.lfHeight = -MulDiv( 9, ::GetDeviceCaps( hdc, LOGPIXELSY ), 72);
	*phFont = theApp.CreateAppFont( lf );
    lf.lfWeight = 700;
	*phBoldFont = theApp.CreateAppFont( lf );
}

extern "C" void HelperDoMeasureItem( HWND hWnd, LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
	lpMeasureItemStruct->itemHeight = 16;
}

extern "C" void HelperDoDrawItem
( HWND hWnd, LPDRAWITEMSTRUCT lpDrawItemStruct, HFONT *phFont, HFONT *phBoldFont,
  MSG_Master *pMaster, BOOL bStaticCtl, int iInitialDepth, LPIMAGEMAP pIImageMap, 
  BOOL bNoPrettyName)
{
	HDC hDC = lpDrawItemStruct->hDC;
	RECT rcItem = lpDrawItemStruct->rcItem;
	RECT rcTemp = rcItem;
	RECT rcText;
	DWORD dwItemData = lpDrawItemStruct->itemData;
	HBRUSH hBrushWindow = ::CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
	HBRUSH hBrushHigh = ::CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) );
	HBRUSH hBrushFill = NULL;

	if ( !*phFont ) {
		HelperInitFonts( hDC, phFont, phBoldFont);
	}

	HFONT hOldFont = NULL;
	if ( *phFont ) {
		hOldFont = (HFONT) ::SelectObject( hDC, *phFont );
	}

	if ( lpDrawItemStruct->itemState & ODS_SELECTED ) {
		hBrushFill = hBrushHigh;
		::SetBkColor( hDC, GetSysColor( COLOR_HIGHLIGHT ) );
		::SetTextColor( hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
	} else {
		hBrushFill = hBrushWindow;
		::SetBkColor( hDC, GetSysColor( COLOR_WINDOW ) );
		::SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );
	}

	VERIFY(::FillRect( hDC, &rcItem, hBrushWindow ));

	if ( lpDrawItemStruct->itemID != -1 &&  dwItemData ) {
		MSG_FolderInfo *folderInfo = (MSG_FolderInfo *) dwItemData;
		MSG_FolderLine folderLine;
		MSG_GetFolderLineById( pMaster, folderInfo, &folderLine);

		int idxImage = WFE_MSGTranslateFolderIcon( folderLine.level,
												   folderLine.flags, 
												   folderLine.numChildren );

		if ( *phBoldFont && folderLine.unseen > 0 ) {
			::SelectObject( hDC, *phBoldFont );
		}
		int iIndent = 4;

		BOOL bStatic = FALSE;
#ifdef _WIN32
	if ( sysInfo.m_bWin4 )
		bStatic = ( lpDrawItemStruct->itemState & ODS_COMBOBOXEDIT ) ? TRUE : FALSE;
	else 
#endif
		bStatic = bStaticCtl;

		if (!bStatic)
			iIndent += (folderLine.level - iInitialDepth) * 8;

        pIImageMap->DrawImage( idxImage, iIndent, rcItem.top, hDC, FALSE );

		LPCTSTR name;
		if (bNoPrettyName)
			name = folderLine.name;
		else
		{
			name = (LPCTSTR) folderLine.prettyName;
			if ( !name || !name[0] )
				name = folderLine.name;
		}

		::DrawText( hDC, name, -1, &rcTemp, DT_SINGLELINE|DT_CALCRECT|DT_NOPREFIX );
		int iWidth = rcTemp.right - rcTemp.left;

		rcTemp = rcItem;
		rcText = rcItem;
		rcTemp.left = iIndent + 20;
		rcTemp.right = rcTemp.left + iWidth + 4;
		if (rcTemp.right > rcItem.right)
			rcTemp.right = rcItem.right;

		VERIFY(::FillRect( hDC, &rcTemp, hBrushFill ));
		rcText.left = rcTemp.left + 2;
		rcText.right = rcTemp.right - 2;
		::DrawText( hDC, name, -1, &rcText, DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX );

		if ( lpDrawItemStruct->itemAction & ODA_FOCUS && 
			 lpDrawItemStruct->itemState & ODS_SELECTED ) {
			::DrawFocusRect( hDC, &rcTemp );
		}
	}
	if ( hBrushHigh ) 
		VERIFY( ::DeleteObject( hBrushHigh ));
	if ( hBrushWindow ) 
		VERIFY( ::DeleteObject( hBrushWindow ));

	if ( hOldFont )
		::SelectObject( hDC, hOldFont );
}

extern "C" void HelperSubPopulate
( HWND hWnd, int *pIndex, MSG_FolderInfo *folder, MSG_Master *pMaster, 
  UINT nAddString, UINT nSetItemData)
{
	int32 iLines = MSG_GetFolderChildren (pMaster, folder, NULL, 0);
	MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
	ASSERT(ppFolderInfo);
	if (ppFolderInfo)
	{
		MSG_GetFolderChildren (pMaster, folder, ppFolderInfo, iLines);
		for (int i = 0; i < iLines; i++)
		{
			MSG_FolderLine folderLine;
			if (MSG_GetFolderLineById (pMaster, ppFolderInfo[i], &folderLine)) {
				if ( !(folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) ||
					  (folderLine.flags & MSG_FOLDER_FLAG_CAT_CONTAINER)) {
					SendMessage( hWnd, nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
					SendMessage( hWnd, nSetItemData, (WPARAM) *pIndex, (LPARAM) folderLine.id );
					(*pIndex)++;
					if ( folderLine.numChildren > 0 ) {
						HelperSubPopulate( hWnd, pIndex, folderLine.id ,pMaster, nAddString, nSetItemData);
					}
				}
			}
		}
		delete [] ppFolderInfo;
	}
}

extern "C" int HelperPopulate
( HWND hWnd, MSG_Master *master, MSG_FolderInfo *mailRoot, MSG_Master **hMaster, 
  UINT nResetContent, int* piInitialDepth, UINT nAddString, UINT nSetItemData)
{
	*hMaster = master;
	int index = 0;

	*piInitialDepth = 1;

	SendMessage( hWnd, nResetContent, (WPARAM) 0, (LPARAM) 0 );

	if ( mailRoot ) {
		MSG_FolderLine folderLine;
		MSG_GetFolderLineById( master, mailRoot, &folderLine );
		*piInitialDepth = folderLine.level;
	}

	HelperSubPopulate( hWnd, &index, mailRoot, master, nAddString, nSetItemData);

	return 1;	
}


/////////////////////////////////////////////////////////////////////////////
// CMailFolderCombo, CMailFolderList

CMailFolderHelper::CMailFolderHelper( UINT nAddString, UINT nSetItemData, 
									  UINT nResetContent)
{
	m_bStaticCtl = FALSE;

	m_hFont = NULL;
	m_hBoldFont = NULL;

	m_nAddString = nAddString;
	m_nSetItemData = nSetItemData;
	m_nResetContent = nResetContent;

    ApiApiPtr(api);
    m_pIImageUnk = api->CreateClassInstance(APICLASS_IMAGEMAP);
	ASSERT(m_pIImageUnk);
    if (m_pIImageUnk) {
        m_pIImageUnk->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIImageMap);
        ASSERT(m_pIImageMap);
        m_pIImageMap->Initialize(IDB_MAILNEWS,16,16);
    }
}

CMailFolderHelper::~CMailFolderHelper()
{
	if (m_pIImageUnk && m_pIImageMap ) {
		m_pIImageUnk->Release();
	}
	if (m_hFont)
		theApp.ReleaseAppFont(m_hFont);
	if (m_hBoldFont)
		theApp.ReleaseAppFont(m_hBoldFont);
}

void CMailFolderHelper::InitFonts( HDC hdc )
{
	::HelperInitFonts(hdc, &m_hFont, &m_hBoldFont);
}

void CMailFolderHelper::DoMeasureItem( HWND hWnd, LPMEASUREITEMSTRUCT lpMeasureItemStruct )
{
	::HelperDoMeasureItem( hWnd, lpMeasureItemStruct );
}

void CMailFolderHelper::DoDrawItem( HWND hWnd, LPDRAWITEMSTRUCT lpDrawItemStruct, BOOL bNoPrettyName)
{
	::HelperDoDrawItem( hWnd, lpDrawItemStruct, &m_hFont, &m_hBoldFont,
					    m_pMaster, m_bStaticCtl, m_iInitialDepth, m_pIImageMap, bNoPrettyName);
}

void CMailFolderHelper::SubPopulate( HWND hWnd, int &index, MSG_FolderInfo *folder )
{
	HelperSubPopulate( hWnd, &index, folder, m_pMaster, m_nAddString, m_nSetItemData);
}

int CMailFolderHelper::Populate( HWND hWnd, MSG_Master *master, MSG_FolderInfo *mailRoot )
{
	return HelperPopulate( hWnd, master, mailRoot, &m_pMaster, m_nResetContent, 
		                   &m_iInitialDepth, m_nAddString, m_nSetItemData);
}

int CMailFolderHelper::PopulateMailServer( HWND hWnd, MSG_Master *master, BOOL bRoots)
{
	m_pMaster = master;
	int index = 0;

	m_iInitialDepth = 1;

	SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );

	int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
	MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
	ASSERT(ppFolderInfo);
	if (ppFolderInfo)
	{
		MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
		for (int i = 0; i < iLines; i++)
		{
			MSG_FolderLine folderLine;
			if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
				if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) {
					if ( bRoots ) {
						SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
						SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
						index++;
					}
				}
			}
		}
		delete [] ppFolderInfo;
	}

	return 1;	
}

int CMailFolderHelper::PopulateMail( HWND hWnd, MSG_Master *master, BOOL bRoots)
{
	m_pMaster = master;
	int index = 0;

	m_iInitialDepth = 1;

	SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );

	int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
	MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
	ASSERT(ppFolderInfo);
	if (ppFolderInfo)
	{
		MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
		for (int i = 0; i < iLines; i++)
		{
			MSG_FolderLine folderLine;
			if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
				if ( folderLine.flags & MSG_FOLDER_FLAG_MAIL ) {
					if ( bRoots ) {
						SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
						SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
						index++;
					}
					if ( folderLine.numChildren > 0 ) {
						SubPopulate( hWnd, index, ppFolderInfo[i] );
					}
				}
			}
		}
		delete [] ppFolderInfo;
	}

	return 1;	
}

int CMailFolderHelper::PopulateNews( HWND hWnd, MSG_Master *master, BOOL bRoots )
{
	m_pMaster = master;
	int index = 0;

	m_iInitialDepth = 1;

	SendMessage( hWnd, m_nResetContent, (WPARAM) 0, (LPARAM) 0 );

	int32 iLines = MSG_GetFolderChildren (m_pMaster, NULL, NULL, 0);
	MSG_FolderInfo **ppFolderInfo = new MSG_FolderInfo *[iLines];
	ASSERT(ppFolderInfo);
	if (ppFolderInfo)
	{
		MSG_GetFolderChildren (m_pMaster, NULL, ppFolderInfo, iLines);
		for (int i = 0; i < iLines; i++)
		{
			MSG_FolderLine folderLine;
			if (MSG_GetFolderLineById (m_pMaster, ppFolderInfo[i], &folderLine)) {
				if ( folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ||
					 folderLine.flags & MSG_FOLDER_FLAG_NEWS_HOST) 
				{
					if ( bRoots ) {
						SendMessage( hWnd, m_nAddString, (WPARAM) 0, (LPARAM) folderLine.name );
						SendMessage( hWnd, m_nSetItemData, (WPARAM) index, (LPARAM) folderLine.id );
						index++;
					}
					if ( folderLine.numChildren > 0 ) {
						SubPopulate( hWnd, index, ppFolderInfo[i] );
					}
				}
			}
		}
		delete ppFolderInfo;
	}

	return 1;	
}


#define NAV_BUTTONWIDTH		24
#define NAV_BUTTONHEIGHT	16

CNavCombo::CNavCombo()
{
	m_bFirst = TRUE;
	m_hFont = NULL;
	m_hBigFont = NULL;
}

CNavCombo::~CNavCombo()
{
}

void CNavCombo::SetFont( CFont *pFont, CFont *pBigFont )
{
	m_hFont = (HFONT) pFont->m_hObject;
	m_hBigFont = (HFONT) pBigFont->m_hObject;

	CMailFolderCombo::SetFont(pFont);
}

void CNavCombo::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
	BOOL bStatic = FALSE;

#ifdef _WIN32
	if ( sysInfo.m_bWin4 )
		bStatic = ( lpDrawItemStruct->itemState & ODS_COMBOBOXEDIT ) ? TRUE : FALSE;
	else 
#endif
		bStatic = m_bStaticCtl;

	if ( bStatic ) {
		HDC hdc = lpDrawItemStruct->hDC;
		RECT rect = lpDrawItemStruct->rcItem; 

		COLORREF oldText;
		COLORREF oldBk;
		if ( lpDrawItemStruct->itemState & ODS_SELECTED ) {
			oldText = ::SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
			oldBk = ::SetBkColor( hdc, GetSysColor(COLOR_HIGHLIGHT));
		} else {
			oldText = ::SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) );
			oldBk = ::SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
		}
		HFONT hOldFont = (HFONT) ::SelectObject( hdc, m_hBigFont );

		MSG_FolderInfo *itemData = (MSG_FolderInfo *) lpDrawItemStruct->itemData;

		if ( (lpDrawItemStruct->itemID != (UINT) -1) && itemData ) {
			MSG_FolderLine folderLine;
			MSG_GetFolderLineById( m_pMaster, itemData, &folderLine);
			
			rect.left += 4;

			LPCTSTR name = (LPCTSTR) folderLine.prettyName;
			if ( !name || !name[0] )
				name = folderLine.name;

			CIntlWin::DrawText( 0, hdc, (LPSTR) name, -1, &rect,
								  DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX );
		}

		if ( hOldFont )
			::SelectObject( hdc, hOldFont );

		::SetTextColor( hdc, oldText );
		::SetBkColor(hdc, oldText);
	} else {
		CMailFolderCombo::DrawItem( lpDrawItemStruct );
	}
}

BEGIN_MESSAGE_MAP( CNavCombo, CMailFolderCombo )
	ON_WM_CTLCOLOR()
	ON_WM_PAINT()
END_MESSAGE_MAP()

void CNavCombo::OnPaint()
{
	m_bStaticCtl = TRUE;
	CMailFolderCombo::OnPaint();
	m_bFirst = TRUE;
}

HBRUSH CNavCombo::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor )
{
	if (nCtlColor == CTLCOLOR_LISTBOX) {
		if (m_bFirst) {
			RECT rcParent;
			GetWindowRect( &rcParent );
			pWnd->GetWindowRect(&m_rcList);
			m_bFirst = FALSE;
			int height = m_rcList.bottom - m_rcList.top;
			if ( (rcParent.bottom + height) > GetSystemMetrics( SM_CYFULLSCREEN ) ) {
				height = GetSystemMetrics( SM_CYFULLSCREEN ) - rcParent.bottom;
			}
			pWnd->MoveWindow( m_rcList.left, rcParent.bottom,
							  m_rcList.right - m_rcList.left, height );
		}
	}

	m_bStaticCtl = (nCtlColor == CTLCOLOR_EDIT);

	return CMailFolderCombo::OnCtlColor( pDC, pWnd, nCtlColor );
}

///////////////////////////////////////////////////////////////////////
// CLinkDropSource

class CLinkDropSource: public COleDropSource
{
protected:
	virtual SCODE GiveFeedback( DROPEFFECT dropEffect );
};

SCODE CLinkDropSource::GiveFeedback( DROPEFFECT dropEffect )
{
	if ( !(dropEffect & (DROPEFFECT_COPY|DROPEFFECT_MOVE)) ) {
		return COleDropSource::GiveFeedback( dropEffect );
	} else {
		::SetCursor( ::LoadCursor( AfxGetResourceHandle(), 
								   MAKEINTRESOURCE( dropEffect & DROPEFFECT_COPY ?
												    IDC_LINK_COPY : IDC_LINK_MOVE ) ) );
		return NOERROR;
	}
}

///////////////////////////////////////////////////////////////////////
// CMailInfoBar

CMailInfoBar::CMailInfoBar()
{
	m_bEraseBackground = TRUE;

	m_idxImage = 0;
	m_pUnkImage = NULL;

	ApiApiPtr(api);
	m_pUnkImage = api->CreateClassInstance( APICLASS_IMAGEMAP,
											NULL, 
											(APISIGNATURE)IDB_MAILNEWS);
	m_pUnkImage->QueryInterface(IID_IImageMap,(LPVOID*)&m_pIImage);
	ASSERT(m_pIImage);
	if (!m_pIImage->GetResourceID())
		m_pIImage->Initialize(IDB_MAILNEWS,16,16);

	m_hbmBanner = NULL;
	m_hFont = NULL;
	m_hBoldFont = NULL;
	m_hIntlFont = NULL;
	m_hBoldIntlFont = NULL;
}

CMailInfoBar::~CMailInfoBar()
{
    if (m_pUnkImage) {
        if (m_pIImage)
            m_pUnkImage->Release();
    }
	if (m_hbmBanner)
		VERIFY(::DeleteObject( m_hbmBanner ));

	if (m_hFont) {
		theApp.ReleaseAppFont(m_hFont);
	}
	if (m_hBoldFont) {
		theApp.ReleaseAppFont(m_hBoldFont);
	}
	if (m_hIntlFont) {
		theApp.ReleaseAppFont(m_hIntlFont);
	}
	if (m_hBoldIntlFont) {
		theApp.ReleaseAppFont(m_hBoldIntlFont);
	}
}

void CMailInfoBar::SetCSID( int csid )
{

	if (m_hFont) {
		theApp.ReleaseAppFont(m_hFont);
	}
	if (m_hBoldFont) {
		theApp.ReleaseAppFont(m_hBoldFont);
	}
	if (m_hIntlFont) {
		theApp.ReleaseAppFont(m_hIntlFont);
	}
	if (m_hBoldIntlFont) {
		theApp.ReleaseAppFont(m_hBoldIntlFont);
	}

	CClientDC dc(this);
	m_iCSID = csid;
	int16 defCSID = INTL_CharSetNameToID(INTL_ResourceCharSet());

    LOGFONT lf;
    memset( &lf, 0, sizeof(LOGFONT) );

    lf.lfPitchAndFamily = FF_SWISS;
	lf.lfCharSet = IntlGetLfCharset(defCSID);
	if (defCSID == CS_LATIN1)
 		_tcscpy(lf.lfFaceName, "MS Sans Serif");
	else
 		_tcscpy(lf.lfFaceName, IntlGetUIPropFaceName(defCSID));

   	lf.lfHeight = -MulDiv( 9, dc.GetDeviceCaps(LOGPIXELSY), 72 );
    lf.lfWeight = 0;
	m_hFont = theApp.CreateAppFont( lf );
   	lf.lfHeight = -MulDiv( 10, dc.GetDeviceCaps(LOGPIXELSY), 72 );
    lf.lfWeight = 700;
	m_hBoldFont = theApp.CreateAppFont( lf );
	lf.lfCharSet = IntlGetLfCharset(csid);
	if (csid == CS_LATIN1)
 		_tcscpy(lf.lfFaceName, "MS Sans Serif");
	else
 		_tcscpy(lf.lfFaceName, IntlGetUIPropFaceName(csid));

   	lf.lfHeight = -MulDiv( 9, dc.GetDeviceCaps(LOGPIXELSY), 72 );
    lf.lfWeight = 0;
	m_hIntlFont = theApp.CreateAppFont( lf );
   	lf.lfHeight = -MulDiv( 10, dc.GetDeviceCaps(LOGPIXELSY), 72 );
    lf.lfWeight = 700;
	m_hBoldIntlFont = theApp.CreateAppFont( lf );

	Invalidate();
}

BOOL CMailInfoBar::Create( CWnd *pWnd, MSG_Pane *pPane )
{
	m_pPane = pPane;

	ASSERT( pWnd && pWnd->IsKindOf( RUNTIME_CLASS(CFrameWnd) ));

	DWORD dwStyle = WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|CBRS_TOP;
	UINT nID = AFX_IDW_CONTROLBAR_FIRST + 0x7e;
	
	LPCTSTR lpszClass = AfxRegisterWndClass( 0, ::LoadCursor( NULL, IDC_ARROW) );

#ifdef _WIN32
	m_dwStyle = dwStyle;
#endif

	BOOL res = CControlBar::Create( lpszClass, _T("InfoBar"), dwStyle, 
									CRect(0,0,0,0), pWnd, nID);

	if (res) {
		SetCSID( INTL_DefaultWinCharSetID(0) );
#ifndef _WIN32
		m_sizeFixedLayout = CalcFixedLayout(TRUE, TRUE);
#endif
	}
	return res;
}

void CMailInfoBar::OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler )
{
}

CSize CMailInfoBar::CalcFixedLayout( BOOL bStretch, BOOL bHorz )
{
	ASSERT( bHorz ); // No vertical, No way

	HDC hDC = ::GetDC( m_hWnd );
	HFONT hOldFont = (HFONT) ::SelectObject( hDC, m_hBoldFont);

	TEXTMETRIC tm;
	GetTextMetrics( hDC, &tm);
	
	::SelectObject( hDC, hOldFont );
	::ReleaseDC( m_hWnd, hDC );

	int iHeight = (tm.tmHeight > 20 ? tm.tmHeight : 20 ) + 4;

	return CSize( 32767, iHeight );
}

BOOL CMailInfoBar::PreTranslateMessage( MSG *pMsg )
{
	if (pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
		m_wndToolTip.RelayEvent( pMsg );

    return CControlBar::PreTranslateMessage( pMsg );
}

void CMailInfoBar::PaintBackground( HDC hDC )
{
	RECT rect;
	GetClientRect( &rect );

	::FillRect( hDC, &rect, sysInfo.m_hbrBtnFace );
}

void CMailInfoBar::DrawInfoText( int iCSID, HDC hDC, LPCSTR lpszText, LPRECT lpRect )
{
	WFE_DrawTextEx( iCSID, hDC, (LPSTR) lpszText, -1, lpRect,
					DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX,
					WFE_DT_CROPRIGHT );
}

void CMailInfoBar::DrawInfoText( HDC hDC, LPCSTR lpszText, LPRECT lpRect )
{
	int16 resCsid = INTL_CharSetNameToID(INTL_ResourceCharSet());
	DrawInfoText( resCsid, hDC, lpszText, lpRect );
}

void CMailInfoBar::MeasureInfoText( int iCSID, HDC hDC, LPCSTR lpszText, LPRECT lpRect )
{
	CIntlWin::DrawText( iCSID, hDC, (LPSTR) lpszText, -1, lpRect, DT_LEFT|DT_SINGLELINE|DT_CALCRECT );
}

void CMailInfoBar::MeasureInfoText( HDC hDC, LPCSTR lpszText, LPRECT lpRect )
{
	int16 resCsid = INTL_CharSetNameToID(INTL_ResourceCharSet());
	MeasureInfoText( resCsid, hDC, lpszText, lpRect );
}

void CMailInfoBar::DragProxie()
{
}

BEGIN_MESSAGE_MAP( CMailInfoBar, CControlBar )
	ON_WM_CREATE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_SHOWWINDOW()
	ON_WM_ERASEBKGND()
	ON_WM_SETCURSOR()
END_MESSAGE_MAP()

int CMailInfoBar::OnCreate(LPCREATESTRUCT lpcs)
{
	int res = CControlBar::OnCreate(lpcs);
	if (res != -1) {
		m_wndToolTip.Create(this, TTS_ALWAYSTIP);
		m_wndToolTip.Activate(TRUE);
	}
	return res;
}
void CMailInfoBar::OnLButtonDown( UINT nFlags, CPoint point )
{
	RECT rect;
	GetClientRect(&rect);
	rect.right = 22;

	if (PtInRect(&rect, point)) {
		DragProxie();
	}
	else{
		// Send this message to the customizable toolbar for dragging
		MapWindowPoints(GetParent(), &point, 1);
		GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
	}

}

void CMailInfoBar::OnLButtonUp( UINT nFlags, CPoint point )
{
	RECT rect;
	GetClientRect(&rect);
	rect.right = 22;

	if (!PtInRect(&rect, point)) {
		// Send this message to the customizable toolbar for dragging
		MapWindowPoints(GetParent(), &point, 1);
		GetParent()->SendMessage(WM_LBUTTONUP, nFlags, MAKELPARAM(point.x, point.y));

	}
	
}

void CMailInfoBar::OnMouseMove( UINT nFlags, CPoint point )
{
	RECT rect;
	GetClientRect(&rect);
	rect.right = 22;

	if (!PtInRect(&rect, point)) {
		// Send this message to the customizable toolbar for dragging
		MapWindowPoints(GetParent(), &point, 1);
		GetParent()->SendMessage(WM_MOUSEMOVE, nFlags, MAKELPARAM(point.x, point.y));
	}

}

void CMailInfoBar::OnShowWindow( BOOL bShow, UINT nStatus )
{
	m_bEraseBackground |= bShow;
}

BOOL CMailInfoBar::OnEraseBkgnd( CDC* pDC )
{
	if ( m_bEraseBackground ) {
		PaintBackground( pDC->m_hDC );
		m_bEraseBackground = FALSE;
	}

	return TRUE;
}

BOOL CMailInfoBar::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
{
	POINT pt;
	RECT rect;
	GetWindowRect(&rect);
	if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
		rect.left += 30;
	rect.right = rect.left + 22;
	GetCursorPos( &pt );

	if ( nHitTest == HTCLIENT && ::PtInRect( &rect, pt ) ) {
		::SetCursor( ::LoadCursor( AfxGetResourceHandle(), MAKEINTRESOURCE(IDC_HANDOPEN) ) );
		return TRUE;
	}

	return CControlBar::OnSetCursor( pWnd, nHitTest, message );
}

/////////////////////////////////////////////////////////////////////
//
// CContainerInfoBar
//
// Info Bar for the Folder Window

void CContainerInfoBar::Update()
{
	LPCSTR szUser = FE_UsersFullName();
	if ( szUser ) {
		m_csBanner.Format( szLoadString( IDS_MAIL_MYCONTAINERS ), szUser);
	} else {
		m_csBanner.LoadString(IDS_MAIL_CONTAINERS);
	}
}

void CContainerInfoBar::DragProxie()
{
	URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );
	if ( url ) {
		COleDataSource *pDataSource = new COleDataSource;
		RDFGLOBAL_DragTitleAndURL( pDataSource, m_csBanner, url->address );
		COleDropSource *pDropSource = new CLinkDropSource;
		DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
												  DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
												  CRect( 0, 0, 0, 0),
												  pDropSource );
		pDataSource->Empty();
		delete pDataSource;
		delete pDropSource;
		NET_FreeURLStruct( url );
	}
}

BEGIN_MESSAGE_MAP( CContainerInfoBar, CMailInfoBar )
	ON_WM_CREATE()
	ON_WM_PAINT()
END_MESSAGE_MAP()

int CContainerInfoBar::OnCreate(LPCREATESTRUCT lpcs)
{
	int res = CMailInfoBar::OnCreate(lpcs);
	if (res != -1) {
		RECT rect;
		SetRectEmpty(&rect);
		m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
	}
	return res;
}
void CContainerInfoBar::OnPaint( )
{
	CPaintDC dc(this);
	CRect rect;
	GetClientRect( &rect );

	PaintBackground( dc.m_hDC );

    m_pIImage->DrawTransImage( IDX_COLLECTION,
							   2,
							   rect.bottom / 2 - 8,
							   &dc );

	RECT rcTool;
	::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
	m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);

	int oldMode = dc.SetBkMode( TRANSPARENT );
	HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldFont );

	int iWidth = rect.right - rect.left;
	rect.left += 22;

	DrawInfoText( dc.m_hDC, m_csBanner, &rect );

	dc.SetBkMode( oldMode );
	dc.SelectObject( hOldFont );
}

///////////////////////////////////////////////////////////////////////
//
// CFolderInfoBar
//
// Info Bar for the Thread Window

CFolderInfoBar::CFolderInfoBar()
{
	m_folderOld = NULL;
}

CFolderInfoBar::~CFolderInfoBar()
{
}

void CFolderInfoBar::SetCSID( int csid )
{
	CMailInfoBar::SetCSID( csid );
	m_wndNavButton.SetFont( CFont::FromHandle( m_hFont ), CFont::FromHandle( m_hBoldFont ) );
}

void CFolderInfoBar::Update()
{
	if (m_pPane) {
		MSG_FolderLine folderLine;
		MSG_FolderInfo *folderInfo = NULL;

		if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
		{
			if (((C3PaneMailFrame*)GetParentFrame())->GetSelectedFolder(&folderLine))
				folderInfo = folderLine.id;
		}
		if (!folderInfo)
			folderInfo = MSG_GetCurFolder( m_pPane );
		if (folderInfo) {
			MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
			if (folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) {
				folderInfo = MSG_GetCategoryContainerForCategory(folderInfo);
				MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
			}

			if ( folderInfo != m_folderOld ) {
				m_wndNavButton.Populate( WFE_MSGGetMaster(), NULL );
				m_wndNavButton.SetCurSel(0);
				for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
					if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == folderInfo ) {
						m_wndNavButton.SetCurSel(i);
						break;
					}
				}
			}

			m_csFolderName = folderLine.prettyName && folderLine.prettyName[0] ?
							 folderLine.prettyName : folderLine.name;

			if (folderLine.flags & MSG_FOLDER_FLAG_CATEGORY) {
				if (folderLine.deepUnseen >= 0) {
					m_csFolderCounts.Format(szLoadString(IDS_FOLDERCOUNTS),
											(int32) folderLine.deepTotal, 
											(int32) folderLine.deepUnseen);
				} else {
					m_csFolderCounts.LoadString(IDS_FOLDERUNKNOWNCOUNTS);
				}
			} else {
				if (folderLine.unseen >= 0) {
					m_csFolderCounts.Format(szLoadString(IDS_FOLDERCOUNTS),
											(int32) folderLine.total, 
											(int32) folderLine.unseen);
				} else {
					m_csFolderCounts.LoadString(IDS_FOLDERUNKNOWNCOUNTS);
				}
			}

			m_idxImage = WFE_MSGTranslateFolderIcon( folderLine.level, 
													 folderLine.flags,
													 FALSE );
			m_folderOld = folderInfo;
		} else {
			m_csFolderName = "";
			m_csFolderCounts = "";
		}
	}
	Invalidate();
	UpdateWindow();
}

void CFolderInfoBar::DragProxie()
{
	URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );
	if ( url ) {
		
		COleDataSource *pDataSource = new COleDataSource;
		RDFGLOBAL_DragTitleAndURL( pDataSource, m_csFolderName, url->address );
		COleDropSource *pDropSource = new CLinkDropSource;
		DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
												  DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
												  CRect( 0, 0, 0, 0),
												  pDropSource );
		pDataSource->Empty();
		delete pDataSource;
		delete pDropSource;
		NET_FreeURLStruct( url );
	}
}

BEGIN_MESSAGE_MAP( CFolderInfoBar, CMailInfoBar )
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_CBN_DROPDOWN(101, OnDropDown)
	ON_CBN_SELENDOK(101, OnCloseUp)
	ON_BN_CLICKED(102, OnContainer )
	ON_COMMAND( ID_BUTTON_CONTAINER, OnContainer )
END_MESSAGE_MAP()

int CFolderInfoBar::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	int res = CMailInfoBar::OnCreate( lpCreateStruct );

	if ( res != -1 ) {
		DWORD dwStyle = 0;

		dwStyle = WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_OWNERDRAWFIXED|CBS_DROPDOWNLIST;

		m_wndNavButton.Create( dwStyle, CRect(22,3,250,480), this, 101 );
		
		CString csFull, csLabel, csTip, csStatus;
		WFE_ParseButtonString( ID_NAVIGATE_CONTAINER, csStatus, csTip, csLabel );

		m_wndBackButton.Create( this, FALSE, CSize(20,20), CSize(20,20), 
								csLabel, csTip, csStatus,
								IDB_BACK, 0, CSize(16,16), 
								ID_BUTTON_CONTAINER, 0, 0 );

		m_wndBackButton.SetActionMessageOwner(this);
		RECT rect;
		SetRectEmpty(&rect);
		m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
	}
	return res;
}	

void CFolderInfoBar::OnSize( UINT nType, int cx, int cy )
{
	if ( nType != SIZE_MINIMIZED ) {
		m_wndBackButton.MoveWindow( cx - 22, 3, 22, cy - 6 );
	}
}

void CFolderInfoBar::OnDropDown()
{
	// Folder Structure might have changed, rebuild.
	m_wndNavButton.Populate( WFE_MSGGetMaster(), NULL );
	m_wndNavButton.SetCurSel(0);
	for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
		if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == m_folderOld ) {
			m_wndNavButton.SetCurSel(i);
			break;
		}
	}
}

void CFolderInfoBar::OnCloseUp()
{
	int iCurSel = m_wndNavButton.GetCurSel();
	m_wndNavButton.m_bFirst = TRUE;

	MSG_FolderInfo *folderInfo = (MSG_FolderInfo *) m_wndNavButton.GetItemData(iCurSel);
	MSG_FolderLine folderLine;
	if ( m_folderOld != folderInfo ) {

		CMsgListFrame* pFrame = C3PaneMailFrame::FindFrame( folderInfo );
		if ( pFrame ) {
			pFrame->ActivateFrame();
		} else {
			if ( !MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine ) ) {
				ASSERT(0); // Shouldn't happen
				return;
			}

			// User selected a folder
			pFrame = (CMsgListFrame *) GetParentFrame();
			ASSERT(pFrame && pFrame->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)));
			if (pFrame->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
			{
				// bounce focus back to frame
				((C3PaneMailFrame*)pFrame)->UpdateFolderPane(folderInfo);
				pFrame->SetFocus();
				return;
			} 
			else 
			{
				if ( folderLine.level > 1 )  
					CFolderFrame::Open( folderInfo );
			}
		}

		// Since we didn't change, reselect our folder
		m_wndNavButton.SetCurSel(0);
		for ( int i = 0; i < m_wndNavButton.GetCount(); i++ ) {
			if ( (MSG_FolderInfo *) m_wndNavButton.GetItemData(i) == m_folderOld ) {
				m_wndNavButton.SetCurSel(i);
				break;
			}
		}
	}
}

void CFolderInfoBar::OnContainer()
{
	GetParentFrame()->PostMessage( WM_COMMAND, (WPARAM) ID_NAVIGATE_CONTAINER );
}

void CFolderInfoBar::OnPaint( )
{
	CPaintDC dc(this);
	CRect rect;
	GetClientRect( &rect );

	PaintBackground( dc.m_hDC );

	m_pIImage->DrawTransImage( m_idxImage,
							   2,
							   rect.bottom / 2 - 8,
							   &dc );

	RECT rcTool;
	::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
	m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);

	int oldMode = dc.SetBkMode( TRANSPARENT );
	HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldFont );

	dc.SelectObject( m_hFont );

	RECT rcText;
	MeasureInfoText( dc.m_hDC, m_csFolderCounts, &rcText);
	int iCountsWidth = rcText.right - rcText.left;

	rect.left = rect.right - iCountsWidth - 32;
	rect.right -= 32;

	DrawInfoText( dc.m_hDC, m_csFolderCounts, &rect );

	dc.SetBkMode( oldMode );
	dc.SelectObject( hOldFont );

	m_wndNavButton.UpdateWindow();
}

///////////////////////////////////////////////////////////////////////
//
// CMessageInfoBar
//
// Info Bar for the Message Window

CMessageInfoBar::CMessageInfoBar()
{
	m_csFolderTip = "";
	m_csFolderStatus = "";
}

CMessageInfoBar::~CMessageInfoBar()
{
}

void CMessageInfoBar::SetCSID( int csid )
{
	CMailInfoBar::SetCSID( csid );
	Update();
}

void CMessageInfoBar::Update()
{
	if (m_pPane) {
		MSG_FolderInfo *folderInfo;
		MessageKey key;
		MSG_ViewIndex index;
		MSG_GetCurMessage( m_pPane, &folderInfo, &key, &index);
		if (folderInfo) {
			MSG_FolderLine folderLine;
			MSG_GetFolderLineById( WFE_MSGGetMaster(), folderInfo, &folderLine );
			m_idxImage = folderLine.flags & MSG_FOLDER_FLAG_NEWSGROUP ? 
						 IDX_NEWSARTICLE :
						 IDX_MAILREAD;
			m_csFolderTip = folderLine.name;
			m_csFolderStatus.Format(szLoadString(IDS_OPEN_STRING), folderLine.name);
		} else {
			m_idxImage = 0;
		}
		if ( key != MSG_MESSAGEKEYNONE ) {
			LPTSTR buf; 
			MSG_MessageLine messageLine;
			MSG_GetThreadLineById( m_pPane, key, &messageLine );
			buf = IntlDecodeMimePartIIStr( messageLine.subject, INTL_DocToWinCharSetID(m_iCSID), FALSE );
			if ( buf ) {
				m_csMessageName = buf;
				XP_FREE(buf);
			} else {
				m_csMessageName = messageLine.subject;
			}
			buf = IntlDecodeMimePartIIStr( messageLine.author, INTL_DocToWinCharSetID(m_iCSID), FALSE );
			if ( buf ) {
				m_csMessageAuthor = buf;
				XP_FREE(buf);
			} else {
				m_csMessageAuthor = messageLine.author;
			}
		} else {
			m_csMessageName = "";
			m_csMessageAuthor = "";
		}
	}
	Invalidate();
}

void CMessageInfoBar::DragProxie()
{
	URL_Struct *url = MSG_ConstructUrlForPane( m_pPane );

	if ( url ) {
		
		COleDataSource *pDataSource = new COleDataSource;
		RDFGLOBAL_DragTitleAndURL( pDataSource, m_csMessageName, url->address );
		COleDropSource *pDropSource = new CLinkDropSource;
		DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_LINK|
												  DROPEFFECT_MOVE|DROPEFFECT_SCROLL,
												  CRect( 0, 0, 0, 0),
												  pDropSource );
		pDataSource->Empty();
		delete pDataSource;
		delete pDropSource;

		NET_FreeURLStruct( url );
	}
}

BEGIN_MESSAGE_MAP( CMessageInfoBar, CMailInfoBar )
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_BN_CLICKED( 102, OnContainer )
	ON_COMMAND( ID_BUTTON_CONTAINER, OnContainer )
END_MESSAGE_MAP()

int CMessageInfoBar::OnCreate( LPCREATESTRUCT lpCreateStruct )
{
	int res = CMailInfoBar::OnCreate( lpCreateStruct );
	if ( res != -1 ) {
		CString csFull, csLabel, csTip, csStatus;
		WFE_ParseButtonString( ID_NAVIGATE_MSGCONTAINER, csStatus, csTip, csLabel );
		m_wndBackButton.Create( this, FALSE, CSize(20,20), CSize(20,20), 
								csLabel, csTip, csStatus,
								IDB_BACK, 0, CSize(16,16), 
								ID_BUTTON_CONTAINER, 0, TB_DYNAMIC_TOOLTIP );

		m_wndBackButton.SetActionMessageOwner(this);

		RECT rect;
		SetRectEmpty(&rect);
		m_wndToolTip.AddTool(this, IDS_PROXIE_FOLDERS, &rect, IDS_PROXIE_FOLDERS);
	}

	return res;
}
		
void CMessageInfoBar::OnSize( UINT nType, int cx, int cy )
{
	if ( nType != SIZE_MINIMIZED ) {
		m_wndBackButton.MoveWindow( cx - 22, 3, 22, cy - 6 );
	}
}

void CMessageInfoBar::OnPaint( )
{
	CPaintDC dc(this);
	CRect rect;
	GetClientRect( &rect );

	PaintBackground( dc.m_hDC );

    m_pIImage->DrawTransImage( m_idxImage,
							   2,
							   rect.bottom / 2 - 8,
							   &dc );

	RECT rcTool;
	::SetRect(&rcTool, 2, rect.bottom / 2 - 8, 18, rect.bottom / 2 + 8);
	m_wndToolTip.SetToolRect(this, IDS_PROXIE_FOLDERS, &rcTool);

	int oldMode = dc.SetBkMode( TRANSPARENT );
	HFONT hOldFont = (HFONT) dc.SelectObject( m_hBoldIntlFont );

	int iWidth = rect.right - rect.left;
	rect.left += 22;
	rect.right = 22 + iWidth / 2;

	DrawInfoText( m_iCSID, dc.m_hDC, m_csMessageName, &rect );

	dc.SelectObject( m_hIntlFont );
	rect.left = rect.right;
	rect.right = iWidth;

	DrawInfoText( m_iCSID, dc.m_hDC, m_csMessageAuthor, &rect );

	dc.SetBkMode( oldMode );
	dc.SelectObject( hOldFont );
}

void CMessageInfoBar::OnContainer()
{
	GetParentFrame()->PostMessage( WM_COMMAND, (WPARAM) ID_NAVIGATE_CONTAINER );
}

///////////////////////////////////////////////////////////////////////

