home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / msgview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  23.0 KB  |  896 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. #include "stdafx.h"
  19. #include "msgcom.h"
  20. #include "mailfrm.h"
  21. #include "msgview.h"
  22. #include "fegui.h"
  23. #include "shcut.h"
  24. #include "cxsave.h"
  25. #include "thrdfrm.h"
  26. #include "rdfglobal.h"
  27.  
  28. #ifndef _AFXDLL
  29. #undef new
  30. #endif
  31. IMPLEMENT_DYNCREATE(CMessageBodyView, CNetscapeView)
  32. #ifndef _AFXDLL
  33. #define new DEBUG_NEW
  34. #endif
  35.  
  36. #ifdef _WIN32
  37.  
  38. /////////////////////////////////////////////////////////////////////
  39. //
  40. // CAttachmentDataSource
  41. //
  42. // DataSource for attachment download for drag-and-drop
  43. //
  44.  
  45. class CAttachmentDataSource: public COleDataSource
  46. {
  47. protected:
  48.     CString m_csURL, m_csName;
  49.  
  50. public:
  51.     CAttachmentDataSource(LPCTSTR lpszURL, LPCTSTR lpszName);
  52.  
  53.     virtual BOOL OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal);
  54. };
  55.  
  56. CAttachmentDataSource::CAttachmentDataSource(LPCTSTR lpszURL, LPCSTR lpszName)
  57. {
  58.     m_csURL = lpszURL;
  59.     m_csName = lpszName;
  60. }
  61.  
  62. BOOL CAttachmentDataSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal)
  63. {
  64.     BOOL bRes = FALSE;
  65.  
  66.     if (!*phGlobal) {
  67.         bRes = CSaveCX::SaveToGlobal(phGlobal, m_csURL, m_csName);
  68.     }
  69.  
  70.     return bRes;
  71. }
  72.  
  73. #endif
  74.  
  75. /////////////////////////////////////////////////////////////////////
  76. //
  77. // CAttachmentTray
  78. //
  79.  
  80. CAttachmentTray::CAttachmentTray()
  81. {
  82.     m_hFont = 0;
  83.     SetCSID(CIntlWin::GetSystemLocaleCsid(), FALSE);
  84.  
  85.     ::SetRectEmpty(&m_rcClient);
  86.  
  87.     m_pAttachmentData = NULL;
  88.     m_nAttachmentCount = 0;
  89.     m_aAttachAux = NULL;
  90.  
  91.     m_sizeSpacing.cx = ::GetSystemMetrics(SM_CXICONSPACING);
  92.     m_sizeSpacing.cy = ::GetSystemMetrics(SM_CYICONSPACING);
  93.     m_sizeIcon.cx = ::GetSystemMetrics(SM_CXICON);
  94.     m_sizeIcon.cy = ::GetSystemMetrics(SM_CYICON);
  95.  
  96.     m_ptOrigin.x = 0;
  97.     m_ptOrigin.y = 0;
  98.     m_sizeMax.cx = 0;
  99.     m_sizeMax.cy = 0;
  100. }
  101.  
  102. CAttachmentTray::~CAttachmentTray()
  103. {
  104.     for (int i = 0; i < m_nAttachmentCount; i++)
  105. #ifdef _WIN32
  106.         ImageList_Destroy(m_aAttachAux[i].hImage);
  107. #else
  108.         DestroyIcon(m_aAttachAux[i].hIcon);
  109. #endif
  110.     delete [] m_aAttachAux;
  111.     theApp.ReleaseAppFont(m_hFont);
  112. }
  113.  
  114. HICON CAttachmentTray::DredgeUpIcon(char *name)
  115. {
  116.     // Get the default icon
  117.     HICON res = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_FILE));
  118. #ifdef _WIN32
  119.     if (sysInfo.m_bWin4) {
  120.         // Do we have a name?
  121.         if (name) {
  122.             // Dig out the extension
  123.             char *pszExt = strrchr(name, '.');
  124.  
  125.             // Did we get an extension?
  126.             if (pszExt) {
  127.                 // Look up the file type
  128.                 _TCHAR szBuf[32];
  129.                 LONG cbBuf = 32;
  130.                 LONG lres = ::RegQueryValue( HKEY_CLASSES_ROOT, pszExt, szBuf, &cbBuf );
  131.  
  132.                 // Did we find a file type?
  133.                 if (lres == ERROR_SUCCESS) {
  134.                     // Figure out the default icon path
  135.                     _TCHAR szIconPath[_MAX_PATH];
  136.                     _TCHAR szRegKey[_MAX_PATH];
  137.                     LONG cbIconPath = _MAX_PATH;
  138.  
  139.                     _tcscpy(szRegKey, szBuf);
  140.                     _tcscat(szRegKey, _T("\\DefaultIcon"));
  141.  
  142.                     lres = ::RegQueryValue( HKEY_CLASSES_ROOT, szRegKey, szIconPath, &cbIconPath );
  143.  
  144.                     // Did we get an icon path
  145.                     if (lres == ERROR_SUCCESS) {
  146.                         // Split up the path given to us
  147.                         _TCHAR *pszPath = _tcstok(szIconPath, ",");
  148.                         _TCHAR *pszIndex = _tcstok(NULL, ",");
  149.                         UINT nIndex = pszIndex ? _ttoi(pszIndex) : 0;
  150.  
  151.                         // Go get the icon
  152.                         HICON resIcon = ::ExtractIcon(AfxGetInstanceHandle(), pszPath, nIndex);
  153.                         if (resIcon && (int) resIcon != 1) {
  154.                             res = resIcon;
  155.                         }
  156.                     }
  157.                 }
  158.             }
  159.         }
  160.     }
  161. #endif
  162.     return res;
  163. }
  164.  
  165. void CAttachmentTray::SetAttachments(int nAttachmentCount, MSG_AttachmentData *pAttachmentData)
  166. {
  167.     // Clean up old images
  168.     if (nAttachmentCount < m_nAttachmentCount) {
  169.         for (int i = 0; i < m_nAttachmentCount; i++)
  170. #ifdef _WIN32
  171.             ImageList_Destroy(m_aAttachAux[i].hImage);
  172. #else
  173.             DestroyIcon(m_aAttachAux[i].hIcon);
  174. #endif
  175.         delete [] m_aAttachAux;
  176.         m_aAttachAux = NULL;
  177.         m_nAttachmentCount = 0;
  178.     }
  179.  
  180.     AttachAux *aTemp = nAttachmentCount > 0 ? new AttachAux[nAttachmentCount] : NULL;
  181.  
  182.     if (nAttachmentCount > 0) {
  183.         int i = 0;
  184.         while (i < nAttachmentCount) {
  185.             if (i < m_nAttachmentCount) {
  186.                 aTemp[i] = m_aAttachAux[i];
  187.             } else {
  188.                 aTemp[i].bSelected = FALSE;
  189. #ifdef _WIN32
  190.                 aTemp[i].hImage = ImageList_Create(m_sizeIcon.cx, m_sizeIcon.cy, ILC_MASK, 1, 1);
  191.                 ImageList_AddIcon(aTemp[i].hImage, DredgeUpIcon(pAttachmentData[i].real_name));
  192. #else
  193.                 aTemp[i].hIcon = DredgeUpIcon(pAttachmentData[i].real_name);
  194. #endif
  195.                 aTemp[i].ptPos.x = 0;
  196.                 aTemp[i].ptPos.y = 0;
  197.             }
  198.             i++;
  199.         }
  200.     }
  201.  
  202.     delete [] m_aAttachAux;
  203.     m_aAttachAux = aTemp;
  204.     m_nAttachmentCount = nAttachmentCount;
  205.     m_pAttachmentData = pAttachmentData;
  206.  
  207.     Layout();
  208.     UpdateWindow();
  209. }
  210.  
  211. void CAttachmentTray::Layout()
  212. {
  213.     int x = 0;
  214.     int y = 0;
  215.     for (int i = 0; i < m_nAttachmentCount; i++) {
  216.         m_aAttachAux[i].ptPos.x = x;
  217.         m_aAttachAux[i].ptPos.y = y;
  218.  
  219.         m_sizeMax.cx = MAX(x + m_sizeSpacing.cx, m_sizeMax.cy);
  220.         m_sizeMax.cy = MAX(y + m_sizeSpacing.cy, m_sizeMax.cy);
  221.  
  222.         x += m_sizeSpacing.cx;
  223.         if ( (x + m_sizeSpacing.cx) > m_rcClient.right ) {
  224.             x = 0;
  225.             y += m_sizeSpacing.cy;
  226.         }
  227.     }
  228.     
  229.     if (m_sizeMax.cy > m_rcClient.bottom) {
  230.         ShowScrollBar(SB_VERT, TRUE);
  231. #ifdef WIN32
  232.         SCROLLINFO ScrollInfo;
  233.         ScrollInfo.cbSize = sizeof(SCROLLINFO);
  234.         ScrollInfo.fMask = SIF_PAGE|SIF_RANGE|SIF_POS;
  235.         ScrollInfo.nMin = 0;
  236.         ScrollInfo.nMax = m_sizeMax.cy;
  237.         ScrollInfo.nPage = m_sizeSpacing.cy;
  238.         ScrollInfo.nPos = m_ptOrigin.y;
  239.         SetScrollInfo(SB_VERT, &ScrollInfo, TRUE);
  240. #else
  241.         SetScrollPos(SB_VERT, m_ptOrigin.y);
  242.         SetScrollRange(SB_VERT, 0, m_sizeMax.cy - m_sizeSpacing.cy + 1, TRUE);
  243. #endif
  244.     } else {
  245.         ShowScrollBar ( SB_VERT, FALSE );
  246.     }
  247.  
  248. }
  249.  
  250. BOOL CAttachmentTray::WaitForDrag()
  251. {
  252.     BOOL bDrag = FALSE;
  253.  
  254.     POINT pt;
  255.     RECT rcDrag;
  256. #ifdef _WIN32
  257.     int dx = ::GetSystemMetrics(SM_CXDRAG);
  258.     int dy = ::GetSystemMetrics(SM_CYDRAG);
  259. #else
  260.     int dx = ::GetSystemMetrics(SM_CXDOUBLECLK);
  261.     int dy = ::GetSystemMetrics(SM_CYDOUBLECLK);
  262. #endif
  263.  
  264.     GetCursorPos(&pt);
  265.     
  266.     ::SetRect(&rcDrag, pt.x - dx, pt.y - dy, pt.x + dx, pt.y + dy);
  267.  
  268.     SetCapture();
  269.     while (!bDrag)
  270.     {
  271.         // some applications steal capture away at random times
  272.         if (CWnd::GetCapture() != this)
  273.             break;
  274.  
  275.         // peek for next input message
  276.         MSG msg;
  277.         if (::PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
  278.             ::PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
  279.         {
  280.             // check for button cancellation (any button down will cancel)
  281.             if (msg.message == WM_LBUTTONUP || msg.message == WM_RBUTTONUP ||
  282.                 msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN)
  283.                 break;
  284.  
  285.             // check for keyboard cancellation
  286.             if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
  287.                 break;
  288.  
  289.             // check for drag start transition
  290.             bDrag = !::PtInRect(&rcDrag, msg.pt);
  291.         }
  292.     }
  293.     ReleaseCapture();
  294.     return bDrag;
  295. }
  296.  
  297.  
  298. int CAttachmentTray::Point2Index(POINT pt)
  299. {
  300.     int i = 0;
  301.     int x = pt.x + m_ptOrigin.x;
  302.     int y = pt.y + m_ptOrigin.y;
  303.     while (i < m_nAttachmentCount) {
  304.         if (x >= m_aAttachAux[i].ptPos.x && 
  305.             y >= m_aAttachAux[i].ptPos.y &&
  306.             x < (m_aAttachAux[i].ptPos.x + m_sizeSpacing.cx) &&
  307.             y < (m_aAttachAux[i].ptPos.y + m_sizeSpacing.cy)) {
  308.             return i;
  309.         }
  310.         i++;
  311.     }
  312.     return -1;
  313. }
  314.  
  315. void CAttachmentTray::Index2Rect(int idx, RECT &rect)
  316. {
  317.     ::SetRectEmpty(&rect);
  318.  
  319.     if (idx < 0 || idx >= m_nAttachmentCount)
  320.         return;
  321.  
  322.     rect.left = m_aAttachAux[idx].ptPos.x - m_ptOrigin.x;
  323.     rect.top = m_aAttachAux[idx].ptPos.y - m_ptOrigin.y;
  324.     rect.right = rect.left + m_sizeSpacing.cx;
  325.     rect.bottom = rect.top + m_sizeSpacing.cy;
  326. }
  327.  
  328. void CAttachmentTray::ClearSelection()
  329. {
  330.     for (int i = 0; i < m_nAttachmentCount; i++) {
  331.         if (m_aAttachAux[i].bSelected) {
  332.             m_aAttachAux[i].bSelected = FALSE;
  333.             RECT rcInval;
  334.             Index2Rect(i, rcInval);
  335.             InvalidateRect(&rcInval);
  336.         }
  337.     }
  338. }
  339.  
  340. BEGIN_MESSAGE_MAP(CAttachmentTray, CWnd)
  341.     ON_WM_PAINT()
  342.     ON_WM_SIZE()
  343.     ON_WM_LBUTTONDOWN()
  344.     ON_WM_LBUTTONDBLCLK()
  345.     ON_WM_RBUTTONDOWN()
  346.     ON_WM_VSCROLL()
  347. END_MESSAGE_MAP()
  348.  
  349. void CAttachmentTray::OnPaint()
  350. {
  351.     CPaintDC dc(this);
  352.  
  353.     HBRUSH hbrush = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
  354.     ::FillRect( dc.m_hDC, &dc.m_ps.rcPaint, hbrush );
  355.     VERIFY(::DeleteObject(hbrush));
  356.  
  357.     int i = 0;
  358.  
  359.     HFONT hOldFont = (HFONT) dc.SelectObject(m_hFont);
  360.     COLORREF oldTextColor = dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  361.     COLORREF oldTextBkColor = dc.SetBkColor(GetSysColor(COLOR_WINDOW));
  362.     while (i < m_nAttachmentCount) {
  363.         int x = m_aAttachAux[i].ptPos.x - m_ptOrigin.x;
  364.         int y = m_aAttachAux[i].ptPos.y - m_ptOrigin.y;
  365.  
  366.         RECT rcInter, rcIcon;
  367.         ::SetRect(&rcIcon, x, y, x + m_sizeSpacing.cx, y + m_sizeSpacing.cy);
  368.         if (::IntersectRect(&rcInter, &rcIcon, &dc.m_ps.rcPaint)) {
  369.             RECT rcText;
  370.             ::SetRect(&rcText, x, y + m_sizeIcon.cy + 8, x+m_sizeSpacing.cx, y + m_sizeSpacing.cy - 2);
  371.             int dx = x + (m_sizeSpacing.cx - m_sizeIcon.cx) / 2;
  372.             int dy = y + 6;
  373.             
  374. #ifdef _WIN32
  375.             if (m_aAttachAux[i].hImage)
  376.                 ImageList_Draw(m_aAttachAux[i].hImage, 0, dc.m_hDC, dx, dy, 
  377.                                m_aAttachAux[i].bSelected ? ILD_SELECTED : ILD_NORMAL);
  378. #else
  379.             if (m_aAttachAux[i].hIcon) {
  380.                 dc.DrawIcon(dx, dy, m_aAttachAux[i].hIcon);
  381.             }
  382. #endif
  383.             if (m_aAttachAux[i].bSelected) {
  384.                 dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
  385.                 dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
  386.             } else {
  387.                 dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
  388.                 dc.SetBkColor(GetSysColor(COLOR_WINDOW));
  389.             }
  390.             if (m_pAttachmentData[i].real_name)
  391.                 WFE_DrawTextEx(0, dc.m_hDC, m_pAttachmentData[i].real_name, -1, &rcText,
  392.                                DT_CENTER|DT_NOPREFIX, WFE_DT_CROPRIGHT);
  393.         }
  394.         i++;
  395.     }
  396.  
  397.     if (hOldFont)
  398.         dc.SelectObject(hOldFont);
  399.     dc.SetTextColor(oldTextColor);
  400.     dc.SetBkColor(oldTextBkColor);
  401. }
  402.  
  403. void CAttachmentTray::OnSize( UINT nType, int cx, int cy )
  404. {
  405.     if (nType != SIZE_MINIMIZED && 
  406.         (m_rcClient.right != cx || m_rcClient.bottom != cy)) {
  407.  
  408.         m_rcClient.right = cx;
  409.         m_rcClient.bottom = cy;
  410.  
  411.         Layout();
  412.     }
  413. }
  414.  
  415. #define ABS(x) ((x) < 0 ? (-x) : (x))
  416.  
  417. void CAttachmentTray::OnLButtonDown( UINT nFlags, CPoint point )
  418. {    
  419.     int idx = Point2Index(point);
  420.  
  421.     // Ignore if nothing hit, for now
  422.     if (idx >= 0) {
  423.         RECT rect;
  424.         Index2Rect(idx, rect);
  425.  
  426.         BOOL bSel = m_aAttachAux[idx].bSelected;
  427.         BOOL bCtrl = ::GetKeyState(VK_CONTROL) & 0x8000;
  428.  
  429.         // If not selected, select immediately
  430.         if (!bSel) {
  431.             ClearSelection();
  432.             m_aAttachAux[idx].bSelected = TRUE;
  433.             InvalidateRect(&rect);
  434.             UpdateWindow();
  435.         }
  436.  
  437.         if (WaitForDrag()) {
  438.             CString csUntitled;
  439.             csUntitled.LoadString(IDS_UNTITLED);
  440.  
  441.             // Drag Drop Section
  442.             const char *name = "";
  443.             if (m_pAttachmentData[idx].real_name)
  444.                 name = m_pAttachmentData[idx].real_name;
  445.             else
  446.                 name = csUntitled;
  447.  
  448. #ifdef _WIN32
  449.             COleDataSource *pDataSource = new CAttachmentDataSource(m_pAttachmentData[idx].url, name);
  450.  
  451.             HGLOBAL hfgd = GlobalAlloc(GMEM_ZEROINIT|GMEM_SHARE,sizeof(FILEGROUPDESCRIPTOR));
  452.             LPFILEGROUPDESCRIPTOR lpfgd = (LPFILEGROUPDESCRIPTOR) GlobalLock(hfgd);
  453.  
  454.             // one file in the file descriptor block
  455.             lpfgd->cItems = 1;
  456.             lpfgd->fgd[0].dwFlags = 0;
  457.             strcpy(lpfgd->fgd[0].cFileName, name);
  458.             GlobalUnlock (hfgd);
  459.  
  460.             // register the file descriptor clipboard format
  461.             UINT cfFileDescriptor = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
  462.  
  463.             // register the clipboard format for file contents
  464.             UINT cfFileContents = RegisterClipboardFormat(CFSTR_FILECONTENTS);
  465.  
  466.             pDataSource->CacheGlobalData(cfFileDescriptor, hfgd);
  467.  
  468.             FORMATETC formatEtc;
  469.             formatEtc.cfFormat = cfFileContents;
  470.             formatEtc.ptd = NULL;
  471.             formatEtc.dwAspect = DVASPECT_CONTENT;
  472.             formatEtc.lindex = 0;
  473.             formatEtc.tymed = TYMED_HGLOBAL;
  474.             pDataSource->DelayRenderFileData(cfFileContents, &formatEtc);
  475.  
  476. #else
  477.             COleDataSource *pDataSource = new COleDataSource;
  478. #endif
  479.             RDFGLOBAL_DragTitleAndURL(pDataSource, name, m_pAttachmentData[idx].url);
  480.  
  481.             DROPEFFECT res = pDataSource->DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_SCROLL );
  482.  
  483.             pDataSource->Empty();
  484.             delete pDataSource;
  485.         } else {
  486.             if (bSel && bCtrl) {
  487.                 m_aAttachAux[idx].bSelected = FALSE;
  488.                 InvalidateRect(&rect);
  489.                 UpdateWindow();
  490.             }
  491.         }
  492.     }
  493. }
  494.  
  495. void CAttachmentTray::OnLButtonDblClk( UINT nFlags, CPoint point )
  496. {
  497.     int idx = Point2Index(point);
  498.     if (idx >= 0) {
  499.         GetParentFrame()->PostMessage(WM_COMMAND, (WPARAM) (FIRST_ATTACH_MENU_ID + idx), (LPARAM) 0);
  500.     }
  501. }
  502.  
  503. void CAttachmentTray::OnRButtonDown( UINT nFlags, CPoint point )
  504. {    
  505.     int idx = Point2Index(point);
  506.  
  507.     // Ignore if nothing hit, for now
  508.     if (idx >= 0) {
  509.         RECT rect;
  510.         Index2Rect(idx, rect);
  511.  
  512.         BOOL bSel = m_aAttachAux[idx].bSelected;
  513.         BOOL bCtrl = ::GetKeyState(VK_CONTROL) & 0x8000;
  514.  
  515.         // If not selected, select immediately
  516.         if (!bSel) {
  517.             ClearSelection();
  518.             m_aAttachAux[idx].bSelected = TRUE;
  519.             InvalidateRect(&rect);
  520.             UpdateWindow();
  521.         }
  522.         HMENU hMenu = ::CreatePopupMenu();
  523.         ::AppendMenu(hMenu, MF_STRING, (FIRST_ATTACH_MENU_ID + idx), szLoadString(IDS_POPUP_OPENATTACHMENT));
  524.         ::AppendMenu(hMenu, MF_STRING, (FIRST_SAVEATTACH_MENU_ID + idx), szLoadString(IDS_POPUP_SAVEATTACHMENTAS));
  525.         ::AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
  526.         ::AppendMenu(hMenu, MF_STRING, (FIRST_ATTACHPROP_MENU_ID + idx), szLoadString(IDS_POPUP_ATTACHMENTPROP));
  527.  
  528.         ::ClientToScreen(m_hWnd, &point);
  529.         ::TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, 0, 
  530.                          GetParentFrame()->GetSafeHwnd(), NULL);
  531.         ::DestroyMenu(hMenu);
  532.     }
  533. }
  534.  
  535. void CAttachmentTray::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
  536. {
  537.     POINT  ptOld = m_ptOrigin;
  538.  
  539.     switch (nSBCode) {
  540.     case SB_BOTTOM:
  541.         m_ptOrigin.y = m_sizeMax.cy - m_sizeSpacing.cy;
  542.         break;
  543.     case SB_ENDSCROLL:
  544.         break;
  545.     case SB_LINEDOWN:
  546.         m_ptOrigin.y++;
  547.         break;
  548.     case SB_LINEUP:
  549.         m_ptOrigin.y--;
  550.         break;
  551.     case SB_PAGEDOWN:
  552.         m_ptOrigin.y += m_sizeSpacing.cy;
  553.         break;
  554.     case SB_PAGEUP:
  555.         m_ptOrigin.y -= m_sizeSpacing.cy;
  556.         break;
  557.     case SB_THUMBPOSITION:
  558.     case SB_THUMBTRACK:
  559.         m_ptOrigin.y = nPos;
  560.         break;
  561.     case SB_TOP:
  562.         m_ptOrigin.y = 0;
  563.         break;
  564.     }
  565.     if (m_ptOrigin.y < 0)
  566.         m_ptOrigin.y = 0;
  567.     if (m_ptOrigin.y > (m_sizeMax.cy - m_rcClient.bottom))
  568.         m_ptOrigin.y = m_sizeMax.cy - m_rcClient.bottom;
  569.  
  570.     int iDiff = ptOld.y - m_ptOrigin.y;
  571.     if ( iDiff != 0 )
  572.     {
  573.         ScrollWindow(0, iDiff );
  574.         UpdateWindow();
  575.     }
  576.     SetScrollPos ( SB_VERT, m_ptOrigin.y );
  577. }
  578.  
  579. void CAttachmentTray::SetCSID(int16 doc_csid, XP_Bool updateWindow)
  580. {
  581.     if (m_hFont)
  582.         theApp.ReleaseAppFont(m_hFont);
  583.  
  584.     LOGFONT lf;  
  585.  
  586.     memset(&lf,0,sizeof(LOGFONT));
  587.  
  588.     lf.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
  589.     lf.lfWeight = FW_NORMAL;
  590.     lf.lfCharSet = IntlGetLfCharset(doc_csid);
  591.     if (doc_csid == CS_LATIN1)
  592.          strcpy(lf.lfFaceName, "MS Sans Serif");
  593.     else
  594.          strcpy(lf.lfFaceName, IntlGetUIPropFaceName(doc_csid));
  595.     lf.lfQuality = PROOF_QUALITY;    
  596.     lf.lfHeight =  -10; // 8 points
  597.     m_hFont = theApp.CreateAppFont( lf );
  598.  
  599.     if (updateWindow)
  600.     {
  601.         Layout();
  602.         Invalidate();
  603.         UpdateWindow();
  604.     }
  605.  
  606. }
  607.  
  608.  
  609. /////////////////////////////////////////////////////////////////////
  610. //
  611. // CMessageBodyView
  612. //
  613.  
  614. BEGIN_MESSAGE_MAP(CMessageBodyView, CNetscapeView)
  615.     ON_WM_SETFOCUS()
  616.     ON_WM_KILLFOCUS()
  617. END_MESSAGE_MAP()
  618.  
  619. void CMessageBodyView::OnSetFocus(CWnd *pOldWnd)
  620. {
  621.     CNetscapeView::OnSetFocus(pOldWnd);
  622.  
  623.     ((CMessageView*)GetParent())->UpdateFocusFrame();
  624. }
  625.  
  626. void CMessageBodyView::OnKillFocus(CWnd *pOldWnd)
  627. {
  628.     CNetscapeView::OnKillFocus(pOldWnd);
  629.  
  630.     ((CMessageView*)GetParent())->UpdateFocusFrame();
  631. }
  632.  
  633. /////////////////////////////////////////////////////////////////////
  634. //
  635. // CMessageView
  636. //
  637.  
  638. CMessageView::CMessageView()
  639. {
  640.     m_pViewMessage = NULL;
  641.     m_pWndAttachments = NULL;
  642. #ifdef WIN32
  643.     m_iAttachmentsHeight = ::GetSystemMetrics(SM_CYICONSPACING) +
  644.                            ::GetSystemMetrics(SM_CYEDGE) * 2;
  645.     m_iSliderHeight = ::GetSystemMetrics(SM_CYSIZEFRAME);
  646. #else
  647.     m_iAttachmentsHeight = ::GetSystemMetrics(SM_CYICONSPACING) +
  648.                            ::GetSystemMetrics(SM_CYBORDER) * 2;
  649.     m_iSliderHeight = ::GetSystemMetrics(SM_CYFRAME);
  650. #endif
  651.     m_bAttachmentsVisible = FALSE;
  652.     ::SetRectEmpty(&m_rcClient);
  653. }
  654.  
  655. CMessageView::~CMessageView()
  656. {
  657.     delete m_pWndAttachments;
  658. }
  659.  
  660. void CMessageView::SetAttachments(int nAttachmentCount, MSG_AttachmentData *pAttachmentData)
  661. {
  662.     m_nAttachmentCount = nAttachmentCount;
  663.     ASSERT(m_pWndAttachments);
  664.     m_pWndAttachments->SetAttachments(nAttachmentCount, pAttachmentData);
  665.  
  666.     OnSize(0, m_rcClient.right, m_rcClient.bottom);
  667. }
  668.  
  669. void CMessageView::ShowAttachments(BOOL bShow)
  670. {
  671.     if (m_bAttachmentsVisible != bShow) {
  672.         m_bAttachmentsVisible = bShow;
  673.  
  674.         OnSize(0, m_rcClient.right, m_rcClient.bottom);
  675.     }
  676. }
  677.  
  678. BOOL CMessageView::AttachmentsVisible() const
  679. {
  680.     return m_bAttachmentsVisible;
  681. }
  682.  
  683. BOOL CMessageView::OnCommand( WPARAM wParam, LPARAM lParam )
  684. {
  685.     BOOL res = (BOOL) m_pViewMessage->SendMessage(WM_COMMAND, wParam, lParam);
  686.     if (!res)
  687.         res = CView::OnCommand(wParam, lParam);
  688.     return res;
  689. }
  690.  
  691. BOOL CMessageView::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo )
  692. {
  693.     BOOL res = m_pViewMessage->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  694.     if (!res)
  695.         res = CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  696.     return res;
  697. }
  698.  
  699. void CMessageView::OnDraw(CDC* pDC)
  700. {
  701.     HBRUSH hbrushButton = CreateSolidBrush( GetSysColor(COLOR_BTNFACE));
  702.     HPEN hpenLight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
  703.     HPEN hpenShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  704.  
  705.     ::FillRect(pDC->m_hDC, &m_rcSlider, hbrushButton);
  706.  
  707.     HPEN hpenOld = (HPEN) SelectObject(pDC->m_hDC, hpenLight);
  708.     ::MoveToEx(pDC->m_hDC, m_rcSlider.left, m_rcSlider.top, NULL);
  709.     ::LineTo(pDC->m_hDC, m_rcSlider.right, m_rcSlider.top);
  710.     SelectObject(pDC->m_hDC, hpenShadow);
  711.     ::MoveToEx(pDC->m_hDC, m_rcSlider.left, m_rcSlider.bottom - 1, NULL);
  712.     ::LineTo(pDC->m_hDC, m_rcSlider.right, m_rcSlider.bottom - 1);
  713.     SelectObject(pDC->m_hDC, hpenOld);
  714.  
  715.     VERIFY(::DeleteObject(hbrushButton));
  716.     VERIFY(::DeleteObject(hpenLight));
  717.     VERIFY(::DeleteObject(hpenShadow));    
  718.  
  719.  
  720.     if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
  721.     {
  722.         HBRUSH hBrush = NULL;
  723.         CWnd* pFocusWnd = GetFocus();
  724.         if (pFocusWnd && (pFocusWnd == this || pFocusWnd == m_pViewMessage ||
  725.             pFocusWnd == m_pWndAttachments))
  726.             hBrush = ::CreateSolidBrush( GetSysColor( COLOR_HIGHLIGHT ) );
  727.         else
  728.             hBrush = ::CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
  729.  
  730.         RECT clientRect;
  731.         GetClientRect(&clientRect);
  732.         ::FrameRect( pDC->m_hDC, &clientRect, hBrush );     
  733.         VERIFY(DeleteObject( hBrush ));
  734.     }
  735. }
  736.  
  737. BEGIN_MESSAGE_MAP(CMessageView, CView)
  738.     ON_WM_CREATE()
  739.     ON_WM_SIZE()
  740.     ON_WM_SETCURSOR()
  741.     ON_WM_SETFOCUS()
  742.     ON_WM_KILLFOCUS()
  743.     ON_WM_LBUTTONDOWN()
  744.     ON_WM_MOUSEMOVE()
  745.     ON_WM_LBUTTONUP()
  746.     ON_WM_DESTROY()
  747. END_MESSAGE_MAP()
  748.  
  749. int CMessageView::OnCreate( LPCREATESTRUCT lpCreateStruct )
  750. {
  751.     int res = CView::OnCreate(lpCreateStruct);
  752.     if (res != -1) {
  753.         m_pViewMessage = (CMessageBodyView *) RUNTIME_CLASS(CMessageBodyView)->CreateObject();
  754. #ifdef _WIN32
  755.         m_pViewMessage->CreateEx(0, NULL, NULL, 
  756.                                WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS,
  757.                                0,0,0,0, m_hWnd, (HMENU) IDW_MESSAGE_PANE, lpCreateStruct->lpCreateParams);
  758. #else
  759.         m_pViewMessage->Create(NULL, NULL, 
  760.                                WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS,
  761.                                CRect(0,0,0,0), this, IDW_MESSAGE_PANE, (CCreateContext *) lpCreateStruct->lpCreateParams);
  762. #endif
  763.         m_pViewMessage->SendMessage(WM_INITIALUPDATE);
  764.  
  765.         m_pWndAttachments = new CAttachmentTray;
  766. #ifdef _WIN32
  767.         m_pWndAttachments->CreateEx(0, NULL, NULL, 
  768.                                     WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS,
  769.                                     0,0,0,0, m_hWnd, (HMENU) IDW_ATTACHMENTS_PANE, lpCreateStruct->lpCreateParams );
  770. #else
  771.         m_pWndAttachments->Create(NULL, NULL, 
  772.                                   WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS,
  773.                                   CRect(0,0,0,0), this, IDW_ATTACHMENTS_PANE, (CCreateContext *) lpCreateStruct->lpCreateParams);
  774. #endif
  775.     }
  776.     return res;
  777. }
  778.  
  779. void CMessageView::OnSize( UINT nType, int cx, int cy )
  780. {
  781.     if (nType == SIZE_MINIMIZED || !cx || !cy)
  782.         return;
  783.  
  784.     m_rcClient.right = cx;
  785.     m_rcClient.bottom = cy;
  786.  
  787.     if (m_bAttachmentsVisible && m_nAttachmentCount > 0) {
  788.         ::SetRect(&m_rcSlider, 0, cy - m_iAttachmentsHeight - m_iSliderHeight - 1, cx, cy - m_iAttachmentsHeight);
  789.     } else {
  790.         ::SetRect(&m_rcSlider, 0, cy - 1, cx, cy);
  791.     }
  792.     if (m_pViewMessage) {
  793.         m_pViewMessage->MoveWindow(1, 1, cx - 2, m_rcSlider.top - 1);
  794.     }
  795.  
  796.     if (m_pWndAttachments) {
  797.         m_pWndAttachments->MoveWindow(1, m_rcSlider.bottom, cx - 2, cy - m_rcSlider.bottom - 1);
  798.     }
  799.     Invalidate();
  800.     UpdateWindow();
  801. }
  802.  
  803. BOOL CMessageView::OnSetCursor( CWnd* pWnd, UINT nHitTest, UINT message )
  804. {
  805.     POINT pt;
  806.     GetCursorPos(&pt);
  807.     ScreenToClient(&pt);
  808.  
  809.     // Handle in OnMouseMove
  810.     if (::PtInRect(&m_rcSlider, pt)) {
  811.         SetCursor( theApp.LoadCursor ( AFX_IDC_VSPLITBAR ) );
  812.         return TRUE;
  813.     } 
  814.     
  815.     return CView::OnSetCursor(pWnd, nHitTest, message);
  816. }
  817.  
  818. void CMessageView::UpdateFocusFrame()
  819. {
  820.     if (GetParentFrame()->IsKindOf(RUNTIME_CLASS(C3PaneMailFrame)))
  821.     {
  822.         RECT clientRect;
  823.         GetClientRect(&clientRect);
  824.         InvalidateRect(&clientRect, FALSE);
  825.         ::InflateRect(&clientRect, -1, -1);
  826.         ValidateRect(&clientRect);
  827.         UpdateWindow();
  828.     }
  829. }
  830.  
  831. void CMessageView::OnSetFocus(CWnd *pOldWnd)
  832. {
  833.     CView::OnSetFocus(pOldWnd);
  834.  
  835.     UpdateFocusFrame();
  836. }
  837.  
  838. void CMessageView::OnKillFocus(CWnd *pOldWnd)
  839. {
  840.     CView::OnKillFocus(pOldWnd);
  841.  
  842.     UpdateFocusFrame();
  843. }
  844.  
  845. void CMessageView::OnLButtonDown( UINT nFlags, CPoint point )
  846. {
  847.     if (::PtInRect(&m_rcSlider, point)) {
  848.         SetCapture();
  849.         m_ptHit = point;
  850.         m_iOldHeight = m_iAttachmentsHeight;
  851.     }
  852. }
  853.  
  854. void CMessageView::OnMouseMove( UINT nFlags, CPoint point )
  855. {
  856.     if (GetCapture() == this) {
  857.         RECT rect;
  858.         GetClientRect(&rect);
  859.         m_iAttachmentsHeight = m_iOldHeight + (m_ptHit.y - point.y);
  860.  
  861.         // Oh, the sanity...
  862.         if (m_iAttachmentsHeight < 0)
  863.             m_iAttachmentsHeight = 0;
  864.         if (m_iAttachmentsHeight > (m_rcClient.bottom - m_iSliderHeight))
  865.             m_iAttachmentsHeight = m_rcClient.bottom - m_iSliderHeight;
  866.  
  867.         OnSize(0, rect.right, rect.bottom);
  868.     }
  869. }
  870.  
  871. void CMessageView::OnLButtonUp( UINT nFlags, CPoint point )
  872. {
  873.     if (GetCapture() == this) {
  874.         ReleaseCapture();
  875.     }
  876. }
  877.  
  878. void CMessageView::OnDestroy()
  879. {
  880.     CView::OnDestroy();
  881. }
  882.  
  883. void CMessageView::SetCSID(int16 doc_csid)
  884. {
  885.     if (m_pWndAttachments)
  886.         m_pWndAttachments->SetCSID(doc_csid);
  887. }
  888.  
  889. #ifndef _AFXDLL
  890. #undef new
  891. #endif
  892. IMPLEMENT_DYNCREATE(CMessageView, CView)
  893. #ifndef _AFXDLL
  894. #define new DEBUG_NEW
  895. #endif
  896.