home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / mprint.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  49.6 KB  |  1,580 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 "mprint.h"
  20.  
  21. #include "CHTMLView.h"
  22. #include "CBrowserContext.h"
  23. #include "CHyperScroller.h"
  24. #include "UGraphicGizmos.h"
  25.  
  26. #include "LListener.h"
  27. #include "LPrintout.h"
  28. #include "PascalString.h"
  29. #include "LCaption.h"
  30.  
  31. #include "MoreMixedMode.h"
  32.  
  33.  
  34. #define NONE_FORM                1
  35. #define PAGE_NUMBER_FORM        2
  36. #define DATE_FORM                3
  37. #define LOCATION_FORM            4
  38. #define TITLE_FORM                5
  39.  
  40. #include "macutil.h"
  41. #include "earlmgr.h"
  42. #include "resgui.h"
  43. #include "macgui.h" // for UGraphics
  44. #include "uerrmgr.h"
  45. #include "shist.h"
  46. #include "libi18n.h"
  47. #include "xlate.h"
  48. #include "np.h"
  49.  
  50. #include "mimages.h"
  51. #include "mplugin.h"
  52.  
  53. #pragma mark --- CPrintHTMLView ---
  54.  
  55. //======================================
  56. class CPrintHTMLView : public CHTMLView
  57. //======================================
  58. {
  59.     private:
  60.         typedef CHTMLView Inherited;
  61.     public:
  62.     
  63.         enum { class_ID = 'PtHt' };
  64.         enum printMode {
  65.             epmBlockDisplay,
  66.             epmLayout,
  67.             epmDisplay
  68.         };
  69.                                 CPrintHTMLView(LStream* inStream);
  70.         virtual                    ~CPrintHTMLView();
  71.                 void             CopyCharacteristicsFrom(const CHTMLView* inHTMLView);
  72.  
  73.          virtual void            CountPanels(Uint32 &outHorizPanels, Uint32 &outVertPanels);
  74.         virtual Boolean            ScrollToPanel (const PanelSpec &inPanel);
  75.  
  76.         void                    SetPrintMode (printMode inMode)
  77.                                     { mPrintMode = inMode; }
  78.         void                    InitializeCapture (void);
  79.         void                    CalculatePageBreaks (void);
  80.  
  81.         CL_Compositor*            GetCompositor (void)
  82.                                     { return mCompositor->mCompositor; }
  83.  
  84.     // overrides
  85.  
  86.         virtual void            AdaptToSuperFrameSize(
  87.                                     Int32 inSurrWidthDelta,
  88.                                     Int32 inSurrHeightDelta,
  89.                                     Boolean inRefresh);
  90.  
  91.     protected:
  92.         virtual void            FinishCreateSelf(void);
  93.         virtual void            InstallBackgroundColor();
  94.                                     // Sets mBackgroundColor. Called from ClearBackground().
  95.                                     // The base class implementation uses the text background
  96.                                     // preference, but derived classes can override this.
  97.                                     // Here we do nothing, because the background color is set
  98.                                     // in CopyCharacteristicsFrom().
  99.         virtual    void            GetFullGridSize(
  100.                                     Int32&                    outWidth,
  101.                                     Int32&                    outHeight);
  102.         void                    CapturePosition (LO_Element *inElement);
  103.         virtual void            ResetBackgroundColor() const;
  104.                                     // Calls RGBBackColor(mBackgroundColor).  Printview overrides.
  105.         virtual    void            DrawFrameFocus();
  106.         virtual    void             DrawBackground(
  107.                                     const Rect&             inArea,
  108.                                     LO_ImageStruct*            inBackdrop = nil);                                
  109.         virtual void             EraseBackground(
  110.                                     int                        inLocation,
  111.                                     Int32                    inX,
  112.                                     Int32                    inY,
  113.                                     Uint32                    inWidth,
  114.                                     Uint32                    inHeight,
  115.                                     LO_Color*                inColor);
  116.  
  117.         Boolean                    BelongsOnPage (LO_Element *inElement);
  118.         inline Boolean            BelongsOnPage (LO_TextStruct *inElement)
  119.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  120.         inline Boolean            BelongsOnPage (LO_LinefeedStruct *inElement)
  121.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  122.         inline Boolean            BelongsOnPage (LO_HorizRuleStruct *inElement)
  123.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  124.         inline Boolean            BelongsOnPage (LO_BullettStruct *inElement)
  125.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  126.         inline Boolean            BelongsOnPage (LO_EmbedStruct *inElement)
  127.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  128.         inline Boolean            BelongsOnPage (LO_TableStruct *inElement)
  129.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  130.         inline Boolean            BelongsOnPage (LO_CellStruct *inElement)
  131.                                     { return BelongsOnPage ((LO_Element *) inElement); }
  132.         Boolean                    BelongsOnPage (LO_FormElementStruct *inElement);
  133.  
  134.         virtual void             DisplaySubtext(
  135.                                     int                     inLocation,
  136.                                     LO_TextStruct*            inText,
  137.                                     Int32                     inStartPos,
  138.                                     Int32                    inEndPos,
  139.                                     XP_Bool                 inNeedBG);
  140.  
  141.         virtual void             DisplayText(
  142.                                     int                     inLocation,
  143.                                     LO_TextStruct*            inText,
  144.                                     XP_Bool                 inNeedBG);
  145.  
  146.         virtual void             DisplayLineFeed(
  147.                                     int                     inLocation,
  148.                                     LO_LinefeedStruct*        inLinefeedStruct,
  149.                                     XP_Bool                 inNeedBG);
  150.  
  151.         virtual void             DisplayHR(
  152.                                     int                     inLocation,
  153.                                     LO_HorizRuleStruct*        inRuleStruct);
  154.  
  155.         virtual void             DisplayBullet(
  156.                                     int                     inLocation,
  157.                                     LO_BullettStruct*        inBulletStruct);
  158.  
  159.         virtual void             DisplayEmbed(
  160.                                     int                     inLocation,
  161.                                     LO_EmbedStruct*            inEmbedStruct);
  162.  
  163.         virtual void             DisplayFormElement(
  164.                                     int                     inLocation,
  165.                                     LO_FormElementStruct*     inFormElement);
  166.  
  167.         virtual void             DisplayEdge(
  168.                                     int                     inLocation,
  169.                                     LO_EdgeStruct*            inEdgeStruct);
  170.  
  171.         virtual void             DisplayTable(
  172.                                     int                     inLocation,
  173.                                     LO_TableStruct*            inTableStruct);
  174.  
  175.         virtual void             DisplayCell(
  176.                                     int                     inLocation,
  177.                                     LO_CellStruct*            inCellStruct);
  178.  
  179.         virtual    void             CreateGridView(
  180.                                     CBrowserContext*        inGridContext,
  181.                                     Int32                    inX,
  182.                                     Int32                     inY,
  183.                                     Int32                    inWidth,
  184.                                     Int32                    inHeight,
  185.                                     Int8                    inScrollMode,
  186.                                     Bool                     inNoEdge);
  187.  
  188.         printMode                mPrintMode;
  189.         LArray                    mElementRects;
  190.         LArray                    mVPanelRects;
  191. }; // class CPrintHTMLView
  192.  
  193. //-----------------------------------
  194. CPrintHTMLView::CPrintHTMLView(LStream* inStream)
  195.     :    mElementRects(sizeof(XP_Rect)),
  196.         mVPanelRects(sizeof(XP_Rect)),
  197.  
  198.         Inherited(inStream)
  199. //-----------------------------------
  200. {
  201.     SetPrintMode (epmDisplay);
  202.     SetScrollMode(LO_SCROLL_NO, false);
  203. }
  204.  
  205. //-----------------------------------
  206. CPrintHTMLView::~CPrintHTMLView()
  207. //-----------------------------------
  208. {
  209. }
  210.  
  211. // Override method to skip code in CHTMLView so that we don't call Repaginate() which
  212. // will destroy CPrintHTMLView early in printing process.
  213. //-----------------------------------
  214. void CPrintHTMLView::AdaptToSuperFrameSize(
  215. //-----------------------------------
  216.     Int32                    inSurrWidthDelta,
  217.     Int32                    inSurrHeightDelta,
  218.     Boolean                    inRefresh)
  219. {
  220.     LView::AdaptToSuperFrameSize(inSurrWidthDelta, inSurrHeightDelta, inRefresh);
  221. }
  222.  
  223. //-----------------------------------
  224. void CPrintHTMLView::CopyCharacteristicsFrom(const CHTMLView* inHTMLView)
  225. //-----------------------------------
  226. {
  227.     if (CPrefs::GetBoolean(CPrefs::PrintBackground))
  228.     {
  229.         // Transfer the back color from the view we're printing to the print view.
  230.         // This is necessary because, e.g., message views and browser views have
  231.         // different default background colors.
  232.         LO_Color bc = UGraphics::MakeLOColor(inHTMLView->GetBackgroundColor());
  233.         SetBackgroundColor(bc.red, bc.green, bc.blue);
  234.     }
  235. }
  236.  
  237. //-----------------------------------
  238. // our version works much like the inherited version (LView's), except we take into
  239. // account an HTML page's variable height.
  240. void CPrintHTMLView::CountPanels(
  241. //-----------------------------------
  242.     Uint32    &outHorizPanels,
  243.     Uint32    &outVertPanels)
  244. {
  245.     SDimension32    imageSize;
  246.     GetImageSize(imageSize);
  247.     
  248.     SDimension16    frameSize;
  249.     GetFrameSize(frameSize);
  250.     
  251.     outHorizPanels = 1;
  252.     if (frameSize.width > 0 && imageSize.width > 0)
  253.         outHorizPanels = ((imageSize.width - 1) / frameSize.width) + 1;
  254.     
  255.     outVertPanels = mVPanelRects.GetCount();
  256. }
  257.  
  258. //-----------------------------------
  259. Boolean CPrintHTMLView::ScrollToPanel (const PanelSpec &inPanel) {
  260. //-----------------------------------
  261.  
  262.     Boolean            panelInImage;
  263.     SDimension16    frameSize;
  264.     GetFrameSize(frameSize);
  265.  
  266.     Uint32    horizPanelCount;
  267.     Uint32    vertPanelCount;
  268.     CountPanels(horizPanelCount, vertPanelCount);
  269.  
  270.     // rely on horizPanelCount, but use mVPanelRects for vertical displacement
  271.     // the simple horizontal calculation is sufficient, since we don't mess with
  272.     // horizontal displacement.  But since we munge page heights, that's more complicated.
  273.  
  274.     panelInImage = false;
  275.     if (inPanel.horizIndex <= horizPanelCount && inPanel.vertIndex <= vertPanelCount) {
  276.         Int32    horizPos = frameSize.width * (inPanel.horizIndex - 1);
  277.         Int32    vertPos;
  278.         int32    pageHeight;
  279.         XP_Rect    panelVRect;
  280.  
  281.         panelInImage = mVPanelRects.FetchItemAt (inPanel.vertIndex, &panelVRect);
  282.         vertPos = panelVRect.top;
  283.         pageHeight = panelVRect.bottom - panelVRect.top;
  284.         if (panelInImage) {
  285.             ScrollImageTo (horizPos, vertPos, false);
  286.  
  287.             // now make XP_CheckElementSpan work for this page
  288.             PrintInfo    *pageInfo = ((MWContext *) *mContext)->prInfo;
  289.             pageInfo->page_topy = vertPos;
  290.             pageInfo->page_break = vertPos + pageHeight;
  291.               pageInfo->page_height = pageHeight;
  292.               pageInfo->page_width = frameSize.width;
  293.  
  294.             if (mCompositor)
  295.                 CL_ResizeCompositorWindow (*mCompositor, frameSize.width, pageHeight);
  296.           }
  297.     }
  298.     
  299.     return panelInImage;
  300. }
  301.  
  302. //-----------------------------------
  303. void CPrintHTMLView::InitializeCapture (void)
  304. //-----------------------------------
  305. {
  306.     mElementRects.RemoveItemsAt (mElementRects.GetCount(), LArray::index_First);
  307.     mVPanelRects.RemoveItemsAt (mVPanelRects.GetCount(), LArray::index_First);
  308. }
  309.  
  310. //-----------------------------------
  311. void CPrintHTMLView::CalculatePageBreaks (void)
  312. //-----------------------------------
  313. {
  314.     Boolean            breakBigElements;    // a large element straddles the boundary; break it
  315.     Rect            pageArea;
  316.     short            pageHeight;
  317.     XP_Rect            vPanelRect,            // page rect
  318.                     elementRect;        // element rectangle
  319.     int32            pageMajorLimit,        // refuse to truncate the page past this point
  320.                     pageMinorLimit;        // secondary page truncation limit
  321.     ArrayIndexT        element;            // index into list of element rectangles
  322.  
  323.     CalcPortFrameRect (pageArea);
  324.  
  325.     pageHeight = pageArea.bottom - pageArea.top;
  326.  
  327.     vPanelRect.left = pageArea.left;
  328.     vPanelRect.right = pageArea.right;
  329.     vPanelRect.top = 0;
  330.     vPanelRect.bottom = pageHeight;
  331.  
  332.     do {
  333.         pageMajorLimit = vPanelRect.bottom - pageHeight / 2;
  334.         pageMinorLimit = vPanelRect.bottom - pageHeight / 32;
  335.         element = LArray::index_First;
  336.         breakBigElements = false;
  337.         while (mElementRects.FetchItemAt (element, &elementRect)) {
  338.             element++;
  339.             // if it spans the page boundary, it's trouble:
  340.             if (elementRect.top < vPanelRect.bottom && elementRect.bottom > vPanelRect.bottom)
  341.                 // if it's bigger than a whole page, don't even consider it
  342.                 if (elementRect.bottom - elementRect.top < pageHeight) {
  343.                     // if we've decided to break on a big element, consider only small elements
  344.                     if (breakBigElements && elementRect.top < pageMinorLimit)
  345.                         continue;
  346.                     // bump up page bottom. if it's been bumped too far, reset and punt
  347.                     vPanelRect.bottom = elementRect.top;
  348.                     element = LArray::index_First;
  349.                     if (vPanelRect.bottom < pageMajorLimit) {
  350.                         vPanelRect.bottom = vPanelRect.top + pageHeight;
  351.                         breakBigElements = true;
  352.                     }
  353.                 }
  354.         }
  355.  
  356.         // remove all elements occurring on this page
  357.         element = LArray::index_First;
  358.         while (mElementRects.FetchItemAt (element, &elementRect))
  359.             if (elementRect.top < vPanelRect.bottom)
  360.                 mElementRects.RemoveItemsAt (1, element);
  361.             else
  362.                 element++;
  363.  
  364.         // store page rect and prepare for next page
  365.         mVPanelRects.InsertItemsAt (1, LArray::index_Last, &vPanelRect);
  366.         vPanelRect.top = vPanelRect.bottom + 1;
  367.         vPanelRect.bottom = vPanelRect.top + pageHeight;
  368.     } while (mElementRects.GetCount() > 0);
  369. }
  370.  
  371. //-----------------------------------
  372. void CPrintHTMLView::FinishCreateSelf(void)
  373. //-----------------------------------
  374. {
  375.     /* Printing contexts want to be drawn back-to-front, only, and all in one pass,
  376.        rather than on a delayed call-back system.  The inherited method creates
  377.        a compositor; we modify it.  Note that while a CHTMLView's mCompositor
  378.        is intended to be a _shared_ object, it appears that this one is used only
  379.        while printing, so it seems safe to make printing-specific changes to it.
  380.     */
  381.     Inherited::FinishCreateSelf();
  382.     CL_SetCompositorDrawingMethod (*mCompositor, CL_DRAWING_METHOD_BACK_TO_FRONT_ONLY);
  383.     CL_SetCompositorFrameRate (*mCompositor, 0);
  384. }
  385.  
  386. //-----------------------------------
  387. void CPrintHTMLView::InstallBackgroundColor()
  388. // Overridden to use a white background
  389. //-----------------------------------
  390. {
  391.     if (!CPrefs::GetBoolean(CPrefs::PrintBackground))
  392.         memset(&mBackgroundColor, 0xFF, sizeof(mBackgroundColor)); // white
  393.     // Else do nothing: use the background color that we copied from the view
  394.     // we're printing.
  395. }
  396. //-----------------------------------
  397. void CPrintHTMLView::ResetBackgroundColor() const
  398. //-----------------------------------
  399. {
  400.     // do nothing.
  401. }
  402.  
  403. //-----------------------------------
  404. void CPrintHTMLView::GetFullGridSize(
  405.     Int32&                    outWidth,
  406.     Int32&                    outHeight)
  407. //-----------------------------------
  408. {
  409.     // We never have scrollers, but is this right?  I'm fairly clueless...
  410.     // The base class gets the size from mScroller which, of course, is null
  411.     // for a print view...
  412.     SDimension16 theContainerSize;
  413.     this->GetFrameSize(theContainerSize);
  414.     outWidth = theContainerSize.width;
  415.     outHeight = theContainerSize.height;
  416. } // CPrintHTMLView::GetFullGridSize
  417.  
  418. //-----------------------------------
  419. void CPrintHTMLView::CapturePosition (LO_Element *inElement) {
  420. //-----------------------------------
  421.  
  422.     XP_Rect            rect;
  423.  
  424.     CalcAbsoluteElementPosition (inElement, rect);
  425.  
  426.     try {
  427.         mElementRects.InsertItemsAt (1, LArray::index_Last, &rect);
  428.     } catch (...) {
  429.         // there's really no one to report this error to.  if we're this out of memory,
  430.         // something else is going to fail worse than this.  failure to add this rect
  431.         // to the list will only cause pagination to happen at inopportune positions.
  432.     }
  433. }
  434.  
  435. //-----------------------------------
  436. // does an object with the given top and height want to be rendered on the current page?
  437. Boolean
  438. CPrintHTMLView::BelongsOnPage (LO_Element *inElement) {
  439. //-----------------------------------
  440.  
  441.     Rect    frame;
  442.     return CalcElementPosition (inElement, frame);
  443. }
  444.  
  445. //-----------------------------------
  446. // does an object with the given top and height want to be rendered on the current page?
  447. Boolean
  448. CPrintHTMLView::BelongsOnPage (LO_FormElementStruct *inElement) {
  449. //-----------------------------------
  450.  
  451.     Rect    frame;
  452.     Boolean    rtnVal;
  453. #ifdef LAYERS
  454.     // hack! HACK! HAAAACK!
  455.     /*    The element position calculation takes layer positions into account.
  456.         That's normally good, except for form elements, which are implemented as PowerPlant
  457.         subpanes.  That's normally good, except that the compositor sticks each form element
  458.         subpane into a layer of its own.  No doubt the compositor thinks that's good, and
  459.         normally we don't have a problem with that.  But here, it results in the calculated
  460.         position of the frame being multiplied by two (since the layer's position is added
  461.         to the element's position).  Here's where we temporarily convince our superclass
  462.         that the current layer is at (0,0):
  463.     */
  464.     // note: if this ever gives you problems, you can probably replace it with simply
  465.     // "return true" and let clipping decide who to display.
  466.     CDrawable    *drawable = mCurrentDrawable;
  467.     SPoint32    origin = mLayerOrigin;
  468.     mCurrentDrawable = NULL;
  469.     mLayerOrigin.h = 0;
  470.     mLayerOrigin.v = 0;
  471. #endif
  472.     rtnVal = CalcElementPosition ((LO_Element *) inElement, frame);
  473. #ifdef LAYERS
  474.     mCurrentDrawable = drawable;
  475.     mLayerOrigin = origin;
  476. #endif
  477.     return rtnVal;
  478. }
  479.  
  480.  
  481. //-----------------------------------
  482. void CPrintHTMLView::DisplaySubtext(
  483.     int                     inLocation,
  484.     LO_TextStruct*            inText,
  485.     Int32                     inStartPos,
  486.     Int32                    inEndPos,
  487.     XP_Bool                 inNeedBG)
  488. //-----------------------------------
  489. {
  490.     switch (mPrintMode) {
  491.         case epmBlockDisplay:
  492.             break;
  493.         case epmLayout:
  494.             // do it all in DisplayText. the assumption here is that DisplaySubtext
  495.             // will be called more often, but DisplayText will be called for each line
  496.             break;
  497.         case epmDisplay:
  498.             if (FocusDraw() && BelongsOnPage (inText))
  499.                 Inherited::DisplaySubtext(inLocation, inText, inStartPos, inEndPos, inNeedBG);
  500.     }
  501. } // CPrintHTMLView::DisplaySubtext
  502.  
  503. //-----------------------------------
  504. void CPrintHTMLView::DisplayText(
  505.     int                     inLocation,
  506.     LO_TextStruct*            inText,
  507.     XP_Bool                 inNeedBG) {
  508. //-----------------------------------
  509.  
  510.     switch (mPrintMode) {
  511.         case epmBlockDisplay:
  512.             break;
  513.         case epmLayout:
  514.             CapturePosition ((LO_Element *) inText);
  515.             break;
  516.         case epmDisplay:
  517.             if (FocusDraw() && BelongsOnPage (inText))
  518.                 Inherited::DisplayText (inLocation, inText, inNeedBG);
  519.     }
  520. }
  521.  
  522. //-----------------------------------
  523. void CPrintHTMLView::DisplayLineFeed(
  524.     int                     inLocation,
  525.     LO_LinefeedStruct*        inLinefeedStruct,
  526.     XP_Bool                 inNeedBG) {
  527. //-----------------------------------
  528.  
  529.     switch (mPrintMode) {
  530.         case epmBlockDisplay:
  531.             break;
  532.         case epmLayout:
  533.             CapturePosition ((LO_Element *) inLinefeedStruct);
  534.             break;
  535.         case epmDisplay:
  536.             if (FocusDraw() && BelongsOnPage (inLinefeedStruct))
  537.                 Inherited::DisplayLineFeed(inLocation, inLinefeedStruct, inNeedBG);
  538.     }
  539. }
  540.  
  541.  
  542. //-----------------------------------
  543. void CPrintHTMLView::DisplayHR(
  544.     int                     inLocation,
  545.     LO_HorizRuleStruct*        inRuleStruct)
  546. //-----------------------------------
  547. {
  548.     switch (mPrintMode) {
  549.         case epmBlockDisplay:
  550.             break;
  551.         case epmLayout:
  552.             CapturePosition ((LO_Element *) inRuleStruct);
  553.             break;
  554.         case epmDisplay:
  555.             if (FocusDraw() && BelongsOnPage (inRuleStruct))
  556.                 Inherited::DisplayHR (inLocation, inRuleStruct);
  557.     }
  558. } // CPrintHTMLView::DisplayHR
  559.  
  560. //-----------------------------------
  561. void CPrintHTMLView::DisplayBullet(
  562.     int                     inLocation,
  563.     LO_BullettStruct*        inBulletStruct) {
  564. //-----------------------------------
  565.  
  566.     switch (mPrintMode) {
  567.         case epmBlockDisplay:
  568.             break;
  569.         case epmLayout:
  570.             CapturePosition ((LO_Element *) inBulletStruct);
  571.             break;
  572.         case epmDisplay:
  573.             if (FocusDraw() && BelongsOnPage (inBulletStruct))
  574.                 Inherited::DisplayBullet (inLocation, inBulletStruct);
  575.     }
  576. } // CPrintHTMLView::DisplayBullet
  577.  
  578. //-----------------------------------
  579. void CPrintHTMLView::DisplayEmbed(
  580.     int                     /*inLocation*/,
  581.     LO_EmbedStruct*            inEmbedStruct) {
  582. //-----------------------------------
  583.  
  584.     switch (mPrintMode) {
  585.         case epmBlockDisplay:
  586.             break;
  587.         case epmLayout:
  588.             CapturePosition ((LO_Element *) inEmbedStruct);
  589.             break;
  590.         case epmDisplay:
  591.             if (FocusDraw() && BelongsOnPage (inEmbedStruct))
  592.                 {
  593.                 NPEmbeddedApp* app = (NPEmbeddedApp*) inEmbedStruct->FE_Data;
  594.                 CPluginView* view = (CPluginView*) app->fe_data;
  595.                 view->EmbedDisplay(inEmbedStruct, true);
  596.                 }
  597.     }
  598. }
  599.  
  600. //-----------------------------------
  601. void CPrintHTMLView::DisplayFormElement(
  602.     int                     inLocation,
  603.     LO_FormElementStruct*     inFormElement) {
  604. //-----------------------------------
  605.  
  606.     switch (mPrintMode) {
  607.         case epmBlockDisplay:
  608.             break;
  609.         case epmLayout:
  610.             CapturePosition ((LO_Element *) inFormElement);
  611.             break;
  612.         case epmDisplay:
  613.             if (FocusDraw() && BelongsOnPage (inFormElement))
  614.                 Inherited::DisplayFormElement(inLocation, inFormElement);
  615.     }
  616. }
  617.  
  618. //-----------------------------------
  619. void CPrintHTMLView::DisplayEdge(
  620.     int                     /*inLocation*/,
  621.     LO_EdgeStruct*            /*inEdgeStruct*/)
  622. //-----------------------------------
  623. {
  624.     // Do nothing for printing.
  625. }
  626.  
  627. //-----------------------------------
  628. void CPrintHTMLView::DisplayTable(
  629.     int                     inLocation,
  630.     LO_TableStruct*            inTableStruct) {
  631. //-----------------------------------
  632.  
  633.     switch (mPrintMode) {
  634.         case epmBlockDisplay:
  635.             break;
  636.         case epmLayout:
  637.             CapturePosition ((LO_Element *) inTableStruct);
  638.             break;
  639.         case epmDisplay:
  640.             if (FocusDraw() && BelongsOnPage (inTableStruct))
  641.                 Inherited::DisplayTable(inLocation, inTableStruct);
  642.     }
  643. } // CPrintHTMLView::DisplayTable
  644.  
  645. //-----------------------------------
  646. void CPrintHTMLView::DisplayCell(
  647.     int                     inLocation,
  648.     LO_CellStruct*            inCellStruct) {
  649. //-----------------------------------
  650.  
  651.     switch (mPrintMode) {
  652.         case epmBlockDisplay:
  653.             break;
  654.         case epmLayout:
  655.             CapturePosition ((LO_Element *) inCellStruct);
  656.             break;
  657.         case epmDisplay:
  658.             if (FocusDraw() && BelongsOnPage (inCellStruct))
  659.                 Inherited::DisplayCell (inLocation, inCellStruct);
  660.     }
  661. } // CPrintHTMLView::DisplayCell
  662.  
  663. //-----------------------------------
  664. void CPrintHTMLView::DrawFrameFocus()
  665. //-----------------------------------
  666. {
  667.     // Do nothing for printing.
  668. } // CPrintHTMLView::DrawFrameFocus
  669.  
  670. //-----------------------------------
  671. void CPrintHTMLView::DrawBackground(
  672.     const Rect&             inArea,
  673.     LO_ImageStruct*            inBackdrop)
  674. //-----------------------------------
  675. {
  676.     // Ñ default white background for printing (also black text)
  677.     if (!CPrefs::GetBoolean(CPrefs::PrintBackground))
  678.         return; 
  679.     Inherited::DrawBackground(inArea, inBackdrop);
  680. } // CPrintHTMLView::DrawBackground
  681.  
  682. //-----------------------------------
  683. void CPrintHTMLView::EraseBackground(
  684.     int                        inLocation,
  685.     Int32                    inX,
  686.     Int32                    inY,
  687.     Uint32                    inWidth,
  688.     Uint32                    inHeight,
  689.     LO_Color*                inColor)
  690. //-----------------------------------
  691. {
  692.     if (inColor != nil && !CPrefs::GetBoolean(CPrefs::PrintBackground))
  693.         return;
  694.     Inherited::EraseBackground(inLocation, inX, inY, inWidth, inHeight, inColor);
  695. } // CPrintHTMLView::EraseBackground
  696.  
  697.  
  698. //-----------------------------------
  699. void CPrintHTMLView::CreateGridView(
  700.     CBrowserContext*        inGridContext,
  701.     Int32                    inX,
  702.     Int32                     inY,
  703.     Int32                    inWidth,
  704.     Int32                    inHeight,
  705.     Int8                    inScrollMode,
  706.     Bool                     inNoEdge)
  707. //-----------------------------------
  708. {
  709.  
  710.     CHyperScroller* theContainer = NULL;
  711.  
  712.     try
  713.     {
  714.         SetScrollMode(LO_SCROLL_NO, false);
  715.         mShowFocus = false;
  716.         
  717.         FocusDraw();
  718.         LCommander::SetDefaultCommander( this );
  719.         LPane::SetDefaultView( this );
  720.  
  721.         theContainer = (CHyperScroller*)UReanimator::ReadObjects('PPob', 1002);
  722.         ThrowIfNULL_(theContainer);
  723.         theContainer->FinishCreate();
  724.         
  725.         CPrintHTMLView* theNewView = (CPrintHTMLView*)theContainer->FindPaneByID(2005);
  726.         ThrowIfNULL_(theNewView);
  727.     
  728.         // Ñ position it
  729.         theNewView->mNoBorder = inNoEdge;
  730.         theNewView->SetSuperHTMLView(this);
  731.  
  732.         Rect theOwningFrame;
  733.         CalcLocalFrameRect(theOwningFrame);
  734.  
  735.         Rect theNewFrame;
  736.         CropFrameToContainer(inX, inY, inWidth, inHeight, theNewFrame);
  737.  
  738.         CHyperScroller* theSuperScroller = mScroller;
  739.         if (!theNewView->mNoBorder)
  740.             {
  741.             //    for each side that intersects the container, 
  742.             //    expand the container out one
  743.             if (inX == 0)
  744.                 if (theSuperScroller)
  745.                     theSuperScroller->ExpandLeft();
  746.                 
  747.             if (inY == 0)
  748.                 if (theSuperScroller)
  749.                     theSuperScroller->ExpandTop();
  750.  
  751.             if (theNewFrame.right == theOwningFrame.right)
  752.                 if (theSuperScroller)
  753.                     theSuperScroller->ExpandRight();
  754.                 
  755.             if (theNewFrame.bottom == theOwningFrame.bottom)
  756.                 if (theSuperScroller)
  757.                     theSuperScroller->ExpandBottom();
  758.             
  759.             if (theSuperScroller)
  760.                 theSuperScroller->AdjustHyperViewBounds();
  761.             }
  762.         else
  763.             {
  764.             theContainer->ExpandLeft();
  765.             theContainer->ExpandTop();
  766.             theContainer->ExpandRight();
  767.             theContainer->ExpandBottom();
  768.             theContainer->AdjustHyperViewBounds();
  769.             }
  770.                                     
  771.         CropFrameToContainer(inX, inY, inWidth, inHeight, theNewFrame);
  772.  
  773.         theContainer->PlaceInSuperFrameAt(theNewFrame.left, theNewFrame.top, false);
  774.         theContainer->ResizeFrameTo(RectWidth(theNewFrame), RectHeight(theNewFrame), false);
  775.  
  776.         if (theSuperScroller)
  777.             theSuperScroller->AdjustHyperViewBounds();
  778.         theContainer->AdjustHyperViewBounds();
  779.  
  780.         theNewView->SetScrollMode(inScrollMode);
  781.         theNewView->mShowFocus = true;
  782.  
  783.         // Ñ so that we call scroller's activate, and it actually enables the scrollbars
  784. //        theContainer->ActivateSelf();
  785. // FIX ME!!! this used to be the line above.  I hope this still works
  786.         theContainer->Activate();
  787.         
  788.         if (theSuperScroller)
  789.             theSuperScroller->Refresh();
  790.  
  791.         theNewView->SetContext(inGridContext);
  792.         mHasGridCells = true;
  793.         
  794.             // give the grid context the same listeners as the root context
  795.         mContext->CopyListenersToContext(inGridContext);    
  796.         }
  797.     catch (...)
  798.         {
  799.         delete theContainer;
  800.         throw;
  801.         }
  802.  
  803. } // CPrintHTMLView::CreateGridView
  804.  
  805. #pragma mark --- CPrintContext ---
  806. //======================================
  807. class CPrintContext : public CBrowserContext
  808. //======================================
  809. {
  810.     public:
  811.         CPrintContext();
  812.         operator MWContext*() { return &mContext; }
  813.         operator MWContext&() { return mContext; }
  814. }; // class CPrintContext
  815.  
  816. //-----------------------------------
  817. CPrintContext::CPrintContext()
  818. :    CBrowserContext(MWContextPrint)
  819. //-----------------------------------
  820. {
  821.     mContext.fancyFTP = false;
  822.     mContext.fancyNews = false;
  823.     
  824.     mContext.convertPixX = 1;
  825.     mContext.convertPixY = 1;
  826.     mContext.fe.view = nil;
  827. //    mContext.fe.realContext = this;
  828.     mContext.is_grid_cell = false;
  829.  
  830.     IL_DisplayData    data;
  831.     data.dither_mode = IL_ClosestColor;
  832.     IL_SetDisplayMode(mContext.img_cx, IL_DITHER_MODE, &data);    
  833. }
  834.  
  835. #pragma mark --- CCustomPageSetup ---
  836.  
  837. #define NUM_POPUPS            6
  838. #define NUM_CONTROLS        7
  839. #define BACKGROUND_CHECKBOX    6    // member of fControls[] which is treated specially
  840.  
  841. //======================================
  842. class CCustomPageSetup
  843. //======================================
  844. {
  845. public:
  846.     static void                InitCustomPageSetup();
  847.     static void                OpenPageSetup( THPrint hPrint );
  848.                             
  849.     static pascal TPPrDlg    CustomStyleDialogInit( THPrint hPrint );
  850.     PROCDECL( static, CustomStyleDialogInit )
  851.  
  852.     static long                GetControlValue( long i );
  853. protected:
  854.     struct ControlStruct
  855.     {
  856.         ControlHandle        handle;
  857.         CPrefs::PrefEnum    prefEnum;
  858.     };
  859.     
  860.     static pascal void CustomStyleItems( DialogPtr xdialogPtr, short itemNo );
  861.     PROCDECL( static, CustomStyleItems )
  862.  
  863.     static TPPrDlg            sPageSetupDialog;    // pointer to style dialog
  864.     static PItemUPP            sItemProc;            // we need to store the old itemProc here
  865.     static long                sFirstItem;            // save our first item here
  866.  
  867.     static ControlStruct    fControls[ NUM_CONTROLS ];
  868. }; // class CCustomPageSetup
  869.  
  870. TPPrDlg CCustomPageSetup::sPageSetupDialog = nil;// pointer to style dialog
  871. PItemUPP CCustomPageSetup::sItemProc = nil;        // we need to store the old itemProc here
  872. long CCustomPageSetup::sFirstItem = nil;        // save our first item here
  873. CCustomPageSetup::ControlStruct    CCustomPageSetup::fControls[ NUM_CONTROLS ];
  874.  
  875. //-----------------------------------
  876. void CCustomPageSetup::InitCustomPageSetup()
  877. //-----------------------------------
  878. {
  879.     fControls[ 0 ].prefEnum = CPrefs::TopLeftHeader;
  880.     fControls[ 1 ].prefEnum = CPrefs::TopMidHeader;
  881.     fControls[ 2 ].prefEnum = CPrefs::TopRightHeader;
  882.     fControls[ 3 ].prefEnum = CPrefs::BottomLeftFooter;
  883.     fControls[ 4 ].prefEnum = CPrefs::BottomMidFooter;
  884.     fControls[ 5 ].prefEnum = CPrefs::BottomRightFooter;
  885.     fControls[ BACKGROUND_CHECKBOX ].prefEnum = CPrefs::PrintBackground;
  886. }
  887.  
  888. //-----------------------------------
  889. void CCustomPageSetup::OpenPageSetup( THPrint hp )
  890. //-----------------------------------
  891. {
  892.     sPageSetupDialog = ::PrStlInit( hp );
  893.     
  894.     if ( PrError() == noErr )
  895.     {
  896.         if ( ::PrDlgMain( hp, (PDlgInitUPP) &PROCPTR( CCustomPageSetup::CustomStyleDialogInit ) ) )
  897.             ;
  898.     }
  899. }
  900.  
  901. //-----------------------------------
  902. long CCustomPageSetup::GetControlValue( long i )
  903. //-----------------------------------
  904. {
  905.     if (i == BACKGROUND_CHECKBOX)
  906.         return CPrefs::GetBoolean (fControls[BACKGROUND_CHECKBOX].prefEnum);
  907.     return CPrefs::GetLong (fControls[i].prefEnum);
  908. }
  909.  
  910. //-----------------------------------
  911. pascal void CCustomPageSetup::CustomStyleItems( DialogPtr xdialogPtr, short itemNo )
  912. //-----------------------------------
  913. {
  914.     TPPrDlg dialogPtr = (TPPrDlg)xdialogPtr;
  915.     long value = 0;
  916.     short myItem = itemNo - sFirstItem;    // "localize" current item No
  917.     if ( myItem >= 0 )                     // if localized item > 0, it's one of ours
  918.     {
  919.         if ( fControls[ myItem ].handle )
  920.         {
  921.             value = ::GetControlValue( fControls[ myItem ].handle );
  922.             if ( myItem == BACKGROUND_CHECKBOX )
  923.             {
  924.                 value = !value;
  925.                 ::SetControlValue( fControls[ myItem ].handle, value );
  926.                 CPrefs::SetBoolean( value, fControls[ myItem ].prefEnum );
  927.             }
  928.             else
  929.                 CPrefs::SetLong( value, fControls[ myItem ].prefEnum );
  930.         }
  931.     }
  932.     else 
  933.         CallPItemProc( sItemProc, (DialogPtr)dialogPtr, itemNo );
  934. }
  935.  
  936.  
  937. PROCEDURE( CCustomPageSetup::CustomStyleItems, uppPItemProcInfo )
  938.  
  939. //-----------------------------------
  940. pascal TPPrDlg CCustomPageSetup::CustomStyleDialogInit( THPrint /*hPrint*/ )
  941. //    this routine appends items to the standard style dialog and sets up the
  942. //    user fields of the printing dialog record TPRDlg 
  943. //    This routine will be called by PrDlgMain
  944. //-----------------------------------
  945. {
  946.     short            itemType = 0;        // needed for GetDialogItem/SetDItem call
  947.     Handle            itemH = nil;
  948.     Rect            itemBox;
  949.     Handle            ditlList;
  950.     
  951.     // Ñ╩append the items from the resource
  952.     ditlList = GetResource( 'DITL', 256 );
  953.     sFirstItem = CountDITL( (DialogPtr)sPageSetupDialog ) + 1;
  954.     AppendDITL( (DialogPtr)sPageSetupDialog, ditlList, appendDITLBottom );
  955.     ReleaseResource( ditlList );
  956.  
  957.     // Ñ╩init all the control values    
  958.     for ( long i = 0; i < NUM_CONTROLS; i++ )
  959.     {
  960.         ::GetDialogItem( (DialogPtr) sPageSetupDialog, sFirstItem + i, &itemType, &itemH, &itemBox );
  961.         fControls[ i ].handle = (ControlHandle)itemH;
  962.         ::SetControlValue( (ControlHandle)itemH, GetControlValue(i) );
  963.     }
  964.     
  965.     // Ñ patch in our item handler
  966.     //        sItemProc is the original item proc,
  967.     //        pItemProc becomes our custom item proc
  968.     sItemProc = sPageSetupDialog->pItemProc;
  969.     sPageSetupDialog->pItemProc = &PROCPTR( CCustomPageSetup::CustomStyleItems );
  970.     
  971.     // Ñ╩PrDlgMain expects a pointer to the modified dialog to be returned╔
  972.     return sPageSetupDialog;
  973. } // CCustomPageSetup::CustomStyleDialogInit
  974. PROCEDURE( CCustomPageSetup::CustomStyleDialogInit, uppPDlgInitProcInfo )
  975.  
  976. //======================================
  977. #pragma mark --- CPrintHeaderCaption ---
  978. //======================================
  979.  
  980. //======================================
  981. class CPrintHeaderCaption: public LCaption
  982. //======================================
  983. {
  984. public:
  985.     enum            { class_ID = 'HPPE' };
  986.     
  987.                     CPrintHeaderCaption( LStream* inStream );
  988.     virtual void    PrintPanelSelf( const PanelSpec& inPanel );
  989.     
  990.     static void        CreateString( long type, CStr255& string, const PanelSpec& inPanel );
  991.     static void        SetPrintContext( MWContext* cntx )
  992.                     {
  993.                         sContext = cntx;
  994.                     }
  995.     static void        SetTemporaryFile( Boolean b ) { sIsTemporaryFile = b; }
  996. protected:
  997.     static MWContext*        sContext;
  998.     static Boolean            sIsTemporaryFile;
  999. }; // class CPrintHeaderCaption
  1000.  
  1001. MWContext* CPrintHeaderCaption::sContext = nil;
  1002. Boolean    CPrintHeaderCaption::sIsTemporaryFile = false;
  1003.  
  1004. //-----------------------------------
  1005. CPrintHeaderCaption::CPrintHeaderCaption( LStream* inStream ): LCaption( inStream )
  1006. //-----------------------------------
  1007. {
  1008. }
  1009.  
  1010. //-----------------------------------
  1011. void CPrintHeaderCaption::CreateString( long form, CStr255& string, const PanelSpec& panel )
  1012. //-----------------------------------
  1013. {
  1014.     switch ( form )
  1015.     {
  1016.         case PAGE_NUMBER_FORM:
  1017.         {
  1018.             char buffer[ 30 ];
  1019.             CStr255 format = GetPString( PG_NUM_FORM_RESID );
  1020.             PR_snprintf( buffer, 30, format, panel.pageNumber );
  1021.             string = buffer;
  1022.         }
  1023.         break;
  1024.         
  1025.         case DATE_FORM:
  1026.             GetDateTimeString( string );
  1027.         break;
  1028.     
  1029.         case LOCATION_FORM:
  1030.             if ( sContext && !sIsTemporaryFile )
  1031.             {
  1032.                 History_entry*        current;
  1033.                 current = SHIST_GetCurrent( &sContext->hist );
  1034.                 if ( current && current->address )
  1035.                 {
  1036.                     char *urlPath = NULL;
  1037.                     // if the URL starts with ftp or http then we'll make an attempt to remove password
  1038.                     if ( (XP_STRNCMP(current->address, "ftp", 3) == 0 || XP_STRNCMP(current->address, "http", 4) == 0 )
  1039.                         && NET_ParseUploadURL( current->address, &urlPath, NULL, NULL ) )
  1040.                     {
  1041.                         string = urlPath;
  1042.                         if ( urlPath )
  1043.                             XP_FREE( urlPath );
  1044.                     }
  1045.                     else // unknown URL; use it as is
  1046.                         string = current->address;
  1047.                 }
  1048.             }
  1049.         break;
  1050.         
  1051.         case TITLE_FORM:
  1052.             if ( sContext && !sIsTemporaryFile )
  1053.             {
  1054.                 History_entry*        current;
  1055.                 current = SHIST_GetCurrent( &sContext->hist );
  1056.                 if ( current )
  1057.                     string = current->title;
  1058.             }
  1059.         break;
  1060.     }
  1061. }
  1062.  
  1063. //-----------------------------------
  1064. void CPrintHeaderCaption::PrintPanelSelf( const PanelSpec& inPanel )
  1065. //-----------------------------------
  1066. {
  1067.     long value = CCustomPageSetup::GetControlValue( mUserCon );
  1068.     CStr255        string;
  1069.     CPrintHeaderCaption::CreateString( value, string, inPanel );
  1070.     
  1071.     unsigned short win_csid = INTL_DefaultWinCharSetID(sContext);
  1072.     if (value == TITLE_FORM && 
  1073.        ((INTL_CharSetNameToID(INTL_ResourceCharSet()) & ~CS_AUTO ) 
  1074.                != (win_csid & ~CS_AUTO)))    
  1075.     {
  1076.         // Save the origional font name and number
  1077.         TextTraitsH origTT = UTextTraits::LoadTextTraits(this->GetTextTraitsID());
  1078.         Int16 origFontNumber = (*origTT)->fontNumber;
  1079.         Str255 origFontName;
  1080.         ::BlockMoveData(origFontName, (*origTT)->fontName, (*origTT)->fontName[0]+1);
  1081.         
  1082.         // SetHandleSize- the handle is compressed.
  1083.         ::SetHandleSize((Handle)origTT, sizeof(TextTraitsRecord));    
  1084.         StHandleLocker lock((Handle) origTT );
  1085.         
  1086.         // Set the Font name and number in the TextTraits to the one in buttonF
  1087.         TextTraitsH csidTT
  1088.             = UTextTraits::LoadTextTraits(CPrefs::GetButtonFontTextResIDs(win_csid));
  1089.  
  1090.         (*origTT)->fontNumber     = (*csidTT)->fontNumber;
  1091.         ::BlockMoveData((*origTT)->fontName, (*csidTT)->fontName, (*csidTT)->fontName[0]+1);
  1092.         
  1093.         // Do the usual job
  1094.         this->SetDescriptor(string);
  1095.         this->DrawSelf();
  1096.         
  1097.         // Restore the font name, number to the origional TextTraits
  1098.         (*origTT)->fontNumber = origFontNumber;
  1099.         ::BlockMoveData((*origTT)->fontName, origFontName, origFontName[0]+1);
  1100.     }
  1101.     else
  1102.     {
  1103.         this->SetDescriptor( string );
  1104.         this->DrawSelf();
  1105.     }    
  1106. } // CPrintHeaderCaption::PrintPanelSelf
  1107.  
  1108. //======================================
  1109. #pragma mark --- CHTMLPrintout ---
  1110. //======================================
  1111.  
  1112. //======================================
  1113. class CHTMLPrintout
  1114.     : public LPrintout
  1115.     , public LListener
  1116. //======================================
  1117. {
  1118. public:
  1119.     enum            { class_ID = 'HPPT' };
  1120.     typedef LPrintout super;
  1121.     
  1122.                     CHTMLPrintout( LStream* inStream );
  1123.                     virtual ~CHTMLPrintout();
  1124.                                     
  1125.     virtual void    FinishCreateSelf();
  1126.     virtual void    ListenToMessage(
  1127.                         MessageT                inMessage,
  1128.                         void*                    ioParam);
  1129.     
  1130.     virtual void    DoProgress( const char* message, int level );
  1131.     static void        BeginPrint( THPrint hp, CHTMLView* view );
  1132.     static CHTMLPrintout*    Get()    { return sHTMLPrintout; }
  1133.     CPrintHTMLView*    GetPrintHTMLView() const { return mPrintHTMLView; }
  1134.     void            LoadPageForPrint(URL_Struct* url, 
  1135.                             MWContext *printcontext, MWContext *viewContext);
  1136.     void            StashPrintRecord(THPrint inPrintRecordH);
  1137.     Boolean            PrintFinished(void)
  1138.                         { return mPrinted && LMGetTicks() >= mFinishedTime; }
  1139.  
  1140. protected:
  1141.  
  1142.     void            Paginate (void);
  1143.     void            CapturePositions (void);
  1144.  
  1145.     static CHTMLPrintout*        sHTMLPrintout;
  1146.  
  1147.     CPrintHTMLView*                mPrintHTMLView;
  1148.     CPrintContext*                mContext;
  1149.     Boolean                        mFinishedLayout,
  1150.                                 mConnectionsCompleted,
  1151.                                 mPrinted;
  1152.     SInt32                        mFinishedTime;
  1153. }; // class CHTMLPrintout
  1154.  
  1155. CHTMLPrintout* CHTMLPrintout::sHTMLPrintout = nil;
  1156.  
  1157. extern void BuildAWindowPalette( MWContext* context, WindowPtr window );
  1158.  
  1159. //-----------------------------------
  1160. CHTMLPrintout::CHTMLPrintout( LStream* inStream )
  1161. //-----------------------------------
  1162. :    LPrintout( inStream )
  1163. ,    mContext(nil)
  1164. ,    mPrintHTMLView(nil)
  1165. ,    mPrinted(false)
  1166. {
  1167.     sHTMLPrintout = this;
  1168. }
  1169.  
  1170. //-----------------------------------
  1171. CHTMLPrintout::~CHTMLPrintout()
  1172. //-----------------------------------
  1173. {
  1174.     if ( XP_IsContextBusy( *mContext ) )
  1175.         NET_InterruptWindow( *mContext );
  1176.     XP_CleanupPrintInfo(*mContext);
  1177.     DestroyImageContext( *mContext );
  1178.     mContext->RemoveListener(this);
  1179.     mContext->RemoveUser(this);
  1180.     sHTMLPrintout = nil;
  1181. }
  1182.  
  1183. //-----------------------------------
  1184. void CHTMLPrintout::FinishCreateSelf()
  1185. //-----------------------------------
  1186. {
  1187.     LPrintout::FinishCreateSelf();
  1188.     mContext = new CPrintContext();
  1189.     ThrowIfNil_(mContext);
  1190.     mContext->AddUser(this);
  1191.     mContext->AddListener(this); // listen for msg_NSCAllConnectionsComplete
  1192.     
  1193.     CreateImageContext( *mContext );
  1194.  
  1195.     mPrintHTMLView = (CPrintHTMLView*)FindPaneByID('PtHt');
  1196.     mPrintHTMLView->SetContext(mContext);
  1197. }
  1198.  
  1199. // editor callback
  1200. void EditorPrintingCallback( char *completeURL, void *data )
  1201. {
  1202.     Try_
  1203.     {
  1204.         URL_Struct* url = NET_CreateURLStruct( completeURL, NET_DONT_RELOAD );
  1205.         ThrowIfNil_(url);
  1206.         
  1207.         CPrintHeaderCaption::SetTemporaryFile( true );
  1208.         CHTMLPrintout::Get()->LoadPageForPrint( url, (MWContext *)data, (MWContext *)data );
  1209.     }
  1210.     Catch_( err )
  1211.     {
  1212.         Throw_( err );
  1213.     }
  1214.     EndCatch_
  1215.     
  1216. }
  1217.  
  1218.  
  1219. //-----------------------------------
  1220. void CHTMLPrintout::StashPrintRecord (THPrint inPrintRecordH)
  1221. //-----------------------------------
  1222. {
  1223.  
  1224. /*   StashPrintRecord is based on LPrintout::SetPrintRecord.  You might think we'd override
  1225.    that method, but it isn't virtual.  So we changed the name to make it obvious that
  1226.    it's a different function, then just called it ourself after LPrintout is finished
  1227.    calling its version.
  1228.      I don't understand why the LPrintout version of this method is supposed to work.
  1229.    It sizes the LPrintout to match the size of the paper, rather than the page.  The
  1230.    comments in that method mumble something about the coordinate system working out
  1231.    better that way.  You can work around this by building into the PPob describing
  1232.    the LPrintout an offset which accounts for the unprintable margin, but that works
  1233.    only as long as the size of the printer margins is about the size built into the PPob.
  1234.    This breaks down terribly if you print at reduced size, which effectively increases
  1235.    the size of the printer margins.
  1236.      So I've changed the PPob to completely fill its parent view, and here I effectively
  1237.    change PowerPlant to use the page size.  As far as I can tell, this works in all
  1238.    cases.
  1239. */
  1240.  
  1241.     // do what LPrintout::SetPrintRecord does, but size ourselves to the page,
  1242.     // rather than the paper
  1243.     UPrintingMgr::ValidatePrintRecord(inPrintRecordH);
  1244.     mPrintRecordH = inPrintRecordH;
  1245.  
  1246.     Rect    pageRect = (**inPrintRecordH).prInfo.rPage;
  1247.  
  1248.     ResizeFrameTo(pageRect.right - pageRect.left,
  1249.                     pageRect.bottom - pageRect.top, false);
  1250.     ResizeImageTo(pageRect.right - pageRect.left,
  1251.                     pageRect.bottom - pageRect.top, false);
  1252.     PlaceInSuperImageAt(pageRect.left, pageRect.top, false);
  1253. }
  1254.  
  1255. //-----------------------------------
  1256. void CHTMLPrintout::LoadPageForPrint(URL_Struct* url, MWContext *printcontext, MWContext *viewContext)
  1257. //-----------------------------------
  1258. {
  1259.     // SHIST_CreateURLStructFromHistoryEntry copies pointers but not
  1260.     // the saved data structures, so we must zero them out to prevent
  1261.     // double-deletions.  An alternative that would preserve saved data
  1262.     // for clients that find it useful (e.g. forms, embeds) would be to
  1263.     // deep copy the saved data objects.
  1264.     XP_MEMSET( &url->savedData, 0, sizeof( SHIST_SavedData ) );
  1265.  
  1266.     NPL_PreparePrint( viewContext, &( url->savedData ) );
  1267.     if ( printcontext->prSetup )
  1268.         printcontext->prSetup->url = url;
  1269.     url->position_tag = 0;
  1270.     if ( url->address )
  1271.         XP_STRTOK( url->address, "#" );
  1272.  
  1273.     CPrintHeaderCaption::SetPrintContext( viewContext );
  1274.     EarlManager::StartLoadURL( url, printcontext, FO_PRESENT );
  1275.     OutOfFocus( nil );
  1276. }
  1277.  
  1278.  
  1279. //-----------------------------------
  1280. void CHTMLPrintout::Paginate (void) {
  1281. //-----------------------------------
  1282.  
  1283.     mPrintHTMLView->InitializeCapture();
  1284.     CapturePositions();
  1285.     mPrintHTMLView->CalculatePageBreaks();
  1286.     mPrintHTMLView->SetPrintMode (CPrintHTMLView::epmDisplay);
  1287. }
  1288.  
  1289. //-----------------------------------
  1290. void CHTMLPrintout::CapturePositions (void) {
  1291. //-----------------------------------
  1292.  
  1293.     Rect            pageArea;
  1294.     short            pageWidth,
  1295.                     pageHeight;
  1296.     CL_Compositor    *compositor = mPrintHTMLView->GetCompositor();
  1297.  
  1298.     mPrintHTMLView->CalcPortFrameRect (pageArea);
  1299.     pageHeight = pageArea.bottom - pageArea.top;
  1300.     pageWidth = pageArea.right - pageArea.left;
  1301.  
  1302.     //  For capturing, we want all the elements in a document to display.
  1303.     //  Since we can't size the compositor window to be the size of the
  1304.     //  document (the compositor window must have coordinates that fit into
  1305.     //  a 16-bit coordinate space), we take snapshots. In other words,
  1306.     //  we make the compositor window the size of the physical page and
  1307.     //  keep scrolling down till capture the entire document.
  1308.  
  1309.     if (compositor) {
  1310.         XP_Rect            drawingRect;
  1311.         SDimension32    documentSize;
  1312.         int                pass;
  1313.         int32            captureScrollOffset;
  1314.  
  1315.         // The compositor window is the size of the page (minus margins)
  1316.         CL_ResizeCompositorWindow (compositor, pageWidth, pageHeight);
  1317.  
  1318.         drawingRect.left = 0;
  1319.         drawingRect.top = 0;
  1320.         drawingRect.right = pageWidth;
  1321.         drawingRect.bottom = pageHeight;
  1322.  
  1323.         // We display all the elements twice. This is to deal with the
  1324.         // fact that certain elements (images, embeds and applets for
  1325.         // instance) are always displayed in a compositor pass after
  1326.         // the containing HTML content. We only capture during the
  1327.         // second pass.
  1328.         mPrintHTMLView->SetPrintMode (CPrintHTMLView::epmBlockDisplay);
  1329.         mPrintHTMLView->GetImageSize (documentSize);
  1330.         for (pass = 0; pass < 2; pass++) {
  1331.             // Till we've covered the entire document, we keep scrolling
  1332.             // down and taking snapshots
  1333.             for (captureScrollOffset = 0; 
  1334.                  captureScrollOffset <= documentSize.height; 
  1335.                  captureScrollOffset += pageHeight) {
  1336.  
  1337.                 CL_ScrollCompositorWindow (compositor, 0, captureScrollOffset);
  1338.                 CL_RefreshWindowRect (compositor, &drawingRect);
  1339.             }
  1340.             mPrintHTMLView->SetPrintMode (CPrintHTMLView::epmLayout);
  1341.         }
  1342.  
  1343.         CL_ScrollCompositorWindow (compositor, 0, 0);
  1344.     } else {
  1345.         mPrintHTMLView->SetPrintMode (CPrintHTMLView::epmLayout);
  1346.         LO_RefreshArea (*mContext, 0, 0, 0x7FFFFFFF, 0x7FFFFFFF);
  1347.     }
  1348. } // end CapturePositions
  1349.  
  1350.  
  1351. //-----------------------------------
  1352. void CHTMLPrintout::DoProgress( const char* /*message*/, int /*level*/ )
  1353. //-----------------------------------
  1354. {
  1355. }
  1356.  
  1357. #ifdef PRE_JRM
  1358. MWContext* CHTMLPrintout::CreateGridContext()
  1359. {
  1360.     MWContext* newContext = mContext->CreateGridContext();
  1361.     newContext->type = MWContextPrint;
  1362.     return newContext;
  1363. }
  1364. #endif
  1365.  
  1366. //-----------------------------------
  1367. void CHTMLPrintout::BeginPrint(THPrint hp, CHTMLView* inViewToPrint)
  1368. //-----------------------------------
  1369. {            
  1370.     if (!hp)
  1371.         return;
  1372.     if (!sHTMLPrintout)
  1373.         sHTMLPrintout = (CHTMLPrintout*)LPrintout::CreatePrintout(1001);
  1374.     ThrowIfNil_(sHTMLPrintout);
  1375.     CPrintHTMLView* printHTMLView = sHTMLPrintout->GetPrintHTMLView();
  1376.     ThrowIfNil_(printHTMLView);
  1377.     
  1378.     // Ñ set the printout (unlike PP, we have our own SAVED print record )
  1379.     sHTMLPrintout->StashPrintRecord(hp);
  1380.  
  1381.     // Ñ setup psfe's structs for measurements
  1382.  
  1383.     //
  1384.     // Keep a reference in the print context to the list of plugin instances
  1385.     // in the on-screen context.  This information is used in mplugin.cp when
  1386.     // printing plugins to avoid creating new instantiations of all the plugins.
  1387.     //
  1388.     ((MWContext*)sHTMLPrintout->mContext)->pEmbeddedApp
  1389.         = ((MWContext*)inViewToPrint->GetContext())->pluginList;
  1390.  
  1391.     // Ñ╩set the encoding type
  1392. #ifdef PRE_JRM
  1393.     sHTMLPrintout->fContext.fe.realContext->default_csid
  1394.         = inViewToPrint->fHContext->fe.realContext->default_csid;
  1395. #endif
  1396.  
  1397.     XP_InitializePrintInfo((MWContext*)*(sHTMLPrintout->mContext));
  1398.  
  1399.     sHTMLPrintout->mFinishedLayout = false;
  1400.     sHTMLPrintout->mConnectionsCompleted = false;
  1401.     sHTMLPrintout->mPrinted = false;
  1402.  
  1403.     // Ñ it's very important that mainLedge actually be enabled and
  1404.     //        not latent, otherwise controls that are printed do not
  1405.     //        behave properly
  1406.     printHTMLView->SetPrintMode (CPrintHTMLView::epmBlockDisplay);
  1407.     printHTMLView->Enable();
  1408.     printHTMLView->CopyCharacteristicsFrom(inViewToPrint);
  1409.  
  1410.     // Ñ go print
  1411.     Try_
  1412.     {
  1413.         URL_Struct *url;
  1414.         Boolean doSuppressURL = false;
  1415.         url = inViewToPrint->GetURLForPrinting( doSuppressURL, *(sHTMLPrintout->mContext) );
  1416.         if ( url )
  1417.         {
  1418.             CPrintHeaderCaption::SetTemporaryFile( doSuppressURL );
  1419.             sHTMLPrintout->LoadPageForPrint( url, ((MWContext*)*(sHTMLPrintout->mContext)), (MWContext*)*inViewToPrint->GetContext());
  1420.         }
  1421.     }
  1422.     Catch_( err )
  1423.     {
  1424.         Throw_( err );
  1425.     }
  1426.     EndCatch_
  1427. } // CHTMLPrintout::BeginPrint
  1428.  
  1429. //-----------------------------------
  1430. void CHTMLPrintout::ListenToMessage(
  1431.     MessageT                inMessage,
  1432.     void*                    /*ioParam*/)
  1433. //-----------------------------------
  1434. {
  1435.     CHTMLView    *htmlView = ExtractHyperView (*mContext);
  1436.  
  1437.     switch (inMessage) {
  1438.         case msg_NSCFinishedLayout:
  1439. //            htmlView->NoteFinishedLayout();    (seems likely, but protected)
  1440.             mFinishedLayout = true;
  1441.             break;            
  1442.         case msg_NSCAllConnectionsComplete:
  1443.             // for frames, don't do print stuff until all contexts are done
  1444. //            htmlView->NoteAllConnectionsComplete();
  1445.             mConnectionsCompleted = !XP_IsContextBusy((MWContext*)*mContext);
  1446.             break;
  1447.     }
  1448.     // the check for mPrinted is necessary; JavaScript will call FinishedLayout twice
  1449.     if (mConnectionsCompleted && mFinishedLayout && !mPrinted) {
  1450.         // lay out for printing
  1451.         Paginate();
  1452.         DoPrintJob();
  1453.  
  1454. #if GENERATING68K
  1455.         //    ***** HACK ***** Fixed weird crash where 68K printer code
  1456.         //    spammed us with an invalid port -- a vivid example of why
  1457.         //    one should not have an invalid port.
  1458.         WindowPtr front = FrontWindow();
  1459.         if (front)
  1460.             SetPort(front);
  1461.         else {
  1462.             CGrafPtr windowMgrPort;
  1463.             GetCWMgrPort(&windowMgrPort);
  1464.             SetPort((GrafPtr)windowMgrPort);
  1465.         }
  1466. #endif
  1467.  
  1468.         mPrinted = true;
  1469.     }
  1470.     mFinishedTime = LMGetTicks() + 600;    // wait 10 seconds for Java to finish
  1471. } // CHTMLPrintout::ListenToMessage
  1472.  
  1473. //======================================
  1474. #pragma mark --- CPrintingCleanupTimer ---
  1475. //======================================
  1476. /*    CPrintingCleanupTimer gives periodic attention to sHTMLPrintout, waiting for it
  1477.     to finish printing.  When sMTMLPrintout claims it's finished, we delete it.
  1478.     This is a (small) change in architecture: originally, sHTMLPrintout deleted itself
  1479.     as soon as it was finished printing.  I hacked in this timer thing to support
  1480.     printing pages with JavaScript.
  1481.       There's no good way to tell whether JavaScript has finished laying out a page.
  1482.     Notably, a page containing JavaScript seems to always get two "finished layout"
  1483.     messages.  Before this timer thing was installed, the first such message caused
  1484.     the page to be printed and deleted.  The second such message brought the machine
  1485.     down.  Now we wait to delete the object until it stops getting messages from
  1486.     layout.  We define "stopped getting messages" as "haven't seen one in ten seconds."
  1487.     This sucks, and will cause your machine to crash if a big delay happens for some
  1488.     reason, but I'm led to believe JavaScript itself must be full of such things,
  1489.     and can't come up with a better plan today.
  1490. */
  1491.  
  1492. //-----------------------------------
  1493. // class definition
  1494. class CPrintingCleanupTimer : public LPeriodical {
  1495.  
  1496. public:
  1497.                     CPrintingCleanupTimer();
  1498.     virtual    void    SpendTime(const EventRecord &inMacEvent);
  1499.     static void        QueueCleanup(void);
  1500.  
  1501. private:
  1502.     static CPrintingCleanupTimer    sTheTimer;
  1503. };
  1504.  
  1505. //-----------------------------------
  1506. CPrintingCleanupTimer::CPrintingCleanupTimer()
  1507. // constructor: like the base class, but don't start repeating until told to
  1508. //-----------------------------------
  1509. {
  1510.     // when we're initialized at app load time, don't yet start asking for time
  1511.     StopRepeating();
  1512. }
  1513.  
  1514. //-----------------------------------
  1515. void CPrintingCleanupTimer::QueueCleanup(void)
  1516. // public access to turn on the timer; call when an sHTMLPrintout has been allocated
  1517. //-----------------------------------
  1518. {
  1519.     sTheTimer.StartRepeating();
  1520. }
  1521.  
  1522. //-----------------------------------
  1523. void CPrintingCleanupTimer::SpendTime(const EventRecord &)
  1524. // internal workings of the timer: wait until sHTMLPrintout says it's finished,
  1525. // then delete it and shut yourself down
  1526. //-----------------------------------
  1527. {
  1528.     CHTMLPrintout    *activePrintout = CHTMLPrintout::Get();
  1529.  
  1530.     if (activePrintout && activePrintout->PrintFinished()) {
  1531.         delete activePrintout;    // which sets sHTMLPrintout to 0 */
  1532.         StopRepeating();
  1533.     }
  1534. }
  1535.  
  1536. //-----------------------------------
  1537. CPrintingCleanupTimer CPrintingCleanupTimer::sTheTimer;
  1538.  
  1539. //======================================
  1540. #pragma mark --- UHTMLPrinting ---
  1541. //======================================
  1542.  
  1543. //-----------------------------------
  1544. void UHTMLPrinting::RegisterHTMLPrintClasses()
  1545. //-----------------------------------
  1546. {
  1547. //#define REGISTER_(letter,root) \
  1548. //    RegisterClass_(letter##root::class_ID, \
  1549. //        (ClassCreatorFunc)letter##root::Create##root##Stream);
  1550.  
  1551. #define REGISTER_(letter,root) RegisterClass_(letter##root);
  1552.     
  1553. #define REGISTERC(root) REGISTER_(C,root)
  1554. #define REGISTERL(root) REGISTER_(L,root)
  1555.     REGISTERC(HTMLPrintout)                        // 97/01/24 jrm
  1556.     REGISTERC(PrintHTMLView)                    // 97/01/24 jrm
  1557.     REGISTERC(PrintHeaderCaption)                // 97/01/24 jrm
  1558. } // UHTMLPrinting::RegisterHTMLPrintClasses
  1559.  
  1560. //-----------------------------------
  1561. void UHTMLPrinting::InitCustomPageSetup()
  1562. //-----------------------------------
  1563. {
  1564.     CCustomPageSetup::InitCustomPageSetup();
  1565. }
  1566.  
  1567. //-----------------------------------
  1568. void UHTMLPrinting::OpenPageSetup( THPrint hPrint )
  1569. //-----------------------------------
  1570. {
  1571.     CCustomPageSetup::OpenPageSetup(hPrint);
  1572. }
  1573.  
  1574. //-----------------------------------
  1575. void UHTMLPrinting::BeginPrint( THPrint hPrint, CHTMLView* inView )
  1576. //-----------------------------------
  1577. {
  1578.     CPrintingCleanupTimer::QueueCleanup();
  1579.     CHTMLPrintout::BeginPrint(hPrint, inView);
  1580. }