home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / printpag.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  32.3 KB  |  1,076 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. /////////////////////////////////////////////////////////////////////////////
  20. // printpag.cpp : implementation file
  21. // contains the printer page setup code.  This files contains
  22. // two objects: the page setup dialog box and the page
  23. // setup default setting object which also implements the
  24. // IPrinter interface. - jre
  25. // 
  26.  
  27. #include "stdafx.h"
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include "printpag.h"        // print page setup
  31. #include "apipage.h"        // page setup api
  32. #include "prefapi.h"
  33.  
  34. #ifdef _DEBUG
  35. #undef THIS_FILE
  36. static char BASED_CODE THIS_FILE[] = __FILE__;
  37. #endif
  38.  
  39. #define    MEASURE_US            1
  40. #define MEASURE_METRIC        2
  41.  
  42. // metric or US measurement flag
  43. static int measureUnit = -1;
  44.  
  45. // conversions
  46. #define    TWIPSPERINCH        1440
  47. #define TWIPSPERCENTIMETER    567
  48.  
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CPrintPageSetup dialog
  51.  
  52.  
  53. CPrintPageSetup::CPrintPageSetup(CWnd* pParent /*=NULL*/)
  54.     : CDialog(CPrintPageSetup::IDD, pParent)
  55. {
  56.     //{{AFX_DATA_INIT(CPrintPageSetup)
  57.     m_bLinesBlack = FALSE;
  58.     m_bPrintBkImage = FALSE;
  59.     m_bTextBlack = FALSE;
  60.     m_bDate = FALSE;
  61.     m_bPageNo = FALSE;
  62.     m_bSolidLines = FALSE;
  63.     m_bTitle = FALSE;
  64.     m_bTotal = FALSE;
  65.     m_bURL = FALSE;
  66.     //}}AFX_DATA_INIT
  67.  
  68.     // Initializes the measurement setting based on the locale
  69.     SetLocaleUnit ( );
  70.  
  71.     ApiPageSetup(api,0);
  72.     api->GetPageSize ( &lWidth, &lHeight );
  73.     api->GetMargins (&m_InitialLeft, &m_InitialRight, &m_InitialTop, &m_InitialBottom );
  74. }
  75.  
  76.  
  77. void CPrintPageSetup::DoDataExchange(CDataExchange* pDX)
  78. {
  79.     CDialog::DoDataExchange(pDX);
  80.     //{{AFX_DATA_MAP(CPrintPageSetup)
  81.     DDX_Control(pDX, IDC_PAGESETUP_SAMPLE, m_PagePreview);
  82.     DDX_Control(pDX, IDC_PAGESETUP_MARGINBOX, m_MarginBox);
  83.     DDX_Control(pDX, IDC_PAGESETUP_MBOTTOM, m_BottomMargin);
  84.     DDX_Control(pDX, IDC_PAGESETUP_MLEFT, m_LeftMargin);
  85.     DDX_Control(pDX, IDC_PAGESETUP_MRIGHT, m_RightMargin);
  86.     DDX_Control(pDX, IDC_PAGESETUP_MTOP, m_TopMargin);
  87.     DDX_Check(pDX, IDC_PAGESETUP_ALLLINESBLACK, m_bLinesBlack);
  88.     DDX_Check(pDX, IDC_PAGESETUP_ALLTEXTBLACK, m_bTextBlack);
  89.     DDX_Check(pDX, IDC_PAGESETUP_DATE, m_bDate);
  90.     DDX_Check(pDX, IDC_PAGESETUP_PAGENUMBERS, m_bPageNo);
  91.     DDX_Check(pDX, IDC_PAGESETUP_SOLIDLINES, m_bSolidLines);
  92.     DDX_Check(pDX, IDC_PAGESETUP_TITLE, m_bTitle);
  93.     DDX_Check(pDX, IDC_PAGESETUP_TOTAL, m_bTotal);
  94.     DDX_Check(pDX, IDC_PAGESETUP_URL, m_bURL);
  95.     DDX_Check(pDX, IDC_PAGESETUP_REVERSEORDER, m_bReverseOrder);
  96. #ifdef XP_WIN32
  97.     DDX_Check(pDX, IDC_PRINTBKIMAGE, m_bPrintBkImage);
  98. #endif
  99.     //}}AFX_DATA_MAP
  100. }
  101.  
  102.  
  103. BEGIN_MESSAGE_MAP(CMarginEdit, CGenericEdit)
  104.     ON_WM_CHAR()
  105. END_MESSAGE_MAP()
  106.  
  107. /////////////////////////////////////////////////////////////////////////////
  108. // Filter out any unwanted characters.  Only allow valid margin characters.
  109.  
  110. void CMarginEdit::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
  111. {
  112.     if ( ( nChar == VK_BACK ) ||
  113.         strchr ( " 0123456789.,cm\"", tolower(nChar) ) 
  114.         )
  115.         CWnd::OnChar ( nChar, nRepCnt, nFlags );
  116. }
  117.  
  118. BEGIN_MESSAGE_MAP(CPrintPageSetup, CDialog)
  119.     //{{AFX_MSG_MAP(CPrintPageSetup)
  120.     //}}AFX_MSG_MAP
  121. END_MESSAGE_MAP()
  122.           
  123. BEGIN_MESSAGE_MAP(CPagePreview,CStatic)
  124.     ON_WM_PAINT()
  125. END_MESSAGE_MAP()
  126.  
  127. void CPagePreview::OnPaint() 
  128. {
  129.     CStatic::OnPaint();
  130.     CClientDC dc(this); // device context for painting
  131.     CPrintPageSetup * pDialog = (CPrintPageSetup *)GetOwner ( );
  132.     if ( pDialog != NULL )
  133.         pDialog->ShowPagePreview ( dc );
  134. }
  135.  
  136. /////////////////////////////////////////////////////////////////////////////
  137. // CPrintPageSetup message handlers
  138.  
  139. // ShowPagePreview displays the small page layout in the the page setup
  140. // control.  The printer coordinates are adjusted to screen coordinates for
  141. // proper proportion.
  142.  
  143. void CPrintPageSetup::ShowPagePreview ( CClientDC & pdc )
  144. {
  145.     RECT rect, shade, margins;                // working rectangles
  146.     long mtop, mbottom, mleft, mright;        // margins in twips
  147.     ApiPageSetup(api,0);                    // Get the page setup API
  148.     int iX,                                 // width of page in pixels
  149.         iY,                                 // height of page in pixels
  150.         AspectXY;                            // aspect ratio mul 1000
  151.  
  152.     // get the bounding rectangle of the sample area
  153.     m_PagePreview.GetClientRect ( &rect );
  154.  
  155.     // compute the width and height
  156.     int width = rect.right - rect.left;
  157.     int height = rect.bottom - rect.top;
  158.  
  159.     // get the margin to display the sample text
  160.     api->GetMargins ( &mleft, &mright, &mtop, &mbottom );
  161.  
  162.     // check page orientation and base on height if normal orientation
  163.     // or on width for landscape... make best use of screen space
  164.  
  165.     if ( lHeight > lWidth )
  166.     {
  167.         iY = height - ( height / 4 );    // use .75 of the height
  168.  
  169.         // compute the aspect ration ( percentage width to height )
  170.         AspectXY = CASTINT(( lWidth * 1000 ) / lHeight);
  171.         
  172.         // get the preview item height in inches
  173.         long lPreviewHeight = 
  174.             ( long(iY) * 1000L ) / pdc.GetDeviceCaps ( LOGPIXELSY );
  175.  
  176.         // compute the inches the width should be from the aspect
  177.         long lX = lPreviewHeight * AspectXY;
  178.         lX /= 1000;
  179.  
  180.         // how many pixels does that translate to?
  181.         lX *= pdc.GetDeviceCaps ( LOGPIXELSX );
  182.         iX = LOWORD(lX/1000);
  183.     }
  184.     else
  185.     {
  186.         iX = width - ( width / 4 );        // use .75 of the width
  187.  
  188.         // compute the aspect ration ( percentage width to height )
  189.         AspectXY = CASTINT(( lHeight * 1000 ) / lWidth);
  190.  
  191.         // get the preview item width in inches
  192.         long lPreviewWidth = 
  193.             ( long(iX) * 1000L ) / pdc.GetDeviceCaps ( LOGPIXELSX );
  194.  
  195.         // compute the inches the height should be from the aspect
  196.         long lY = lPreviewWidth * AspectXY;
  197.         lY /= 1000;
  198.  
  199.         // how many pixels does that translate to?
  200.         lY *= pdc.GetDeviceCaps ( LOGPIXELSY );
  201.         iY = LOWORD(lY/1000);
  202.     }
  203.  
  204.     // compute the number of twips per pixel for margin computation
  205.     long iXTwipsPerPixel = lWidth / iX;
  206.     long iYTwipsPerPixel = lHeight / iY;
  207.  
  208.     HDC hdc = pdc.GetSafeHdc();
  209.     // create a black pen for borders
  210. //    CPen blackPen (PS_SOLID,1,RGB(0,0,0));
  211. //    pdc.SelectObject(&blackPen);
  212.     ::SelectObject(hdc, (HPEN)::GetStockObject(BLACK_PEN));
  213.     // center the page in the sample area
  214.     rect.left += ( width  - iX ) / 2;
  215.     rect.top  += ( height - iY ) / 2;
  216.     rect.right = rect.left + iX;
  217.     rect.bottom = rect.top + iY;
  218.  
  219. //    CBrush brWindow ( GetSysColor(COLOR_WINDOW) );
  220.     HBRUSH brWindow = (HBRUSH)::CreateSolidBrush(GetSysColor(COLOR_WINDOW) );
  221. //    pdc.SelectObject ( &brWindow );
  222.     ::SelectObject(hdc, (HBRUSH)brWindow);
  223.  
  224.     // draw the small folded over flap on the top left handl corner
  225.     int iFoldOver = height / 15;
  226.     ::MoveToEx( hdc, rect.left, rect.top + iFoldOver, NULL);
  227.     ::LineTo (hdc, rect.left, rect.bottom );
  228.     ::LineTo (hdc, rect.right, rect.bottom );
  229.     ::LineTo (hdc, rect.right, rect.top );
  230.     ::LineTo (hdc, rect.left + iFoldOver, rect.top );
  231.     ::LineTo (hdc, rect.left, rect.top + iFoldOver );
  232.  
  233.     ::FloodFill (hdc, rect.right / 2, rect.bottom / 2, RGB(0,0,0) );
  234.     ::LineTo (hdc, rect.left + iFoldOver, rect.top + iFoldOver );
  235.     ::LineTo (hdc, rect.left + iFoldOver, rect.top );
  236. #if 0
  237.     pdc.MoveTo ( rect.left, rect.top + iFoldOver );
  238.     pdc.LineTo ( rect.left, rect.bottom );
  239.     pdc.LineTo ( rect.right, rect.bottom );
  240.     pdc.LineTo ( rect.right, rect.top );
  241.     pdc.LineTo ( rect.left + iFoldOver, rect.top );
  242.     pdc.LineTo ( rect.left, rect.top + iFoldOver );
  243.  
  244.     pdc.FloodFill ( rect.right / 2, rect.bottom / 2, RGB(0,0,0) );
  245.  
  246.     pdc.LineTo ( rect.left + iFoldOver, rect.top + iFoldOver );
  247.     pdc.LineTo ( rect.left + iFoldOver, rect.top );
  248. #endif
  249.     // compute the text area from the margin layout
  250.     memcpy ( &margins, &rect, sizeof(rect) );
  251.     margins.left   += CASTINT( mleft   / iXTwipsPerPixel );
  252.     margins.right  -= CASTINT( mright  / iXTwipsPerPixel );
  253.     margins.top    += CASTINT( mtop    / iYTwipsPerPixel );
  254.     margins.bottom -= CASTINT( mbottom / iYTwipsPerPixel );
  255.  
  256.     if ( ( margins.left < margins.right ) && ( margins.top < margins.bottom ) )
  257.     {
  258.  
  259.         // create a gray pen to display the sample text
  260. //        CPen greyPen ( PS_SOLID, 1, GetSysColor(COLOR_ACTIVECAPTION) );
  261. //        pdc.SelectObject ( &greyPen );
  262.  
  263.         HPEN greyPen = ::CreatePen(PS_SOLID, 1,GetSysColor(COLOR_ACTIVECAPTION)); 
  264.         HPEN hOldPen = (HPEN)::SelectObject(hdc,     (HPEN)greyPen);
  265.         int iy, iline;
  266.         BOOL bIndent = TRUE;
  267.  
  268.         // draw lines for text layout the entire print area minus margins
  269.         for ( iy = 0, iline = 0; iy <= ( margins.bottom - margins.top ); iy++ )
  270.         {
  271.             if ( !( iy % 4 ) )        // every 4 pixel rows draw a line
  272.             {
  273.                 if ( bIndent )        // is this the beginning of a paragraph?
  274.                 {
  275.  
  276.                     // don't draw the line in the little fold over flap
  277.  
  278.                     if ( ( ( iy + margins.top ) < ( rect.top + iFoldOver ) ) &&
  279.                     ( ( margins.left + ( iX / 10 ) ) < ( rect.left + iFoldOver ) ) )
  280. //                        pdc.MoveTo ( rect.left + iFoldOver, iy + margins.top );
  281.                         ::MoveToEx (hdc, rect.left + iFoldOver, iy + margins.top, NULL );
  282.                     else                    
  283. //                        pdc.MoveTo ( margins.left + ( iX / 10 ), iy + margins.top );
  284.                         ::MoveToEx ( hdc, margins.left + ( iX / 10 ), iy + margins.top, NULL );
  285.  
  286. //                    pdc.LineTo ( margins.right, iy + margins.top ); 
  287.                     ::LineTo ( hdc, margins.right, iy + margins.top ); 
  288.                     bIndent = FALSE;
  289.                 } 
  290.                 else if ( !( iline % 5 ) )    // is this the end of a paragraph?
  291.                 {
  292. //                    pdc.MoveTo ( margins.left, iy + margins.top );
  293. //                    pdc.LineTo ( margins.left + ( iX / 3 ), iy + margins.top ); 
  294.                     ::MoveToEx ( hdc, margins.left, iy + margins.top, NULL );
  295.                     ::LineTo  ( hdc, margins.left + ( iX / 3 ), iy + margins.top ); 
  296.                     bIndent = TRUE;
  297.                 }
  298.                 else         // just draw a normal straight across line
  299.                 {
  300.                     // don't draw the line in the little fold over flap
  301.     
  302.                     if ( ( ( iy + margins.top ) < ( rect.top + iFoldOver ) ) &&
  303.                     ( margins.left < ( rect.left + iFoldOver ) ) )
  304.                         ::MoveToEx  ( hdc, rect.left + iFoldOver, iy + margins.top, NULL);
  305.                     else
  306.                         ::MoveToEx  ( hdc, margins.left, iy + margins.top, NULL);
  307.                     ::LineTo (hdc, margins.right, iy + margins.top );
  308.                 }
  309.  
  310.                 iline++;
  311.             }
  312.         }
  313.         ::SelectObject(hdc,     (HPEN)hOldPen);
  314.         ::DeleteObject(greyPen);
  315.  
  316.     }
  317.  
  318.     // draw the shading around the sample
  319. //    shade.left   = rect.right;
  320. //    shade.right  = rect.right + 3;
  321. //    shade.top    = rect.top + 6;
  322. //    shade.bottom = rect.bottom + 3;
  323.  
  324.     ::SelectObject(hdc, (HPEN)::GetStockObject(BLACK_PEN));
  325.     ::SelectObject(hdc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
  326. //    pdc.Rectangle ( &shade );
  327.     ::Rectangle(hdc,rect.right, rect.top + 6, rect.right + 3, rect.bottom + 3);
  328.  
  329. //    shade.left   = rect.left + 6;
  330. //    shade.top    = rect.bottom;
  331.  
  332. //    pdc.Rectangle ( &shade );
  333.     ::Rectangle(hdc,rect.left + 6, rect.bottom, rect.right + 3, rect.bottom + 3);
  334.     ::SelectObject(hdc, (HPEN)::GetStockObject(NULL_PEN));
  335.     ::SelectObject(hdc, (HBRUSH)::GetStockObject(NULL_BRUSH ));
  336.     ::DeleteObject(brWindow);
  337. }
  338.  
  339. void CPrintPageSetup::MarginError ( char * szTitle )
  340. {
  341.     MessageBox ( 
  342.         "The margin value entered was not valid.  Try a smaller number.",
  343.         szTitle, MB_OK | MB_ICONEXCLAMATION );
  344.  
  345. }
  346.  
  347. // function reads all the margin text from the margin controls, converts
  348. // it from the locale measurement units and stores the values back in the
  349. // page setup object.
  350.  
  351. int CPrintPageSetup::UpdateMargins ( BOOL check )
  352. {
  353.     char szBuffer[ 10 ];                    // buffer holds edit control data
  354.     long mtop, mbottom, mleft, mright;        // margins in twips
  355.     long mtopold, mbottomold, mleftold, mrightold;
  356.     ApiPageSetup(api,0);                     // Get the page setup API
  357.  
  358.     api->GetMargins ( &mleftold, &mrightold, &mtopold, &mbottomold );
  359.  
  360.     // get the margin text from the edit controls and convert it 
  361.     // to twips
  362.  
  363.     memset ( szBuffer, '\0', sizeof(szBuffer) );
  364.     m_TopMargin.GetLine ( 0, szBuffer, sizeof(szBuffer) );
  365.     strlwr ( szBuffer );
  366.     mtop = LocaleUnitToTwips ( szBuffer );
  367.  
  368.     // if we are range checking, check to see if this is a valid margin
  369.  
  370.     if ( check && ( mtop < 0 ) )
  371.     {
  372.         MarginError ( szLoadString(IDS_TOPMARGINERROR) );
  373.         m_TopMargin.SetFocus ( );
  374.         m_TopMargin.SetSel ( 0, -1 );
  375.         return 1;
  376.     }
  377.    
  378.     memset ( szBuffer, '\0', sizeof(szBuffer) );
  379.     m_BottomMargin.GetLine ( 0, szBuffer, sizeof(szBuffer) );
  380.     strlwr ( szBuffer );
  381.     mbottom = LocaleUnitToTwips ( szBuffer );
  382.  
  383.     if ( check && ( mbottom < 0 ) )
  384.     {
  385.         MarginError ( szLoadString(IDS_BOTTOMMARGINERROR) );
  386.         m_BottomMargin.SetFocus ( );
  387.         m_BottomMargin.SetSel ( 0, -1 );
  388.         return 1;
  389.     }
  390.  
  391.     memset ( szBuffer, '\0', sizeof(szBuffer) );
  392.     m_LeftMargin.GetLine ( 0, szBuffer, sizeof(szBuffer) );
  393.     strlwr ( szBuffer );
  394.     mleft = LocaleUnitToTwips ( szBuffer );
  395.  
  396.     if ( check && ( mleft < 0 ) )
  397.     {
  398.         MarginError ( szLoadString(IDS_LEFTMARGINERROR) );
  399.         m_LeftMargin.SetFocus ( );
  400.         m_LeftMargin.SetSel ( 0, -1 );
  401.         return 1;
  402.     }
  403.  
  404.     memset ( szBuffer, '\0', sizeof(szBuffer) );
  405.     m_RightMargin.GetLine ( 0, szBuffer, sizeof(szBuffer) );
  406.     strlwr ( szBuffer );
  407.     mright = LocaleUnitToTwips ( szBuffer );
  408.  
  409.     if ( check && ( mright < 0 ) )
  410.     {
  411.         MarginError ( szLoadString(IDS_RIGHTMARGINERROR) );
  412.         m_RightMargin.SetFocus ( );
  413.         m_RightMargin.SetSel ( 0, -1 );
  414.         return 1;
  415.     }
  416.  
  417.     //  1 inch x 1 inch minimum space.
  418.     if(check) {
  419.         if(mtop + mbottom >= lHeight - TWIPSPERINCH) {
  420.             //  Send them to the top/bottom margin for editing the problem.
  421.             if(mtop >= mbottom) {
  422.                 MarginError ( szLoadString(IDS_TOPMARGINERROR) );
  423.                 m_TopMargin.SetFocus ( );
  424.                 m_TopMargin.SetSel ( 0, -1 );
  425.             }
  426.             else {
  427.                 MarginError ( szLoadString(IDS_BOTTOMMARGINERROR) );
  428.                 m_BottomMargin.SetFocus ( );
  429.                 m_BottomMargin.SetSel ( 0, -1 );
  430.             }
  431.             return 1;
  432.         }
  433.         else if(mleft + mright >= lWidth - TWIPSPERINCH) {
  434.             //  Send them to left/right margin for editing the problem.
  435.             if(mleft >= mright)  {
  436.                 MarginError ( szLoadString(IDS_LEFTMARGINERROR) );
  437.                 m_LeftMargin.SetFocus ( );
  438.                 m_LeftMargin.SetSel ( 0, -1 );
  439.             }
  440.             else {
  441.                 MarginError ( szLoadString(IDS_RIGHTMARGINERROR) );
  442.                 m_RightMargin.SetFocus ( );
  443.                 m_RightMargin.SetSel ( 0, -1 );
  444.             }
  445.             return 1;
  446.         }
  447.     }
  448.  
  449.     // update the preview area only if margins have changed
  450.  
  451.     if ( ( mright != mrightold ) || 
  452.         ( mleft != mleftold ) ||
  453.         ( mbottom != mbottomold ) || 
  454.         ( mtop != mtopold ) )
  455.     {
  456.         m_PagePreview.Invalidate ( );
  457.         // set the margins in the page setup object
  458.         api->SetMargins ( mleft, mright, mtop, mbottom );
  459.     }
  460.  
  461.     return 0;
  462. }
  463.  
  464. void CPrintPageSetup::OnCancel()
  465. {
  466.     ApiPageSetup(api,0);                         // Get the page setup API
  467.     api->SetMargins (m_InitialLeft, m_InitialRight, m_InitialTop, m_InitialBottom );
  468.     CDialog::OnCancel();
  469. }
  470.  
  471. // processed when the user presses OK button.  Does all margin validations
  472. // etc.  Sets up the printer page setup object with the selected options.
  473.  
  474. void CPrintPageSetup::OnOK() 
  475. {
  476.     ApiPageSetup(api,0);                         // Get the page setup API
  477.  
  478.     UpdateData ( );    
  479.  
  480.     if ( UpdateMargins ( TRUE ) )
  481.         return;
  482.  
  483.     // set up the header information
  484.     api->Header (                 
  485.         ( m_bTitle ? PRINT_TITLE : 0 ) | 
  486.         ( m_bURL ? PRINT_URL : 0 ) );
  487.  
  488.     // set the footer information
  489.     api->Footer (
  490.         ( m_bPageNo ? PRINT_PAGENO : 0 ) |
  491.         ( m_bDate   ? PRINT_DATE   : 0 ) |
  492.         ( m_bTotal     ? PRINT_PAGECOUNT : 0 ) );
  493.  
  494.     // set up the miscellaneous page options
  495.     api->BlackLines ( m_bLinesBlack );
  496.     api->BlackText( m_bTextBlack );
  497.     api->SolidLines ( !m_bSolidLines );
  498.     api->ReverseOrder ( m_bReverseOrder );
  499.     api->SetPrintingBkImage ( m_bPrintBkImage );
  500.     
  501.     CDialog::OnOK();
  502. }
  503.  
  504. // OnCommand handler looks at the KILLFOCUS messages from the edit controls.
  505. // The new margin values are retrieved and the layout area is updated. Also,
  506. // the values are normalized and restored back in the edit control
  507.  
  508. BOOL CPrintPageSetup::OnCommand(WPARAM wParam, LPARAM lParam) 
  509. {
  510. #ifdef WIN32
  511.     if ( HIWORD(wParam) == EN_KILLFOCUS )
  512. #else
  513.     if ( HIWORD(lParam) == EN_KILLFOCUS )
  514. #endif
  515.     {
  516.         if ( ( LOWORD(wParam) == IDC_PAGESETUP_MTOP ) ||
  517.             ( LOWORD(wParam) == IDC_PAGESETUP_MBOTTOM ) ||
  518.             ( LOWORD(wParam) == IDC_PAGESETUP_MLEFT ) ||
  519.             ( LOWORD(wParam) == IDC_PAGESETUP_MRIGHT ) )
  520.         {
  521.             UpdateMargins ( );        // update the margin values - relayout
  522.  
  523.             // get the edit control and normalize the value
  524.             CMarginEdit * pEdit = (CMarginEdit *) GetDlgItem ( LOWORD(wParam) );
  525.             if ( pEdit )
  526.             {
  527.                 char szBuffer[10];
  528.                 long lTwips;
  529.                 memset ( szBuffer, '\0', sizeof(szBuffer) );
  530.                 pEdit->GetLine ( 0, szBuffer, sizeof(szBuffer) );
  531.                 strlwr ( szBuffer );
  532.                 lTwips = LocaleUnitToTwips ( szBuffer );
  533.                 pEdit->SetWindowText( TwipsToLocaleUnit ( lTwips ) );
  534.             }
  535.         }
  536.     }
  537.     return CDialog::OnCommand(wParam, lParam);
  538. }
  539.  
  540. // function converts twips to centimeters or inches based on the
  541. // conversion and the locale.
  542.  
  543. char * CPrintPageSetup::TwipsToString ( long twips, long conversion )
  544. {
  545.     static char szBuffer[ 10 ];
  546.  
  547.     // load the centimeter abbreviation
  548.     CString cs;
  549.     cs.LoadString( IDS_PAGESETUP_CM );
  550.  
  551.     // Save to static buffer rounding to 2 dec places
  552.     sprintf( szBuffer, "%.2f", (float)twips/(float)conversion );
  553.  
  554. #ifdef XP_WIN32
  555.     char buf[10];
  556.     GetNumberFormat(LOCALE_SYSTEM_DEFAULT, NULL, szBuffer, NULL, buf, 10);
  557.     strcpy(szBuffer, buf);
  558. #endif
  559.     strcat(szBuffer, ( measureUnit == MEASURE_US ) ? "\"" : (const char *)cs);
  560.  
  561.     return szBuffer;    // return conversion
  562. }
  563.  
  564. // function takes a text buffer and converts it to twips from
  565. // inches or centimeters.  If the text contains a ", it assumed
  566. // inches.  If the text is preceded by 'cm' it is assumed 
  567. // metric.  Locale can be overriden by specifying one of the formentioned
  568. // identifiers.
  569. // 1440 twips/inch
  570. //  567 twips/cm
  571.  
  572. long CPrintPageSetup::StringToTwips ( char * szBuffer, long conversion )
  573. {
  574.     int len = strlen ( szBuffer );    // string length to parse
  575.     long lDecPart = 0;                // decimal part
  576.     long lFracPart = 0;                // fractional part
  577.     int precision = 0;              // make sure at least 2 decimal points
  578.     int i;    
  579.     BOOL decimal = TRUE;            // what part are we currently parsing
  580.  
  581.     // process the entire string
  582.     for ( i = 0; i < len; i++ )
  583.     {
  584.         // ignore anything but digits for numeric processing
  585.         if ( isdigit ( szBuffer[ i ] ) )    
  586.         {
  587.             // are we processing the decimal or fractional part
  588.             if ( decimal )
  589.                 lDecPart = ( lDecPart * 10 ) + ( szBuffer[ i ] - '0' );
  590.             else
  591.             {
  592.                 lFracPart = ( lFracPart * 10 ) + ( szBuffer[ i ] - '0' );
  593.                 precision++;
  594.             }
  595.         }
  596.         // toggle the dec/frac flag when we hit a decimal point
  597.         else if ( szBuffer[ i ] == '.' || szBuffer[ i ] == ',' )
  598.             decimal = FALSE;
  599.     }
  600.     
  601.     lFracPart *= conversion;
  602.     while ( precision-- )
  603.         lFracPart /= 10;
  604.  
  605.     // final conversion for total twips    
  606.     return (( lDecPart * conversion ) + lFracPart);
  607. }
  608.  
  609. // function checks the locale and sets the units of measurement to either
  610. // US or metric. 
  611.  
  612. void CPrintPageSetup::SetLocaleUnit ( void )
  613. {
  614.     // check only if the flag hasn't been initialized
  615.     if ( measureUnit == -1 )
  616.     {
  617. #ifdef WIN32
  618.         char szLCStr[2];
  619.         GetLocaleInfo (
  620.             GetSystemDefaultLCID(),    // current locale
  621.             LOCALE_IMEASURE,        // measurement system
  622.             szLCStr,                // will return '0'-metric,'1'-US
  623.             sizeof(szLCStr) );
  624.  
  625.         if ( szLCStr[ 0 ] == '0' )
  626.             measureUnit = MEASURE_METRIC;
  627.         else
  628.             measureUnit = MEASURE_US;
  629. #else
  630.         if (GetProfileInt("intl", "iMeasure", 0) == 0)
  631.             measureUnit = MEASURE_METRIC;
  632.         else
  633.             measureUnit = MEASURE_US;
  634. #endif
  635.     }
  636. }
  637.  
  638. // function converts twip count to a text string representing the
  639. // value in centimeters or inches based on the locale
  640.  
  641. char * CPrintPageSetup::TwipsToLocaleUnit ( long lTwips )
  642. {
  643.     switch ( measureUnit )
  644.     {
  645.         case MEASURE_US:
  646.             return TwipsToString ( lTwips, TWIPSPERINCH );
  647.             break;
  648.  
  649.         case MEASURE_METRIC:
  650.             return TwipsToString ( lTwips, TWIPSPERCENTIMETER );
  651.             break;
  652.     }
  653.     
  654.     return 0;
  655.  
  656. }
  657.  
  658. // function accepts a text string representing either inches or
  659. // centimeters and converts it to twips.  The locale can be overriden
  660. // by adding either a '"' for inches or 'cm' for centimeters.
  661.  
  662. long CPrintPageSetup::LocaleUnitToTwips ( char * szBuffer )
  663. {
  664.     CString cs;
  665.     cs.LoadString ( IDS_PAGESETUP_CM );    // get the centimeter abrv.
  666.  
  667.     // check for locale override
  668.     if ( strstr ( szBuffer, cs ) )
  669.         return StringToTwips ( szBuffer, TWIPSPERCENTIMETER );
  670.     else if ( strchr ( szBuffer, '\"' ) )
  671.         return StringToTwips ( szBuffer, TWIPSPERINCH );
  672.  
  673.     // no locale overrides, convert based on system locale
  674.     if ( measureUnit == MEASURE_US )
  675.         return StringToTwips ( szBuffer, TWIPSPERINCH );
  676.     else 
  677.         return StringToTwips ( szBuffer, TWIPSPERCENTIMETER );
  678.     
  679.     return 0;
  680. }
  681.  
  682. // called to preinitialize the page setup dialog.  This function takes
  683. // the values from the page setup object and initializes the page setup
  684. // dialog with them.
  685.  
  686. BOOL CPrintPageSetup::OnInitDialog() 
  687. {
  688.     CString cs, SampleText;    
  689.      long mright, mleft, mtop, mbottom;
  690.     ApiPageSetup(api,0);        // page setup api
  691.     // get the margins from the object
  692.     api->GetMargins ( &mleft, &mright, &mtop, &mbottom );
  693.  
  694.     CDialog::OnInitDialog();
  695.  
  696.     // print the paer size on the sample window
  697.     char szSize[50], szWidth[10], szHeight[10], szSample[50];
  698.     strcpy ( szWidth, TwipsToLocaleUnit ( lWidth ) );
  699.     if ( strchr ( szWidth, '\"' ) ) * strchr ( szWidth, '\"' ) = '\0';
  700.     strcpy ( szHeight, TwipsToLocaleUnit ( lHeight ) );
  701.     if ( strchr ( szHeight, '\"' ) ) * strchr ( szHeight, '\"' ) = '\0';
  702.     wsprintf ( szSize, " (%s x %s)", szWidth, szHeight );
  703.     CStatic * pBox = (CStatic *)GetDlgItem(IDC_PAGESETUP_SAMPLE);
  704.     GetDlgItemText(IDC_PAGESETUP_SAMPLE, szSample, 50);
  705.     SampleText = szSample;
  706.     SampleText+=szSize;
  707.     pBox->SetWindowText ( SampleText );
  708.  
  709.     
  710.     // load the inches or centimeters message based on the locale
  711.     if ( measureUnit == MEASURE_METRIC )
  712.         cs.LoadString ( IDS_PAGESETUP_CENTIMETERS );
  713.     else
  714.         cs.LoadString ( IDS_PAGESETUP_INCHES );
  715.  
  716.     // set the 'Margins (Inches)' or 'Margins (Centimeters)' heading
  717.     m_MarginBox.SetWindowText ( cs );
  718.  
  719.     // convert from twips and initialize the dialog with the default
  720.     // types
  721.     m_RightMargin.SetWindowText( TwipsToLocaleUnit ( mright ) );
  722.     m_TopMargin.SetWindowText( TwipsToLocaleUnit ( mtop ) );
  723.     m_BottomMargin.SetWindowText( TwipsToLocaleUnit ( mbottom ) );
  724.     m_LeftMargin.SetWindowText( TwipsToLocaleUnit ( mleft ) );
  725.  
  726.     // initialize the focus to the first margin setting selected
  727.     m_TopMargin.SetFocus ( );
  728.     m_TopMargin.SetSel ( 0, -1 );
  729.  
  730.     // initialize the check boxes
  731.     m_bLinesBlack = api->BlackLines();
  732.     m_bTextBlack  = api->BlackText();
  733.     m_bSolidLines = api->SolidLines();
  734.     m_bTitle  = ( api->Header() & PRINT_TITLE ) ? TRUE : FALSE;
  735.     m_bURL    = ( api->Header() & PRINT_URL ) ? TRUE : FALSE;
  736.     m_bPageNo = ( api->Footer() & PRINT_PAGENO ) ? TRUE : FALSE;
  737.     m_bTotal  = ( api->Footer() & PRINT_PAGECOUNT ) ? TRUE : FALSE;
  738.     m_bDate   = ( api->Footer() & PRINT_DATE ) ? TRUE : FALSE;    
  739.     m_bPrintBkImage = api->IsPrintingBkImage();
  740.     m_bReverseOrder = api->ReverseOrder();
  741.  
  742.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_SOLIDLINES) )->SetCheck ( !m_bSolidLines );
  743.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_ALLTEXTBLACK) )->SetCheck ( m_bTextBlack );
  744.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_ALLLINESBLACK) )->SetCheck ( m_bLinesBlack );
  745.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_TITLE) )->SetCheck ( m_bTitle );
  746.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_PAGENUMBERS) )->SetCheck ( m_bPageNo);
  747.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_URL) )->SetCheck ( m_bURL );
  748.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_DATE) )->SetCheck( m_bDate );
  749.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_TOTAL) )->SetCheck ( m_bTotal );
  750.     ( (CButton *) GetDlgItem(IDC_PAGESETUP_REVERSEORDER) )->SetCheck ( m_bReverseOrder );
  751. #ifdef XP_WIN32
  752.     ( (CButton *) GetDlgItem(IDC_PRINTBKIMAGE) )->SetCheck ( m_bPrintBkImage );
  753. #endif
  754.     // return TRUE;  // return TRUE unless you set the focus to a control
  755.                   // EXCEPTION: OCX Property Pages should return FALSE
  756.     return FALSE;
  757. }
  758.  
  759. // Default page setup options.  This is a class that is statically instantiated
  760. // which implements the IPageSetup API.
  761.  
  762. class CPageSetupInfo :     public IUnknown,
  763.                         public IPageSetup
  764. {
  765. protected:
  766.  
  767.     ULONG m_ulRefCount;
  768.  
  769.     // page setup values
  770.     long m_lLeftMargin;
  771.     long m_lRightMargin;
  772.     long m_lTopMargin;
  773.     long m_lBottomMargin;
  774.     int  m_iHeader;
  775.     int  m_iFooter;
  776.     int  m_iSolidLines;
  777.     int  m_iBlackText;
  778.     int  m_iBlackLines;
  779.     int  m_iReverseOrder;
  780.     BOOL  m_bPrintBkImage;
  781.  
  782.     long lWidth, lHeight;
  783.     
  784. public:
  785.  
  786.     CPageSetupInfo ( );
  787.     ~CPageSetupInfo ( );
  788.  
  789.     // IUnknown Interface
  790.     STDMETHODIMP            QueryInterface(REFIID,LPVOID *);
  791.     STDMETHODIMP_(ULONG)    AddRef(void);
  792.     STDMETHODIMP_(ULONG) Release(void);
  793.    
  794.     // IClassFactory Interface
  795.     STDMETHODIMP            CreateInstance(LPUNKNOWN,REFIID,LPVOID*);
  796.     STDMETHODIMP            LockServer(BOOL);
  797.  
  798.     // IPageSetup Interface
  799.     void GetMargins ( long *, long *, long *, long * );
  800.     void SetMargins ( long, long, long, long );
  801.     void GetPageSize ( long *, long * );
  802.     void SetPageSize ( long, long );
  803.     int Header ( int flag );
  804.     int Footer ( int flag );
  805.     int SolidLines ( int flag );
  806.     int BlackText ( int flag );
  807.     int BlackLines ( int flag );
  808.     int ReverseOrder ( int flag );
  809.     void SetPrintingBkImage (BOOL flag);
  810.     BOOL IsPrintingBkImage (void);
  811. };
  812.  
  813. class CPageSetupInfoFactory :    public IClassFactory
  814. {
  815. protected:
  816.     ULONG m_ulRefCount;
  817.  
  818. public:
  819.     CPageSetupInfoFactory();
  820.  
  821.     // IUnknown Interface
  822.     STDMETHODIMP            QueryInterface(REFIID,LPVOID *);
  823.     STDMETHODIMP_(ULONG)    AddRef(void);
  824.     STDMETHODIMP_(ULONG) Release(void);
  825.    
  826.     // IClassFactory Interface
  827.     STDMETHODIMP            CreateInstance(LPUNKNOWN,REFIID,LPVOID*);
  828.     STDMETHODIMP            LockServer(BOOL);
  829. };
  830.  
  831. CPageSetupInfoFactory::CPageSetupInfoFactory()
  832. {
  833.     ApiApiPtr(api);        
  834.     api->RegisterClassFactory(APICLASS_PAGESETUP,(LPCLASSFACTORY)this);
  835.     api->CreateClassInstance(APICLASS_PAGESETUP);
  836. }
  837.  
  838. STDMETHODIMP CPageSetupInfoFactory::QueryInterface(REFIID refiid, LPVOID * ppv)
  839. {
  840.     *ppv = NULL;
  841.     if (IsEqualIID(refiid,IID_IUnknown))
  842.            *ppv = (LPUNKNOWN) this;
  843.     else if (IsEqualIID(refiid,IID_IClassFactory))
  844.         *ppv = (LPCLASSFACTORY) this;
  845.  
  846.     if (*ppv != NULL) {
  847.         AddRef();
  848.         return NOERROR;
  849.     }
  850.             
  851.     return ResultFromScode(E_NOINTERFACE);
  852. }
  853.  
  854. STDMETHODIMP_(ULONG) CPageSetupInfoFactory::AddRef(void)
  855. {
  856.     return ++m_ulRefCount;
  857. }
  858.  
  859. STDMETHODIMP_(ULONG) CPageSetupInfoFactory::Release(void)
  860. {
  861.     ULONG ulRef;
  862.     ulRef = --m_ulRefCount;
  863.     if (m_ulRefCount == 0) 
  864.         delete this;       
  865.     return ulRef;       
  866. }
  867.  
  868. STDMETHODIMP CPageSetupInfoFactory::CreateInstance(
  869.     LPUNKNOWN pUnkOuter,REFIID refiid, LPVOID * ppvObj)
  870. {
  871.     *ppvObj = NULL;
  872.     CPageSetupInfo * pRepository = new CPageSetupInfo;
  873.     return pRepository->QueryInterface(refiid,ppvObj);   
  874. }
  875.  
  876. STDMETHODIMP CPageSetupInfoFactory::LockServer(BOOL fLock)
  877. {
  878.     return NOERROR;
  879. }
  880.  
  881. // Constructor initializes the default values and registers the object
  882. // as the implementor of the IPrinter interface.
  883.  
  884. CPageSetupInfo::CPageSetupInfo ( ) 
  885. {
  886.     m_ulRefCount = 0;
  887.  
  888.     m_lLeftMargin = 720;        // 0.5 inches
  889.     m_lRightMargin = 720;
  890.     m_lTopMargin = 720;
  891.     m_lBottomMargin = 720;
  892.     m_iHeader = PRINT_TITLE | PRINT_URL;
  893.     m_iFooter = PRINT_PAGENO | PRINT_PAGECOUNT | PRINT_DATE;
  894.     m_iSolidLines = FALSE;
  895.     m_iBlackText = FALSE;
  896.     m_iBlackLines = FALSE;
  897.     m_iReverseOrder = FALSE;
  898.  
  899.     lWidth = lHeight = 0;
  900. }
  901.  
  902. // constructor releases the default API which causes it to automatically
  903. // unregister based on a zero reference count.  The API will not dissapear
  904. // until everyone is done with it.
  905.  
  906. CPageSetupInfo::~CPageSetupInfo ( )
  907. {
  908. }
  909.  
  910. STDMETHODIMP CPageSetupInfo::QueryInterface(REFIID refiid, LPVOID * ppv)
  911. {
  912.     *ppv = NULL;
  913.     if (IsEqualIID(refiid,IID_IUnknown))
  914.            *ppv = (LPUNKNOWN) this;
  915.     else if (IsEqualIID(refiid,IID_IPageSetup))
  916.         *ppv = (LPPAGESETUP) this;
  917.  
  918.     if (*ppv != NULL) {
  919.         AddRef();
  920.         return NOERROR;
  921.     }
  922.             
  923.     return ResultFromScode(E_NOINTERFACE);
  924. }
  925.  
  926. STDMETHODIMP_(ULONG) CPageSetupInfo::AddRef(void)
  927. {
  928.     return ++m_ulRefCount;
  929. }
  930.  
  931. STDMETHODIMP_(ULONG) CPageSetupInfo::Release(void)
  932. {
  933.     ULONG ulRef;
  934.     ulRef = --m_ulRefCount;
  935.     if (m_ulRefCount == 0) 
  936.         delete this;       
  937.     return ulRef;       
  938. }
  939.  
  940. void CPageSetupInfo::SetPrintingBkImage (BOOL flag)
  941. {
  942.     PREF_SetBoolPref("browser.print_background",flag);
  943.     m_bPrintBkImage = flag;
  944. }
  945. BOOL CPageSetupInfo::IsPrintingBkImage (void) 
  946. {
  947.     if (PREF_GetBoolPref("browser.print_background",&m_bPrintBkImage) != PREF_OK)
  948.         m_bPrintBkImage = FALSE;
  949.     return m_bPrintBkImage;
  950. }
  951. // function sets the margins in twips
  952.  
  953. void CPageSetupInfo::SetMargins ( long lLeft, long lRight, long lTop, long lBottom )
  954. {
  955.     m_lLeftMargin = lLeft;
  956.     m_lRightMargin = lRight;
  957.     m_lTopMargin = lTop;
  958.     m_lBottomMargin = lBottom;
  959. }
  960.  
  961. // gets the margins
  962.  
  963. void CPageSetupInfo::GetMargins ( long * plLeft, long * plRight, long * plTop, long * plBottom )
  964. {
  965.     *plLeft = m_lLeftMargin;
  966.     *plRight = m_lRightMargin;
  967.     *plTop = m_lTopMargin;
  968.     *plBottom = m_lBottomMargin;
  969. }
  970.  
  971. // get-set the header flags, -1 gets the value (default)
  972. // flags are: PRINT_TITLE | PRINT_URL
  973.  
  974. int CPageSetupInfo::Header ( int flag )
  975. {
  976.     if ( flag == -1 )
  977.         return m_iHeader;
  978.     int temp = m_iHeader;
  979.     m_iHeader = flag;
  980.     return temp;
  981. }
  982.  
  983. // get-set the footer flag, -1 gets the value (default)
  984. // flags are: PRINT_PAGENO | PRINT_PAGECOUNT | PRINT_DATE
  985.  
  986. int CPageSetupInfo::Footer ( int flag )
  987. {
  988.     if ( flag == -1 )
  989.         return m_iFooter;
  990.     int temp = m_iFooter;
  991.     m_iFooter = flag;
  992.     return temp;
  993. }
  994.  
  995. // get-set solid line flag.  Control printing of textured bevels
  996.  
  997. int CPageSetupInfo::SolidLines ( int flag )
  998. {
  999.     if ( flag == -1 )
  1000.         return m_iSolidLines;
  1001.     int temp = m_iSolidLines;
  1002.     m_iSolidLines = flag;
  1003.     return temp;
  1004.     
  1005. }
  1006.  
  1007. // get-set all text black flag.  If set to TRUE, all text is printed
  1008. // in black
  1009.  
  1010. int CPageSetupInfo::BlackText ( int flag )
  1011. {
  1012.     if ( flag == -1 )
  1013.         return m_iBlackText;
  1014.     int temp = m_iBlackText;
  1015.     m_iBlackText = flag;
  1016.     return temp;
  1017. }
  1018.  
  1019. // get-set all line black flag
  1020.  
  1021. int CPageSetupInfo::BlackLines ( int flag )
  1022. {
  1023.     if ( flag == -1 )
  1024.         return m_iBlackLines;
  1025.     int temp = m_iBlackLines;
  1026.     m_iBlackLines = flag;
  1027.     return temp;
  1028. }
  1029.  
  1030. void CPageSetupInfo::SetPageSize ( long lw, long lh )
  1031. {
  1032.     lWidth = lw;
  1033.     lHeight = lh;
  1034. }
  1035.  
  1036. void CPageSetupInfo::GetPageSize ( long * plWidth, long * plHeight )
  1037. {
  1038.     CPrintDialog printDialog ( FALSE );
  1039.     if ( printDialog.GetDefaults ( ) )
  1040.     {
  1041.         HDC hPrintDC = printDialog.GetPrinterDC ( );
  1042.         if ( hPrintDC != NULL )
  1043.         {
  1044.             POINT point;
  1045.             ::Escape ( hPrintDC, GETPHYSPAGESIZE, NULL, NULL, &point );
  1046.             lWidth = point.x;
  1047.             lHeight = point.y;
  1048.             lWidth = ( lWidth * TWIPSPERINCH ) / ::GetDeviceCaps ( hPrintDC, LOGPIXELSX );
  1049.             lHeight = ( lHeight * TWIPSPERINCH ) / ::GetDeviceCaps ( hPrintDC, LOGPIXELSY );
  1050.         }
  1051.         ::DeleteDC(hPrintDC);
  1052.         ::GlobalFree(printDialog.m_pd.hDevNames);
  1053.         ::GlobalFree(printDialog.m_pd.hDevMode);
  1054.     }
  1055.     if ( !lWidth || !lHeight )
  1056.     {
  1057.         lWidth = (TWIPSPERINCH * 85L ) / 10;
  1058.         lHeight = TWIPSPERINCH * 11;
  1059.     }
  1060.  
  1061.     *plWidth = lWidth;
  1062.     *plHeight = lHeight;
  1063.  
  1064. }
  1065.  
  1066. int CPageSetupInfo::ReverseOrder ( int flag )
  1067. {
  1068.     if ( flag == -1 )
  1069.         return m_iReverseOrder;
  1070.     int temp = m_iReverseOrder;
  1071.     m_iReverseOrder = flag;
  1072.     return temp;
  1073. }
  1074.  
  1075. static CPageSetupInfoFactory _defSettings;  // static instantiation of page setup object
  1076.