home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / tclist.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  7.7 KB  |  286 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. // TabList.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "tclist.h"
  24.  
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CTCList
  33.  
  34. // initialize string to calculate average char width
  35. CString CTCList::m_strCharSet = 
  36.     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  37.  
  38. CTCList::CTCList()
  39. {
  40.     m_nSpacing = 2;            // init column spacing
  41.     m_nTabs = MIN_TAB_SIZE;    // init number of tabs
  42.     m_nAvgCharWidth = 8;    // a reasonable default
  43.                                      
  44.     // init size of tab setting and column width arrays
  45.     m_aTabs.SetSize (MIN_TAB_SIZE);
  46.     m_aColWidth.SetSize (MIN_TAB_SIZE);    
  47.  
  48.     InitColWidth();            // init column width array
  49. }
  50.  
  51. CTCList::~CTCList()
  52. {
  53. }
  54.  
  55.  
  56. BEGIN_MESSAGE_MAP(CTCList, CListBox)
  57.     //{{AFX_MSG_MAP(CTCList)
  58.     ON_MESSAGE(LB_ADDSTRING,    OnAddString)
  59.     ON_MESSAGE(LB_INSERTSTRING,    OnInsertString)
  60.     ON_MESSAGE(LB_DELETESTRING,    OnDeleteString)
  61.     //}}AFX_MSG_MAP
  62. END_MESSAGE_MAP()
  63.  
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CTCList message handlers
  66.  
  67. // Set the number of spaces to separate columns.
  68. void CTCList::SetColumnSpace(int nSpacing)
  69. {                             
  70.     // only process if different              
  71.     if (nSpacing != m_nSpacing) 
  72.     {
  73.         m_nSpacing = nSpacing;    // store the number of character spaces
  74.         CalculateTabs();        // calculate new tab settings
  75.         SetTabStops(m_nTabs, 
  76.             (LPINT) &m_aTabs[0]);    // set tab settings
  77.     }
  78. }
  79.  
  80.  
  81. // Calculate average character width. The average character width is 
  82. // calculated using the same method used by GetDialogBaseUnits function;
  83. // average char width = (pixel width of "ABC...Zabc...z") / 52.
  84. // The current font is used for the calculation.
  85.  
  86. void CTCList::CalculateAvgCharWidth(CDC* pDC)
  87. {
  88.     CFont* pCurrentFont = GetFont();    // get font currently using for list box
  89.  
  90.     // GetFont will return NULL if using System font.
  91.     // If using system font just call GetDialogBaseUnits.
  92.     if (!pCurrentFont)
  93.         m_nAvgCharWidth = LOWORD(GetDialogBaseUnits());
  94.  
  95.     // if not using system font, select font into dc and 
  96.     // calculate average char width
  97.     else
  98.     {        
  99.         // have to select object into the dc before 
  100.         // we can calculate width of string
  101.         CFont* pOldFont = pDC->SelectObject(pCurrentFont);
  102.  
  103.         // get width of string
  104.         CSize size = pDC->GetTextExtent(m_strCharSet, 
  105.             m_strCharSet.GetLength());
  106.  
  107.         // calculate average char width and round result
  108.         m_nAvgCharWidth = MulDiv(1, size.cx, m_strCharSet.GetLength());
  109.  
  110.         // select old font back into dc
  111.         pDC->SelectObject(pOldFont);
  112.     }
  113. }
  114.  
  115. // calculate tabs from maximum column array
  116. void CTCList::CalculateTabs()
  117. {
  118.     UINT nIndex;    // index to array
  119.  
  120.     // first tab setting is the fist col width
  121.     m_aTabs[0] = ((m_aColWidth[0]+(m_nAvgCharWidth*m_nSpacing)) * 4) / 
  122.         m_nAvgCharWidth;
  123.  
  124.     // calculate each tab setting
  125.     for (nIndex=1; nIndex < m_nTabs; nIndex++)
  126.         m_aTabs[nIndex] = m_aTabs[nIndex-1] + 
  127.         ((m_aColWidth[nIndex]+(m_nAvgCharWidth*m_nSpacing)) * 4) / 
  128.             m_nAvgCharWidth;
  129. }
  130.  
  131. // re-calculate maximum column widths
  132. void CTCList::Recalc()
  133. {
  134.     // we are totally recalculating, so reset size of arrays
  135.     m_aTabs.SetSize(MIN_TAB_SIZE);        // reset tab stop array size
  136.     m_aColWidth.SetSize(MIN_TAB_SIZE);    // reset col width array size
  137.     m_nTabs = MIN_TAB_SIZE;            // set number of tab settings
  138.     InitColWidth();                    // init col width array
  139.  
  140.     // loop through list box and calculate col widths for each string
  141.     CString str;
  142.     for (int nItem = GetCount() - 1; nItem >= 0; --nItem)
  143.     {
  144.         GetText(nItem, str);    // get list box item string 
  145.         CalculateColWidths(str);    // calculate column widths of string
  146.     }
  147.  
  148.     CalculateTabs();            // calculate tab settings
  149. }
  150.  
  151. // initialize column width to 0
  152. void CTCList::InitColWidth()
  153. {
  154.     // initialize col width settings to a length of 0
  155.     UINT nIndex;
  156.     for (nIndex=0; nIndex < m_nTabs; nIndex++)
  157.         m_aColWidth[nIndex] = 0;
  158. }
  159.  
  160.  
  161. // calculate column widths of string
  162. BOOL CTCList::CalculateColWidths(LPCSTR pString, BOOL bSetWidths)
  163. {
  164.     BOOL bMaxColumn = FALSE;    // returns if this string contains max column
  165.     CDC* pDC = GetDC();        // get dc of list box window
  166.     UINT nCol=0;            // column currently processing
  167.     
  168.     if (pDC)
  169.     {
  170.         // calculate average char width
  171.         CalculateAvgCharWidth(pDC);        
  172.  
  173.         // select current font into dc so can measure width of string
  174.         CFont* pOldFont = pDC->SelectObject(GetFont());
  175.  
  176.         CString strRow;        // row string
  177.         CString strCol;        // column string
  178.         CSize size;        // size of column string
  179.         int nIndex=0;        // index to row string
  180.             
  181.         strRow = pString;    // set row string to passed string
  182.  
  183.         // divide row string up into column strings
  184.         while (nIndex != -1)
  185.         {
  186.             // check if need to grow tab setting and column width
  187.             if (nCol+1 > m_nTabs)
  188.             {
  189.                 m_aTabs.SetSize(m_nTabs+1);
  190.                 m_aColWidth.SetSize(m_nTabs+1);
  191.                 m_nTabs += 1;
  192.             }
  193.  
  194.             // parse out column string from row string
  195.             if ((nIndex = strRow.Find('\t')) == -1)
  196.                 strCol = strRow;
  197.             else
  198.             {
  199.                 strCol = strRow.Left(nIndex);
  200.                 strRow = strRow.Mid(nIndex+1);    
  201.             }
  202.  
  203.             // get pixel width of column string            
  204.             size = pDC->GetTextExtent(strCol, strCol.GetLength());
  205.  
  206.             // see if this is the widest column string
  207.             if ((UINT)size.cx >= m_aColWidth[nCol])
  208.             {
  209.                 // this string contains a longest column string
  210.                 bMaxColumn = TRUE;    
  211.  
  212.                 // store information to column width array 
  213.                    if (bSetWidths)
  214.                     m_aColWidth[nCol] = size.cx;
  215.             }
  216.             
  217.             nCol++;    // move to the next column
  218.         } 
  219.  
  220.         pDC->SelectObject(pOldFont);        
  221.         ReleaseDC(pDC);                        
  222.     }
  223.         
  224.     return bMaxColumn;
  225. }
  226.  
  227.  
  228. // process the LB_INSERTSTRING message
  229. LRESULT CTCList::OnInsertString(WPARAM wParam, LPARAM lParam)
  230. {
  231.     // adjust the col width array for this string
  232.     BOOL bRet = CalculateColWidths((LPCSTR)lParam);
  233.  
  234.     // set tab stop if required
  235.     if (bRet)
  236.     {
  237.         CalculateTabs();            // adjust the tab setting array
  238.            SetTabStops(m_nTabs, 
  239.                (LPINT)&m_aTabs[0]);    // set tab stops 
  240.     }
  241.  
  242.     return Default();
  243. }
  244.  
  245.  
  246. // process the LB_ADDSTRING message
  247. LRESULT CTCList::OnAddString(WPARAM wParam, LPARAM lParam)
  248. {
  249.     // adjust the col width array for this string
  250.     BOOL bRet = CalculateColWidths((LPCSTR)lParam);
  251.  
  252.     // set tab stop if required
  253.     if (bRet)
  254.     {
  255.         CalculateTabs();            // adjust the tab setting array
  256.            SetTabStops(m_nTabs, (LPINT)&m_aTabs[0]);    // set tab stops 
  257.     }
  258.  
  259.     return Default();
  260. }
  261.  
  262.  
  263. // process the LB_DELETESTRING message
  264. LRESULT CTCList::OnDeleteString(WPARAM wParam, LPARAM lParam)
  265. {
  266.     CString    str;                
  267.     GetText(wParam, str);    
  268.  
  269.     // see if need to recalculate tab stops
  270.     BOOL bRecalc = CalculateColWidths(str, FALSE);
  271.  
  272.     // delete string from list box
  273.     // pass message along to list box proc
  274.       LRESULT lRet = Default();
  275.  
  276.     // recalculate tab stops if required
  277.     if (bRecalc)
  278.     {
  279.         Recalc();
  280.         SetTabStops(m_nTabs, (LPINT)&m_aTabs[0]);
  281.     }
  282.  
  283.     return lRet;        
  284. }
  285.  
  286.