home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / nsadrlst.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  53.5 KB  |  1,804 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "stdafx.h"
  20. #include "nsadrlst.h"
  21. #ifdef __APIAPIDLL
  22. #include "festuff.h"
  23. #else
  24. #include "compstd.h"
  25. #endif
  26. #include "resource.h"
  27.  
  28. #define IDM_HEADER                      8192
  29. #define MAX_HEADER_ITEMS                20
  30.  
  31. //============================================================ CNSAddressList
  32. CNSAddressList::CNSAddressList()
  33. {
  34.    m_hPenNormal            = ::CreatePen(PS_SOLID,0,GetSysColor(COLOR_WINDOW));
  35.    m_hPenGrid              = ::CreatePen(PS_SOLID,0,RGB(202,202,255));
  36.    m_hPenGrey              = ::CreatePen(PS_SOLID, 0, RGB(202,202,255));
  37.    m_hBrushNormal          = ::CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  38.    m_lastIndex             = 0;
  39.    m_iDefaultBitmapId      = 0;
  40.    m_bDrawTypeList         = FALSE;
  41.    m_bArrowDown            = FALSE;
  42.    m_iFieldControlWidth    = 0;
  43.    m_iBitmapWidth          = 0;
  44.    m_iTypeBitmapWidth      = 0;
  45.    m_pNameField            = new CNSAddressNameEditField;
  46.    m_pAddressTypeList      = new CNSAddressTypeControl;
  47.    m_iItemHeight           = 0;
  48.    m_pIAddressParent       = NULL;
  49.    m_bCreated              = FALSE;
  50.    m_hTextFont             = NULL;
  51.    m_bParse                = TRUE;
  52. }
  53.  
  54. LRESULT CNSAddressList::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  55. {
  56.     switch (message)
  57.     {
  58.         case WM_ERASEBKGND:
  59.             return DoEraseBkgnd(m_hWnd,(HDC)wParam);
  60.         case WM_SETFOCUS:
  61.             CListBox::DefWindowProc(message,wParam,lParam);
  62.             DoSetFocus((HWND)wParam);
  63.             return 0;
  64.         case WM_KILLFOCUS:
  65.             DoKillFocus((HWND)wParam);
  66.             break;
  67.         case WM_LBUTTONDOWN:
  68.             {
  69.                 POINT point;
  70.                 CListBox::DefWindowProc(message,wParam,lParam);
  71.                 point.x = LOWORD(lParam);  // horizontal position of cursor 
  72.                 point.y = HIWORD(lParam);  // vertical position of cursor 
  73.                 DoLButtonDown(m_hWnd,wParam,&point);
  74.             }
  75.             return 0;
  76.         case WM_LBUTTONUP:
  77.             {
  78.                 POINT point;
  79.                 CListBox::DefWindowProc(message,wParam,lParam);
  80.                 point.x = LOWORD(lParam);  // horizontal position of cursor 
  81.                 point.y = HIWORD(lParam);  // vertical position of cursor 
  82.                 DoLButtonUp(m_hWnd,wParam,&point);
  83.             }
  84.             return 0;
  85.         case WM_VSCROLL:
  86.             {
  87.                 CListBox::DefWindowProc(message,wParam,lParam);
  88.                 int nScrollCode = (int) LOWORD(wParam); // scroll bar value 
  89.                 int nPos = (short int) HIWORD(wParam);  // scroll box position 
  90.                 DoVScroll(m_hWnd, nScrollCode, nPos);
  91.             }
  92.             return 0;
  93.         case WM_CHILDLOSTFOCUS:
  94.             DoChildLostFocus();
  95.             return 0;
  96.         case WM_NOTIFYSELECTIONCHANGE:
  97.             return (DoNotifySelectionChange());
  98.         case WM_DISPLAYTYPELIST:
  99.             DoDisplayTypeList();
  100.             return 0;
  101.         case WM_COMMAND:
  102. #ifdef XP_WIN16
  103.             if (HIWORD(lParam) == EN_CHANGE)
  104. #else
  105.             if (HIWORD(wParam) == EN_CHANGE)
  106. #endif
  107.             {
  108.                  CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection());
  109.                 pAddress->SetExpansion(TRUE);
  110.             }
  111.             if (DoCommand(m_hWnd,wParam,lParam))
  112.                return 0;
  113.             break;
  114.     }
  115.     return CListBox::DefWindowProc(message,wParam,lParam);
  116. }
  117.  
  118. void CNSAddressList::EnableParsing(BOOL bParse)
  119. {
  120.     m_bParse = bParse;
  121. }
  122.  
  123. void CNSAddressList::SetControlParent(LPADDRESSPARENT pIAddressParent)
  124. {
  125.     m_pIAddressParent = pIAddressParent;
  126.     ASSERT(m_pNameField);
  127.     m_pNameField->SetControlParent(pIAddressParent);
  128. }
  129.  
  130. //=========================================================== ~CNSAddressList
  131. CNSAddressList::~CNSAddressList()
  132. {
  133.     if (m_hTextFont) {
  134.         theApp.ReleaseAppFont(m_hTextFont);
  135.     }
  136.     if (m_hPenNormal != NULL)
  137.         ::DeleteObject((HGDIOBJ)m_hPenNormal);
  138.     if (m_hPenGrid != NULL)
  139.         ::DeleteObject((HGDIOBJ)m_hPenGrid);
  140.     if (m_hBrushNormal != NULL)
  141.         ::DeleteObject((HGDIOBJ)m_hBrushNormal);
  142.     if (m_hPenGrey != NULL)
  143.         ::DeleteObject((HGDIOBJ)m_hPenGrey);
  144.     delete m_pAddressTypeList;
  145.     delete m_pNameField;
  146. }
  147.  
  148. BOOL CNSAddressList::DoCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
  149. {
  150. #ifdef XP_WIN16
  151.     if (HIWORD(lParam) == EN_CHANGE)
  152. #else
  153.     if (HIWORD(wParam) == EN_CHANGE)
  154. #endif
  155.     {
  156.         UpdateHeaderContents();
  157.         return TRUE;
  158.     }
  159. #ifdef XP_WIN16
  160.     else if (HIWORD(lParam) == LBN_SELCHANGE)
  161. #else
  162.     else if (HIWORD(wParam) == LBN_SELCHANGE)
  163. #endif
  164.     {
  165.         UpdateHeaderType();
  166.         return TRUE;
  167.     }
  168. #ifdef XP_WIN16
  169.     else if (wParam >= IDM_HEADER && wParam <= IDM_HEADER+MAX_HEADER_ITEMS)
  170.     {
  171.         HeaderCommand(wParam-IDM_HEADER);
  172.         return TRUE;
  173.     }
  174. #else
  175.     else if (!HIWORD(wParam) && // zero if from a menu.
  176.         (LOWORD(wParam) >= IDM_HEADER && LOWORD(wParam) <= IDM_HEADER+MAX_HEADER_ITEMS))
  177.     {
  178.         HeaderCommand(LOWORD(wParam)-IDM_HEADER);
  179.         return TRUE;
  180.     }
  181. #endif
  182.     return FALSE;
  183. }
  184.  
  185. int CNSAddressList::SetActiveSelection(int nSelect)
  186. {
  187.     if (GetActiveSelection() != nSelect)
  188.         return SetCurSel(nSelect);
  189.     return nSelect;
  190. }
  191.  
  192. BOOL CNSAddressList::Create(CWnd *pParent, int id)
  193. {
  194.     RECT rect;
  195.     ::GetClientRect(pParent->m_hWnd, &rect);
  196.     BOOL bRetVal = CListBox::Create(
  197.         WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE|WS_VSCROLL|
  198.         LBS_HASSTRINGS|LBS_OWNERDRAWFIXED|LBS_NOTIFY|LBS_WANTKEYBOARDINPUT|LBS_NOINTEGRALHEIGHT,
  199.         rect,pParent,id);
  200.     m_bCreated = TRUE;
  201.  
  202.     return bRetVal;
  203. }
  204.  
  205. //=============================================================== SetSel
  206. int CNSAddressList::SetSel(int nIndex, BOOL bSelect)
  207. {    
  208.     int result;
  209.     if (bSelect)
  210.     {
  211.         result = SetActiveSelection(nIndex);
  212.         m_pNameField->SetSel(0,-1,TRUE);
  213.     }
  214.     else
  215.     {
  216.         result = SetActiveSelection(-1);
  217.         m_pNameField->SetSel(-1,0,TRUE);
  218.     }
  219.     Invalidate();
  220.     return result;
  221. }
  222.  
  223. //=============================================================== AppendEntry
  224. int CNSAddressList::AppendEntry( NSAddressListEntry *pAddressEntry, BOOL expandName )
  225. {
  226.     SetActiveSelection(-1);
  227.     return InsertEntry( (int)-1, pAddressEntry, expandName );
  228. }
  229.  
  230. //=============================================================== InsertEntry
  231. int CNSAddressList::InsertEntry( int nIndex, NSAddressListEntry *pAddressEntry, BOOL expandName )
  232. {
  233.    if (pAddressEntry && pAddressEntry->szName && strlen(pAddressEntry->szName))
  234.    {
  235.       if (m_bDrawTypeList)
  236.       {
  237.          if (pAddressEntry->szType && strlen(pAddressEntry->szType))
  238.          {
  239.             int iPos;
  240.             ASSERT(m_pAddressTypeList);
  241.                 if ((iPos =m_pAddressTypeList->FindStringExact(-1,pAddressEntry->szType))!=LB_ERR)
  242.             {
  243.                CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iPos);
  244.                ASSERT(pInfo);
  245.                if (pInfo->GetExclusive())
  246.                {
  247.                   CString cs;
  248.                   cs = pInfo->GetValue();
  249.                   if (cs.GetLength())
  250.                   {
  251.                       cs += ",";
  252.                       cs += pAddressEntry->szName;  
  253.                   }
  254.                   else
  255.                       cs = pAddressEntry->szName;
  256.                   pInfo->SetValue(cs);
  257.                }
  258.                if (pInfo->GetHidden())
  259.                   return LB_ERR;
  260.             }
  261.          }
  262.       }
  263.        if (GetActiveSelection()!=LB_ERR && !m_pNameField->LineLength())
  264.        {
  265.           NSAddressListEntry pTemp;
  266.           GetEntry(GetActiveSelection(),&pTemp);
  267.           if (!pTemp.szName||!strlen(pTemp.szName))
  268.           {
  269.             SetEntry(GetActiveSelection(),pAddressEntry);
  270.             CRect rect;
  271.             GetItemRect(m_hWnd, GetActiveSelection(),&rect);
  272.             InvalidateRect(rect);
  273.             m_pNameField->SetFocus();
  274.             return GetActiveSelection();
  275.           }
  276.        }
  277.    }
  278.     CNSAddressInfo *pAddress = new CNSAddressInfo;
  279.     if ( pAddressEntry == NULL)
  280.     {
  281.         // Default to callback provided bitmap and the first
  282.         // address type in the address type list.
  283.         if (m_bDrawTypeList)
  284.         {
  285.               CString cs;
  286.             int index = GetCount();
  287.             if (index > 0 && index != LB_ERR)
  288.             {
  289.                 CNSAddressInfo *pLastAddress = 
  290.                     (CNSAddressInfo *)GetItemDataPtr(index-1);
  291.                 cs = pLastAddress->GetType();                                    
  292.                 int index = m_pAddressTypeList->FindStringExact(-1,cs);
  293.                 if (index != LB_ERR)
  294.                 {
  295.                     CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(index);
  296.                     ASSERT(pInfo);
  297.                     if (pInfo->GetExclusive())
  298.                         m_pAddressTypeList->GetText(0,cs);
  299.                 }
  300.             }
  301.             else
  302.                   m_pAddressTypeList->GetText(0,cs);
  303.             pAddress->SetType(cs);
  304.             pAddress->SetBitmap(0);
  305.             pAddress->SetEntryID();
  306.             pAddress->SetName("");
  307.         }
  308.     }
  309.     else
  310.     {
  311.         if (m_bDrawTypeList)
  312.         {
  313.             BOOL bFound = FALSE;
  314.             for (int i = 0; i < m_pAddressTypeList->GetCount(); i++)
  315.             {
  316.                 CString cs;
  317.                 m_pAddressTypeList->GetText(i,cs);
  318.                 if (cs == pAddressEntry->szType)
  319.                 {
  320.                     bFound = TRUE;
  321.                     m_pAddressTypeList->SetCurSel(i);
  322.                     break;
  323.                 }
  324.             }
  325.             if (!bFound)
  326.             {
  327.                 delete pAddress;
  328.                 return (int)LB_ERR;
  329.             }
  330.         }
  331.         pAddress->SetType(pAddressEntry->szType);
  332.         pAddress->SetName(pAddressEntry->szName);
  333.         pAddress->SetBitmap(pAddressEntry->idBitmap);
  334.         pAddress->SetEntryID(pAddressEntry->idEntry);
  335.     }
  336.     int index = InsertString( nIndex, (LPCTSTR)pAddress );
  337.     if ( index < 0 )
  338.         return FALSE;
  339.     SetItemDataPtr( index, pAddress );
  340.     // this ensures that there will always be a selected line if there are entries
  341.     if ( (GetCount() == 1) || (GetActiveSelection() == LB_ERR) ) 
  342.     {
  343.         SetActiveSelection( 0 );
  344.         UpdateHeaderType();
  345.         UpdateHeaderContents();
  346.     }
  347.  
  348.     CRect WindowRect, ItemRect;
  349.     GetWindowRect(WindowRect);
  350.     
  351.     if (m_pIAddressParent && expandName)
  352.         m_pIAddressParent->AddedItem(m_hWnd, 0, index);
  353.  
  354.     SetActiveSelection(index);
  355.     return index;
  356. }
  357. //================================================================== SetEntry
  358. void CNSAddressList::SetCSID( int16 csid )
  359. {
  360.     if(m_hWnd)
  361.     {
  362.         HDC hDC = ::GetDC(m_hWnd);
  363.         LOGFONT lf;                 
  364.         memset(&lf,0,sizeof(LOGFONT));
  365.  
  366.         lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
  367.         strcpy(lf.lfFaceName, IntlGetUIFixFaceName(csid));
  368.         lf.lfHeight = -MulDiv(NS_ADDRESSFONTSIZE,::GetDeviceCaps(hDC,LOGPIXELSY),72);
  369.         lf.lfQuality = PROOF_QUALITY;
  370.         lf.lfCharSet = IntlGetLfCharset(csid); 
  371.         m_hTextFont = theApp.CreateAppFont( lf);
  372.         ::SendMessage(GetSafeHwnd(), WM_SETFONT, (WPARAM)m_hTextFont, FALSE);
  373.         ::ReleaseDC(m_hWnd,hDC);
  374.     }
  375.  
  376.     if(m_pNameField)
  377.         m_pNameField->SetCSID(csid);
  378. }
  379.  
  380. //================================================================== SetEntry
  381. BOOL CNSAddressList::SetEntry( int nIndex, NSAddressListEntry *pNewAddressEntry )
  382. {
  383.     // sanity checks
  384.     if ( (int)nIndex >= GetCount() )
  385.         return FALSE;
  386.     if (m_bDrawTypeList)
  387.         if (IsWindow(m_pAddressTypeList->m_hWnd))
  388.             if ( m_pAddressTypeList->FindStringExact( -1, pNewAddressEntry->szType ) == LB_ERR )
  389.                 return FALSE;
  390.     // update entry
  391.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  392.     pAddress->SetType(pNewAddressEntry->szType);
  393.     pAddress->SetName(pNewAddressEntry->szName);
  394.     pAddress->SetBitmap(pNewAddressEntry->idBitmap);
  395.     pAddress->SetEntryID(pNewAddressEntry->idEntry);
  396.  
  397.     if (m_pIAddressParent)
  398.     {
  399.         NSAddressListEntry entry;
  400.         BOOL bRetVal = GetEntry(nIndex,&entry);
  401.         if (bRetVal)
  402.         {
  403.             unsigned long entryID = 0;
  404.             UINT bitmapID = 0;
  405.             char * pszFullName = NULL;
  406.  
  407.             CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  408.             if (pAddress && pAddress->GetExpansion())
  409.             {
  410.                 BOOL bExpand = TRUE;
  411.                 if (m_bDrawTypeList)
  412.                 {
  413.                     CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(
  414.                         m_pAddressTypeList->GetCurSel());
  415.                     bExpand = pInfo->GetExpand();
  416.                 }
  417.                 if (bExpand)
  418.                 {
  419.                     m_pIAddressParent->ChangedItem((char*)entry.szName, nIndex, m_hWnd, 
  420.                         &pszFullName, &entryID, &bitmapID);
  421.                     if (pszFullName != NULL)
  422.                     {
  423.                         pAddress->SetName(pszFullName);
  424.                         if (bitmapID)
  425.                             SetItemBitmap(nIndex, bitmapID);
  426.                         if (entryID)
  427.                             SetItemEntryID(nIndex, entryID);
  428.                         free(pszFullName);
  429.                     }
  430.                 }
  431.             }
  432.         }
  433.     }
  434.  
  435.     return TRUE;
  436. }
  437.  
  438.  
  439. //================================================================== GetEntry
  440. BOOL CNSAddressList::GetEntry( int nIndex, NSAddressListEntry *pAddressEntry )
  441. {
  442.     if ( (int)nIndex >= GetCount() )
  443.         return FALSE;
  444.     // fill out the NSAddressListEntry to return it to the caller
  445.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  446.     if ( pAddress == (CNSAddressInfo *)-1 || !pAddress->GetName())
  447.         return FALSE;
  448.     pAddressEntry->szType = pAddress->GetType();
  449.     pAddressEntry->szName = pAddress->GetName();
  450.     pAddressEntry->idBitmap = pAddress->GetBitmap();
  451.     pAddressEntry->idEntry = pAddress->GetEntryID();
  452.     return TRUE;
  453. }
  454.  
  455.  
  456. BOOL CNSAddressList::RemoveSelection(int nIndex)
  457. {
  458.     if (nIndex == -1)
  459.     {
  460.     int iSel = GetActiveSelection();
  461.     if (iSel != LB_ERR)
  462.         return DeleteEntry(iSel);
  463.     return FALSE;
  464.     }
  465.     return DeleteEntry(nIndex);
  466. }
  467. //=============================================================== DeleteEntry
  468. BOOL CNSAddressList::DeleteEntry( int nIndex )
  469. {
  470.     // sanity check
  471.     if( (int)nIndex >= GetCount() )
  472.         return FALSE;
  473.  
  474.     if (m_bDrawTypeList)
  475.     {
  476.         CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(
  477.             m_pAddressTypeList->GetCurSel());
  478.         if (pInfo)
  479.         {
  480.             if (pInfo->GetExclusive())
  481.                 pInfo->SetValue(NULL);
  482.         }
  483.     }
  484.  
  485.     if (GetCount() == 1)
  486.     {
  487.         m_pNameField->SetWindowText("");
  488.         UpdateHeaderContents();
  489.         if (m_pIAddressParent)
  490.             m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex);
  491.         return FALSE;
  492.     }
  493.     // handle selection if deleting selected address
  494.     if ( (int)nIndex == GetActiveSelection() )
  495.     {
  496.         // delete only entry?
  497.         if ( GetCount() == 1 )
  498.         {
  499.             if (m_bDrawTypeList)
  500.                 m_pAddressTypeList->ShowWindow( SW_HIDE );
  501.             m_pNameField->ShowWindow( SW_HIDE );
  502.         }
  503.         else if ( nIndex > 0 ) 
  504.         {
  505.             SetActiveSelection(nIndex-1);
  506.         }
  507.     }
  508.     // delete this entry
  509.     if ( DeleteString( nIndex ) == LB_ERR )
  510.         return FALSE;
  511.  
  512.     if (m_pIAddressParent)
  513.     m_pIAddressParent->DeletedItem(m_hWnd, 0, nIndex);
  514.  
  515.     return TRUE;
  516. }
  517.  
  518.  
  519. //================================================================= FindEntry
  520. int CNSAddressList::FindEntry( int nStart, LPCTSTR lpszName )
  521. {
  522.     CNSAddressInfo *pAddress;
  523.     if ( nStart == (int)-1 )
  524.         nStart = 0;
  525.     for ( int i = nStart; i < GetCount(); i++ )
  526.     {
  527.         pAddress = (CNSAddressInfo *)GetItemDataPtr(i);
  528.     if (pAddress->GetName())
  529.         if ( strcmp( pAddress->GetName(), lpszName ) == 0 )
  530.             return i;
  531.     }
  532.     return (int)LB_ERR;
  533. }
  534.  
  535.  
  536. BOOL CNSAddressList::AddAddressType(
  537.     char * pszChoice,
  538.     UINT pidBitmap,
  539.     BOOL bExpand,
  540.     BOOL bHidden,
  541.     BOOL bExclusive,
  542.     DWORD dwUserData)
  543. {
  544.     // Create the ComboBox if necessary
  545.     if (pszChoice != NULL)
  546.     {
  547.         if ( !IsWindow( m_pAddressTypeList->m_hWnd ) )
  548.             VERIFY( m_pAddressTypeList->Create( this ) );
  549.         // create the edit field if necessary
  550.         int position = m_pAddressTypeList->InsertString( -1, pszChoice );
  551.         if (position == LB_ERR)
  552.             return FALSE;
  553.         CNSAddressTypeInfo * pInfo = new CNSAddressTypeInfo(pidBitmap,bHidden,bExclusive,dwUserData,bExpand);
  554.         if (pInfo == NULL)
  555.             return FALSE;
  556.         m_pAddressTypeList->SetItemData(position,(DWORD)pInfo);
  557.         m_bDrawTypeList = TRUE;
  558.         if (m_pAddressTypeList->GetCurSel()==LB_ERR)
  559.             m_pAddressTypeList->SetCurSel(0);
  560.     }
  561.        if ( !IsWindow( m_pNameField->m_hWnd ) )
  562.            VERIFY( m_pNameField->Create( this ) );
  563.     return TRUE;
  564. }
  565.  
  566.  
  567. //==================================================== GetAddressTypeComboBox
  568. CListBox * CNSAddressList::GetAddressTypeComboBox( void )
  569. {
  570.     // Create the ComboBox if necessary
  571.     if ( !IsWindow( m_pAddressTypeList->m_hWnd ) )
  572.         VERIFY( m_pAddressTypeList->Create( this ) );
  573.     return (CListBox*)m_pAddressTypeList;
  574. }
  575.  
  576.  
  577. //======================================================= GetAddressNameField
  578. CEdit * CNSAddressList::GetAddressNameField( void )
  579. {
  580.     return m_pNameField;
  581. }
  582.  
  583.  
  584. //=========================================================== EnableGridLines
  585. void CNSAddressList::EnableGridLines( BOOL bEnable )
  586. {
  587.     if ( m_bGridLines == bEnable )
  588.         return;
  589.     m_bGridLines = bEnable;
  590.     // redraw the control using the new grid-lines setting
  591.     Invalidate( TRUE );
  592. }
  593.  
  594.  
  595. int CNSAddressList::GetItemFromPoint(LPPOINT lpPoint)
  596. {
  597.    BOOL bOutside;
  598.    return ItemFromPoint(m_hWnd,lpPoint,&bOutside);
  599. }
  600.  
  601. /////////////////////////////////////////////////////////////////////////////
  602. // CNSAddressList private API
  603.  
  604.  
  605.  
  606.  
  607. UINT CNSAddressList::ItemFromPoint(HWND hwnd, LPPOINT lpPoint, BOOL * bOutside) const
  608. {
  609.     RECT rect;
  610.     ::GetClientRect(hwnd, &rect);
  611.  
  612.     int iHeight = (int)::SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0);
  613.     int iCount = (int)::SendMessage(hwnd, LB_GETCOUNT, 0, 0);
  614.     int iTopIndex = (int)::SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
  615.  
  616.     int iListHeight = iHeight * ( iCount - iTopIndex );
  617.     rect.bottom = rect.bottom < iListHeight ? rect.bottom : iListHeight;
  618.  
  619.     *bOutside = !::PtInRect(&rect, *lpPoint);
  620.  
  621.     if ( *bOutside ) {
  622.         return 0;
  623.     } 
  624.  
  625.     return (lpPoint->y / iHeight) + iTopIndex; 
  626. }
  627.  
  628. //================================================================ OnKeyPress
  629. BOOL CNSAddressList::OnKeyPress( CWnd *pChildControl, UINT nKey, UINT nRepCnt, UINT nFlags )
  630. {
  631.     switch (nKey) 
  632.     {
  633.         case VK_HOME:
  634.             if (GetActiveSelection()) 
  635.                 SetActiveSelection(0);
  636.             else if (m_bDrawTypeList)
  637.                 m_pAddressTypeList->SetFocus();
  638.             break;
  639.         case VK_END:
  640.             if (GetActiveSelection() != (GetCount()-1)) 
  641.                 SetActiveSelection(GetCount()-1);
  642.             else
  643.                 m_pNameField->SetFocus();
  644.             break;
  645.         case VK_UP:
  646.             if (GetActiveSelection()) 
  647.                 SetActiveSelection(GetActiveSelection()-1);
  648.             break;
  649.         case VK_DOWN:
  650.             if (GetActiveSelection()<GetCount()) 
  651.                 SetActiveSelection(GetActiveSelection()+1);
  652.             break;
  653.         case VK_DELETE:
  654.             if (GetActiveSelection()!=LB_ERR)
  655.             {
  656.                 int nSelect = GetActiveSelection();
  657.                 if ((nSelect+1)<GetCount())
  658.                     DeleteEntry(GetActiveSelection());
  659.                 int iLineLength = m_pNameField->LineLength();
  660.                 if (nKey == VK_DELETE)
  661.                 {
  662.                     if (nSelect >= GetCount())
  663.                     nSelect = GetCount()-1;
  664.                     SetActiveSelection(nSelect);
  665.                     Invalidate();
  666.                 }
  667.                 else
  668.                     m_pNameField->SetSel(iLineLength,iLineLength,TRUE);
  669.                 return TRUE;
  670.             }
  671.             break;
  672.         case VK_BACK:
  673.             if (!m_pNameField->LineLength())
  674.             {
  675.                 if (GetCount()>1 && GetActiveSelection())
  676.                 {
  677.                     DeleteEntry(GetActiveSelection());
  678.                     if (GetActiveSelection()==LB_ERR)
  679.                         SetActiveSelection(0);
  680.                     UpdateWindow();
  681.                     int iLineLength = m_pNameField->LineLength();
  682.                     m_pNameField->SetSel(iLineLength,iLineLength,TRUE);
  683.                 }
  684.                 else
  685.                     return FALSE;
  686.                 return TRUE;
  687.             }
  688.             break;
  689.         case VK_RETURN:
  690.             if (DoNotifySelectionChange() != -1)
  691.             {
  692.                 if ((GetActiveSelection()+1 == GetCount()))
  693.                 {
  694.                     // don't add a second blank line
  695.                     if ( m_pNameField->LineLength() == 0 )
  696.                     {
  697.                         CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT);
  698.                         if (pNextWnd) 
  699.                             pNextWnd->SetFocus();
  700.                         else
  701.                             GetParent()->SendMessage(WM_LEAVINGLASTFIELD);
  702.                         return TRUE;
  703.                     }
  704.                     // add the new address entry to the list
  705.                     InsertEntry( GetActiveSelection()+1,NULL);
  706.                     // select the new address and make sure its visible
  707.                     SetActiveSelection( GetActiveSelection()+1 );
  708.                     return TRUE;
  709.                 } 
  710.                 else 
  711.                 {
  712.                     SetActiveSelection( GetActiveSelection()+1 );
  713.                 }
  714.                 return TRUE;
  715.             }
  716.             else
  717.                 SetSel( GetActiveSelection(), TRUE);
  718.  
  719.             return TRUE;
  720.             break;
  721.     }
  722.  
  723.     if (nKey == VK_TAB)
  724.     {
  725.         if (DoNotifySelectionChange() != -1)
  726.         {
  727.             BOOL bShift = GetKeyState( VK_SHIFT ) & 0x8000;
  728.             if ( !bShift && (pChildControl->m_hWnd == m_pAddressTypeList->m_hWnd) )
  729.                 m_pNameField->SetFocus();
  730.             else if ( m_bDrawTypeList && bShift && (pChildControl->m_hWnd == m_pNameField->m_hWnd) )
  731.                 m_pAddressTypeList->SetFocus();
  732.             else if ( !bShift && (GetActiveSelection()+1 == GetCount()) )
  733.             {
  734.                 CWnd *pNextWnd = GetNextWindow(GW_HWNDNEXT);
  735.                 if (pNextWnd) 
  736.                     pNextWnd->SetFocus();
  737.                 else
  738.                     GetParent()->SendMessage(WM_LEAVINGLASTFIELD);
  739.             }
  740.             else if ( bShift && (GetActiveSelection() == 0) ) // first line
  741.             {
  742.                 CWnd *pNextWnd = GetNextWindow( GW_HWNDPREV );
  743.                 if (pNextWnd)
  744.                 pNextWnd->SetFocus();
  745.             }
  746.             else // middle line
  747.             {
  748.                 // select the next or previous line in the address list
  749.                 if ( bShift )
  750.                 {
  751.                     SetActiveSelection( GetActiveSelection()-1 );
  752.                     m_pNameField->SetFocus();
  753.                 }
  754.                 else
  755.                 {
  756.                     SetActiveSelection( GetActiveSelection()+1 );
  757.                     if (m_bDrawTypeList)
  758.                         m_pAddressTypeList->SetFocus();
  759.                 }
  760.             }
  761.         }
  762.         else
  763.             SetSel( GetActiveSelection(), TRUE);
  764.  
  765.     return TRUE;
  766.     }
  767.  
  768.     return FALSE; // not handled - let the child continue processing this key
  769. }
  770.  
  771. void CNSAddressList::DrawEntryBitmap(
  772.     int iSel, 
  773.     CNSAddressInfo * pAddress, 
  774.     CDC * pDC,
  775.     BOOL bErase )
  776. {
  777.     CRect rect;
  778.     if (GetItemRect(m_hWnd,iSel,rect)!=LB_ERR)
  779.     {
  780.         CRect rectBitmap( m_iFieldControlWidth, rect.top, 
  781.             m_iFieldControlWidth + m_iBitmapWidth, rect.bottom );
  782.         if (!m_bDrawTypeList)
  783.         {
  784.             rectBitmap.left = rect.left;
  785.             rectBitmap.right = rect.left + m_iBitmapWidth;
  786.         }
  787.         int iBitmap = pAddress->GetBitmap();
  788.         if (!iBitmap)
  789.             iBitmap = GetDefaultBitmapId();
  790.         if (iBitmap)
  791.         {
  792.             if (bErase)
  793.                 NS_FillSolidRect(pDC->GetSafeHdc(),rectBitmap,GetSysColor(COLOR_WINDOW));
  794.             BITMAP bitmap;
  795.             CBitmap cbitmap;
  796.             cbitmap.LoadBitmap(MAKEINTRESOURCE(iBitmap));
  797.             cbitmap.GetObject(sizeof(BITMAP),&bitmap);
  798.             int center_x = rectBitmap.left + (rectBitmap.Width() - bitmap.bmWidth)/2;
  799.             int center_y = rectBitmap.top + (rectBitmap.Height()-bitmap.bmHeight)/2;
  800.             DrawTransparentBitmap( 
  801.                 pDC->GetSafeHdc(), 
  802.                 (HBITMAP)cbitmap.GetSafeHandle(), 
  803.                 center_x, center_y, 
  804.                 RGB(255,0,255));
  805.             cbitmap.DeleteObject();
  806.         }
  807.     }
  808. }
  809.  
  810. void CNSAddressList::UpdateHeaderType(void)
  811. {
  812.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection());
  813.     if (pAddress != (CNSAddressInfo *)-1 && IsWindow(m_pAddressTypeList->m_hWnd) && m_bDrawTypeList)
  814.     {
  815.         CString cs;
  816.         m_pAddressTypeList->GetText(m_pAddressTypeList->GetCurSel(),cs);
  817.         if (strcmp(pAddress->GetType(),cs))
  818.         {
  819.             pAddress->SetType(cs);
  820.             int iSel = m_pAddressTypeList->GetCurSel();
  821.             if (iSel != -1)
  822.             {
  823.                 CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(iSel);
  824.                 ASSERT(pInfo!=(CNSAddressTypeInfo*)-1);
  825.                 UINT idBitmap = pInfo->GetBitmap();
  826.                 pAddress->SetBitmap(idBitmap);
  827.                 CRect rect;
  828.                 CDC * pDC = GetDC();
  829.                 DrawEntryBitmap(GetActiveSelection(), pAddress, pDC, TRUE);
  830.                 ReleaseDC(pDC);
  831.             }
  832.         }
  833.         GetTypeFieldLength();        
  834.     }
  835. }
  836.  
  837. int CNSAddressList::GetTypeFieldLength()
  838. {
  839.     CString cs = "";
  840.     char * pszString;
  841.     HDC hDC = ::GetDC(m_hWnd);
  842.     HGDIOBJ hOldFont =  ::SelectObject(hDC, (HFONT) ::SendMessage(m_pAddressTypeList->GetSafeHwnd(), WM_GETFONT, 0 ,0));
  843.     int iMaxLength = 0;
  844.     SIZE ptSize;
  845.     for (int i =0; i<GetCount();i++ )
  846.     {
  847.         CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(i);
  848.         pszString = pAddress->GetType();
  849.         ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize);
  850.         int iTemp = ptSize.cx + (TEXT_PAD * 2) + m_iTypeBitmapWidth;
  851.         if (iTemp > iMaxLength)
  852.             iMaxLength = iTemp;
  853.     }
  854.     pszString = "A&";
  855.      ::GetTextExtentPoint(hDC,pszString,strlen(pszString),&ptSize);
  856.     iMaxLength -= ptSize.cx;
  857.     ::SelectObject(hDC,hOldFont);
  858.     ::ReleaseDC(m_hWnd,hDC);
  859.     if (iMaxLength != m_iFieldControlWidth)
  860.     {
  861.         m_iFieldControlWidth = iMaxLength;
  862.         ::InvalidateRect(m_hWnd,NULL,TRUE);
  863.         ::UpdateWindow(m_hWnd);
  864.     }
  865.     return iMaxLength;
  866. }
  867.  
  868. void CNSAddressList::UpdateHeaderContents(void)
  869. {
  870.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection());
  871.     if (pAddress != (CNSAddressInfo *)-1)
  872.     {
  873.         CString cs;
  874.         m_pNameField->GetWindowText(cs);
  875.         pAddress->SetName(cs);
  876.         if (m_bDrawTypeList)
  877.         {
  878.             CNSAddressTypeInfo * pInfo = 
  879.                 (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(m_pAddressTypeList->GetCurSel());
  880.             if (pInfo != (CNSAddressTypeInfo*)-1)
  881.             {
  882.                 if (pInfo->GetExclusive())
  883.                     pInfo->SetValue(cs);
  884.             }
  885.         }
  886.     }
  887. }
  888.  
  889. void CNSAddressList::HeaderCommand(int nID)
  890. {
  891.     if (GetActiveSelection()!=LB_ERR && m_bDrawTypeList)
  892.     {
  893.         m_pAddressTypeList->SetCurSel(nID);
  894.         UpdateHeaderType();
  895.         m_pNameField->SetFocus();
  896.         CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(nID);
  897.         ASSERT(pInfo);
  898.         if (pInfo->GetExclusive())
  899.         {
  900.             CString cs;
  901.             m_pNameField->GetWindowText(cs);
  902.             if (!cs.GetLength())
  903.                m_pNameField->SetWindowText(pInfo->GetValue());
  904.             pInfo->SetHidden(FALSE);
  905.             pInfo->SetExclusive(FALSE);
  906.             UpdateHeaderContents();
  907.             int iLineLength = m_pNameField->LineLength();
  908.             UpdateWindow();
  909.             m_pNameField->SetSel(iLineLength,iLineLength,TRUE);
  910.         }
  911.         else
  912.         {
  913.             CString cs;
  914.             m_pAddressTypeList->GetText (nID, cs);
  915.             if (!strnicmp(cs,szLoadString(IDS_ADDRESSREPLYTO),strlen(szLoadString(IDS_ADDRESSREPLYTO))))
  916.                 pInfo->SetExclusive(TRUE);
  917.             else if (!strnicmp(cs,szLoadString(IDS_ADDRESSFOLLOWUPTO), strlen(szLoadString(IDS_ADDRESSFOLLOWUPTO))))
  918.                 pInfo->SetExclusive(TRUE);
  919.         }
  920.     }
  921. }
  922.  
  923. void CNSAddressList::DoSetFocus(HWND hwnd) 
  924. {
  925.     if ( (GetCount() > 0)
  926.         && (GetActiveSelection() != LB_ERR)
  927.    )
  928.     {
  929.         if (m_bDrawTypeList)
  930.             ::ShowWindow(m_pAddressTypeList->m_hWnd, SW_SHOW);
  931.         m_pNameField->ShowWindow( SW_SHOW );
  932.         if ( GetActiveSelection() == GetCount()-1 )
  933.             ::SetFocus(m_pNameField->m_hWnd);
  934.         else if (m_bDrawTypeList)
  935.             ::SetFocus(m_pAddressTypeList->m_hWnd);
  936.     }
  937. }
  938.  
  939.  
  940. void CNSAddressList::DoKillFocus(HWND hNewWnd) 
  941. {
  942.     if (::GetFocus() == m_pAddressTypeList->m_hWnd || ::GetFocus() == m_pNameField->m_hWnd || 
  943.         ::GetFocus() == m_hWnd )
  944.     {
  945.         // focus is going to one the child controls
  946.         return;
  947.     }
  948.     if (m_bDrawTypeList)
  949.         ::ShowWindow(m_pAddressTypeList->m_hWnd,SW_HIDE);
  950.     if (IsWindow(m_pNameField->m_hWnd))
  951.         ::ShowWindow(m_pNameField->m_hWnd,SW_HIDE);
  952. }
  953.  
  954.  
  955. /////////////////////////////////////////////////////////////////////////////
  956. // CNSAddressList virtual functions (overrides)
  957.  
  958. void CNSAddressList::DrawGridLine(CRect &rect, CDC * pDC)
  959. {
  960.     HDC hdc = pDC->GetSafeHdc();
  961.     HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenGrey);
  962.     ::MoveToEx(hdc, rect.left + m_iFieldControlWidth, rect.bottom-1, NULL);
  963.     ::LineTo(hdc, rect.right, rect.bottom-1);
  964.     ::SelectObject(hdc,(HGDIOBJ)hOldPen);
  965. }
  966.  
  967. void CNSAddressList::ComputeFieldWidths(CDC * pDC)
  968. {
  969.     if (m_bDrawTypeList)
  970.     {
  971.         m_iFieldControlWidth = 0;
  972.         CBitmap cbitmap;
  973.         cbitmap.LoadBitmap(IDB_ARROW3D);
  974.         BITMAP bitmap;
  975.         cbitmap.GetObject(sizeof(BITMAP), &bitmap );
  976.         m_iTypeBitmapWidth = bitmap.bmWidth;
  977.         cbitmap.DeleteObject();
  978.     }
  979.  
  980.     m_iBitmapWidth = 24;
  981. }
  982.  
  983. //=============================================================== DrawAddress
  984. void CNSAddressList::DrawAddress( int nIndex, CRect &rect, CDC *pDC, BOOL bSelected )
  985. {
  986.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(nIndex);
  987.     if (!pAddress)
  988.         return;
  989.  
  990.     if (!m_iFieldControlWidth) 
  991.         ComputeFieldWidths(pDC);
  992.  
  993.     // create CRects for each of the fields
  994.     CRect rectType( rect.left, rect.top, m_iFieldControlWidth, rect.bottom );
  995.     CRect rectAddress( 
  996.         (m_bDrawTypeList ? rectType.right : rect.left) + m_iBitmapWidth, rect.top, 
  997.         rect.right, rect.bottom );
  998.     // end CRects
  999.  
  1000.     // shrink the rectangle so that the controls draw within the grid
  1001.      rectAddress.bottom--;
  1002.  
  1003.     // If the bitmap is not provided, ask for it
  1004.  
  1005.     if( pAddress->GetBitmap() == NULL && m_bDrawTypeList )
  1006.     {
  1007.         // send notification to parent
  1008.         int position = m_pAddressTypeList->FindString(-1,pAddress->GetType());
  1009.         if (position != LB_ERR)
  1010.         {
  1011.             CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)m_pAddressTypeList->GetItemData(position);
  1012.             ASSERT(pInfo);
  1013.             pAddress->SetBitmap(pInfo->GetBitmap());
  1014.         }
  1015.     }
  1016.  
  1017.     int oldLine = m_lastIndex;
  1018.  
  1019.     int ioffset = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)/2;
  1020.     int iremain = ((rectAddress.Height()-m_pNameField->m_iTextHeight)+1)%2;
  1021.     rectAddress.top += (ioffset+iremain);
  1022.     rectAddress.bottom -= ioffset;
  1023.     // draw the address type and address name fields
  1024.     if ( bSelected )
  1025.     {
  1026.         if (m_bDrawTypeList)
  1027.         {
  1028.                 // set the combobox
  1029.             m_pAddressTypeList->MoveWindow( rectType, FALSE );
  1030.             m_pAddressTypeList->SelectString(-1, pAddress->GetType());
  1031.             CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(
  1032.                m_pAddressTypeList->GetCurSel());
  1033.             m_pNameField->SetNameCompletionFlag(pInfo->GetExpand());
  1034.         }
  1035.  
  1036.         int nStart, nEnd;
  1037.         m_pNameField->GetSel(nStart,nEnd);
  1038.         m_pNameField->SetWindowText(pAddress->GetName());
  1039.         m_pNameField->MoveWindow( rectAddress, FALSE );
  1040.         m_pNameField->UpdateWindow();
  1041.         m_lastIndex = nIndex;
  1042.         m_pNameField->SetSel(nStart,nEnd);
  1043.     }
  1044.  
  1045.     if (!bSelected || !m_pNameField->IsWindowVisible())
  1046.     {
  1047.  
  1048.         COLORREF cText = pDC->SetTextColor( GetSysColor( COLOR_WINDOWTEXT ) );
  1049.         int iMode = pDC->SetBkMode( TRANSPARENT );
  1050.  
  1051.         // draw the address
  1052.         pDC->DrawText(
  1053.             pAddress->GetName() ? pAddress->GetName() : "", 
  1054.             -1, rectAddress, DT_LEFT | DT_BOTTOM | DT_NOPREFIX );
  1055.  
  1056.         pDC->SetTextColor(cText);
  1057.         pDC->SetBkMode(iMode);
  1058.  
  1059.         if (m_bDrawTypeList)
  1060.             m_pAddressTypeList->DrawItemSoItLooksLikeAButton(
  1061.                 pDC,rectType,CString(pAddress->GetType() ? pAddress->GetType():""));
  1062.  
  1063.     }
  1064.     // end fields
  1065.  
  1066.     // draw the bitmap
  1067.     DrawEntryBitmap(nIndex,pAddress,pDC, 
  1068.         (GetCurSel()==(int)nIndex)?TRUE:FALSE);
  1069.  
  1070.     HDC hdc = pDC->GetSafeHdc();
  1071.     if (GetCurSel()==(int)nIndex)
  1072.     {
  1073.         HPEN hOldPen = (HPEN)::SelectObject(hdc, m_hPenNormal);
  1074.         if (GetCurSel()==GetTopIndex())
  1075.         {
  1076.             ::MoveToEx(hdc,m_iFieldControlWidth,rect.top, NULL);
  1077.             ::LineTo(hdc,rect.right,rect.top);
  1078.         }
  1079.         ::MoveToEx(hdc,m_iFieldControlWidth,rect.bottom-1, NULL);
  1080.         ::LineTo(hdc,rect.right,rect.bottom-1);
  1081.         ::SelectObject(hdc,(HGDIOBJ)hOldPen);
  1082.     }
  1083.  
  1084.        DrawGridLine(rect, pDC);
  1085.     ValidateRect(&rect);
  1086.  
  1087.     // draw the last line
  1088.     if (m_lastIndex != oldLine)
  1089.     {
  1090.         CRect badRect(0, 0, 0, 0);
  1091.         GetItemRect(m_hWnd,oldLine,badRect);
  1092.         InvalidateRect(badRect);
  1093.     }
  1094. }
  1095.  
  1096. //================================================================== DrawItem
  1097. void CNSAddressList::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ) 
  1098. {
  1099.     if (lpDrawItemStruct->itemID != -1) 
  1100.     {
  1101.         CRect rect(lpDrawItemStruct->rcItem);
  1102.         if (!m_iItemHeight)
  1103.             m_iItemHeight = rect.Height();
  1104.         CDC dc;
  1105.         dc.Attach(lpDrawItemStruct->hDC);
  1106.         DrawAddress(
  1107.             lpDrawItemStruct->itemID,
  1108.             rect,&dc,
  1109.             (int)lpDrawItemStruct->itemID == GetActiveSelection());
  1110.  
  1111.         dc.Detach();
  1112.     }
  1113. }
  1114.  
  1115.  
  1116. //=============================================================== MeasureItem
  1117. void CNSAddressList::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct )
  1118. {
  1119.     static int iHeight = 0;
  1120.     if (!iHeight)
  1121.     {
  1122.         CDC * pdc = GetDC();
  1123.         TEXTMETRIC tm;
  1124.         pdc->GetTextMetrics(&tm);
  1125.         iHeight = tm.tmHeight;
  1126.         ReleaseDC(pdc);
  1127.     }
  1128.     lpMeasureItemStruct->itemHeight = iHeight + 1;
  1129. }
  1130.  
  1131.  
  1132. //================================================================ DeleteItem
  1133. void CNSAddressList::DeleteItem( LPDELETEITEMSTRUCT lpDeleteItemStruct ) 
  1134. {
  1135.     delete (CNSAddressInfo *)GetItemDataPtr( lpDeleteItemStruct->itemID );
  1136. }
  1137.  
  1138. void CNSAddressList::DisplayTypeList(int item)
  1139. {
  1140.     CRect rect;
  1141.     if (item == -1)
  1142.     item = GetActiveSelection();
  1143.     CMenu cmenu;
  1144.     if (cmenu.CreatePopupMenu()) 
  1145.     {
  1146.         for (int i = 0; i < m_pAddressTypeList->GetCount(); i++) 
  1147.         {
  1148.             CString cs;
  1149.             m_pAddressTypeList->GetText(i,cs);
  1150.             cmenu.AppendMenu(MF_STRING, IDM_HEADER+i, cs.Right(cs.GetLength()-1));
  1151.         }
  1152.         GetItemRect(m_hWnd,item,rect);
  1153.         CPoint pt(rect.left + m_iTypeBitmapWidth,rect.bottom);
  1154.         ClientToScreen(&pt);
  1155.         pt.y -= 2;
  1156.         cmenu.TrackPopupMenu(TPM_LEFTALIGN, pt.x, pt.y, this);
  1157.     }
  1158. }
  1159.  
  1160. int CNSAddressList::GetItemRect(HWND hwnd, int nIndex, LPRECT lpRect) const
  1161.     ASSERT(::IsWindow(hwnd)); 
  1162.     return (int)::SendMessage(m_hWnd, LB_GETITEMRECT, nIndex, (LPARAM)lpRect); 
  1163. }
  1164.  
  1165. //=============================================================== OnLButtonDown
  1166. void CNSAddressList::DoLButtonDown(HWND hwnd, UINT nFlags, LPPOINT lpPoint) 
  1167. {
  1168.     if (m_bDrawTypeList)
  1169.     {
  1170.         BOOL bOutside;
  1171.         int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside );
  1172.         RECT rect;
  1173.         GetItemRect(m_hWnd,nNewSelect,&rect);
  1174.         int iHeight = rect.bottom - rect.top;
  1175.         if (((lpPoint->y+iHeight)/iHeight)+GetTopIndex()>GetCount())
  1176.         {
  1177.             if (GetCount())
  1178.             {
  1179.                 CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetCount()-1);
  1180.                 if (!pAddress->GetName()||!strlen(pAddress->GetName()))
  1181.                 {
  1182.                     SetActiveSelection(GetCount()-1);
  1183.                     ::SetFocus(m_pNameField->m_hWnd);
  1184.                     return;
  1185.                 }
  1186.             }
  1187.             AppendEntry();
  1188.             ::SetFocus(m_pNameField->m_hWnd);
  1189.             return;
  1190.         }
  1191.         SetActiveSelection(nNewSelect);
  1192.         rect.right = m_iFieldControlWidth;
  1193.         if ((lpPoint->x >= rect.left) && (lpPoint->x <= rect.right) &&
  1194.             (lpPoint->y >= rect.top) && (lpPoint->y <= rect.bottom))
  1195.         {
  1196.             m_bArrowDown = TRUE;
  1197.             DisplayTypeList(nNewSelect);
  1198.         }
  1199.         else if (lpPoint->x < m_iFieldControlWidth)
  1200.            ::SetFocus(m_pAddressTypeList->m_hWnd);
  1201.         else
  1202.            ::SetFocus(m_pNameField->m_hWnd);
  1203.     }
  1204. }
  1205.  
  1206. void CNSAddressList::DoLButtonUp(HWND hwnd, UINT nFlags, LPPOINT lpPoint)
  1207. {
  1208.     BOOL bOutside;
  1209.     int nNewSelect = ItemFromPoint(hwnd, lpPoint, &bOutside );
  1210.     if ( bOutside ) 
  1211.         return;
  1212.     if (m_bArrowDown) 
  1213.     {
  1214.         m_bArrowDown = FALSE;
  1215.     }
  1216.     else
  1217.     {
  1218.  
  1219.         // set the selection
  1220.         if ( nNewSelect != GetActiveSelection() )
  1221.         {
  1222.             SetActiveSelection( nNewSelect );
  1223.         }
  1224.  
  1225.         // set the focus
  1226.         if (lpPoint->x <=  m_iFieldControlWidth)
  1227.             ::SetFocus(m_pAddressTypeList->m_hWnd);
  1228.         else 
  1229.             ::SetFocus(m_pNameField->m_hWnd);
  1230.     }
  1231. }
  1232.  
  1233. void CNSAddressList::DoVScroll(HWND hwnd, UINT nSBCode, UINT nPos) 
  1234. {
  1235.     ::SetScrollPos(hwnd, SB_VERT, GetTopIndex(), TRUE);
  1236. }
  1237.  
  1238. //========================================================== OnChildLostFocus
  1239. // This method is called when one of the child control looses
  1240. // focus without preparation (ie no Tab or Enter).
  1241.  
  1242. void CNSAddressList::DoChildLostFocus()
  1243. {
  1244.     if (DoNotifySelectionChange() != -1)
  1245.         DoKillFocus(NULL);
  1246. }
  1247.  
  1248. BOOL CNSAddressList::ParseAddressEntry(int nSelection)
  1249. {
  1250.     if (!m_bParse)
  1251.         return FALSE;
  1252.     NSAddressListEntry entry;
  1253.     if (GetEntry(nSelection, &entry))
  1254.     {
  1255.         int iCount;
  1256.         char * pNames = NULL, * pAddresses = NULL;
  1257.         if (!entry.szName || XP_STRLEN (entry.szName) == 0)
  1258.             return FALSE;
  1259.  
  1260.         char * pName = m_pIAddressParent->NameCompletion((char *)entry.szName);
  1261.         if (pName)
  1262.         {
  1263.             free(pName);
  1264.             return FALSE;
  1265.         }
  1266.         
  1267.         iCount = MSG_ParseRFC822Addresses(entry.szName, &pNames, &pAddresses);
  1268.         if (iCount > 1)
  1269.         {
  1270.             char * p1, * p2;
  1271.             char *pLastType = NULL;
  1272.             BOOL bExpanded = FALSE;
  1273.             p1 = pNames;
  1274.             p2 = pAddresses;
  1275.             LockWindowUpdate();
  1276.             for (int i = 0; i<iCount; i++)
  1277.             {
  1278.                 NSAddressListEntry address;
  1279.                 memset(&address,'\0',sizeof(address));
  1280.                 address.szType = entry.szType;
  1281.                 if (pLastType)
  1282.                     free(pLastType);
  1283.                 if (address.szType)
  1284.                     pLastType = strdup(address.szType);
  1285.                 address.szName = MSG_MakeFullAddress(p1,p2);
  1286.                 while (*p1 != '\0') p1++;
  1287.                 p1++;
  1288.                 while (*p2 != '\0') p2++;
  1289.                 p2++;
  1290.                 address.idEntry = (ULONG)-1;
  1291.                 bExpanded = TRUE;
  1292.                 InsertEntry(nSelection+i+1,&address, FALSE);
  1293.             }
  1294.  
  1295.             if (bExpanded)
  1296.             {
  1297.                 DeleteEntry(nSelection);
  1298.                 NSAddressListEntry address;
  1299.                 memset(&address,'\0',sizeof(address));
  1300.                 char * pNextType = NULL;
  1301.                 if (pLastType)
  1302.                 {
  1303.                     if (!strnicmp(pLastType,szLoadString(IDS_ADDRESSTO),strlen(szLoadString(IDS_ADDRESSTO))))
  1304.                         pNextType = szLoadString(IDS_ADDRESSCC);
  1305.                     else if (!strnicmp(pLastType,szLoadString(IDS_ADDRESSCC), strlen(szLoadString(IDS_ADDRESSCC))))
  1306.                         pNextType = szLoadString(IDS_ADDRESSBCC);
  1307.                 }
  1308.                 address.szName = "";
  1309.                 address.szType = pNextType;
  1310.                 address.idEntry = (ULONG)-1;
  1311.                 AppendEntry(pNextType != NULL ? &address : NULL);
  1312.             }
  1313.             if (pLastType)
  1314.                 free(pLastType);
  1315.             ::LockWindowUpdate(NULL);
  1316.             Invalidate();
  1317.             return TRUE;
  1318.         }
  1319.  
  1320.         if (pNames)
  1321.             XP_FREE(pNames);
  1322.         if (pAddresses)
  1323.             XP_FREE(pAddresses);
  1324.  
  1325.     }
  1326.     return FALSE;
  1327. }
  1328.  
  1329. int CNSAddressList::DoNotifySelectionChange()
  1330. {
  1331.     int result = TRUE;
  1332.     if (!ParseAddressEntry(GetActiveSelection()))
  1333.     {
  1334.         if (m_pIAddressParent)
  1335.         {
  1336.             NSAddressListEntry entry;
  1337.             BOOL bRetVal = GetEntry(GetActiveSelection(),&entry);
  1338.             if (bRetVal)
  1339.             {
  1340.                 unsigned long entryID = entry.idEntry;
  1341.                 UINT bitmapID = entry.idBitmap;
  1342.                 char * pszFullName = NULL;
  1343.                 BOOL bExpand = TRUE;
  1344.                 if (m_bDrawTypeList)
  1345.                 {
  1346.                     CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo *)m_pAddressTypeList->GetItemData(
  1347.                         m_pAddressTypeList->GetCurSel());
  1348.                     bExpand = pInfo->GetExpand();
  1349.                 }
  1350.                 if (bExpand)
  1351.                 {
  1352.                     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr(GetActiveSelection());
  1353.                     if (pAddress && pAddress->GetExpansion())
  1354.                     {
  1355.  
  1356.                         result = m_pIAddressParent->ChangedItem(
  1357.                             (char*)entry.szName,GetActiveSelection(),m_hWnd, &pszFullName, &entryID, &bitmapID);
  1358.                         if (pszFullName != NULL)
  1359.                         {
  1360.                             pAddress->SetName(pszFullName);
  1361.                             if (bitmapID)
  1362.                                 SetItemBitmap(GetActiveSelection(), bitmapID);
  1363.                             if (entryID)
  1364.                                 SetItemEntryID(GetActiveSelection(), entryID);
  1365.                             free(pszFullName);
  1366.                         }
  1367.                     }
  1368.                 }
  1369.             }
  1370.             Invalidate();
  1371.         }
  1372.     }
  1373.     return result;
  1374. }
  1375.  
  1376. void CNSAddressList::DoDisplayTypeList()
  1377. {
  1378.     DisplayTypeList();
  1379. }
  1380.  
  1381. void CNSAddressList::SetItemName(int nIndex, char * text)
  1382. {
  1383.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  1384.     pAddress->SetName(text);
  1385. }
  1386.  
  1387. void CNSAddressList::SetItemBitmap(int nIndex, UINT id)
  1388. {
  1389.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  1390.     pAddress->SetBitmap(id);
  1391.     CRect rect;
  1392.     GetItemRect(m_hWnd,nIndex,rect);
  1393. }
  1394.  
  1395. void CNSAddressList::SetItemEntryID(int nIndex, unsigned long id)
  1396. {
  1397.     CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( nIndex );
  1398.     pAddress->SetEntryID(id);
  1399.     CRect rect;
  1400.     GetItemRect(m_hWnd,nIndex,rect);
  1401. }
  1402.  
  1403. BOOL CNSAddressList::DoEraseBkgnd(HWND hwnd, HDC hdc) 
  1404. {
  1405.     RECT rect;
  1406.     ::GetClientRect(hwnd,&rect);
  1407.     if (!m_iItemHeight)
  1408.         m_iItemHeight = GetItemHeight(0);
  1409.     int iGridLines = (rect.bottom-rect.top)/m_iItemHeight;
  1410.     HBRUSH hOldBrush = (HBRUSH)::SelectObject(hdc,(HGDIOBJ)m_hBrushNormal);
  1411.     HPEN hOldPen = (HPEN)::SelectObject(hdc,(HGDIOBJ)m_hPenNormal);
  1412.     int iTotal = GetCount() - GetTopIndex();
  1413.     for (int i = 0; i <= iGridLines; i++)
  1414.     {
  1415.         CRect GridRect(
  1416.             rect.left,rect.top+(i*m_iItemHeight),
  1417.             rect.right,rect.top + ((i+1)*m_iItemHeight) - 1);
  1418.         GridRect.top--;
  1419.         if (i < iTotal)
  1420.             GridRect.left = m_iFieldControlWidth;
  1421.         GridRect.top++;
  1422.         NS_FillSolidRect(hdc,GridRect,GetSysColor(COLOR_WINDOW));
  1423.         GridRect.top--;
  1424.         ::SelectObject(hdc,(HGDIOBJ)m_hPenGrid);
  1425.         ::MoveToEx(hdc,GridRect.left, GridRect.bottom , NULL);
  1426.         ::LineTo(hdc,GridRect.right, GridRect.bottom );
  1427.         if (m_bDrawTypeList && m_pAddressTypeList->GetCount() && (i >= iTotal))
  1428.         {
  1429.             ::MoveToEx(hdc,GridRect.left+m_iFieldControlWidth,GridRect.top, NULL);
  1430.             ::LineTo(hdc,GridRect.left+m_iFieldControlWidth,GridRect.bottom );
  1431.         }
  1432.         ::SelectObject(hdc,(HGDIOBJ)m_hPenNormal);
  1433.     }
  1434.     ::SelectObject(hdc,(HGDIOBJ)hOldPen);
  1435.     ::SelectObject(hdc,(HGDIOBJ)hOldBrush);
  1436.     return TRUE;
  1437. }
  1438.  
  1439. int CNSAddressList::SetAddressList (
  1440.     LPNSADDRESSLIST pAddressList,
  1441.     int count 
  1442.     )
  1443. {
  1444.     ResetContent();
  1445.     if (pAddressList)
  1446.     {
  1447.         for (int index = 0; index < count; index++)
  1448.         {
  1449.             NSAddressListEntry address;
  1450.             address.szType = MSG_HeaderMaskToString(pAddressList[index].ulHeaderType);
  1451.             address.idBitmap = pAddressList[index].idBitmap;
  1452.             address.idEntry = pAddressList[index].idEntry;
  1453.             if (pAddressList[index].szAddress)
  1454.             {
  1455.                 address.szName = strdup (pAddressList[index].szAddress);
  1456.                 free (pAddressList[index].szAddress);
  1457.             }
  1458.             AppendEntry(&address);
  1459.         }
  1460.         free(pAddressList);
  1461.     }
  1462.     return count;
  1463. }
  1464.  
  1465.  
  1466. int CNSAddressList::AppendEntry(
  1467.     BOOL expandName,
  1468.     LPCTSTR szType, 
  1469.     LPCTSTR szName, 
  1470.     UINT idBitmap, 
  1471.     unsigned long idEntry)
  1472. {
  1473.     if (!szType && !szName && !idBitmap && !idEntry)
  1474.         return AppendEntry();
  1475.     NSAddressListEntry address;
  1476.     address.szType = szType;
  1477.     address.szName = szName;
  1478.     address.idBitmap = idBitmap;
  1479.     address.idEntry = idEntry;
  1480.     return AppendEntry(&address, expandName);
  1481. }
  1482.  
  1483. int CNSAddressList::InsertEntry(
  1484.     int nIndex, 
  1485.     BOOL expandName,
  1486.     LPCTSTR szType, 
  1487.     LPCTSTR szName, 
  1488.     UINT idBitmap, 
  1489.     unsigned long idEntry)
  1490. {
  1491.     if (!szType && !szName && !idBitmap && !idEntry)
  1492.         return InsertEntry(nIndex,NULL);
  1493.     NSAddressListEntry address;
  1494.     address.szType = szType;
  1495.     address.szName = szName;
  1496.     address.idBitmap = idBitmap;
  1497.     address.idEntry = idEntry;
  1498.     return InsertEntry(nIndex,&address, expandName);
  1499. }
  1500.  
  1501. BOOL CNSAddressList::SetEntry( 
  1502.     int nIndex, 
  1503.     LPCTSTR szType, 
  1504.     LPCTSTR szName, 
  1505.     UINT idBitmap, 
  1506.     unsigned long idEntry)
  1507. {
  1508.     NSAddressListEntry address;
  1509.     address.szType = szType;
  1510.     address.szName = szName;
  1511.     address.idBitmap = idBitmap;
  1512.     address.idEntry = idEntry;
  1513.     return SetEntry(nIndex,&address);
  1514. }
  1515.  
  1516. #pragma optimize
  1517. void CNSAddressList::GetTypeInfo(
  1518.     int nIndex, 
  1519.     ADDRESS_TYPE_FLAG flag, 
  1520.     void ** pData)
  1521. {
  1522.     CListBox * pTypeList = GetAddressTypeComboBox();
  1523.     CNSAddressTypeInfo * pInfo = (CNSAddressTypeInfo*)pTypeList->GetItemData(nIndex);
  1524.     ASSERT(pData);
  1525.     *pData = NULL;
  1526.     if (flag & ADDRESS_TYPE_FLAG_VALUE)
  1527.         *pData = (void*)pInfo->GetValue();
  1528.     else if (flag & ADDRESS_TYPE_FLAG_HIDDEN)
  1529.         *pData = (void*)pInfo->GetHidden();
  1530.     else if (flag & ADDRESS_TYPE_FLAG_EXCLUSIVE)
  1531.         *pData = (void*)pInfo->GetExclusive();
  1532.     else if (flag & ADDRESS_TYPE_FLAG_USER)
  1533.         *pData = (void*)pInfo->GetUserData();
  1534.     else if (flag & ADDRESS_TYPE_FLAG_BITMAP)
  1535.         *pData = (void*)pInfo->GetBitmap();
  1536. }
  1537.  
  1538. BOOL CNSAddressList::GetEntry( 
  1539.     int nIndex, 
  1540.     char **szType, 
  1541.     char **szName, 
  1542.     UINT *idBitmap, 
  1543.     unsigned long *idEntry)
  1544. {
  1545.     NSAddressListEntry address;
  1546.     BOOL bRetVal = GetEntry(nIndex,&address);
  1547.     if (bRetVal)
  1548.     {
  1549.         if (szType)
  1550.             *szType = (char*)address.szType;
  1551.         if (szName)
  1552.             *szName = (char*)address.szName;
  1553.         if (idBitmap)
  1554.             *idBitmap = address.idBitmap;
  1555.         if (idEntry)
  1556.             *idEntry = address.idEntry;
  1557.     }
  1558.     return bRetVal;
  1559. }
  1560.  
  1561.  
  1562. int CNSAddressList::GetAddressList (
  1563.     LPNSADDRESSLIST * ppAddressList
  1564.     )
  1565. {
  1566.     int count = GetCount();
  1567.     if (count)
  1568.     {
  1569.         *ppAddressList = (LPNSADDRESSLIST)calloc(count,sizeof(NSADDRESSLIST));
  1570.         if (*ppAddressList)
  1571.         {
  1572.             for (int index = 0; index < count; index++)
  1573.             {
  1574.                 CNSAddressInfo *pAddress = (CNSAddressInfo *)GetItemDataPtr( index );
  1575.                 ASSERT(pAddress);
  1576.                 if (pAddress->GetType())
  1577.                     (*ppAddressList)[index].ulHeaderType = 
  1578.                     MSG_StringToHeaderMask(pAddress->GetType());
  1579.                 if (pAddress->GetName())
  1580.                     (*ppAddressList)[index].szAddress = strdup(pAddress->GetName());
  1581.                 (*ppAddressList)[index].idEntry = pAddress->GetEntryID();
  1582.                 (*ppAddressList)[index].idBitmap = pAddress->GetBitmap();
  1583.             }
  1584.         }
  1585.     }
  1586.     return count;
  1587. }
  1588.  
  1589. STDMETHODIMP CNSAddressList::QueryInterface(
  1590.    REFIID refiid,
  1591.    LPVOID * ppv)
  1592. {
  1593.     *ppv = NULL;
  1594.  
  1595.     if (IsEqualIID(refiid,IID_IAddressControl))
  1596.         *ppv = (LPADDRESSCONTROL) this;
  1597.  
  1598.     if (*ppv != NULL) {
  1599.          AddRef();
  1600.          return NOERROR;
  1601.     }
  1602.  
  1603.     return CGenericObject::QueryInterface(refiid,ppv);
  1604. }
  1605.  
  1606. STDMETHODIMP_(ULONG) CNSAddressList::Release(void)
  1607. {
  1608.    ULONG ulRef;
  1609.    ulRef = --m_ulRefCount;
  1610.    if (m_ulRefCount == 0) {
  1611.       LPAPIAPI  pApiapi = GetAPIAPI();
  1612.       pApiapi->RemoveInstance(this);
  1613.       delete this;
  1614.    }
  1615.     return ulRef;       
  1616. }
  1617.  
  1618. // Address Control Factory
  1619. ////////////////////////////////////////////////////////////////////////////////////////
  1620.  
  1621. class CNSAddressControlFactory :  public  CGenericFactory
  1622. {
  1623. public:
  1624.     CNSAddressControlFactory();
  1625.     ~CNSAddressControlFactory();
  1626.     STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,REFIID refiid, LPVOID * ppvObj);
  1627. };
  1628.  
  1629. CNSAddressControlFactory::CNSAddressControlFactory()
  1630. {
  1631.     ApiApiPtr(api);
  1632.     api->RegisterClassFactory(APICLASS_ADDRESSCONTROL,this);
  1633. }
  1634.  
  1635. CNSAddressControlFactory::~CNSAddressControlFactory()
  1636. {
  1637. }
  1638.  
  1639. STDMETHODIMP CNSAddressControlFactory::CreateInstance(
  1640.     LPUNKNOWN pUnkOuter,
  1641.     REFIID refiid,
  1642.     LPVOID * ppvObj)
  1643. {
  1644.     CNSAddressList * pAddressControl = new CNSAddressList;
  1645.     *ppvObj = (LPVOID)((LPUNKNOWN)pAddressControl);
  1646.     return NOERROR;
  1647. }
  1648.  
  1649.  
  1650. static void FillSolidRect(HDC hdc, LPCRECT lpRect, COLORREF clr)
  1651. {
  1652.     ::SetBkColor(hdc, clr);
  1653.     ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
  1654. }
  1655.  
  1656. static void FillSolidRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clr)
  1657. {
  1658.     ::SetBkColor(hdc, clr);
  1659.     RECT rect;
  1660.     rect.left = x;
  1661.     rect.top = y;
  1662.     rect.right =  x + cx;
  1663.     rect.bottom = y + cy;
  1664.     ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
  1665. }
  1666.  
  1667. static void Draw3dRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
  1668. {
  1669.     FillSolidRect(hdc, x, y, cx - 1, 1, clrTopLeft);
  1670.     FillSolidRect(hdc, x, y, 1, cy - 1, clrTopLeft);
  1671.     FillSolidRect(hdc, x + cx, y, -1, cy, clrBottomRight);
  1672.     FillSolidRect(hdc, x, y + cy, cx, -1, clrBottomRight);
  1673. }
  1674.  
  1675. static void Draw3dRect(HDC hdc, LPCRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
  1676. {
  1677.     Draw3dRect(hdc, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  1678.         lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
  1679. }
  1680.  
  1681. void NS_FillSolidRect(HDC hdc, LPCRECT crRect, COLORREF rgbFill)    {
  1682.     FillSolidRect(hdc,crRect, rgbFill);
  1683. }
  1684.  
  1685. void NS_Draw3dRect(HDC hdc, LPCRECT crRect, COLORREF rgbTL, COLORREF rgbBR)    
  1686. {
  1687. #ifdef XP_WIN32
  1688.     Draw3dRect(hdc, crRect, rgbTL, rgbBR);
  1689. #else
  1690.     CRect crMunge = crRect;
  1691.     crMunge.right -= 1;
  1692.     crMunge.bottom = crMunge.top + 1;    
  1693.     NS_FillSolidRect(hdc, crMunge, rgbTL);
  1694.     
  1695.     crMunge = crRect;
  1696.     crMunge.right = crMunge.left + 1;
  1697.     crMunge.bottom -= 1;
  1698.     NS_FillSolidRect(hdc, crMunge, rgbTL);
  1699.     
  1700.     crMunge = crRect;
  1701.     crMunge.left += crMunge.right;
  1702.     crMunge.right -= 1;
  1703.     NS_FillSolidRect(hdc, crMunge, rgbBR);
  1704.     
  1705.     crMunge = crRect;
  1706.     crMunge.top = crMunge.bottom;
  1707.     crMunge.bottom -= 1;
  1708.     NS_FillSolidRect(hdc, crMunge, rgbBR);
  1709. #endif    
  1710. }
  1711.  
  1712. //============================================================= DrawHighlight
  1713. // Draw the highlight around the area
  1714. static void DrawHighlight( HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight )
  1715. {
  1716.     HPEN hpenTopLeft = ::CreatePen( PS_SOLID, 0, clrTopLeft );
  1717.     HPEN hpenBottomRight = ::CreatePen( PS_SOLID, 0, clrBottomRight );
  1718.     HPEN hpenOld = (HPEN) ::SelectObject( hDC, hpenTopLeft );
  1719.  
  1720.     ::MoveToEx( hDC, lpRect->left, lpRect->bottom, NULL );
  1721.     ::LineTo( hDC, lpRect->left, lpRect->top );
  1722.     ::LineTo( hDC, lpRect->right - 1, lpRect->top );
  1723.  
  1724.     ::SelectObject( hDC, hpenBottomRight );
  1725.     ::LineTo( hDC, lpRect->right - 1, lpRect->bottom - 1);
  1726.     ::LineTo( hDC, lpRect->left, lpRect->bottom - 1);
  1727.  
  1728.     ::SelectObject( hDC, hpenOld );
  1729.  
  1730.     VERIFY(::DeleteObject( hpenTopLeft ));
  1731.     VERIFY(::DeleteObject( hpenBottomRight ));
  1732. }
  1733.  
  1734.  
  1735. //============================================================ DrawRaisedRect
  1736. void NS_DrawRaisedRect( HDC hDC, LPRECT lpRect )
  1737. {
  1738.     RECT rcTmp = *lpRect;
  1739.     ::InflateRect( &rcTmp, -1, -1 );
  1740. #ifdef _WIN32
  1741.     DrawHighlight( hDC, &rcTmp, 
  1742.                    GetSysColor( COLOR_3DLIGHT ), 
  1743.                    GetSysColor( COLOR_3DSHADOW ) );
  1744.     DrawHighlight( hDC, lpRect, 
  1745.                    GetSysColor( COLOR_3DHILIGHT ), 
  1746.                    GetSysColor( COLOR_3DDKSHADOW ) );
  1747. #else
  1748.     DrawHighlight( hDC, lpRect, 
  1749.                    GetSysColor( COLOR_BTNHIGHLIGHT ), 
  1750.                    GetSysColor( COLOR_BTNSHADOW ) );
  1751.     DrawHighlight( hDC, &rcTmp, 
  1752.                    GetSysColor( COLOR_BTNHIGHLIGHT ), 
  1753.                    GetSysColor( COLOR_BTNSHADOW ) );
  1754. #endif
  1755. }
  1756.  
  1757.  
  1758. //=========================================================== DrawLoweredRect
  1759. void NS_DrawLoweredRect( HDC hDC, LPRECT lpRect )
  1760. {
  1761.     RECT rcTmp = *lpRect;
  1762.     ::InflateRect( &rcTmp, -1, -1 );
  1763. #ifdef _WIN32
  1764.     DrawHighlight( hDC, &rcTmp, 
  1765.                    GetSysColor( COLOR_3DSHADOW ), 
  1766.                    GetSysColor( COLOR_3DLIGHT ) );
  1767.     DrawHighlight( hDC, lpRect, 
  1768.                    GetSysColor( COLOR_3DDKSHADOW ), 
  1769.                    GetSysColor( COLOR_3DHILIGHT) );
  1770. #else
  1771.     DrawHighlight( hDC, &rcTmp, 
  1772.                    GetSysColor( COLOR_BTNSHADOW ), 
  1773.                    GetSysColor( COLOR_BTNHIGHLIGHT ) );
  1774.     DrawHighlight( hDC, lpRect, 
  1775.                    GetSysColor( COLOR_BTNSHADOW ), 
  1776.                    GetSysColor( COLOR_BTNHIGHLIGHT ) );
  1777. #endif
  1778. }
  1779.  
  1780. void NS_Draw3DButtonRect( HDC hDC, LPRECT lpRect, BOOL bPushed )
  1781. {
  1782.     if ( bPushed ) {
  1783.         NS_DrawLoweredRect( hDC, lpRect );
  1784.     } else {
  1785.         NS_DrawRaisedRect( hDC, lpRect );
  1786.     }
  1787. }
  1788.  
  1789. #if defined(__APIAPIDLL)
  1790. __declspec( dllexport )
  1791. int ApiBooter(char * pszClassName)
  1792. {
  1793.     if (!stricmp(pszClassName,APICLASS_ADDRESSCONTROL))
  1794.         new CNSAddressControlFactory;
  1795.     return 1;
  1796. }
  1797. #else
  1798. DECLARE_FACTORY(CNSAddressControlFactory);
  1799. #endif
  1800.  
  1801. // Address Control Object
  1802.  
  1803.