/* -*- 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 "nsadrlst.h" #include "namcomp.h" #ifdef __APIAPIDLL #include "festuff.h" #else #include "compstd.h" #endif #include "resource.h" #include "addrfrm.h" //to get MOZ_NEWADDR #include "wfemsg.h" #include "intl_csi.h" #define IDM_HEADER 8192 #define MAX_HEADER_ITEMS 20 CListNameCompletionCX::CListNameCompletionCX(CListNameCompletionEntryList *pOwnerList) : CStubsCX(AddressCX, MWContextAddressBook) { m_pOwnerList = pOwnerList; m_lPercent = 0; m_bAnimated = FALSE; } void CListNameCompletionCX::SetOwnerList(CListNameCompletionEntryList *pOwnerList) { m_pOwnerList = pOwnerList; } void CListNameCompletionCX::SetProgressBarPercent(MWContext *pContext, int32 lPercent ) { // Ensure the safety of the value. lPercent = lPercent < 0 ? 0 : ( lPercent > 100 ? 100 : lPercent ); if ( m_lPercent == lPercent ) { return; } m_lPercent = lPercent; if (m_pOwnerList) { m_pOwnerList->SetProgressBarPercent(lPercent); } } void CListNameCompletionCX::Progress(MWContext *pContext, const char *pMessage) { if ( m_pOwnerList ) { m_pOwnerList->SetStatusText(pMessage); } } int32 CListNameCompletionCX::QueryProgressPercent() { return m_lPercent; } void CListNameCompletionCX::AllConnectionsComplete(MWContext *pContext) { // Call the base. CStubsCX::AllConnectionsComplete(pContext); // Also, we can clear the progress bar now. m_lPercent = 0; if ( m_pOwnerList ) { m_pOwnerList->SetProgressBarPercent(m_lPercent); m_pOwnerList->AllConnectionsComplete(pContext); } if (m_pOwnerList) { CWnd *pOwnerWindow = m_pOwnerList->GetOwnerWindow(); if(pOwnerWindow) { pOwnerWindow->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0); } } } void CListNameCompletionCX::UpdateStopState( MWContext *pContext ) { if (m_pOwnerList) { CWnd *pOwnerWindow = m_pOwnerList->GetOwnerWindow(); if(pOwnerWindow) { pOwnerWindow->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0); } } } CWnd *CListNameCompletionCX::GetDialogOwner() const { return m_pOwnerList->GetOwnerWindow(); } ///////////////////////////////////////////////////////////////////////////// // CListNameCompletionEntryList STDMETHODIMP CListNameCompletionEntryList::QueryInterface(REFIID refiid, LPVOID * ppv) { *ppv = NULL; if (IsEqualIID(refiid,IID_IUnknown)) *ppv = (LPUNKNOWN) this; else if (IsEqualIID(refiid,IID_IMsgList)) *ppv = (LPMSGLIST) this; else if (IsEqualIID(refiid,IID_IMailFrame)) *ppv = (LPMAILFRAME) m_pMailFrame; if (*ppv != NULL) { AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CListNameCompletionEntryList::AddRef(void) { return ++m_ulRefCount; } STDMETHODIMP_(ULONG) CListNameCompletionEntryList::Release(void) { ULONG ulRef; ulRef = --m_ulRefCount; if (m_ulRefCount == 0) delete this; return ulRef; } void CListNameCompletionEntryList::ListChangeStarting( MSG_Pane* pane, XP_Bool asynchronous, MSG_NOTIFY_CODE notify, MSG_ViewIndex where, int32 num) { } void CListNameCompletionEntryList::ListChangeFinished( MSG_Pane* pane, XP_Bool asynchronous, MSG_NOTIFY_CODE notify, MSG_ViewIndex where, int32 num) { switch ( notify ) { case MSG_NotifyInsertOrDelete: // if its insert or delete then tell my frame to add the next chunk of values // from the search if (notify == MSG_NotifyInsertOrDelete && num > 0) { if(m_bSearching) { AB_LDAPSearchResultsAB2(m_pPickerPane, where, num); } } else { } break; } } void CListNameCompletionEntryList::GetSelection( MSG_Pane* pane, MSG_ViewIndex **indices, int *count, int *focus) { } void CListNameCompletionEntryList::SelectItem( MSG_Pane* pane, int item ) { } void CListNameCompletionEntryList::SetProgressBarPercent(int32 lPercent) { m_pList->SetProgressBarPercent(lPercent); } void CListNameCompletionEntryList::SetStatusText(const char* pMessage) { m_pList->SetStatusText(pMessage); } void CListNameCompletionEntryList::AllConnectionsComplete(MWContext *pContext) { /* PerformDirectorySearch(); int total = m_pOutliner->GetTotalLines(); CString csStatus; if ( total > 1 ) { csStatus.Format( szLoadString( IDS_SEARCHHITS ), total ); } else if ( total > 0 ) { csStatus.LoadString( IDS_SEARCHONEHIT ); } else { csStatus.LoadString( IDS_SEARCHNOHITS ); } m_barStatus.SetWindowText( csStatus ); SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, (LPARAM)0); */ CAddrFrame::HandleErrorReturn(AB_FinishSearchAB2(m_pPickerPane)); } CWnd *CListNameCompletionEntryList::GetOwnerWindow() { return m_pList->GetOwnerWindow(); } STDMETHODIMP CListNameCompletionEntryMailFrame::QueryInterface(REFIID refiid, LPVOID * ppv) { *ppv = NULL; if (IsEqualIID(refiid,IID_IUnknown)) *ppv = (LPUNKNOWN) this; else if (IsEqualIID(refiid,IID_IMailFrame)) *ppv = (LPMAILFRAME) this; if (*ppv != NULL) { AddRef(); return NOERROR; } return ResultFromScode(E_NOINTERFACE); } STDMETHODIMP_(ULONG) CListNameCompletionEntryMailFrame::AddRef(void) { return 0; } STDMETHODIMP_(ULONG) CListNameCompletionEntryMailFrame::Release(void) { return 0; } // IMailFrame interface CMailNewsFrame *CListNameCompletionEntryMailFrame::GetMailNewsFrame() { return (CMailNewsFrame *) NULL; } MSG_Pane *CListNameCompletionEntryMailFrame::GetPane() { return (MSG_Pane*) m_pParentList->m_pPickerPane; } void CListNameCompletionEntryMailFrame::PaneChanged(MSG_Pane *pane, XP_Bool asynchronous, MSG_PANE_CHANGED_NOTIFY_CODE notify, int32 value) { if (notify == MSG_PaneNotifyStartSearching) { m_pParentList->m_bSearching = TRUE; m_pParentList->m_pList->SearchStarted(); // m_barStatus.StartAnimation(); } else if(notify == MSG_PaneNotifyStopSearching ) { m_pParentList->m_bSearching = FALSE; m_pParentList->m_pList->SearchStopped(); // m_barStatus.StopAnimation(); } } //============================================================ CNSAddressList CNSAddressList::CNSAddressList() { m_hPenNormal = ::CreatePen(PS_SOLID,0,GetSysColor(COLOR_WINDOW)); m_hPenGrid = ::CreatePen(PS_SOLID,0,RGB(202,202,255)); m_hPenGrey = ::CreatePen(PS_SOLID, 0, RGB(202,202,255)); m_hBrushNormal = ::CreateSolidBrush(GetSysColor(COLOR_WINDOW)); m_lastIndex = 0; m_iDefaultBitmapId = 0; m_bDrawTypeList = FALSE; m_bArrowDown = FALSE; m_iFieldControlWidth = 0; m_iBitmapWidth = 0; m_iTypeBitmapWidth = 0; m_pNameField = new CNSAddressNameEditField(this); m_pAddressTypeList = new CNSAddressTypeControl; m_iItemHeight = 0; m_pIAddressParent = NULL; m_bCreated = FALSE; m_hTextFont = NULL; m_bParse = TRUE; m_bDragging = FALSE; m_pContext = NULL; m_pCX = new CListNameCompletionCX(NULL); INTL_CharSetInfo csi; csi = LO_GetDocumentCharacterSetInfo(m_pCX->GetContext()); m_pCX->GetContext()->type = MWContextAddressBook; m_pCX->GetContext()->fancyFTP = TRUE; m_pCX->GetContext()->fancyNews = TRUE; m_pCX->GetContext()->intrupt = FALSE; m_pCX->GetContext()->reSize = FALSE; INTL_SetCSIWinCSID(csi, CIntlWin::GetSystemLocaleCsid()); m_pPickerPane = NULL; m_bExpansion = TRUE; #ifdef MOZ_NEWADDR int result; result = AB_CreateABPickerPane(&m_pPickerPane, m_pCX->GetContext(), WFE_MSGGetMaster(), 1); CListNameCompletionEntryList* pInstance = new CListNameCompletionEntryList(m_pPickerPane, this); pInstance->QueryInterface( IID_IMsgList, (LPVOID *) &m_pINameCompList ); MSG_SetFEData( (MSG_Pane*) m_pPickerPane, (LPVOID) (LPUNKNOWN) (LPMAILFRAME) m_pINameCompList ); m_pCX->SetOwnerList(pInstance); #endif } LRESULT CNSAddressList::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_ERASEBKGND: return DoEraseBkgnd(m_hWnd,(HDC)wParam); case WM_SETFOCUS: CListBox::DefWindowProc(message,wParam,lParam); DoSetFocus((HWND)wParam); return 0; case WM_KILLFOCUS: DoKillFocus((HWND)wParam); break; case WM_LBUTTONDOWN: { POINT point; CListBox::DefWindowProc(message,wParam,lParam); point.x = LOWORD(lParam); // horizontal position of cursor point.y = HIWORD(lParam); // vertical position of cursor DoLButtonDown(m_hWnd,wParam,&point); } return 0; case WM_LBUTTONUP: { POINT point; CListBox::DefWindowProc(message,wParam,lParam); point.x = LOWORD(lParam); // horizontal position of cursor point.y = HIWORD(lParam); // vertical position of cursor DoLButtonUp(m_hWnd,wParam,&point); } return 0; case WM_VSCROLL: { CListBox::DefWindowProc(message,wParam,lParam); int nScrollCode = (int) LOWORD(wParam); // scroll bar value int nPos = (short int) HIWORD(wParam); // scroll box position DoVScroll(m_hWnd, nScrollCode, nPos); } return 0; case WM_CHILDLOSTFOCUS: DoChildLostFocus(); return 0; case WM_NOTIFYSELECTIONCHANGE: return (DoNotifySelectionChange(FALSE)); case WM_DISPLAYTYPELIST: DoDisplayTypeList(); return 0; case WM_COMMAND: #ifdef XP_WIN16 if (HIWORD(lParam) == EN_CHANGE) #else if (HIWORD(wParam) == EN_CHANGE) #endif { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); pAddress->SetExpansion(TRUE); } if (DoCommand(m_hWnd,wParam,lParam)) return 0; break; case WM_GETDLGCODE: return DLGC_WANTTAB | DLGC_WANTARROWS; case WM_KEYDOWN: onKeyDown((int)wParam, (DWORD)lParam); break; case WM_MOUSEMOVE: onMouseMove(m_hWnd, (WORD)wParam, (int)LOWORD(lParam), (int)HIWORD(lParam)); break; } return CListBox::DefWindowProc(message,wParam,lParam); } void CNSAddressList::EnableParsing(BOOL bParse) { m_bParse = bParse; } BOOL CNSAddressList::GetEnableParsing() { return m_bParse; } void CNSAddressList::EnableExpansion(BOOL bExpansion) { m_bExpansion = bExpansion; } BOOL CNSAddressList::GetEnableExpansion() { return m_bExpansion; } void CNSAddressList::SetControlParent(LPADDRESSPARENT pIAddressParent) { m_pIAddressParent = pIAddressParent; ASSERT(m_pNameField); m_pNameField->SetControlParent(pIAddressParent); } //=========================================================== ~CNSAddressList CNSAddressList::~CNSAddressList() { if (m_hTextFont) { theApp.ReleaseAppFont(m_hTextFont); } if (m_hPenNormal != NULL) ::DeleteObject((HGDIOBJ)m_hPenNormal); if (m_hPenGrid != NULL) ::DeleteObject((HGDIOBJ)m_hPenGrid); if (m_hBrushNormal != NULL) ::DeleteObject((HGDIOBJ)m_hBrushNormal); if (m_hPenGrey != NULL) ::DeleteObject((HGDIOBJ)m_hPenGrey); delete m_pAddressTypeList; delete m_pNameField; if(!m_pCX->IsDestroyed()) { m_pCX->DestroyContext(); } #ifdef MOZ_NEWADDR if(m_pPickerPane) { AB_ClosePane(m_pPickerPane); } m_pINameCompList->Release(); #endif } BOOL CNSAddressList::DoCommand( HWND hwnd, WPARAM wParam, LPARAM lParam ) { #ifdef XP_WIN16 if (HIWORD(lParam) == EN_SETFOCUS) #else if (HIWORD(wParam) == EN_SETFOCUS) #endif { selectAllEntries(FALSE); return TRUE; } #ifdef XP_WIN16 if (HIWORD(lParam) == EN_CHANGE) #else if (HIWORD(wParam) == EN_CHANGE) #endif { UpdateHeaderContents(); return TRUE; } #ifdef XP_WIN16 else if (HIWORD(lParam) == LBN_SELCHANGE) #else else if (HIWORD(wParam) == LBN_SELCHANGE) #endif { UpdateHeaderType(); return TRUE; } #ifdef XP_WIN16 else if (wParam >= IDM_HEADER && wParam <= IDM_HEADER+MAX_HEADER_ITEMS) { HeaderCommand(wParam-IDM_HEADER); return TRUE; } #else else if (!HIWORD(wParam) && // zero if from a menu. (LOWORD(wParam) >= IDM_HEADER && LOWORD(wParam) <= IDM_HEADER+MAX_HEADER_ITEMS)) { HeaderCommand(LOWORD(wParam)-IDM_HEADER); return TRUE; } #endif return FALSE; } int CNSAddressList::SetActiveSelection(int nSelect) { if (GetActiveSelection() != nSelect) return SetCurSel(nSelect); return nSelect; } BOOL CNSAddressList::Create(CWnd *pParent, int id) { RECT rect; ::GetClientRect(pParent->m_hWnd, &rect); BOOL bRetVal = CListBox::Create( WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE|WS_VSCROLL| LBS_HASSTRINGS|LBS_OWNERDRAWFIXED|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT|LBS_NOINTEGRALHEIGHT, rect,pParent,id); m_bCreated = TRUE; return bRetVal; } //=============================================================== SetSel int CNSAddressList::SetSel(int nIndex, BOOL bSelect) { int result; if (bSelect) { result = SetActiveSelection(nIndex); m_pNameField->SetSel(0,-1,TRUE); } else { result = SetActiveSelection(-1); m_pNameField->SetSel(-1,0,TRUE); } Invalidate(); return result; } //=============================================================== AppendEntry int CNSAddressList::AppendEntry( NSAddressListEntry *pAddressEntry, BOOL expandName ) { SetActiveSelection(-1); return InsertEntry( (int)-1, pAddressEntry, expandName ); } //=============================================================== InsertEntry int CNSAddressList::InsertEntry( int nIndex, NSAddressListEntry *pAddressEntry, BOOL expandName ) { if (pAddressEntry && pAddressEntry->szName && strlen(pAddressEntry->szName)) { if (m_bDrawTypeList) { if (pAddressEntry->szType && strlen(pAddressEntry->szType)) { int iPos; ASSERT(m_pAddressTypeList); if ((iPos =m_pAddressTypeList->FindStringExact(-1,pAddressEntry->szType))!=LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iPos); ASSERT(pInfo); if (pInfo->GetExclusive()) { CString cs; cs = pInfo->GetValue(); if (cs.GetLength()) { cs += ","; cs += pAddressEntry->szName; } else cs = pAddressEntry->szName; pInfo->SetValue(cs); } if (pInfo->GetHidden()) return LB_ERR; } } } if (GetActiveSelection()!=LB_ERR && !m_pNameField->LineLength()) { NSAddressListEntry pTemp; GetEntry(GetActiveSelection(),&pTemp); if (!pTemp.szName||!strlen(pTemp.szName)) { SetEntry(GetActiveSelection(),pAddressEntry); CRect rect; GetItemRect(m_hWnd, GetActiveSelection(),&rect); InvalidateRect(rect); m_pNameField->SetFocus(); return GetActiveSelection(); } } } CNSAddressInfo *pAddress = new CNSAddressInfo; if ( pAddressEntry == NULL) { // Default to callback provided bitmap and the first // address type in the address type list. if (m_bDrawTypeList) { CString cs; int index = GetCount(); if (index > 0 && index != LB_ERR) { CNSAddressInfo *pLastAddress = (CNSAddressInfo *)GetItemDataPtr(index-1); cs = pLastAddress->GetType(); int index = m_pAddressTypeList->FindStringExact(-1,cs); if (index != LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(index); ASSERT(pInfo); if (pInfo->GetExclusive()) m_pAddressTypeList->GetText(index, cs); } } else { m_pAddressTypeList->GetText(0, cs); } pAddress->SetType(cs); pAddress->SetBitmap(0); pAddress->SetEntryID(); pAddress->SetName(""); } #ifdef MOZ_NEWADDR pAddress->SetPickerPane(m_pPickerPane); #endif } else { if (m_bDrawTypeList) { BOOL bFound = FALSE; for (int i = 0; i < m_pAddressTypeList->GetCount(); i++) { CString cs; m_pAddressTypeList->GetText(i,cs); if (cs == pAddressEntry->szType) { bFound = TRUE; m_pAddressTypeList->SetCurSel(i); break; } } if (!bFound) { delete pAddress; return (int)LB_ERR; } } pAddress->SetType(pAddressEntry->szType); pAddress->SetName(pAddressEntry->szName); pAddress->SetBitmap(pAddressEntry->idBitmap); pAddress->SetEntryID(pAddressEntry->idEntry); #ifdef MOZ_NEWADDR pAddress->SetPickerPane(m_pPickerPane); #endif } int index = InsertString( nIndex, (LPCTSTR)pAddress ); if ( index < 0 ) return FALSE; SetItemDataPtr( index, pAddress ); // this ensures that there will always be a selected line if there are entries if ( (GetCount() == 1) || (GetActiveSelection() == LB_ERR) ) { SetActiveSelection( 0 ); UpdateHeaderType(); UpdateHeaderContents(); } CRect WindowRect, ItemRect; GetWindowRect(WindowRect); if (m_pIAddressParent && expandName) m_pIAddressParent->AddedItem(m_hWnd, 0, index); SetActiveSelection(index); return index; } //================================================================== SetEntry void CNSAddressList::SetCSID( int16 csid ) { if(m_hWnd) { HDC hDC = ::GetDC(m_hWnd); LOGFONT lf; memset(&lf,0,sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH; strcpy(lf.lfFaceName, IntlGetUIFixFaceName(csid)); lf.lfHeight = -MulDiv(NS_ADDRESSFONTSIZE,::GetDeviceCaps(hDC,LOGPIXELSY),72); lf.lfQuality = PROOF_QUALITY; lf.lfCharSet = IntlGetLfCharset(csid); m_hTextFont = theApp.CreateAppFont( lf); ::SendMessage(GetSafeHwnd(), WM_SETFONT, (WPARAM)m_hTextFont, FALSE); ::ReleaseDC(m_hWnd,hDC); } if(m_pNameField) m_pNameField->SetCSID(csid); } //==================================================================ShowNameCompletionPicker void CNSAddressList::ShowNameCompletionPicker(CWnd* pParent) { CString name; //Stop the current name completion StopNameCompletion(); //turn parsing and expansion off while we have dialog up BOOL pOldParse = GetEnableParsing(); BOOL pOldExpansion = GetEnableExpansion(); EnableParsing(FALSE); EnableExpansion(FALSE); CEdit *pNameField = GetAddressNameField(); if(pNameField) { pNameField->GetWindowText(name); CNameCompletion dialog( name, pParent); int result = dialog.DoModal(); //reset parsing and expansion state. EnableParsing(pOldParse); EnableExpansion(pOldExpansion); if(result == IDOK) { AB_NameCompletionCookie *pCookie = dialog.GetNameCompletionCookie(); if(pCookie) { SetNameCompletionCookieInfo(pCookie, 1, NC_NameComplete); DoNotifySelectionChange(); } if ((GetActiveSelection()+1 == GetCount())) { // don't add a second blank line if ( m_pNameField->LineLength() != 0 ) { // add the new address entry to the list InsertEntry( GetActiveSelection()+1,NULL); } } SetActiveSelection( GetActiveSelection()+1 ); pNameField->SetFocus(); } if(result == IDCANCEL) { //they have chosen not to accept a result so they have //turned of name completion until they type something again. SetNameCompletionCookieInfo(NULL, 0, NC_NameComplete); pNameField->SetFocus(); } } } //=================================================================NameCompletionExit int NameCompletionExit(AB_NameCompletionCookie *cookie, int numResults, void *FEcookie) { if(FEcookie) { FENameCompletionCookieInfo *pCookieInfo = (FENameCompletionCookieInfo*)FEcookie; CNSAddressList *pList = pCookieInfo->GetList(); int nIndex = pCookieInfo->GetIndex(); if(pList) { pList->SetNameCompletionCookieInfo(cookie, numResults, NC_NameComplete, nIndex ); //how do we make correct name show up correctly? CNSAddressNameEditField * nameField = (CNSAddressNameEditField *)pList->GetAddressNameField(); nameField->DrawNameCompletion(); } } return 0; } int NameExpansionExit(AB_NameCompletionCookie *cookie, int numResults, void *FEcookie) { if(FEcookie) { FENameCompletionCookieInfo *pCookieInfo = (FENameCompletionCookieInfo*)FEcookie; CNSAddressList *pList = pCookieInfo->GetList(); int nIndex = pCookieInfo->GetIndex(); if(pList) { pList->SetNameCompletionCookieInfo(cookie, numResults, NC_Expand, nIndex ); } } return 0; } //=================================================================StartNameCompletion void CNSAddressList::StartNameCompletion(int nIndex) { CString text; m_pNameField->GetWindowText(text); int result; if(nIndex != -1 && (nIndex < 0 || nIndex >= GetCount())) { return; } if(nIndex == -1) nIndex = GetActiveSelection(); if(nIndex != LB_ERR) { //dont do if name completion is turned off for this index CNSAddressInfo *info = (CNSAddressInfo*)GetItemDataPtr(nIndex); if(info->GetNameCompletionEnum() != NC_None) { FENameCompletionCookieInfo *pCookieInfo = new FENameCompletionCookieInfo(); pCookieInfo->SetList(this); pCookieInfo->SetIndex(nIndex); if(info) { #ifdef FE_IMPLEMENTS_VISIBLE_NC result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) text, NameCompletionExit, FALSE, pCookieInfo); #else result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) text, NameCompletionExit, pCookieInfo); #endif } } } } //=================================================================StopNameCompletion void CNSAddressList::StopNameCompletion(int nIndex, BOOL bEraseCookie) { CString text; int result; if(nIndex != -1 && (nIndex < 0 || nIndex >= GetCount())) { return; } if(nIndex == -1) nIndex = GetActiveSelection(); if(nIndex != LB_ERR) { CNSAddressInfo *info = (CNSAddressInfo*)GetItemDataPtr(nIndex); if(bEraseCookie) { AB_NameCompletionCookie *pOldCookie = info->GetNameCompletionCookie(); if(pOldCookie) { AB_FreeNameCompletionCookie(pOldCookie); } info->SetNameCompletionCookie(NULL); info->SetNumNameCompletionResults(-1); } //make sure m_pNameField doesn't keep setting timer off m_pNameField->StopNameCompletion(); if(info) { #ifdef FE_IMPLEMENTS_VISIBLE_NC result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) NULL, NameCompletionExit, FALSE, NULL); #else result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) NULL, NameCompletionExit, NULL); #endif } } } //=================================================================StartNameExpansion void CNSAddressList::StartNameExpansion(int nIndex) { CString text; m_pNameField->GetWindowText(text); int result; if(nIndex != -1 && (nIndex < 0 || nIndex >= GetCount())) { return; } if(nIndex == -1) nIndex = GetActiveSelection(); if(nIndex != LB_ERR) { CNSAddressInfo *info = (CNSAddressInfo*)GetItemDataPtr(nIndex); FENameCompletionCookieInfo *pCookieInfo = new FENameCompletionCookieInfo(); pCookieInfo->SetList(this); pCookieInfo->SetIndex(nIndex); if(info) { #ifdef FE_IMPLEMENTS_VISIBLE_NC result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) text, NameExpansionExit, FALSE, pCookieInfo); #else result = AB_NameCompletionSearch(info->GetPickerPane(), (const char*) text, NameExpansionExit, pCookieInfo); #endif } } } //================================================================== SetEntryHasNameCompletion void CNSAddressList::SetEntryHasNameCompletion(BOOL bHasNameCompletion, int nIndex) { if(nIndex != -1 && (nIndex < 0 || nIndex >= GetCount())) { return; } if(nIndex == -1) { nIndex = GetActiveSelection(); } if(nIndex != LB_ERR) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); if(bHasNameCompletion) { pAddress->SetNameCompletionEnum(NC_NameComplete); StartNameCompletion(nIndex); } else { pAddress->SetNameCompletionEnum(NC_None); StopNameCompletion(nIndex); Invalidate(); } } } //================================================================== GetEntryHasNameCompletion BOOL CNSAddressList::GetEntryHasNameCompletion(int nIndex) { if(nIndex != -1 && (nIndex < 0 || nIndex >= GetCount())) { return FALSE; } if(nIndex == -1) { nIndex = GetActiveSelection(); } if(nIndex != LB_ERR) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); return (pAddress->GetNameCompletionEnum() != NC_None); } return FALSE; } //================================================================== SetContext void CNSAddressList::SetContext(MWContext *pContext) { m_pContext = pContext; } //================================================================== GetContext MWContext *CNSAddressList::GetContext() { return m_pContext; } //==============================================SetNameCompletionCookieInfo void CNSAddressList::SetNameCompletionCookieInfo(AB_NameCompletionCookie *pCookie, int nNumResults, NameCompletionEnum ncEnum, int nIndex) { if(nIndex != -1 && nIndex < 0 && nIndex > GetCount()) { return; } if(nIndex == -1) { nIndex = GetActiveSelection(); } if(nIndex != LB_ERR) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); AB_NameCompletionCookie *pOldCookie = pAddress->GetNameCompletionCookie(); if(pOldCookie != NULL && pOldCookie == pCookie) { int i = 0; } if(pOldCookie) { AB_FreeNameCompletionCookie(pOldCookie); } pAddress->SetNameCompletionCookie(pCookie); pAddress->SetNumNameCompletionResults(nNumResults); pAddress->SetNameCompletionEnum(ncEnum); //if we are supposed to expand then expand the address if(ncEnum == NC_Expand) { if(pCookie != NULL && nNumResults == 1) { char *pName = AB_GetHeaderString(pCookie); pAddress->SetName(pName); XP_FREE(pName); Invalidate(); } } } } void CNSAddressList::GetNameCompletionCookieInfo(AB_NameCompletionCookie **pCookie, int *pNumResults, int nIndex) { *pCookie = NULL; *pNumResults = 0; if(nIndex != -1 && nIndex < 0 && nIndex > GetCount()) { return; } if(nIndex == -1) { nIndex = GetActiveSelection(); } if(nIndex != LB_ERR) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); *pCookie = pAddress->GetNameCompletionCookie(); *pNumResults = pAddress->GetNumNameCompletionResults(); } } //================================================================== SearchStarted void CNSAddressList::SearchStarted() { if(m_pIAddressParent) { m_pIAddressParent->StartNameCompletionSearch(); } } //================================================================== SearchStopped void CNSAddressList::SearchStopped() { if(m_pIAddressParent) { m_pIAddressParent->StopNameCompletionSearch(); } } void CNSAddressList::SetProgressBarPercent(int32 lPercent) { if(m_pIAddressParent) { m_pIAddressParent->SetProgressBarPercent(lPercent); } } void CNSAddressList::SetStatusText(const char* pMessage) { if(m_pIAddressParent) { m_pIAddressParent->SetStatusText(pMessage); } } CWnd *CNSAddressList::GetOwnerWindow() { if(m_pIAddressParent) { return m_pIAddressParent->GetOwnerWindow(); } return NULL; } //================================================================== SetEntry BOOL CNSAddressList::SetEntry( int nIndex, NSAddressListEntry *pNewAddressEntry ) { // sanity checks if ( (int)nIndex >= GetCount() ) return FALSE; if (m_bDrawTypeList) if (IsWindow(m_pAddressTypeList->m_hWnd)) if ( m_pAddressTypeList->FindStringExact( -1, pNewAddressEntry->szType ) == LB_ERR ) return FALSE; // update entry CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetType(pNewAddressEntry->szType); pAddress->SetName(pNewAddressEntry->szName); pAddress->SetBitmap(pNewAddressEntry->idBitmap); pAddress->SetEntryID(pNewAddressEntry->idEntry); unsigned long entryID = 0; UINT bitmapID = 0; char * pszFullName = NULL; #ifdef MOZ_NEWADDR //since we just changed the name up there we should notify parent. m_pIAddressParent->ChangedItem((char*)pNewAddressEntry->szName, nIndex, m_hWnd, &pszFullName, &entryID, &bitmapID); #endif if (m_pIAddressParent) { NSAddressListEntry entry; BOOL bRetVal = GetEntry(nIndex,&entry); if (bRetVal) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); if (pAddress && pAddress->GetExpansion()) { BOOL bExpand = TRUE; if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); bExpand = pInfo->GetExpand(); } if (bExpand && m_bExpansion) { #ifdef MOZ_NEWADDR AB_NameCompletionCookie *pCookie = pAddress->GetNameCompletionCookie(); int nNumResults = pAddress->GetNumNameCompletionResults(); BOOL bExpandName = FALSE; if(pCookie != NULL && nNumResults == 1) { pszFullName = AB_GetHeaderString(pCookie); } //if we have multiple matches and preference is set. else if(pCookie != NULL && nNumResults > 1 && g_MsgPrefs.m_bShowCompletionPicker) { ShowNameCompletionPicker(this); return TRUE; } else { pszFullName = XP_STRDUP((char*)entry.szName); } //since we just changed the name, we need to notify parent. m_pIAddressParent->ChangedItem((char*)entry.szName, nIndex, m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(GetActiveSelection(), bitmapID); if (entryID) SetItemEntryID(GetActiveSelection(), entryID); free(pszFullName); } #else m_pIAddressParent->ChangedItem((char*)entry.szName, nIndex, m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(nIndex, bitmapID); if (entryID) SetItemEntryID(nIndex, entryID); free(pszFullName); } #endif } } } } return TRUE; } //================================================================== GetEntry BOOL CNSAddressList::GetEntry( int nIndex, NSAddressListEntry *pAddressEntry ) { if ( (int)nIndex >= GetCount() ) return FALSE; // fill out the NSAddressListEntry to return it to the caller CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); if ( pAddress == (CNSAddressInfo *)-1 || !pAddress->GetName()) return FALSE; pAddressEntry->szType = pAddress->GetType(); pAddressEntry->szName = pAddress->GetName(); pAddressEntry->idBitmap = pAddress->GetBitmap(); pAddressEntry->idEntry = pAddress->GetEntryID(); return TRUE; } BOOL CNSAddressList::RemoveSelection(int nIndex) { if (nIndex == -1) { int iSel = GetActiveSelection(); if (iSel != LB_ERR) return DeleteEntry(iSel); return FALSE; } return DeleteEntry(nIndex); } //=============================================================== DeleteEntry BOOL CNSAddressList::DeleteEntry( int nIndex ) { // sanity check if( (int)nIndex >= GetCount() ) return FALSE; if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); if (pInfo) { if (pInfo->GetExclusive()) pInfo->SetValue(NULL); } } if(m_bDrawTypeList) { if (GetCount() == 1) { m_pNameField->SetWindowText(""); UpdateHeaderContents(); if (m_pIAddressParent) m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex); return FALSE; } } // handle selection if deleting selected address if ( (int)nIndex == GetActiveSelection() ) { // delete only entry? if ( GetCount() == 1 ) { if (m_bDrawTypeList) m_pAddressTypeList->ShowWindow( SW_HIDE ); m_pNameField->ShowWindow( SW_HIDE ); } else if ( nIndex > 0 ) { SetActiveSelection(nIndex-1); } } // delete this entry if ( DeleteString( nIndex ) == LB_ERR ) return FALSE; if (m_pIAddressParent) m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex); return TRUE; } //================================================================= FindEntry int CNSAddressList::FindEntry( int nStart, LPCTSTR lpszName ) { CNSAddressInfo *pAddress; if ( nStart == (int)-1 ) nStart = 0; for ( int i = nStart; i < GetCount(); i++ ) { pAddress = (CNSAddressInfo *)GetItemDataPtr(i); if (pAddress->GetName()) if ( strcmp( pAddress->GetName(), lpszName ) == 0 ) return i; } return (int)LB_ERR; } BOOL CNSAddressList::AddAddressType( char * pszChoice, UINT pidBitmap, BOOL bExpand, BOOL bHidden, BOOL bExclusive, DWORD dwUserData) { // Create the ComboBox if necessary if (pszChoice != NULL) { if ( !IsWindow( m_pAddressTypeList->m_hWnd ) ) VERIFY( m_pAddressTypeList->Create( this ) ); // create the edit field if necessary int position = m_pAddressTypeList->InsertString( -1, pszChoice ); if (position == LB_ERR) return FALSE; CNSAddressTypeInfo * pInfo = new CNSAddressTypeInfo(pidBitmap,bHidden,bExclusive,dwUserData,bExpand); if (pInfo == NULL) return FALSE; m_pAddressTypeList->SetItemData(position,(DWORD)pInfo); m_bDrawTypeList = TRUE; if (m_pAddressTypeList->GetCurSel()==LB_ERR) m_pAddressTypeList->SetCurSel(0); } if ( !IsWindow( m_pNameField->m_hWnd ) ) VERIFY( m_pNameField->Create( this, m_pContext ) ); return TRUE; } //==================================================== GetAddressTypeComboBox CListBox * CNSAddressList::GetAddressTypeComboBox( void ) { // Create the ComboBox if necessary if ( !IsWindow( m_pAddressTypeList->m_hWnd ) ) VERIFY( m_pAddressTypeList->Create( this ) ); return (CListBox*)m_pAddressTypeList; } //======================================================= GetAddressNameField CEdit * CNSAddressList::GetAddressNameField( void ) { return m_pNameField; } //=========================================================== EnableGridLines void CNSAddressList::EnableGridLines( BOOL bEnable ) { if ( m_bGridLines == bEnable ) return; m_bGridLines = bEnable; // redraw the control using the new grid-lines setting Invalidate( TRUE ); } int CNSAddressList::GetItemFromPoint(LPPOINT lpPoint) { BOOL bOutside; return ItemFromPoint(m_hWnd,lpPoint,&bOutside); } ///////////////////////////////////////////////////////////////////////////// // CNSAddressList private API UINT CNSAddressList::ItemFromPoint(HWND hwnd, LPPOINT lpPoint, BOOL * bOutside) const { RECT rect; ::GetClientRect(hwnd, &rect); int iHeight = (int)::SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); int iCount = (int)::SendMessage(hwnd, LB_GETCOUNT, 0, 0); int iTopIndex = (int)::SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); int iListHeight = iHeight * ( iCount - iTopIndex ); rect.bottom = rect.bottom < iListHeight ? rect.bottom : iListHeight; *bOutside = !::PtInRect(&rect, *lpPoint); if ( *bOutside ) { return 0; } return (lpPoint->y / iHeight) + iTopIndex; } //================================================================ OnKeyPress BOOL CNSAddressList::OnKeyPress( CWnd *pChildControl, UINT nKey, UINT nRepCnt, UINT nFlags ) { switch (nKey) { #ifdef MOZ_NEWADDR case 'J': case 'j': { BOOL bCtrl = GetKeyState( VK_CONTROL ) & 0x8000; if(bCtrl) { ShowNameCompletionPicker(this); return TRUE; } } break; #endif case VK_HOME: if (GetActiveSelection()) SetActiveSelection(0); else if (m_bDrawTypeList) m_pAddressTypeList->SetFocus(); break; case VK_END: if (GetActiveSelection() != (GetCount()-1)) SetActiveSelection(GetCount()-1); else m_pNameField->SetFocus(); break; case VK_UP: if (GetActiveSelection()) SetActiveSelection(GetActiveSelection()-1); break; case VK_DOWN: if (GetActiveSelection()LineLength(); if (nKey == VK_DELETE) { if (nSelect >= GetCount()) nSelect = GetCount()-1; SetActiveSelection(nSelect); Invalidate(); } else m_pNameField->SetSel(iLineLength,iLineLength,TRUE); return TRUE; } break; case VK_BACK: if (!m_pNameField->LineLength()) { if (GetCount()>1 && GetActiveSelection()) { DeleteEntry(GetActiveSelection()); if (GetActiveSelection()==LB_ERR) SetActiveSelection(0); UpdateWindow(); int iLineLength = m_pNameField->LineLength(); m_pNameField->SetSel(iLineLength,iLineLength,TRUE); } else return FALSE; return TRUE; } break; case VK_RETURN: if (DoNotifySelectionChange() != -1) { if ((GetActiveSelection()+1 == GetCount())) { // don't add a second blank line if ( m_pNameField->LineLength() == 0 ) { CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT); if (pNextWnd) pNextWnd->SetFocus(); else GetParent()->SendMessage(WM_LEAVINGLASTFIELD); return TRUE; } // add the new address entry to the list InsertEntry( GetActiveSelection()+1,NULL); // select the new address and make sure its visible SetActiveSelection( GetActiveSelection()+1 ); return TRUE; } else { SetActiveSelection( GetActiveSelection()+1 ); } return TRUE; } else SetSel( GetActiveSelection(), TRUE); return TRUE; break; } if (nKey == VK_TAB) { if (DoNotifySelectionChange() != -1) { BOOL bShift = GetKeyState( VK_SHIFT ) & 0x8000; if ( !bShift && (pChildControl->m_hWnd == m_pAddressTypeList->m_hWnd) ) { m_pNameField->SetFocus(); } else if ( m_bDrawTypeList && bShift && (pChildControl->m_hWnd == m_pNameField->m_hWnd) ) m_pAddressTypeList->SetFocus(); else if ( !bShift && (GetActiveSelection()+1 == GetCount()) ) { CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT); if (pNextWnd) pNextWnd->SetFocus(); else GetParent()->SendMessage(WM_LEAVINGLASTFIELD); } else if ( bShift && (GetActiveSelection() == 0) ) // first line { CWnd *pNextWnd = GetNextWindow( GW_HWNDPREV ); if (pNextWnd) pNextWnd->SetFocus(); } else // middle line { // select the next or previous line in the address list if ( bShift ) { SetActiveSelection( GetActiveSelection()-1 ); m_pNameField->SetFocus(); } else { SetActiveSelection( GetActiveSelection()+1 ); if (m_bDrawTypeList) m_pAddressTypeList->SetFocus(); } } } else SetSel( GetActiveSelection(), TRUE); return TRUE; } return FALSE; // not handled - let the child continue processing this key } BOOL CNSAddressList::isPointInItemBitmap(LPPOINT pPoint, int iIndex) { CRect rect; if(GetItemRect(m_hWnd, iIndex, rect) == LB_ERR) return FALSE; CRect rectBitmap(m_iFieldControlWidth, rect.top, m_iFieldControlWidth + m_iBitmapWidth, rect.bottom ); if (!m_bDrawTypeList) { rectBitmap.left = rect.left; rectBitmap.right = rect.left + m_iBitmapWidth; } BOOL bRet = rectBitmap.PtInRect(*pPoint); return bRet; } void CNSAddressList::selectEntry(int iIndex, BOOL bState) { if(iIndex >= GetCount()) return; CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(iIndex); if(pAddress == NULL) return; if(pAddress->getEntrySelectedState() == bState) return; pAddress->setEntrySelectedState(bState); RECT rcItem; GetItemRect(m_hWnd, iIndex, &rcItem); InvalidateRect(&rcItem); } BOOL CNSAddressList::isEntrySelected(int iIndex) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(iIndex); if(pAddress == NULL) return FALSE; return pAddress->getEntrySelectedState(); } void CNSAddressList::selectAllEntries(BOOL bState) { for(int i = 0; i < GetCount(); i++) selectEntry(i, bState); } int CNSAddressList::getEntryMultipleSelectionStatus(BOOL * pbContinuous, int * piFirst, int * piLast) { if(GetCount() == 0) return 0; int iFirst = -1; int iLast = -1; int iCounter = 0; BOOL bContinuousSelectionStarted = FALSE; BOOL bContinuousSelectionStopped = FALSE; BOOL bBroken = FALSE; for(int i = 0; i < GetCount(); i++) { if(isEntrySelected(i)) { if(iFirst == -1) iFirst = i; iLast = i; if(bContinuousSelectionStopped) bBroken = TRUE; bContinuousSelectionStarted = TRUE; iCounter++; continue; } if(bContinuousSelectionStarted) bContinuousSelectionStopped = TRUE; } *pbContinuous = !bBroken; *piFirst = iFirst; *piLast = iLast; return iCounter; } void CNSAddressList::DrawEntryBitmap( int iSel, CNSAddressInfo * pAddress, CDC * pDC, BOOL bErase ) { CRect rect; if (GetItemRect(m_hWnd,iSel,rect)!=LB_ERR) { CRect rectBitmap( m_iFieldControlWidth, rect.top, m_iFieldControlWidth + m_iBitmapWidth, rect.bottom ); if (!m_bDrawTypeList) { rectBitmap.left = rect.left; rectBitmap.right = rect.left + m_iBitmapWidth; } int iBitmap = pAddress->GetBitmap(); if (!iBitmap) iBitmap = GetDefaultBitmapId(); if (iBitmap) { if(!isEntrySelected(iSel)) NS_FillSolidRect(pDC->GetSafeHdc(),rectBitmap,GetSysColor(COLOR_WINDOW)); else { rectBitmap.InflateRect(0, -1); NS_FillSolidRect(pDC->GetSafeHdc(),rectBitmap,GetSysColor(COLOR_HIGHLIGHT)); rectBitmap.InflateRect(0, 1); } BITMAP bitmap; CBitmap cbitmap; cbitmap.LoadBitmap(MAKEINTRESOURCE(iBitmap)); cbitmap.GetObject(sizeof(BITMAP),&bitmap); int center_x = rectBitmap.left + (rectBitmap.Width() - bitmap.bmWidth)/2; int center_y = rectBitmap.top + (rectBitmap.Height()-bitmap.bmHeight)/2; DrawTransparentBitmap( pDC->GetSafeHdc(), (HBITMAP)cbitmap.GetSafeHandle(), center_x, center_y, RGB(255,0,255)); cbitmap.DeleteObject(); } } } void CNSAddressList::UpdateHeaderType(void) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress != (CNSAddressInfo *)-1 && IsWindow(m_pAddressTypeList->m_hWnd) && m_bDrawTypeList) { CString cs; m_pAddressTypeList->GetText(m_pAddressTypeList->GetCurSel(),cs); if (strcmp(pAddress->GetType(),cs)) { pAddress->SetType(cs); int iSel = m_pAddressTypeList->GetCurSel(); if (iSel != -1) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iSel); ASSERT(pInfo!=(CNSAddressTypeInfo*)-1); UINT idBitmap = pInfo->GetBitmap(); pAddress->SetBitmap(idBitmap); CRect rect; CDC * pDC = GetDC(); DrawEntryBitmap(GetActiveSelection(), pAddress, pDC, TRUE); ReleaseDC(pDC); } } GetTypeFieldLength(); } } int CNSAddressList::GetTypeFieldLength() { CString cs = ""; char * pszString; HDC hDC = ::GetDC(m_hWnd); HGDIOBJ hOldFont = ::SelectObject(hDC, (HFONT) ::SendMessage(m_pAddressTypeList->GetSafeHwnd(), WM_GETFONT, 0 ,0)); int iMaxLength = 0; SIZE ptSize; for (int i =0; iGetType(); ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize); int iTemp = ptSize.cx + (TEXT_PAD * 2) + m_iTypeBitmapWidth; if (iTemp > iMaxLength) iMaxLength = iTemp; } pszString = "A&"; ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize); iMaxLength -= ptSize.cx; ::SelectObject(hDC,hOldFont); ::ReleaseDC(m_hWnd,hDC); if (iMaxLength != m_iFieldControlWidth) { m_iFieldControlWidth = iMaxLength; ::InvalidateRect(m_hWnd,NULL,TRUE); ::UpdateWindow(m_hWnd); } return iMaxLength; } void CNSAddressList::UpdateHeaderContents(void) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress != (CNSAddressInfo *)-1) { CString cs; m_pNameField->GetWindowText(cs); pAddress->SetName(cs); if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(m_pAddressTypeList->GetCurSel()); if (pInfo != (CNSAddressTypeInfo*)-1) { if (pInfo->GetExclusive()) pInfo->SetValue(cs); } } } } void CNSAddressList::SingleHeaderCommand(int nID) { if (GetActiveSelection()!=LB_ERR && m_bDrawTypeList) { m_pAddressTypeList->SetCurSel(nID); UpdateHeaderType(); if(!isEntrySelected(GetActiveSelection())) m_pNameField->SetFocus(); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(nID); ASSERT(pInfo); if (pInfo->GetExclusive()) { CString cs; m_pNameField->GetWindowText(cs); if (!cs.GetLength()) m_pNameField->SetWindowText(pInfo->GetValue()); pInfo->SetHidden(FALSE); pInfo->SetExclusive(FALSE); UpdateHeaderContents(); int iLineLength = m_pNameField->LineLength(); UpdateWindow(); m_pNameField->SetSel(iLineLength,iLineLength,TRUE); } else { pInfo->SetExclusive(TRUE); } } } void CNSAddressList::HeaderCommand(int nID) { BOOL bCont; int iFirst = 0; int iLast = 0; int iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); if(iCount <= 0) { SingleHeaderCommand(nID); return; } int iCurSel = GetActiveSelection(); for(int i = iFirst; i <= iLast; i++) { if(!isEntrySelected(i)) continue; SetActiveSelection(i); SingleHeaderCommand(nID); } SetActiveSelection(iCurSel); } void CNSAddressList::DoSetFocus(HWND hwnd) { if ( (GetCount() > 0) && (GetActiveSelection() != LB_ERR) ) { if (m_bDrawTypeList) ::ShowWindow(m_pAddressTypeList->m_hWnd, SW_SHOW); m_pNameField->ShowWindow( SW_SHOW ); if(m_EntrySelector.WhatEntryBitmapClicked() == -1) { if ( GetActiveSelection() == GetCount()-1 ) ::SetFocus(m_pNameField->m_hWnd); else if (m_bDrawTypeList) ::SetFocus(m_pAddressTypeList->m_hWnd); } } } void CNSAddressList::DoKillFocus(HWND hNewWnd) { if (::GetFocus() == m_pAddressTypeList->m_hWnd || ::GetFocus() == m_pNameField->m_hWnd || ::GetFocus() == m_hWnd ) { // focus is going to one the child controls return; } if (m_bDrawTypeList) ::ShowWindow(m_pAddressTypeList->m_hWnd,SW_HIDE); if (IsWindow(m_pNameField->m_hWnd)) ::ShowWindow(m_pNameField->m_hWnd,SW_HIDE); } ///////////////////////////////////////////////////////////////////////////// // CNSAddressList virtual functions (overrides) void CNSAddressList::DrawGridLine(CRect &rect, CDC * pDC) { HDC hdc = pDC->GetSafeHdc(); HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenGrey); ::MoveToEx(hdc, rect.left + m_iFieldControlWidth, rect.bottom-1, NULL); ::LineTo(hdc, rect.right, rect.bottom-1); ::SelectObject(hdc,(HGDIOBJ)hOldPen); } void CNSAddressList::ComputeFieldWidths(CDC * pDC) { if (m_bDrawTypeList) { m_iFieldControlWidth = 0; CBitmap cbitmap; cbitmap.LoadBitmap(IDB_ARROW3D); BITMAP bitmap; cbitmap.GetObject(sizeof(BITMAP), &bitmap ); m_iTypeBitmapWidth = bitmap.bmWidth; cbitmap.DeleteObject(); } m_iBitmapWidth = 24; } //=============================================================== DrawAddress void CNSAddressList::DrawAddress( int nIndex, CRect &rect, CDC *pDC, BOOL bSelected ) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(nIndex); if (!pAddress) return; if (!m_iFieldControlWidth) ComputeFieldWidths(pDC); // create CRects for each of the fields CRect rectType( rect.left, rect.top, m_iFieldControlWidth, rect.bottom ); CRect rectAddress( (m_bDrawTypeList ? rectType.right : rect.left) + m_iBitmapWidth, rect.top, rect.right, rect.bottom ); // end CRects // shrink the rectangle so that the controls draw within the grid rectAddress.bottom--; // If the bitmap is not provided, ask for it if( pAddress->GetBitmap() == NULL && m_bDrawTypeList ) { // send notification to parent int position = m_pAddressTypeList->FindString(-1,pAddress->GetType()); if (position != LB_ERR) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(position); ASSERT(pInfo); pAddress->SetBitmap(pInfo->GetBitmap()); } } int oldLine = m_lastIndex; int ioffset = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)/2; int iremain = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)%2; rectAddress.top += (ioffset+iremain); rectAddress.bottom -= ioffset; // draw the address type and address name fields if ( bSelected ) { if (m_bDrawTypeList) { // set the combobox m_pAddressTypeList->MoveWindow( rectType, FALSE ); m_pAddressTypeList->SelectString(-1, pAddress->GetType()); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); m_pNameField->SetNameCompletionFlag(pInfo->GetExpand()); } int nStart, nEnd; m_pNameField->GetSel(nStart,nEnd); m_pNameField->SetWindowText(pAddress->GetName()); m_pNameField->MoveWindow( rectAddress, FALSE ); m_pNameField->UpdateWindow(); m_lastIndex = nIndex; m_pNameField->SetSel(nStart,nEnd); } if (!bSelected || !m_pNameField->IsWindowVisible()) { COLORREF cText = pDC->SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) ); int iMode = pDC->SetBkMode(TRANSPARENT); // draw the address pDC->DrawText( pAddress->GetName() ? pAddress->GetName() : "", -1, rectAddress, DT_LEFT | DT_BOTTOM | DT_NOPREFIX ); if (m_bDrawTypeList) m_pAddressTypeList->DrawItemSoItLooksLikeAButton( pDC,rectType,CString(pAddress->GetType() ? pAddress->GetType():"")); pDC->SetTextColor(cText); pDC->SetBkMode(iMode); } // end fields // draw the bitmap DrawEntryBitmap(nIndex,pAddress,pDC, (GetCurSel()==(int)nIndex)?TRUE:FALSE); HDC hdc = pDC->GetSafeHdc(); if (GetCurSel()==(int)nIndex) { HPEN hOldPen = (HPEN)::SelectObject(hdc, m_hPenNormal); if (GetCurSel()==GetTopIndex()) { ::MoveToEx(hdc,m_iFieldControlWidth,rect.top, NULL); ::LineTo(hdc,rect.right,rect.top); } ::MoveToEx(hdc,m_iFieldControlWidth,rect.bottom-1, NULL); ::LineTo(hdc,rect.right,rect.bottom-1); ::SelectObject(hdc,(HGDIOBJ)hOldPen); } DrawGridLine(rect, pDC); //ValidateRect(&rect); // draw the last line if (m_lastIndex != oldLine) { CRect badRect(0, 0, 0, 0); GetItemRect(m_hWnd,oldLine,badRect); InvalidateRect(badRect); } } //================================================================== DrawItem void CNSAddressList::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ) { if (lpDrawItemStruct->itemID != -1) { CRect rect(lpDrawItemStruct->rcItem); if (!m_iItemHeight) m_iItemHeight = rect.Height(); CDC dc; dc.Attach(lpDrawItemStruct->hDC); DrawAddress( lpDrawItemStruct->itemID, rect,&dc, (int)lpDrawItemStruct->itemID == GetActiveSelection()); dc.Detach(); } } //=============================================================== MeasureItem void CNSAddressList::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct ) { static int iHeight = 0; if (!iHeight) { CDC * pdc = GetDC(); TEXTMETRIC tm; pdc->GetTextMetrics(&tm); iHeight = tm.tmHeight; ReleaseDC(pdc); } lpMeasureItemStruct->itemHeight = iHeight + 1; } //================================================================ DeleteItem void CNSAddressList::DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct ) { delete (CNSAddressInfo *)GetItemDataPtr( lpDeleteItemStruct->itemID ); } void CNSAddressList::DisplayTypeList(int item) { CRect rect; if (item == -1) item = GetActiveSelection(); CMenu cmenu; if (cmenu.CreatePopupMenu()) { for (int i = 0; i < m_pAddressTypeList->GetCount(); i++) { CString cs; m_pAddressTypeList->GetText(i,cs); cmenu.AppendMenu(MF_STRING, IDM_HEADER+i, cs.Right(cs.GetLength()-1)); } GetItemRect(m_hWnd,item,rect); CPoint pt(rect.left + m_iTypeBitmapWidth,rect.bottom); ClientToScreen(&pt); pt.y -= 2; cmenu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, this); } } int CNSAddressList::GetItemRect(HWND hwnd, int nIndex, LPRECT lpRect) const { ASSERT(::IsWindow(hwnd)); return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); } static BOOL IsShiftPressed() { short sShiftState = GetKeyState(VK_SHIFT); BOOL bDown = (sShiftState < 0); return bDown; } void CNSAddressList::onKeyDown(int iVirtKey, DWORD dwFlags) { switch (iVirtKey) { case VK_TAB: selectAllEntries(FALSE); ::SetFocus((m_pNameField->m_hWnd)); break; case VK_UP: case VK_LEFT: { if(GetCount() <= 1) break; int iIndex = GetActiveSelection(); if(iIndex <= 0) break; if(IsShiftPressed()) { if(!isEntrySelected(iIndex - 1)) selectEntry(iIndex - 1, TRUE); else selectEntry(iIndex, FALSE); } else { BOOL bCont; int iFirst = 0; int iLast = 0; int iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); if(iCount < 1) break; if(iCount > 1) selectAllEntries(FALSE); else selectEntry(iIndex, FALSE); selectEntry(iIndex - 1, TRUE); } break; } case VK_DOWN: case VK_RIGHT: { if(GetCount() <= 1) break; int iIndex = GetActiveSelection(); if(iIndex >= GetCount() - 1) break; if(IsShiftPressed()) { if(!isEntrySelected(iIndex + 1)) selectEntry(iIndex + 1, TRUE); else selectEntry(iIndex, FALSE); } else { BOOL bCont; int iFirst = 0; int iLast = 0; int iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); if(iCount < 1) break; if(iCount > 1) selectAllEntries(FALSE); else selectEntry(iIndex, FALSE); selectEntry(iIndex + 1, TRUE); } break; } case VK_DELETE: case VK_BACK: { BOOL bCont; int iFirst = 0; int iLast = 0; int iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); for(int i = GetCount() - 1; i >= 0; i--) { if(isEntrySelected(i)) { if(!DeleteEntry(i)) break; } } if(GetCount() == 1) selectEntry(0, FALSE); SetActiveSelection((iLast < GetCount()) ? iLast : GetCount() - 1); ::InvalidateRect(m_hWnd, NULL, TRUE); ::UpdateWindow(m_hWnd); ::SetFocus((m_pNameField->m_hWnd)); break; } default: break; } } static HCURSOR setDragYesCursor() { HINSTANCE hInst = #ifdef _AFXDLL AfxFindResourceHandle(MAKEINTRESOURCE(IDC_MOVEBUTTON), RT_GROUP_CURSOR); #else AfxGetResourceHandle(); #endif HCURSOR hCursor = ::LoadCursor(hInst, MAKEINTRESOURCE(IDC_TEXT_MOVE)); HCURSOR hCursorOld = ::SetCursor(hCursor); return hCursorOld; } static HCURSOR setDragNoCursor() { HCURSOR hCursor = ::LoadCursor(NULL, IDC_NO); HCURSOR hCursorOld = ::SetCursor(hCursor); return hCursorOld; } static BOOL bDrugYesCursor = TRUE; void CNSAddressList::onMouseMove(HWND hWnd, WORD wFlags, int iX, int iY) { if(!(wFlags & MK_LBUTTON)) return; if((wFlags & MK_CONTROL) || (wFlags & MK_SHIFT)) return; if(m_EntrySelector.WhatEntryBitmapClicked() == -1) return; BOOL bCont; int iFirst = 0; int iLast = 0; int iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); if(iCount == GetCount()) return; if(!m_bDragging) { int iDelta = 3; if((abs(m_EntrySelector.m_iX - iX) <= iDelta) && (abs(m_EntrySelector.m_iY - iY) <= iDelta)) return; ::SetCapture(hWnd); m_hCursorBackup = setDragYesCursor(); m_bDragging = TRUE; } else { RECT rc; ::GetClientRect(m_hWnd, &rc); if((iY < rc.top) || (iY > rc.bottom) || (iX < rc.left) || (iX > rc.right)) { if(bDrugYesCursor) { setDragNoCursor(); bDrugYesCursor = FALSE; } } else { if(!bDrugYesCursor) { setDragYesCursor(); bDrugYesCursor = TRUE; } } } } static int minFromThree(int i1, int i2, int i3) { int iRes = min(min(i1, i2), i3); return iRes; } static int maxFromThree(int i1, int i2, int i3) { int iRes = max(max(i1, i2), i3); return iRes; } //=============================================================== OnLButtonDown void CNSAddressList::DoLButtonDown(HWND hwnd, UINT nFlags, LPPOINT lpPoint) { if (m_bDrawTypeList) { BOOL bOutside; int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside ); if(!isPointInItemBitmap(lpPoint, nNewSelect)) { RECT rect; GetItemRect(m_hWnd,nNewSelect,&rect); int iHeight = rect.bottom - rect.top; if (((lpPoint->y+iHeight)/iHeight)+GetTopIndex()>GetCount()) { if (GetCount()) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetCount()-1); if (!pAddress->GetName()||!strlen(pAddress->GetName())) { SetActiveSelection(GetCount()-1); ::SetFocus(m_pNameField->m_hWnd); return; } } AppendEntry(); ::SetFocus(m_pNameField->m_hWnd); return; } SetActiveSelection(nNewSelect); rect.right = m_iFieldControlWidth; if ((lpPoint->x >= rect.left) && (lpPoint->x <= rect.right) && (lpPoint->y >= rect.top) && (lpPoint->y <= rect.bottom)) { if(!isEntrySelected(nNewSelect)) selectAllEntries(FALSE); m_bArrowDown = TRUE; DisplayTypeList(nNewSelect); } else if (lpPoint->x < m_iFieldControlWidth) { ::SetFocus(m_pAddressTypeList->m_hWnd); } else ::SetFocus(m_pNameField->m_hWnd); } else { SetActiveSelection(nNewSelect); m_EntrySelector.LButtonDown(nNewSelect); m_EntrySelector.m_iX = (int)lpPoint->x; m_EntrySelector.m_iY = (int)lpPoint->y; if(!(nFlags & MK_CONTROL)) { BOOL bCont = FALSE; int iCount = 0; int iFirst = 0; int iLast = 0; if(nFlags & MK_SHIFT) { iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); int iMin = minFromThree(nNewSelect, iFirst, iLast); int iMax = maxFromThree(nNewSelect, iFirst, iLast); int iStart = 0; int iStop = 0; if(iCount == 0) { iStart = 0; iStop = nNewSelect; } else if(iCount == 1) { iStart = min(iFirst, nNewSelect); iStop = max(nNewSelect, iLast); } else if(nNewSelect == iMin) { iStart = nNewSelect; iStop = iLast; } else if(nNewSelect == iMax) { iStart = iMin; iStop = nNewSelect; } else { iStart = iMin; iStop = nNewSelect; } selectAllEntries(FALSE); for(int i = iStart; i <= iStop; i++) { selectEntry(i, TRUE); } } else { if(!isEntrySelected(nNewSelect)) { selectAllEntries(FALSE); selectEntry(nNewSelect, TRUE); } else { iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); if(!bCont) { selectAllEntries(FALSE); selectEntry(nNewSelect, TRUE); } else m_EntrySelector.m_bPostponedTillButtonUp = TRUE; } } } ::SetFocus(::GetParent(m_pAddressTypeList->m_hWnd)); return; } } } void CNSAddressList::DoLButtonUp(HWND hwnd, UINT nFlags, LPPOINT lpPoint) { BOOL bOutside; int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside ); if(GetCount() > 1) { if(isPointInItemBitmap(lpPoint, nNewSelect) && !m_bDragging) { if(m_EntrySelector.m_bPostponedTillButtonUp) { selectAllEntries(FALSE); selectEntry(nNewSelect, TRUE); } if((nFlags & MK_CONTROL) && (m_EntrySelector.WhatEntryBitmapClicked() == nNewSelect)) { selectEntry(nNewSelect, !isEntrySelected(nNewSelect)); } } m_EntrySelector.LButtonUp(); } if(m_bDragging) { int iItemHeight = GetItemHeight(0); BOOL bAtTheVeryEnd = (lpPoint->y > iItemHeight * GetCount()); int iInsertBefore = bAtTheVeryEnd ? GetCount() : nNewSelect; BOOL bCont = FALSE; int iCount = 0; int iFirst = 0; int iLast = 0; iCount = getEntryMultipleSelectionStatus(&bCont, &iFirst, &iLast); ASSERT(bCont); ASSERT(iFirst != -1); ASSERT(iLast != -1); if(!bCont || (iFirst == -1) || (iLast == -1)) goto DontDrop; if((iInsertBefore <= iLast + 1) && (iInsertBefore >= iFirst)) goto DontDrop; { NSAddressListEntry nsale; BOOL bDraggingDown = TRUE; if(iInsertBefore < iFirst) bDraggingDown = FALSE; int iCount = 0; for(int i = iFirst; i <= iLast; i++) { if(bDraggingDown) { GetEntry(iFirst, &nsale); InsertEntry(iInsertBefore, &nsale); selectEntry(iInsertBefore, TRUE); DeleteEntry(iFirst); } else { int iCount = i - iFirst; GetEntry(iFirst + iCount, &nsale); InsertEntry(iInsertBefore + iCount, &nsale); selectEntry(iInsertBefore + iCount, TRUE); DeleteEntry(iFirst + iCount + 1); } } if(bAtTheVeryEnd) { ::InvalidateRect(m_hWnd, NULL, TRUE); ::UpdateWindow(m_hWnd); } } if(bAtTheVeryEnd) { ::InvalidateRect(m_hWnd, NULL, TRUE); ::UpdateWindow(m_hWnd); } DontDrop: if(m_hCursorBackup != NULL) ::SetCursor(m_hCursorBackup); ::ReleaseCapture(); m_bDragging = FALSE; } m_EntrySelector.m_bPostponedTillButtonUp = FALSE; if ( bOutside ) return; if (m_bArrowDown) { m_bArrowDown = FALSE; } else { if(!isPointInItemBitmap(lpPoint, nNewSelect)) { // set the selection if ( nNewSelect != GetActiveSelection() ) SetActiveSelection( nNewSelect ); } // set the focus if (lpPoint->x <= m_iFieldControlWidth) ::SetFocus(m_pAddressTypeList->m_hWnd); else if((!isPointInItemBitmap(lpPoint, nNewSelect)) && (GetCount() > 1)) ::SetFocus(m_pNameField->m_hWnd); } } void CNSAddressList::DoVScroll(HWND hwnd, UINT nSBCode, UINT nPos) { ::SetScrollPos(hwnd, SB_VERT, GetTopIndex(), TRUE); } //========================================================== OnChildLostFocus // This method is called when one of the child control looses // focus without preparation (ie no Tab or Enter). void CNSAddressList::DoChildLostFocus() { if (DoNotifySelectionChange(FALSE) != -1) DoKillFocus(NULL); } BOOL CNSAddressList::ParseAddressEntry(int nSelection) { if (!m_bParse) return FALSE; NSAddressListEntry entry; if (GetEntry(nSelection, &entry)) { int iCount; char * pNames = NULL, * pAddresses = NULL; if (!entry.szName || XP_STRLEN (entry.szName) == 0) return FALSE; #ifndef MOZ_NEWADDR char * pName = m_pIAddressParent->NameCompletion((char *)entry.szName); if (pName) { free(pName); return FALSE; } #endif #ifdef MOZ_NEWADDR // if it's got a cookie and has one result then we don't want to parse it CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress) { AB_NameCompletionCookie *pCookie = pAddress->GetNameCompletionCookie(); int nNumResults = pAddress->GetNumNameCompletionResults(); if(pCookie && nNumResults == 1) return FALSE; //likewise, if we are in show picker mode and we have more than one //result, we don't want to parse it either. if(pCookie && nNumResults > 1 && g_MsgPrefs.m_bShowCompletionPicker) return FALSE; //or if we are in show picker mode and don't have a cookie we don't want to //show it if(pCookie == NULL && g_MsgPrefs.m_bShowCompletionPicker) return FALSE; } #endif iCount = MSG_ParseRFC822Addresses(entry.szName, &pNames, &pAddresses); if (iCount > 1) { char * p1, * p2; char *pLastType = NULL; BOOL bExpanded = FALSE; p1 = pNames; p2 = pAddresses; LockWindowUpdate(); for (int i = 0; iSetNameCompletionCookie(pCookie); // pAddress->SetNumNameCompletionResults(1); XP_FREE((void*)address.szName); address.szName = AB_GetHeaderString(pCookie); #endif address.idEntry = (ULONG)-1; bExpanded = TRUE; InsertEntry(nSelection+i+1,&address, FALSE); if (m_pIAddressParent) m_pIAddressParent->AddedItem(m_hWnd, 0, nSelection+i+1); } if (bExpanded) { DeleteEntry(nSelection); NSAddressListEntry address; memset(&address,'\0',sizeof(address)); char * pNextType = NULL; if (pLastType) { if (!strnicmp(pLastType,szLoadString(IDS_ADDRESSTO),strlen(szLoadString(IDS_ADDRESSTO)))) pNextType = szLoadString(IDS_ADDRESSCC); else if (!strnicmp(pLastType,szLoadString(IDS_ADDRESSCC), strlen(szLoadString(IDS_ADDRESSCC)))) pNextType = szLoadString(IDS_ADDRESSBCC); } address.szName = ""; address.szType = pNextType; address.idEntry = (ULONG)-1; AppendEntry(pNextType != NULL ? &address : NULL); } if (pLastType) free(pLastType); ::LockWindowUpdate(NULL); Invalidate(); return TRUE; } if (pNames) XP_FREE(pNames); if (pAddresses) XP_FREE(pAddresses); } return FALSE; } int CNSAddressList::DoNotifySelectionChange(BOOL bShowPicker) { int result = TRUE; if (!ParseAddressEntry(GetActiveSelection())) { if (m_pIAddressParent) { NSAddressListEntry entry; BOOL bRetVal = GetEntry(GetActiveSelection(),&entry); if (bRetVal) { unsigned long entryID = entry.idEntry; UINT bitmapID = entry.idBitmap; char * pszFullName = NULL; BOOL bExpand = TRUE; if (m_bDrawTypeList) { CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData( m_pAddressTypeList->GetCurSel()); bExpand = pInfo->GetExpand(); } if (bExpand && m_bExpansion) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection()); if (pAddress && pAddress->GetExpansion()) { #ifdef MOZ_NEWADDR AB_NameCompletionCookie *pCookie = pAddress->GetNameCompletionCookie(); int nNumResults = pAddress->GetNumNameCompletionResults(); BOOL bExpandName = FALSE; if(pCookie != NULL && nNumResults == 1) { pszFullName = AB_GetHeaderString(pCookie); } //if we have multiple matches and preference is set and we've been told it's //ok to show the picker(i.e. KillFocus doesn't show picker). else if((pCookie != NULL && nNumResults > 1 && bShowPicker && g_MsgPrefs.m_bShowCompletionPicker )|| (pCookie == NULL && nNumResults != 0 && g_MsgPrefs.m_bShowCompletionPicker)) { ShowNameCompletionPicker(this); return -1; } //otherwise it's a naked address, so let's append the default domain. else { pCookie = AB_GetNameCompletionCookieForNakedAddress(entry.szName); pAddress->SetNameCompletionCookie(pCookie); pAddress->SetNumNameCompletionResults(1); pszFullName = AB_GetHeaderString(pCookie); } result = m_pIAddressParent->ChangedItem( (char*)entry.szName,GetActiveSelection(),m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(GetActiveSelection(), bitmapID); if (entryID) SetItemEntryID(GetActiveSelection(), entryID); free(pszFullName); } StopNameCompletion(-1, FALSE); #else result = m_pIAddressParent->ChangedItem( (char*)entry.szName,GetActiveSelection(),m_hWnd, &pszFullName, &entryID, &bitmapID); if (pszFullName != NULL) { pAddress->SetName(pszFullName); if (bitmapID) SetItemBitmap(GetActiveSelection(), bitmapID); if (entryID) SetItemEntryID(GetActiveSelection(), entryID); free(pszFullName); } #endif } } } Invalidate(); } } return result; } void CNSAddressList::DoDisplayTypeList() { DisplayTypeList(); } void CNSAddressList::SetItemName(int nIndex, char * text) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetName(text); } void CNSAddressList::SetItemBitmap(int nIndex, UINT id) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetBitmap(id); CRect rect; GetItemRect(m_hWnd,nIndex,rect); } void CNSAddressList::SetItemEntryID(int nIndex, unsigned long id) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex ); pAddress->SetEntryID(id); CRect rect; GetItemRect(m_hWnd,nIndex,rect); } BOOL CNSAddressList::DoEraseBkgnd(HWND hwnd, HDC hdc) { RECT rect; ::GetClientRect(hwnd,&rect); if (!m_iItemHeight) m_iItemHeight = GetItemHeight(0); int iGridLines = (rect.bottom-rect.top)/m_iItemHeight; HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc,(HGDIOBJ)m_hBrushNormal); HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenNormal); int iTotal = GetCount() - GetTopIndex(); for (int i = 0; i <= iGridLines; i++) { CRect GridRect( rect.left,rect.top+(i*m_iItemHeight), rect.right,rect.top + ((i+1)*m_iItemHeight) - 1); GridRect.top--; if (i < iTotal) GridRect.left = m_iFieldControlWidth; GridRect.top++; NS_FillSolidRect(hdc,GridRect,GetSysColor(COLOR_WINDOW)); GridRect.top--; ::SelectObject(hdc,(HGDIOBJ)m_hPenGrid); ::MoveToEx(hdc,GridRect.left, GridRect.bottom , NULL); ::LineTo(hdc,GridRect.right, GridRect.bottom ); if (m_bDrawTypeList && m_pAddressTypeList->GetCount() && (i >= iTotal)) { ::MoveToEx(hdc,GridRect.left+m_iFieldControlWidth,GridRect.top, NULL); ::LineTo(hdc,GridRect.left+m_iFieldControlWidth,GridRect.bottom ); } ::SelectObject(hdc,(HGDIOBJ)m_hPenNormal); } ::SelectObject(hdc,(HGDIOBJ)hOldPen); ::SelectObject(hdc,(HGDIOBJ)hOldBrush); return TRUE; } int CNSAddressList::SetAddressList ( LPNSADDRESSLIST pAddressList, int count ) { ResetContent(); if (pAddressList) { for (int index = 0; index < count; index++) { NSAddressListEntry address; address.szType = MSG_HeaderMaskToString(pAddressList[index].ulHeaderType); address.idBitmap = pAddressList[index].idBitmap; address.idEntry = pAddressList[index].idEntry; if (pAddressList[index].szAddress) { address.szName = strdup (pAddressList[index].szAddress); free (pAddressList[index].szAddress); } AppendEntry(&address); } free(pAddressList); } return count; } int CNSAddressList::AppendEntry( BOOL expandName, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { if (!szType && !szName && !idBitmap && !idEntry) return AppendEntry(NULL, expandName); NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return AppendEntry(&address, expandName); } int CNSAddressList::InsertEntry( int nIndex, BOOL expandName, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { if (!szType && !szName && !idBitmap && !idEntry) return InsertEntry(nIndex,NULL); NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return InsertEntry(nIndex,&address, expandName); } BOOL CNSAddressList::SetEntry( int nIndex, LPCTSTR szType, LPCTSTR szName, UINT idBitmap, unsigned long idEntry) { NSAddressListEntry address; address.szType = szType; address.szName = szName; address.idBitmap = idBitmap; address.idEntry = idEntry; return SetEntry(nIndex,&address); } #pragma optimize void CNSAddressList::GetTypeInfo( int nIndex, ADDRESS_TYPE_FLAG flag, void ** pData) { CListBox * pTypeList = GetAddressTypeComboBox(); CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)pTypeList->GetItemData(nIndex); ASSERT(pData); *pData = NULL; if (flag & ADDRESS_TYPE_FLAG_VALUE) *pData = (void*)pInfo->GetValue(); else if (flag & ADDRESS_TYPE_FLAG_HIDDEN) *pData = (void*)pInfo->GetHidden(); else if (flag & ADDRESS_TYPE_FLAG_EXCLUSIVE) *pData = (void*)pInfo->GetExclusive(); else if (flag & ADDRESS_TYPE_FLAG_USER) *pData = (void*)pInfo->GetUserData(); else if (flag & ADDRESS_TYPE_FLAG_BITMAP) *pData = (void*)pInfo->GetBitmap(); } BOOL CNSAddressList::GetEntry( int nIndex, char **szType, char **szName, UINT *idBitmap, unsigned long *idEntry) { NSAddressListEntry address; BOOL bRetVal = GetEntry(nIndex,&address); if (bRetVal) { if (szType) *szType = (char*)address.szType; if (szName) *szName = (char*)address.szName; if (idBitmap) *idBitmap = address.idBitmap; if (idEntry) *idEntry = address.idEntry; } return bRetVal; } int CNSAddressList::GetAddressList ( LPNSADDRESSLIST * ppAddressList ) { int count = GetCount(); if (count) { *ppAddressList = (LPNSADDRESSLIST)calloc(count,sizeof(NSADDRESSLIST)); if (*ppAddressList) { for (int index = 0; index < count; index++) { CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( index ); ASSERT(pAddress); if (pAddress->GetType()) (*ppAddressList)[index].ulHeaderType = MSG_StringToHeaderMask(pAddress->GetType()); if (pAddress->GetName()) (*ppAddressList)[index].szAddress = strdup(pAddress->GetName()); (*ppAddressList)[index].idEntry = pAddress->GetEntryID(); (*ppAddressList)[index].idBitmap = pAddress->GetBitmap(); } } } return count; } STDMETHODIMP CNSAddressList::QueryInterface( REFIID refiid, LPVOID * ppv) { *ppv = NULL; if (IsEqualIID(refiid,IID_IAddressControl)) *ppv = (LPADDRESSCONTROL) this; if (*ppv != NULL) { AddRef(); return NOERROR; } return CGenericObject::QueryInterface(refiid,ppv); } STDMETHODIMP_(ULONG) CNSAddressList::Release(void) { ULONG ulRef; ulRef = --m_ulRefCount; if (m_ulRefCount == 0) { LPAPIAPI pApiapi = GetAPIAPI(); pApiapi->RemoveInstance(this); delete this; } return ulRef; } // Address Control Factory //////////////////////////////////////////////////////////////////////////////////////// class CNSAddressControlFactory : public CGenericFactory { public: CNSAddressControlFactory(); ~CNSAddressControlFactory(); STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,REFIID refiid, LPVOID * ppvObj); }; CNSAddressControlFactory::CNSAddressControlFactory() { ApiApiPtr(api); api->RegisterClassFactory(APICLASS_ADDRESSCONTROL,this); } CNSAddressControlFactory::~CNSAddressControlFactory() { } STDMETHODIMP CNSAddressControlFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID refiid, LPVOID * ppvObj) { CNSAddressList * pAddressControl = new CNSAddressList; *ppvObj = (LPVOID)((LPUNKNOWN)pAddressControl); return NOERROR; } static void FillSolidRect(HDC hdc, LPCRECT lpRect, COLORREF clr) { ::SetBkColor(hdc, clr); ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); } static void FillSolidRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clr) { ::SetBkColor(hdc, clr); RECT rect; rect.left = x; rect.top = y; rect.right = x + cx; rect.bottom = y + cy; ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); } static void Draw3dRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight) { FillSolidRect(hdc, x, y, cx - 1, 1, clrTopLeft); FillSolidRect(hdc, x, y, 1, cy - 1, clrTopLeft); FillSolidRect(hdc, x + cx, y, -1, cy, clrBottomRight); FillSolidRect(hdc, x, y + cy, cx, -1, clrBottomRight); } static void Draw3dRect(HDC hdc, LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight) { Draw3dRect(hdc, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight); } void NS_FillSolidRect(HDC hdc, LPCRECT crRect, COLORREF rgbFill) { FillSolidRect(hdc,crRect, rgbFill); } void NS_Draw3dRect(HDC hdc, LPCRECT crRect, COLORREF rgbTL, COLORREF rgbBR) { #ifdef XP_WIN32 Draw3dRect(hdc, crRect, rgbTL, rgbBR); #else CRect crMunge = crRect; crMunge.right -= 1; crMunge.bottom = crMunge.top + 1; NS_FillSolidRect(hdc, crMunge, rgbTL); crMunge = crRect; crMunge.right = crMunge.left + 1; crMunge.bottom -= 1; NS_FillSolidRect(hdc, crMunge, rgbTL); crMunge = crRect; crMunge.left += crMunge.right; crMunge.right -= 1; NS_FillSolidRect(hdc, crMunge, rgbBR); crMunge = crRect; crMunge.top = crMunge.bottom; crMunge.bottom -= 1; NS_FillSolidRect(hdc, crMunge, rgbBR); #endif } //============================================================= DrawHighlight // Draw the highlight around the area static void DrawHighlight( HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight ) { HPEN hpenTopLeft = ::CreatePen( PS_SOLID, 0, clrTopLeft ); HPEN hpenBottomRight = ::CreatePen( PS_SOLID, 0, clrBottomRight ); HPEN hpenOld = (HPEN) ::SelectObject( hDC, hpenTopLeft ); ::MoveToEx( hDC, lpRect->left, lpRect->bottom, NULL ); ::LineTo( hDC, lpRect->left, lpRect->top ); ::LineTo( hDC, lpRect->right - 1, lpRect->top ); ::SelectObject( hDC, hpenBottomRight ); ::LineTo( hDC, lpRect->right - 1, lpRect->bottom - 1); ::LineTo( hDC, lpRect->left, lpRect->bottom - 1); ::SelectObject( hDC, hpenOld ); VERIFY(::DeleteObject( hpenTopLeft )); VERIFY(::DeleteObject( hpenBottomRight )); } //============================================================ DrawRaisedRect void NS_DrawRaisedRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DLIGHT ), GetSysColor( COLOR_3DSHADOW ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DHILIGHT ), GetSysColor( COLOR_3DDKSHADOW ) ); #else DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNHIGHLIGHT ), GetSysColor( COLOR_BTNSHADOW ) ); #endif } //=========================================================== DrawLoweredRect void NS_DrawLoweredRect( HDC hDC, LPRECT lpRect ) { RECT rcTmp = *lpRect; ::InflateRect( &rcTmp, -1, -1 ); #ifdef _WIN32 DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_3DSHADOW ), GetSysColor( COLOR_3DLIGHT ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_3DDKSHADOW ), GetSysColor( COLOR_3DHILIGHT) ); #else DrawHighlight( hDC, &rcTmp, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); DrawHighlight( hDC, lpRect, GetSysColor( COLOR_BTNSHADOW ), GetSysColor( COLOR_BTNHIGHLIGHT ) ); #endif } void NS_Draw3DButtonRect( HDC hDC, LPRECT lpRect, BOOL bPushed ) { if ( bPushed ) { NS_DrawLoweredRect( hDC, lpRect ); } else { NS_DrawRaisedRect( hDC, lpRect ); } } #if defined(__APIAPIDLL) __declspec( dllexport ) int ApiBooter(char * pszClassName) { if (!stricmp(pszClassName,APICLASS_ADDRESSCONTROL)) new CNSAddressControlFactory; return 1; } #else DECLARE_FACTORY(CNSAddressControlFactory); #endif // Address Control Object