2803 lines
95 KiB
Plaintext
2803 lines
95 KiB
Plaintext
<HTML XMLNS:IE>
|
|
<HEAD>
|
|
<?import namespace="ie" implementation="#default">
|
|
<META HTTP-EQUIV="MSThemeCompatible" CONTENT="Yes">
|
|
|
|
<TITLE>Print Preview</TITLE>
|
|
#include "preview.h"
|
|
|
|
<STYLE>
|
|
.divPage
|
|
{
|
|
position: absolute;
|
|
top: -20000px;
|
|
border-left: 1 solid black;
|
|
border-top: 1 solid black;
|
|
border-right: 4 solid black;
|
|
border-bottom: 4 solid black;
|
|
}
|
|
.page
|
|
{
|
|
background: white; // pages are rendered over a white background
|
|
width: 8.5in;
|
|
height: 11in;
|
|
margin: 0px;
|
|
overflow: hidden;
|
|
}
|
|
.mRect
|
|
{
|
|
position: absolute;
|
|
margin: 1in;
|
|
width: 6.5in;
|
|
height: 9in;
|
|
border: none;
|
|
overflow : hidden;
|
|
}
|
|
|
|
.divHead
|
|
{
|
|
position: absolute;
|
|
overflow: hidden;
|
|
top: 0in;
|
|
left: 0in;
|
|
width: 8.5in;
|
|
}
|
|
.divFoot
|
|
{
|
|
position: absolute;
|
|
overflow: hidden;
|
|
bottom: 0in;
|
|
left: 0in;
|
|
width: 8.5in;
|
|
}
|
|
|
|
|
|
|
|
BODY { overflow: hidden; padding: 0; margin: 0; background: threedface; }
|
|
TABLE { margin: 0px; padding: 0px; background: threedface; }
|
|
.THeader { border: none; background: white; color: black; } // white to match .page
|
|
.TFooter { border: none; background: white; color: black; } // white to match .page
|
|
TD { padding: 0; margin: 0; border: none; }
|
|
TD.UIPane { width: 20px; border: none; font-family: 'ms sans serif'; font-size: 8pt; }
|
|
TD.UISeparator { width: 1px; border-left: 2px threedhighlight ridge; }
|
|
BUTTON { border: 1px solid threedface; background: threedface; font-family: 'ms sans serif'; font-size: 8pt; color: buttontext;}
|
|
</STYLE>
|
|
|
|
<SCRIPT DEFER>
|
|
#define NUM_ABSTRACT_ZOOMS 3
|
|
#define ZOOM_PAGE_WIDTH -1
|
|
#define ZOOM_WHOLE_PAGE -2
|
|
#define ZOOM_TWO_PAGES -3
|
|
#define FRAMESET_LAID_OUT 0
|
|
#define FRAMESET_SELECTED 1
|
|
#define FRAMESET_SEPARATE 2
|
|
#define STR_ZOOM_PAGE_WIDTH "-1"
|
|
#define STR_ZOOM_WHOLE_PAGE "-2"
|
|
#define STR_ZOOM_TWO_PAGES "-3"
|
|
#define STR_FRAMESET_LAID_OUT "0"
|
|
#define STR_FRAMESET_SELECTED "1"
|
|
#define STR_FRAMESET_SEPARATE "2"
|
|
|
|
#define HEADFOOTHEIGHT 27
|
|
|
|
var g_aDocTree = new Object(); // Array of CPrintDoc's... using IDispatch expandos
|
|
var g_nDispPage = -1; // 0...n Which of the pages is currently being previewed?
|
|
var g_nZoomFactor = 0; // What level of zoom is currently applying to the page?
|
|
var g_cLeftToPrint = 0; // How many documents are left to print? (Used in printing).
|
|
var g_fRTL;
|
|
var g_fPreview;
|
|
|
|
// HACKHACK (greglett) (IE6#17478)
|
|
// When printing WebOC apps from a nonbrowse thread (hyperlink "Print Target", PrintHTML API, File->Print + AllLinkedDocuments)
|
|
// we instantiate the WebOC on the background thread and call in IPrint::Print (via CTemplatePrinter::printNonNative).
|
|
// When that (asynchronously) returns, we close the printing thread... and the WebOC that is trying to print.
|
|
// This produces a vareity of interesting effects, all bad, and some dire.
|
|
// Note that we don't do this for Print Preview, Print All Linked Documents, because it would look very bad to the user.
|
|
var g_fDelayClose = false; // Delay window.close()
|
|
|
|
// Global value caches - mainly used to make sure we don't need to do any extra work:
|
|
// Require FULL REPAGINATION:
|
|
var g_nMarginTop = 0;
|
|
var g_nMarginBottom = 0;
|
|
var g_nMarginLeft = 0;
|
|
var g_nMarginRight = 0;
|
|
var g_nPageWidth = 0;
|
|
var g_nPageHeight = 0;
|
|
// Require only HEADER/FOOTER REAPPLICATION
|
|
var g_nUnprintTop = 0;
|
|
var g_nUnprintBottom = 0;
|
|
var g_strHeader = "";
|
|
var g_strFooter = "";
|
|
var g_fTableOfLinks = false;
|
|
|
|
// keep track of page layout space
|
|
var g_cPagesDisplayed = 0;
|
|
var g_cxDisplaySlots = 1;
|
|
var g_cyDisplaySlots = 1;
|
|
|
|
// keep track of whether the mouse is over any buttons
|
|
var g_imgUnderMouse = null;
|
|
|
|
// keep track of frameset layout-related stuff
|
|
var g_nFramesetLayout = FRAMESET_LAID_OUT; // Which of the frameset layouts is currently active?
|
|
var g_strActiveFrame = null; // Which frame "C_x_x," or null, is the active frame?
|
|
var g_nTotalPages = 0; // How many total pages will be printed if the user
|
|
var g_nDocsToCalc = 0;
|
|
var g_nFramesLeft = 0; // # of frames currently being processed
|
|
// selects FRAMESET_SEPARATE?
|
|
#ifdef DEBUG
|
|
g_fReallyClose = true; // Close template when Close() is called?
|
|
#endif
|
|
//----------------------------------------------------------------------
|
|
// Functions GetRuleFromSelector()
|
|
//
|
|
// Synopsis: Gets the first rule in the first stylesheet on the document
|
|
// that applies to the given selector.
|
|
// This will do the job for us so long as we have only one
|
|
// stylesheet and only one rule per selector.
|
|
//
|
|
// Returns: the rule or null if no match was found.
|
|
//----------------------------------------------------------------------
|
|
function GetRuleFromSelector(strSelector)
|
|
{
|
|
var i;
|
|
var oRule;
|
|
var oSS = document.styleSheets[0]; // Assume one style sheet
|
|
|
|
// Linear search.
|
|
for (i=0;;i++)
|
|
{
|
|
oRule = oSS.rules[i];
|
|
|
|
if (oRule == null)
|
|
break;
|
|
|
|
if (oRule.selectorText == strSelector)
|
|
break;
|
|
}
|
|
|
|
// Either null (no match found) or a rule.
|
|
return oRule;
|
|
}
|
|
|
|
function UnprintableURL(strLink)
|
|
{
|
|
var fUnprintable = false;
|
|
var cIndex;
|
|
|
|
// Sniff the URL scheme prefix to make sure we can print it.
|
|
cIndex = strLink.indexOf(":");
|
|
switch (cIndex)
|
|
{
|
|
case 4:
|
|
if (strLink.substr(0, cIndex) == "news")
|
|
fUnprintable = true;
|
|
break;
|
|
|
|
case 5:
|
|
if (strLink.substr(0, cIndex) == "snews")
|
|
fUnprintable = true;
|
|
break;
|
|
|
|
case 6:
|
|
if ( strLink.substr(0, cIndex) == "telnet"
|
|
|| strLink.substr(0, cIndex) == "mailto")
|
|
fUnprintable = true;
|
|
break;
|
|
|
|
case 8:
|
|
if (strLink.substr(0,cIndex) == "vbscript")
|
|
fUnprintable = true;
|
|
break;
|
|
|
|
case 10:
|
|
if (strLink.substr(0,cIndex) == "javascript")
|
|
fUnprintable = true;
|
|
break;
|
|
|
|
}
|
|
|
|
// (greglett) If we ever choose to check MIME type from script (unlikely),
|
|
// this is the place to do it.
|
|
return fUnprintable;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
function StatusToString(nStatus)
|
|
{
|
|
var strStatus;
|
|
switch (nStatus)
|
|
{
|
|
case 0:
|
|
strStatus="LOADING_OEHEADER";
|
|
break;
|
|
case 1:
|
|
strStatus="LOADING_CONTENT";
|
|
break;
|
|
case 2:
|
|
strStatus="LOADING_TABLEOFLINKS";
|
|
break;
|
|
case 3:
|
|
strStatus="PAGING_COMPLETE";
|
|
break;
|
|
case 4:
|
|
strStatus="READY_TO_PRINT";
|
|
break;
|
|
default:
|
|
strStatus="??? (" + nStatus + ")";
|
|
break;
|
|
}
|
|
return strStatus;
|
|
}
|
|
|
|
function Log(strEntry)
|
|
{
|
|
var oDate = new Date();
|
|
|
|
LogContainer.insertAdjacentHTML("beforeEnd", "[" + oDate.getTime() + "] " + strEntry + "<BR>");
|
|
}
|
|
|
|
#endif
|
|
|
|
function OnKeyPress()
|
|
{
|
|
if (event.keyCode == 27) // esc
|
|
{
|
|
Close();
|
|
}
|
|
#ifdef DEBUG
|
|
else if (event.keyCode == 126) // '~'
|
|
{
|
|
LogContainer.style.display = (LogContainer.currentStyle.display == "none") ? "block" : "none";
|
|
}
|
|
else if (event.keyCode == 33) // '!'
|
|
{
|
|
var strDocNew = prompt("(DEBUG only!) Command to execute?", "");
|
|
|
|
eval(strDocNew);
|
|
}
|
|
else if (event.keyCode == 64) // '@'
|
|
{
|
|
g_fReallyClose = !g_fReallyClose;
|
|
butClose.style.color = (g_fReallyClose) ? "" : "red";
|
|
}
|
|
#endif
|
|
}
|
|
|
|
function OnKeyDown()
|
|
{
|
|
if (event.altKey)
|
|
{
|
|
switch (event.keyCode)
|
|
{
|
|
case 37: // left arrow
|
|
ChangeDispPage(g_nDispPage-1);
|
|
break;
|
|
|
|
case 39: // right arrow
|
|
ChangeDispPage(g_nDispPage+1);
|
|
break;
|
|
|
|
case 107: // number pad +
|
|
case 187: // keyboard +
|
|
HandleZoom(-1);
|
|
break;
|
|
|
|
case 109: // number pad -
|
|
case 189: // keyboard -
|
|
HandleZoom(1);
|
|
break;
|
|
|
|
case 35: // end
|
|
HandleLastPage();
|
|
break;
|
|
|
|
case 36: //home
|
|
HandleFirstPage();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
function ShowHelp()
|
|
{
|
|
window.showHelp("iexplore.chm::/print_preview.htm");
|
|
}
|
|
|
|
function AttachDialogEvents()
|
|
{
|
|
// Attach events. This is done here to:
|
|
// 1. Prevent UI before we're able to handle it
|
|
// 2. Load the dialog faster.
|
|
// Attach button events
|
|
butPrint.onclick = HandlePrintClick;
|
|
butPageSetup.onclick = HandlePageSetup;
|
|
butFirstPage.onclick = HandleFirstPage;
|
|
butBackPage.onclick = HandleBackPage;
|
|
butNextPage.onclick = HandleForwardPage;
|
|
butLastPage.onclick = HandleLastPage;
|
|
butZoomIn.onclick = HandleZoomInButton;
|
|
butZoomOut.onclick = HandleZoomOutButton;
|
|
butClose.onclick = Close;
|
|
butHelp.onclick = ShowHelp;
|
|
|
|
document.onhelp = ShowHelp;
|
|
|
|
butPrint.onmousedown = buttonDown;
|
|
butPageSetup.onmousedown = buttonDown;
|
|
butFirstPage.onmousedown = buttonDown;
|
|
butBackPage.onmousedown = buttonDown;
|
|
butNextPage.onmousedown = buttonDown;
|
|
butLastPage.onmousedown = buttonDown;
|
|
butZoomIn.onmousedown = buttonDown;
|
|
butZoomOut.onmousedown = buttonDown;
|
|
butClose.onmousedown = buttonDown;
|
|
butHelp.onmousedown = buttonDown;
|
|
|
|
// Attach image UI events
|
|
printCtl.onmouseover = buttonOver;
|
|
printCtl.onmouseout = buttonOut;
|
|
begin.onmouseover = buttonOver;
|
|
begin.onmouseout = buttonOut;
|
|
prev.onmouseover = buttonOver;
|
|
prev.onmouseout = buttonOut;
|
|
next.onmouseover = buttonOver;
|
|
next.onmouseout = buttonOut;
|
|
end.onmouseover = buttonOver;
|
|
end.onmouseout = buttonOut;
|
|
zoomIn.onmouseover = buttonOver;
|
|
zoomIn.onmouseout = buttonOut;
|
|
zoomOut.onmouseover = buttonOver;
|
|
zoomOut.onmouseout = buttonOut;
|
|
butPrint.onmouseover = new Function("buttonRaise(this);");
|
|
butPrint.onmouseout = new Function("buttonLower(this);");
|
|
butClose.onmouseover = new Function("buttonRaise(this);");
|
|
butClose.onmouseout = new Function("buttonLower(this);");
|
|
butHelp.onmouseover = new Function("buttonRaise(this);");
|
|
butHelp.onmouseout = new Function("buttonLower(this);");
|
|
|
|
// Attach input events
|
|
inputPageNum.onkeypress = HandleInputKeyPress;
|
|
inputPageNum.onchange = HandlePageSelect;
|
|
selectZoom.onchange = HandleZoomSelect;
|
|
selectFrameset.onchange = HandleFramesetSelect;
|
|
|
|
// Attach document events
|
|
window.onresize = OnResizeBody;
|
|
window.onerror = HandleError;
|
|
|
|
// Focus maintenance: anytime we return from another dialog (page setup, help, etc.),
|
|
// push the focus back onto the document body (for scrolling and accessibility).
|
|
window.onfocus = new Function("MasterContainer.focus()");
|
|
|
|
document.body.onkeypress = OnKeyPress;
|
|
document.body.onkeydown = OnKeyDown;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Body event handlers.
|
|
//----------------------------------------------------------------------
|
|
function OnLoadBody()
|
|
{
|
|
g_fRTL = (document.body.currentStyle.direction.toLowerCase() == "rtl");
|
|
g_fPreview = dialogArguments.__IE_PrintType == "Preview";
|
|
|
|
// For "printTarget" on an unprintable link URL on the body, we can have a bad URL.
|
|
// Sniff it for printability, and bail if not so good. (greglett) (103361)
|
|
if (UnprintableURL(dialogArguments.__IE_ContentDocumentUrl))
|
|
{
|
|
// JurgenE , variables for localization must be in the form L_someIDtext_Text_
|
|
var L_Invalid_Text = "Unable to print URL. Please navigate directly to this page and select Print.";
|
|
alert(L_Invalid_Text);
|
|
window.close();
|
|
}
|
|
|
|
// Set up "base" values for each of the arrow images - the image source will be different for LTR vs. RTL sy1stems.
|
|
// This assumes all images will be initialized to *_inactive.gif
|
|
// We could avoid doing all this string mangling by adding an inline "base" property on the IMG and localizing it.
|
|
var str;
|
|
str = begin.src;
|
|
begin.base = str.slice(str.lastIndexOf("/")+1,str.indexOf("_"));
|
|
str = end.src;
|
|
end.base = str.slice(str.lastIndexOf("/")+1,str.indexOf("_"));
|
|
str = next.src;
|
|
next.base = str.slice(str.lastIndexOf("/")+1,str.indexOf("_"));
|
|
str = prev.src;
|
|
prev.base = str.slice(str.lastIndexOf("/")+1,str.indexOf("_"));
|
|
|
|
ChangeZoom(75);
|
|
|
|
// Do this H/F switch before EnsureDocuments
|
|
if (dialogArguments.__IE_HeaderString)
|
|
Printer.header = dialogArguments.__IE_HeaderString
|
|
|
|
if (dialogArguments.__IE_FooterString)
|
|
Printer.footer = dialogArguments.__IE_FooterString
|
|
|
|
EnsureDocuments(); // Get defaults (no documents means little work)
|
|
|
|
|
|
// Make the cursor look like an hourglass while we wait for the frames to build
|
|
window.document.body.style.cursor="wait";
|
|
|
|
CreateDocument("document", "C", true);
|
|
ChangeDispPage(1);
|
|
|
|
// Set up the counter of remaning frames to load, and begin the iterative process
|
|
g_nFramesLeft = 1;
|
|
// Build those frames
|
|
// (greglett) We may want to revise how and when we do this for the printing only,
|
|
// i.e. non-preview situations. This may have a significant perf hit on how long
|
|
// it takes the print to happen, and most of the time, we don't really need to
|
|
// generate all those frames for a printout. We only do it this way so that we're
|
|
// prepared if a user decides to try the FRAMESET_SEPARATE option in preview.
|
|
OnBuildAllFrames("C");
|
|
|
|
if (g_fPreview)
|
|
{
|
|
AttachDialogEvents();
|
|
|
|
// make sure the display region is sized properly
|
|
OverflowContainer.style.top = idDivToolbar.offsetHeight;
|
|
OverflowContainer.style.height = document.body.clientHeight - idDivToolbar.offsetHeight;
|
|
}
|
|
else
|
|
{
|
|
PrintNow(dialogArguments.__IE_PrintType == "Prompt");
|
|
}
|
|
}
|
|
|
|
function BuildAllFramesComplete()
|
|
{
|
|
AssertSz(g_nFramesLeft == 0, "BuildAllFramesComplete when not complete?");
|
|
|
|
// Restore the cursor to its normal operation
|
|
window.document.body.style.cursor="auto";
|
|
|
|
// (t-svoida) Not sure this is the best or final place for this step to happen.
|
|
// (greglett) It almost certainly isn't: we wait for all frames to be built to allow someone to
|
|
// do the frameset selection thing.
|
|
UpdateFramesetSelect();
|
|
}
|
|
|
|
function CalcDocsComplete()
|
|
{
|
|
AssertSz(g_nDocsToCalc == 0, "CalcDocsComplete when not complete?");
|
|
|
|
// If we're currently laid out as FRAMESET_SEPARATE, we need to recompute our frame/page table
|
|
if (g_nFramesetLayout == FRAMESET_SEPARATE)
|
|
{
|
|
ChangeFramesetLayout(g_nFramesetLayout, true) // FORCE update
|
|
}
|
|
}
|
|
|
|
function OnResizeBody()
|
|
{
|
|
// make sure the display region is sized properly
|
|
OverflowContainer.style.height = Math.max(0, document.body.clientHeight - idDivToolbar.offsetHeight);
|
|
|
|
// make sure zoom gets updated if we're in an abstract zoom mode
|
|
HandleDynamicZoom();
|
|
|
|
// make sure a relayout happens, because the layout space changed
|
|
PositionPages(g_nDispPage);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Synopsis: Turns off error messages in dialogs
|
|
//
|
|
// Arguments: none
|
|
//
|
|
// returns: true (tells browser not to handle message)
|
|
//
|
|
//--------------------------------------------------------------------
|
|
function HandleError(message, url, line)
|
|
{
|
|
#ifdef DEBUG
|
|
var str = "";
|
|
if (url == document.URL)
|
|
str += "Template ";
|
|
|
|
// Debug only, no need to localize
|
|
str += "Error (" + url + ":" + line + "): " + message;
|
|
|
|
alert(str);
|
|
#else
|
|
var L_Internal_ErrorMessage = "There was an internal error, and Internet Explorer is unable to print this document.";
|
|
alert(L_Internal_ErrorMessage);
|
|
window.close();
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// TODO (greglett) (TASK 5182)
|
|
// Q: So, why two RectComplete handlers, one called with a setTimeout from the other?
|
|
// A: Because otherwise we spend *all* of our time processing RectCompletes, and never give Trident a chance
|
|
// to do any redrawing, &c... In order to provide a somewhat interactive UI, we need this delay.
|
|
// Work to fix this should accompany incremental pagination.
|
|
function OnRectComplete( strDoc )
|
|
{
|
|
if (!g_aDocTree[strDoc])
|
|
{
|
|
// No need to localize the string - it is only displayed in debug mode.
|
|
HandleError("Document " + strDoc + " does not exist.", document.URL, "OnRectComplete");
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
Log("OnRectComplete " + event.srcElement.id + " " + event.contentOverflow);
|
|
#endif
|
|
window.setTimeout("OnRectCompleteNext('" + strDoc + "', " + event.contentOverflow + ",'" + event.srcElement.id + "');", 25);
|
|
}
|
|
function OnRectCompleteNext( strDoc, fOverflow, strElement)
|
|
{
|
|
#ifdef DEBUG
|
|
Log("OnRectCompleteNext " + strElement + " " + fOverflow);
|
|
#endif
|
|
g_aDocTree[strDoc].RectComplete(fOverflow, strElement);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// utilities for managing widget state
|
|
//----------------------------------------------------------------------
|
|
|
|
function enableButton(btn, img)
|
|
{
|
|
btn.disabled = false;
|
|
if (g_imgUnderMouse == img)
|
|
{
|
|
img.src = img.base + "_hilite.gif";
|
|
buttonRaise(btn);
|
|
}
|
|
else
|
|
{
|
|
img.src = img.base + ".gif";
|
|
buttonLower(btn);
|
|
}
|
|
}
|
|
|
|
function disableButton(btn, img)
|
|
{
|
|
btn.disabled = true;
|
|
buttonLower(btn);
|
|
|
|
// accept null because some buttons share
|
|
// a common inactive image and this
|
|
// generic naming scheme is broken
|
|
|
|
if (img != null)
|
|
{
|
|
img.src = img.base + "_inactive.gif";
|
|
}
|
|
}
|
|
|
|
function updateNavButtons()
|
|
{
|
|
//
|
|
// disable any nav buttons that need to be
|
|
//
|
|
|
|
if (g_nDispPage == 1)
|
|
{
|
|
disableButton(butFirstPage, begin);
|
|
disableButton(butBackPage, prev);
|
|
}
|
|
else
|
|
{
|
|
enableButton(butFirstPage, begin);
|
|
enableButton(butBackPage, prev);
|
|
}
|
|
|
|
if (TotalDisplayPages() - g_nDispPage < g_cxDisplaySlots * g_cyDisplaySlots)
|
|
{
|
|
disableButton(butNextPage, next);
|
|
disableButton(butLastPage, end);
|
|
}
|
|
else
|
|
{
|
|
enableButton(butNextPage, next);
|
|
enableButton(butLastPage, end);
|
|
}
|
|
}
|
|
|
|
function updateZoomButtons()
|
|
{
|
|
var fZoomOutDisabled = false;
|
|
var fZoomInDisabled = false;
|
|
|
|
//
|
|
// disable any zoom buttons necessary
|
|
//
|
|
|
|
var oOptions = selectZoom.options;
|
|
|
|
if (g_nZoomFactor >= parseInt(oOptions[0].value))
|
|
{
|
|
// we're on the largest zoom or larger, so disable zoom in
|
|
disableButton(butZoomIn, null);
|
|
zoomIn.src = "zoom_inactive.gif";
|
|
fZoomInDisabled = true;
|
|
}
|
|
else if (g_nZoomFactor <= parseInt(oOptions[oOptions.length-1-NUM_ABSTRACT_ZOOMS].value))
|
|
{
|
|
// we're on the smallest zoom or smaller, so disable zoon out
|
|
disableButton(butZoomOut, null);
|
|
zoomOut.src = "zoom_inactive.gif";
|
|
fZoomOutDisabled = true;
|
|
}
|
|
|
|
//
|
|
// and enable any zoom buttons that are left
|
|
//
|
|
|
|
if (!fZoomOutDisabled)
|
|
{
|
|
enableButton(butZoomOut, zoomOut);
|
|
}
|
|
|
|
if (!fZoomInDisabled)
|
|
{
|
|
enableButton(butZoomIn, zoomIn);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function Synopsis
|
|
// UpdateFramesetSelect()
|
|
// Preps frameset layout select for user interaction, by
|
|
// pruning off the SELECTED option if there's no selection
|
|
// and hiding the control altogether if it's not a frameset
|
|
// page.
|
|
//----------------------------------------------------------------------
|
|
function UpdateFramesetSelect()
|
|
{
|
|
// Check main document's frameset status first
|
|
if ( g_aDocTree["C"]._fFrameset )
|
|
{
|
|
// Pare the "Only the selected frame" option if there's no selected frame
|
|
// (and the list is still at its original length)
|
|
if (!g_strActiveFrame)
|
|
{
|
|
selectFrameset.options.remove(1);
|
|
}
|
|
|
|
// Show both the control and the preceding separator
|
|
separatorFrameset.style.display = "inline";
|
|
cellFrameset.style.display = "inline";
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
// Hide both the control and the preceding separator
|
|
// separatorFrameset.style.display = "none";
|
|
// cellFrameset.style.display = "none";
|
|
|
|
// (greglett) They should already be hidden. Let's make this an assert.
|
|
AssertSz( separatorFrameset.currentStyle.display == "none"
|
|
&& cellFrameset.currentStyle.display == "none", "UI Visible when it shouldn't be?");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function Synopses
|
|
// getPageWidth, getPageHeight
|
|
// Returns the global size of each page - assumes constant sized pages.
|
|
// Return value is in screen CSS pixels.
|
|
//----------------------------------------------------------------------
|
|
function getPageWidth()
|
|
{
|
|
return g_aDocTree["C"].Page(1).offsetWidth;
|
|
}
|
|
|
|
function getPageHeight()
|
|
{
|
|
return g_aDocTree["C"].Page(1).offsetHeight;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// UndisplayPages()
|
|
// Undisplays all visible pages
|
|
//----------------------------------------------------------------------
|
|
function UndisplayPages()
|
|
{
|
|
while (g_cPagesDisplayed > 0)
|
|
{
|
|
var oPage = DisplayPage(g_nDispPage + g_cPagesDisplayed - 1);
|
|
if (oPage != null)
|
|
{
|
|
oPage.style.top = "-20000px";
|
|
if (g_fRTL)
|
|
oPage.style.right = "10px";
|
|
else
|
|
oPage.style.left = "10px";
|
|
}
|
|
|
|
g_cPagesDisplayed--;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// PositionPages(nDispPage)
|
|
// Sets the x and y positioning for the pages currently being
|
|
// displayed. If the given # is outside valid bounds, the
|
|
// nearest valid boundary is selected instead.
|
|
// PERF (greglett) We may want to make redisplay smarter - right now, all
|
|
// pages are redisplayed every time the window is resized. We really should
|
|
// have the funtion check if pages need to be redisplayed, with a force flag option.
|
|
//----------------------------------------------------------------------
|
|
function PositionPages(nDispPage)
|
|
{
|
|
// Cache the current display doc
|
|
var strDispDoc = DisplayDocument(nDispPage);
|
|
|
|
if ( g_aDocTree != null
|
|
&& g_aDocTree[strDispDoc] != null
|
|
&& g_aDocTree[strDispDoc].Pages() > 0)
|
|
{
|
|
// first clear the old pages
|
|
UndisplayPages();
|
|
|
|
//
|
|
// now draw the new pages with the new settings
|
|
//
|
|
|
|
// figure out how many pages we can show this time
|
|
var xPageWidth = getPageWidth();
|
|
var yPageHeight = getPageHeight();
|
|
var nMaxPage = TotalDisplayPages();
|
|
|
|
g_cxDisplaySlots = Math.max(1, Math.floor((OverflowContainer.offsetWidth*100)/(g_nZoomFactor*(xPageWidth+10))));
|
|
g_cyDisplaySlots = Math.max(1, Math.floor((OverflowContainer.offsetHeight*100)/(g_nZoomFactor*(yPageHeight+10))));
|
|
|
|
// Trim nDispPage to be inside a valid page range.
|
|
var nMaxPageRequest = Math.max(nMaxPage - g_cxDisplaySlots * g_cyDisplaySlots + 1, 1);
|
|
|
|
if ( nDispPage < 1 )
|
|
nDispPage = 1;
|
|
else if (nDispPage > nMaxPageRequest)
|
|
nDispPage = nMaxPageRequest;
|
|
|
|
// now start using the new (bounded) page index
|
|
g_nDispPage = nDispPage;
|
|
|
|
// Update the page display to show the right numbers
|
|
document.all.spanPageTotal.innerText = nMaxPage;
|
|
document.all.inputPageNum.value = g_nDispPage;
|
|
|
|
// fix the begin, prev, next, end arrows
|
|
updateNavButtons();
|
|
|
|
//
|
|
// set up pages until we run out of pages
|
|
// or run out of rows of slots to fill
|
|
//
|
|
|
|
var xDisplaySlot = 1;
|
|
var yDisplaySlot = 1;
|
|
var iPage = g_nDispPage;
|
|
|
|
g_cPagesDisplayed = 0;
|
|
|
|
// PERF We really don't need to do a DisplayPage each time
|
|
// We could loop through the DisplayDocuments, and loop through
|
|
// each of their pages to many multiple lookups inherent in calling
|
|
// DisplayPage each iteration of the loop (greglett)
|
|
while (iPage <= nMaxPage && yDisplaySlot <= g_cyDisplaySlots)
|
|
{
|
|
var xPos = xDisplaySlot*10 + (xDisplaySlot-1)*xPageWidth;
|
|
var yPos = yDisplaySlot*10 + (yDisplaySlot-1)*yPageHeight;
|
|
var oPage = DisplayPage(iPage);
|
|
|
|
if (g_fRTL)
|
|
oPage.style.right = xPos;
|
|
else
|
|
oPage.style.left = xPos;
|
|
|
|
oPage.style.top = yPos;
|
|
|
|
iPage++;
|
|
if (++xDisplaySlot > g_cxDisplaySlots)
|
|
{
|
|
xDisplaySlot = 1;
|
|
yDisplaySlot++;
|
|
}
|
|
|
|
g_cPagesDisplayed++;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
function ChangeDispPage(nDispPageNew)
|
|
{
|
|
if (isNaN(nDispPageNew))
|
|
{
|
|
// make sure the UI shows a valid number
|
|
inputPageNum.value = g_nDispPage;
|
|
}
|
|
else
|
|
{
|
|
// Range check
|
|
if (nDispPageNew < 1)
|
|
nDispPageNew = 1;
|
|
else if (nDispPageNew > TotalDisplayPages())
|
|
nDispPageNew = TotalDisplayPages();
|
|
|
|
// make sure the top of the page is showing
|
|
OverflowContainer.scrollTop = 0;
|
|
|
|
PositionPages(nDispPageNew);
|
|
}
|
|
|
|
return g_nDispPage;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function Synopsis
|
|
// DisplayDocument()
|
|
// As below. Only valid when not FRAMESET_SELECT.
|
|
// DisplayDocument(nWhichPage)
|
|
// Returns either the current display document (indicated by
|
|
// g_nDispPage) in the format "C_x_x", or, when passed a page
|
|
// number from 1...total pages (includes all frames in SEPARATE
|
|
// frameset layout), returns the display document shown on that
|
|
// page. Will return null if the page number passed is out
|
|
// of range.
|
|
//----------------------------------------------------------------------
|
|
function DisplayDocument(nWhichPage)
|
|
{
|
|
switch (g_nFramesetLayout)
|
|
{
|
|
case FRAMESET_LAID_OUT:
|
|
// In LAID_OUT case, display doc is always the master, "C"
|
|
return "C";
|
|
break;
|
|
|
|
case FRAMESET_SELECTED:
|
|
// In SELECTED casem display doc is always the active frame
|
|
return g_strActiveFrame;
|
|
break;
|
|
|
|
case FRAMESET_SEPARATE:
|
|
var i;
|
|
|
|
if (!nWhichPage)
|
|
return null;
|
|
|
|
AssertSz(nWhichPage > 0 && nWhichPage <= g_nTotalPages, "DisplayDocument called with invalid page: " + nWhichPage);
|
|
|
|
// Otherwise, count to find correct document
|
|
for (i in g_aDocTree)
|
|
{
|
|
if ( nWhichPage >= g_aDocTree[i]._nStartingPage
|
|
&& nWhichPage < (g_aDocTree[i]._nStartingPage + g_aDocTree[i].Pages()))
|
|
return i;
|
|
}
|
|
|
|
default:
|
|
// Should never happen!
|
|
// Don't localize this string, debug code only
|
|
HandleError("Display document cannot be found!", document.URL, "DisplayDocument");
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member TotalDisplayPages
|
|
//
|
|
// Synopsis: With multiple page arrays per CPrintDoc, these functions
|
|
// are to provide the illusion of one array. Unlike Pages(),
|
|
// this returns the number of pages in this CPrintDoc if the
|
|
// frameset layout is LAID_OUT or SELECTED, or the total
|
|
// number of pages in all individual frames if the frameset
|
|
// layout is SEPARATE. To make this closer to user UI, this
|
|
// virtual array is 1 based, not 0 based.
|
|
//----------------------------------------------------------------------
|
|
function TotalDisplayPages()
|
|
{
|
|
if (g_nFramesetLayout == FRAMESET_SEPARATE)
|
|
return g_nTotalPages;
|
|
|
|
AssertSz(DisplayDocument(), "TotalDisplayPages: No DisplayDocument!") // DEBUG only: don't localize.
|
|
return g_aDocTree[DisplayDocument()].Pages();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// DisplayPage(nWhichPage)
|
|
// Returns the specified page of the displayed set
|
|
//
|
|
// The only situation this is different than the DisplayDocument
|
|
// is for "all frames individually." Imagine two two page frames.
|
|
// Then, the function would return:
|
|
// nWhichPage Return
|
|
// 1-2 Frame1.Page(nWhichPage)
|
|
// 3-4 Frame2.Page(nWhichPage - 2)
|
|
//----------------------------------------------------------------------
|
|
function DisplayPage(nWhichPage)
|
|
{
|
|
AssertSz(nWhichPage >= 0, "Negative or null display page requested: " + nWhichPage);
|
|
|
|
// Local page numbers are always the same as total page
|
|
// numbers unless the layout is SEPARATE
|
|
if (g_nFramesetLayout != FRAMESET_SEPARATE)
|
|
return g_aDocTree[DisplayDocument(nWhichPage)].Page(nWhichPage);
|
|
|
|
// Compute the page offset into the current document, and ask for that page.
|
|
return g_aDocTree[DisplayDocument(nWhichPage)].Page(nWhichPage - g_aDocTree[DisplayDocument(nWhichPage)]._nStartingPage + 1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function ChangeZoom
|
|
// Checks the bounds and changes the document zoom level to the new value.
|
|
//----------------------------------------------------------------------
|
|
function ChangeZoom(nNewVal)
|
|
{
|
|
if (nNewVal < 10)
|
|
nNewVal = 10;
|
|
else if (nNewVal > 1000)
|
|
nNewVal = 1000;
|
|
else if (isNaN(nNewVal))
|
|
nNewVal = g_nZoomFactor;
|
|
|
|
if (nNewVal != g_nZoomFactor)
|
|
{
|
|
MasterContainer.style.zoom = nNewVal + "%";
|
|
g_nZoomFactor = nNewVal;
|
|
updateZoomButtons();
|
|
PositionPages(g_nDispPage);
|
|
}
|
|
|
|
return g_nZoomFactor;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function BuildTableOfLinks
|
|
//
|
|
// Synopsis: These function takes a document, and uses its links collection
|
|
// to create another document with a table of links.
|
|
// Returns the document, or null if no links were encountered.
|
|
//----------------------------------------------------------------------
|
|
function BuildTableOfLinks( docSource )
|
|
{
|
|
var aLinks = docSource.links;
|
|
var nLinks = aLinks.length;
|
|
if (nLinks > 0)
|
|
{
|
|
var fDuplicate;
|
|
var i;
|
|
var j;
|
|
var newHTM;
|
|
var docLinkTable = document.createElement("BODY");
|
|
var L_LINKSHEADER1_Text = "Shortcut Text";
|
|
var L_LINKSHEADER2_Text = "Internet Address";
|
|
|
|
newHTM = "<CENTER><TABLE BORDER=1>";
|
|
newHTM += "<THEAD style=\"display:table-header-group\"><TR><TH>"
|
|
+ L_LINKSHEADER1_Text
|
|
+ "</TH><TH>" + L_LINKSHEADER2_Text + "</TH></TR></THEAD><TBODY>";
|
|
|
|
// Old behvaior: Print each linked URL only once. Do include a self link.
|
|
// Ack! Yes, this is a dreaded N-squared algorithm. This is what we used to do, though, so we're no worse.
|
|
// If we deem it important enough, we can pare it down to NlogN via a more efficient sorting algorithm. (greglett)
|
|
for (i = 0; i < nLinks; i++)
|
|
{
|
|
fDuplicate = false;
|
|
|
|
for (j = 0; (!fDuplicate) && (j < i); j++)
|
|
{
|
|
if (aLinks[i].href == aLinks[j].href)
|
|
fDuplicate = true;
|
|
}
|
|
|
|
if (!fDuplicate)
|
|
newHTM += ("<TR><TD>" + aLinks[i].innerText + "</TD><TD>" + aLinks[i].href + "</TD></TR>");
|
|
}
|
|
|
|
newHTM += "</TBODY></TABLE></CENTER>";
|
|
|
|
docLinkTable.innerHTML = newHTM;
|
|
|
|
return docLinkTable.document;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function CreateDocument
|
|
//
|
|
// Synopsis: Allocates and initializes a new CPrintDoc with the
|
|
// given contentURL and documentID. Also passed: Should
|
|
// we pay attention to any existing stream header.
|
|
//----------------------------------------------------------------------
|
|
function CreateDocument( docURL, strDocID, fUseStreamHeader )
|
|
{
|
|
if (g_aDocTree[strDocID])
|
|
return;
|
|
|
|
g_aDocTree[strDocID] = new CPrintDoc( strDocID, docURL );
|
|
g_aDocTree[strDocID].InitDocument( fUseStreamHeader );
|
|
}
|
|
|
|
function ChangeFramesetLayout( nNewLayout, fForce )
|
|
{
|
|
// Don't do any work if none is needed
|
|
if ( g_nFramesetLayout == nNewLayout
|
|
&& !fForce)
|
|
return;
|
|
|
|
// Hide the currently displayed page view
|
|
UndisplayPages();
|
|
|
|
// Grab the new frameset layout setting
|
|
g_nFramesetLayout = nNewLayout;
|
|
|
|
switch ( nNewLayout )
|
|
{
|
|
case FRAMESET_LAID_OUT:
|
|
case FRAMESET_SELECTED:
|
|
break;
|
|
|
|
case FRAMESET_SEPARATE:
|
|
// Recount all individual pages and assign starting page
|
|
// numbers to each. If a page has no starting page number,
|
|
// i.e. _nStartingPage = 0, then it's either a frameset page
|
|
// or the selection bit, and we don't want to include it in
|
|
// the SEPARATE-type frameset previews. We have to do this
|
|
// computation each time, or else we can get errors after
|
|
// repaginations.
|
|
g_nTotalPages = 0;
|
|
|
|
for (i in g_aDocTree)
|
|
{
|
|
if ( g_aDocTree[i]._fFrameset
|
|
|| i == "S")
|
|
g_aDocTree[i]._nStartingPage = 0;
|
|
else
|
|
{
|
|
g_aDocTree[i]._nStartingPage = g_nTotalPages + 1;
|
|
g_nTotalPages += g_aDocTree[i].Pages();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("Impossible frameset layout type: " + nNewLayout, document.URL, "ChangeFramesetLayout");
|
|
}
|
|
|
|
// Allow the logic in ChangeDispPage to select the correct page
|
|
// and page number, and then display it.
|
|
ChangeDispPage(1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function EnsureDocuments()
|
|
//
|
|
// Synopsis: This function picks up and applies style changes, resetting all
|
|
// the documents states so they do enough work to reflow.
|
|
//
|
|
// Returns: nothing
|
|
//----------------------------------------------------------------------
|
|
function EnsureDocuments()
|
|
{
|
|
var i;
|
|
var tmp;
|
|
|
|
// Units received are 1/100"; convert to 1"
|
|
// Changes in these require repagination:
|
|
var top = Printer.marginTop / 100;
|
|
var bottom = Printer.marginBottom / 100;
|
|
var left = Printer.marginLeft / 100;
|
|
var right = Printer.marginRight / 100;
|
|
var pageWidth = Printer.pageWidth / 100;
|
|
var pageHeight = Printer.pageHeight / 100;
|
|
|
|
// Changes in these require repagination of the table of links:
|
|
var linktable = Printer.tableOfLinks;
|
|
|
|
// Changes in these require reapplication of headers/footers:
|
|
var upTop = Printer.unprintableTop / 100;
|
|
var upBottom = Printer.unprintableBottom / 100;
|
|
var header = Printer.header;
|
|
var footer = Printer.footer;
|
|
|
|
// Handle case where (unprintable) + (header/footer size) > (specified margin)
|
|
// Just autoincrease the margin...
|
|
// TODO (greglett) For now, use a guesstimation for the H/F size, as it is always one
|
|
// line of the same font. Frontload work to prevent reflow, and use a constant.
|
|
// Fixing this is REQUIRED for HTML headers/footers.
|
|
// TODO (greglett) (99287)
|
|
// On top of that, we are sizing the page slightly wrong - our "page size"
|
|
// should not include the 1px/4px borders on the page for UI. This could be amended by surrounding
|
|
// the page in a DIV contiainer (the UI page), and printing/sizing the inner page, while positioning
|
|
// the outer page. This has some difficulties due to interaction of absolutely positioning stuff.
|
|
if (header)
|
|
{
|
|
tmp = upTop + (HEADFOOTHEIGHT / 100);
|
|
if (tmp > top)
|
|
top = tmp;
|
|
}
|
|
if (footer)
|
|
{
|
|
tmp = upBottom + (HEADFOOTHEIGHT / 100);
|
|
if (tmp > bottom)
|
|
bottom = tmp;
|
|
}
|
|
|
|
if (upTop != g_nUnprintTop)
|
|
{
|
|
g_nUnprintTop = upTop;
|
|
|
|
// Set styles on Header
|
|
oRule = GetRuleFromSelector(".divHead");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.divHead' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.top = upTop + "in";
|
|
}
|
|
if (upBottom != g_nUnprintBottom)
|
|
{
|
|
g_nUnprintBottom= upBottom;
|
|
|
|
// Set styles on Footer
|
|
oRule = GetRuleFromSelector(".divFoot");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.divFoot' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.bottom = upBottom + "in";
|
|
}
|
|
|
|
// Check if something has changed that will force work on the document.
|
|
if ( top != g_nMarginTop
|
|
|| bottom != g_nMarginBottom
|
|
|| left != g_nMarginLeft
|
|
|| right != g_nMarginRight
|
|
|| pageWidth != g_nPageWidth
|
|
|| pageHeight != g_nPageHeight
|
|
|| header != g_strHeader
|
|
|| footer != g_strFooter )
|
|
{
|
|
var conWidth = pageWidth - left - right;
|
|
var conHeight = pageHeight - top - bottom;
|
|
var oStyleSheet = document.styleSheets[0];
|
|
var oRule;
|
|
|
|
if (conWidth < 0)
|
|
conWidth = 0;
|
|
if (conHeight < 0)
|
|
conHeight = 0;
|
|
|
|
// Hide currently displayed pages - they're about to become invalid.
|
|
UndisplayPages();
|
|
|
|
// Clear page numbering for FRAMESET_SEPARATE layout
|
|
g_nTotalPages = 0;
|
|
g_nDocsToCalc = 0;
|
|
|
|
// All documents are about to be repaginated!
|
|
for (i in g_aDocTree)
|
|
{
|
|
g_nDocsToCalc++;
|
|
g_aDocTree[i].ResetDocument();
|
|
}
|
|
|
|
// Cache new values.
|
|
g_nMarginTop = top;
|
|
g_nMarginBottom = bottom;
|
|
g_nMarginLeft = left;
|
|
g_nMarginRight = right;
|
|
g_nPageWidth = pageWidth;
|
|
g_nPageHeight = pageHeight;
|
|
g_fTableofLinks = linktable;
|
|
g_strHeader = header;
|
|
g_strFooter = footer;
|
|
HeadFoot.textHead = g_strHeader;
|
|
HeadFoot.textFoot = g_strFooter;
|
|
|
|
// Set styles on pages.
|
|
oRule = GetRuleFromSelector(".page");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.page' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.width = pageWidth + "in";
|
|
oRule.style.height = pageHeight + "in";
|
|
|
|
// Set styles on layout rects.
|
|
oRule = GetRuleFromSelector(".mRect");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.mRect' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.marginLeft = left + "in";
|
|
oRule.style.marginRight = right + "in";
|
|
oRule.style.marginTop = top + "in";
|
|
oRule.style.marginBottom = bottom + "in";
|
|
oRule.style.width = conWidth + "in";
|
|
oRule.style.height = conHeight + "in";
|
|
|
|
// Set styles on Header
|
|
oRule = GetRuleFromSelector(".divHead");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.divHead' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.left = left + "in";
|
|
oRule.style.width = conWidth + "in";
|
|
// Set styles on Header
|
|
oRule = GetRuleFromSelector(".divFoot");
|
|
if (oRule == null)
|
|
{
|
|
// Should never happen!
|
|
//Don't localize this string, debug code only
|
|
HandleError("'.divHead' rule does not exist!", document.URL, "CPrintDoc::EnsureDocuments");
|
|
}
|
|
oRule.style.left = left + "in";
|
|
oRule.style.width = conWidth + "in";
|
|
|
|
// HACKHACK (greglett) 94479
|
|
// The viewchain is not capable of recalcing if the layout rect properties are changed right now.
|
|
// So, we unhook the LR, change the properties (ABOVE) and then reload/reparse the entire document (HERE)
|
|
for (i in g_aDocTree)
|
|
{
|
|
// Reinit document - and pass whether or not we're using an OE header.
|
|
g_aDocTree[i].InitDocument((g_aDocTree[i]._anMerge[LOADING_CONTENT] == 1));
|
|
}
|
|
|
|
// Repagination screws up the delicate frame page table used to figure out how
|
|
// many pages are in which documents. Force update.
|
|
if (g_nFramesetLayout == FRAMESET_SEPARATE)
|
|
ChangeFramesetLayout(g_nFramesetLayout, true);
|
|
|
|
// Repaint the current page(s) that we hid above with UndisplayPages()
|
|
PositionPages(g_nDispPage);
|
|
}
|
|
|
|
else if (linktable != g_fTableOfLinks)
|
|
{
|
|
|
|
// Cache new values.
|
|
g_fTableOfLinks = linktable;
|
|
|
|
// All documents are about to be table of linked! (?)
|
|
for (i in g_aDocTree)
|
|
{
|
|
g_aDocTree[i].ResetTableOfLinks();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Functions: Button utilities.
|
|
//
|
|
// Synopsis: These various & sundry functions are button UI utilities
|
|
// and provide basic toolbar UI
|
|
//----------------------------------------------------------------------
|
|
function buttonRaise( elem )
|
|
{
|
|
elem.style.borderStyle = "outset";
|
|
elem.style.borderColor = "threedhighlight";
|
|
}
|
|
function buttonLower( elem )
|
|
{
|
|
elem.style.borderStyle = "solid";
|
|
elem.style.borderColor = "threedface";
|
|
}
|
|
function buttonDepress(elem)
|
|
{
|
|
elem.style.borderStyle = "inset";
|
|
elem.style.borderColor = "threedshadow";
|
|
}
|
|
|
|
// PERF (greglett)
|
|
// We don't need to do a whole updateXXXButtons!
|
|
function buttonOver()
|
|
{
|
|
var imgSrc = event.srcElement;
|
|
|
|
g_imgUnderMouse = imgSrc;
|
|
|
|
if (imgSrc == begin ||
|
|
imgSrc == prev ||
|
|
imgSrc == next ||
|
|
imgSrc == end)
|
|
{
|
|
updateNavButtons();
|
|
}
|
|
else if (imgSrc == zoomIn ||
|
|
imgSrc == zoomOut)
|
|
{
|
|
updateZoomButtons();
|
|
}
|
|
else
|
|
{
|
|
imgSrc.src= "" + imgSrc.id + "_hilite.gif";
|
|
buttonRaise( imgSrc.parentNode );
|
|
}
|
|
}
|
|
|
|
// PERF (greglett)
|
|
// We don't need to do a whole updateXXXButtons!
|
|
function buttonOut()
|
|
{
|
|
var imgSrc = event.srcElement;
|
|
|
|
g_imgUnderMouse = null;
|
|
|
|
if (imgSrc == begin ||
|
|
imgSrc == prev ||
|
|
imgSrc == next ||
|
|
imgSrc == end)
|
|
{
|
|
updateNavButtons();
|
|
}
|
|
else if (imgSrc == zoomIn ||
|
|
imgSrc == zoomOut)
|
|
{
|
|
updateZoomButtons();
|
|
}
|
|
else
|
|
{
|
|
imgSrc.src= "" + imgSrc.id + ".gif";
|
|
buttonLower( imgSrc.parentNode );
|
|
}
|
|
}
|
|
|
|
function buttonDown()
|
|
{
|
|
buttonDepress(event.srcElement);
|
|
}
|
|
|
|
// --------------------------------------------------------
|
|
function HandlePageSelect()
|
|
{
|
|
event.srcElement.value = ChangeDispPage(parseInt(inputPageNum.value));
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
function HandlePageSetup()
|
|
{
|
|
if (Printer.showPageSetupDialog())
|
|
EnsureDocuments();
|
|
}
|
|
function HandleForwardPage()
|
|
{
|
|
ChangeDispPage(g_nDispPage + 1);
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
function HandleBackPage()
|
|
{
|
|
ChangeDispPage(g_nDispPage - 1);
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
function HandleFirstPage()
|
|
{
|
|
ChangeDispPage(1);
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
function HandleLastPage()
|
|
{
|
|
ChangeDispPage(TotalDisplayPages());
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
|
|
function NumericFromSpecialZoom(fnBounder)
|
|
{
|
|
var iMaxNumericZoom = selectZoom.options.length-1-NUM_ABSTRACT_ZOOMS; // specials zooms follow numeric zooms
|
|
var iBelow = -1;
|
|
var nBelow = 0;
|
|
var iAbove = iMaxNumericZoom + 1;
|
|
var i;
|
|
|
|
// establish iBelow and iAbove so that they are the selection indices just
|
|
// below and above the current value of g_nZoomFactor. if there's an
|
|
// exact match, then iBelow and iAbove have to both be the index whose
|
|
// value matches
|
|
|
|
// get iBelow
|
|
for (i = 0; i <= iMaxNumericZoom; i++)
|
|
{
|
|
var nThisIndex = parseInt(selectZoom.options[i].value);
|
|
if (nThisIndex >= g_nZoomFactor)
|
|
{
|
|
iBelow = i;
|
|
nBelow = nThisIndex;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// get iAbove
|
|
if (nBelow > g_nZoomFactor)
|
|
{
|
|
iAbove = iBelow + 1;
|
|
}
|
|
else
|
|
{
|
|
iAbove = iBelow;
|
|
}
|
|
|
|
return fnBounder(iBelow, iAbove);
|
|
}
|
|
|
|
function HandleZoom(nZoomIndexDelta)
|
|
{
|
|
var iCurrZoom = selectZoom.selectedIndex;
|
|
var iMaxNumericZoom = selectZoom.options.length-1-NUM_ABSTRACT_ZOOMS; // specials zooms follow numeric zooms
|
|
|
|
if (iCurrZoom > iMaxNumericZoom)
|
|
{
|
|
var fnRemapBounder = null;
|
|
|
|
// we're on a special zoom setting and now need to
|
|
// remap back into numeric zoom mode
|
|
|
|
if (nZoomIndexDelta == 1)
|
|
{
|
|
// we're going to be moving down the list
|
|
// so the index returned by NFSZ needs
|
|
// to be the vertically highest index
|
|
// which is the min index
|
|
|
|
fnRemapBounder = Math.min;
|
|
}
|
|
else
|
|
{
|
|
// moving up the list, need vertically lowest index
|
|
fnRemapBounder = Math.max;
|
|
}
|
|
|
|
iCurrZoom = NumericFromSpecialZoom(fnRemapBounder);
|
|
}
|
|
|
|
// move up or down the selection list as indicated by nZoomIndexDelta
|
|
selectZoom.selectedIndex = Math.min(Math.max(0, iCurrZoom + nZoomIndexDelta), iMaxNumericZoom);
|
|
|
|
ChangeZoom(parseInt(selectZoom.options[selectZoom.selectedIndex].value));
|
|
}
|
|
|
|
function HandleDynamicZoom()
|
|
{
|
|
var nZoomType = parseInt(selectZoom.options[selectZoom.selectedIndex].value);
|
|
|
|
if (nZoomType < 0)
|
|
{
|
|
var nZoomFactor = 100;
|
|
|
|
var xPageWidth = getPageWidth();
|
|
|
|
switch (nZoomType)
|
|
{
|
|
// page width
|
|
case ZOOM_PAGE_WIDTH:
|
|
nZoomFactor = Math.floor(((OverflowContainer.offsetWidth - 20) * 100) / xPageWidth);
|
|
break;
|
|
|
|
// whole page
|
|
case ZOOM_WHOLE_PAGE:
|
|
var xZoom = Math.floor(((OverflowContainer.offsetWidth - 20) * 100) / xPageWidth);
|
|
var yZoom = Math.floor(((OverflowContainer.offsetHeight - 20) * 100) / getPageHeight());
|
|
nZoomFactor = Math.min(xZoom, yZoom);
|
|
break;
|
|
|
|
// two pages
|
|
case ZOOM_TWO_PAGES:
|
|
nZoomFactor = Math.floor(((OverflowContainer.offsetWidth - 30) * 100) / (2 * xPageWidth));
|
|
break;
|
|
|
|
// eh?
|
|
default:
|
|
nZoomFactor = 100;
|
|
break;
|
|
}
|
|
|
|
ChangeZoom(nZoomFactor);
|
|
}
|
|
}
|
|
|
|
function HandleZoomSelect()
|
|
{
|
|
var nZoomFactor = parseInt(selectZoom.options[selectZoom.selectedIndex].value);
|
|
|
|
if (nZoomFactor < 0)
|
|
{
|
|
HandleDynamicZoom();
|
|
}
|
|
else
|
|
{
|
|
ChangeZoom(nZoomFactor);
|
|
}
|
|
|
|
// The selects require a user to be able to arrow between values, selecting each in succession.
|
|
// As such, we cannot refocus the master container here.
|
|
}
|
|
|
|
function HandleFramesetSelect()
|
|
{
|
|
ChangeFramesetLayout(parseInt(selectFrameset.options[selectFrameset.selectedIndex].value), false);
|
|
|
|
// The selects require a user to be able to arrow between values, selecting each in succession.
|
|
// As such, we cannot refocus the master container here.
|
|
}
|
|
|
|
function HandleZoomInButton()
|
|
{
|
|
HandleZoom(-1);
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
|
|
function HandleZoomOutButton()
|
|
{
|
|
HandleZoom(1);
|
|
|
|
// Force focus back to the preview document so keyboard
|
|
// accelerators work as expected
|
|
MasterContainer.focus();
|
|
}
|
|
|
|
function HandleInputKeyPress()
|
|
{
|
|
var keyStroke = event.keyCode;
|
|
|
|
if (keyStroke == 13) // Enter
|
|
{
|
|
event.srcElement.onchange();
|
|
}
|
|
else if (keyStroke < 48 || keyStroke > 57)
|
|
{
|
|
// only allow numeric input
|
|
event.returnValue = false;
|
|
}
|
|
}
|
|
|
|
function Close()
|
|
{
|
|
// (greglett) The point of this is to give the host an update on the page# we're
|
|
// printing. Since it's slow, and noone uses it now anyway except as a boolean,
|
|
// we just use it as an on/off for the printer status icon.
|
|
Printer.updatePageStatus(-1); // Display the printing icon in the browser
|
|
|
|
// HACKHACK (greglett) See defnition of this variable above for details.
|
|
if (g_fDelayClose)
|
|
{
|
|
g_fDelayClose = false;
|
|
window.setTimeout("Close()", 120000); // Allow 2 minutes
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (!g_fReallyClose)
|
|
return;
|
|
#endif
|
|
|
|
window.close();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Function PrintAll()
|
|
//
|
|
// Synopsis: This function ensures that all settings are current,
|
|
// creates all linked documents (if the user has specified that
|
|
// print option), and asks each CPrintDoc to print itself.
|
|
//----------------------------------------------------------------------
|
|
function PrintAll()
|
|
{
|
|
var i;
|
|
var nFirstDoc;
|
|
|
|
// (greglett) If we're printing frames in any way other than as shown, we should
|
|
// wait on all the little frameset documents to load. Consider a better way?
|
|
if ( g_nFramesLeft > 0
|
|
&& Printer.framesetDocument
|
|
&& !Printer.frameAsShown )
|
|
{
|
|
// The OnBuildFrames timeout should be smaller than this one's - since this is gating on a variable that
|
|
// only changes when OnBuildFrames has had a chance to spin.
|
|
window.setTimeout("PrintAll()", 100); // Poll every tenth of a second.
|
|
return;
|
|
}
|
|
|
|
EnsureDocuments();
|
|
|
|
// Nothing to do if we have no copies
|
|
if (Printer.copies <= 0)
|
|
{
|
|
Close();
|
|
}
|
|
// Some OS's don't force this restriction in the Print dialog. We do it posthumously.
|
|
else if ( Printer.selectedPages
|
|
&& Printer.pageFrom > Printer.pageTo )
|
|
{
|
|
var L_PAGERANGE_ErrorMessage = "The 'From' value cannot be greater than the 'To' value.";
|
|
alert(L_PAGERANGE_ErrorMessage);
|
|
|
|
// A "Preview" print should just exit the function. The user can click print again.
|
|
// A "NoPrompt" print should never be here.
|
|
AssertSz(dialogArguments.__IE_PrintType != "NoPrompt", "From > To with no possible UI?");
|
|
|
|
// A "Prompt" print will leak the template if we just let it leave the function!
|
|
// Throw the dialog again.
|
|
if (!g_fPreview)
|
|
PrintNow(true);
|
|
}
|
|
else
|
|
{
|
|
// How do we know when to close the window (all docs done printing)?
|
|
// Right now, we have each doc decrement the g_cLeftToPrint until
|
|
// it hits zero; the last one then closes the window.
|
|
g_cLeftToPrint = 1;
|
|
|
|
// (greglett) The point of this is to give the host an update on the page# we're
|
|
// printing. Since it's slow, and noone uses it now anyway except as a boolean,
|
|
// we just use it as an on/off for the printer status icon.
|
|
Printer.updatePageStatus(1); // Display the printing icon in the browser
|
|
|
|
PrintSentinel(((Printer.selection)
|
|
? "S"
|
|
: (Printer.frameActive && !!g_strActiveFrame)
|
|
? g_strActiveFrame
|
|
: "C"),
|
|
true);
|
|
}
|
|
}
|
|
|
|
// No syncrohization mechanism exists in JScript except for brute force. Instead of pure busy waiting,
|
|
// let's at least sleep for fixed time periods.
|
|
function PrintSentinel( strDoc, fRecursionOK )
|
|
{
|
|
// Gate on the document being ready to print.
|
|
if ( !g_aDocTree[strDoc]
|
|
|| !g_aDocTree[strDoc].ReadyToPrint() )
|
|
{
|
|
window.setTimeout("PrintSentinel('" + strDoc + "'," + fRecursionOK + ");", 500);
|
|
return;
|
|
}
|
|
|
|
g_aDocTree[strDoc].Print(fRecursionOK);
|
|
}
|
|
|
|
function PrintDocumentComplete()
|
|
{
|
|
g_cLeftToPrint--;
|
|
|
|
if (g_cLeftToPrint <= 0)
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// PrintNow()
|
|
// We've either been called without preview or from the preview
|
|
// helper function, HandlePrintClick(). In either case, just do
|
|
// that printing thing now. In preview situations, the user should
|
|
// always get a print dialog and the template should NOT close
|
|
// if the user clicks 'Cancel' in the dialog. In straight-print
|
|
// situations with a print dialog, a 'Cancel' selection will close
|
|
// the template.
|
|
//----------------------------------------------------------------------
|
|
function PrintNow( fWithPrompt)
|
|
{
|
|
|
|
// We have to gate on the loading of the original document right now for
|
|
// frameset information.
|
|
if ( !g_aDocTree["C"]
|
|
|| !g_aDocTree["C"]._aaRect[LOADING_CONTENT][0]
|
|
|| !g_aDocTree["C"]._aaRect[LOADING_CONTENT][0].contentDocument.body) // 89002 - may not exist yet.
|
|
{
|
|
window.setTimeout("PrintNow('" + fWithPrompt + "');", 100); // Poll every tenth of a second.
|
|
return;
|
|
}
|
|
|
|
var oDoc = g_aDocTree["C"]._aaRect[LOADING_CONTENT][0].contentDocument;
|
|
var fConfirmed;
|
|
var fFramesetDocument = (oDoc.body.tagName.toUpperCase() == "FRAMESET");
|
|
// fActiveFrame includes:
|
|
// FRAMESET documents (which will have a g_strActiveFrame)
|
|
// IFRAME documents (which will not!)
|
|
var fActiveFrame = (oDoc.all.tags("HTML").item(0).__IE_ActiveFrame != null);
|
|
|
|
Printer.framesetDocument = fFramesetDocument;
|
|
Printer.frameActiveEnabled = fActiveFrame;
|
|
|
|
if (g_fPreview)
|
|
{
|
|
Printer.frameActive = (g_nFramesetLayout == FRAMESET_SELECTED);
|
|
Printer.frameAsShown = (g_nFramesetLayout == FRAMESET_LAID_OUT);
|
|
Printer.currentPageAvail = true;
|
|
}
|
|
else
|
|
{
|
|
Printer.frameActive = fActiveFrame;
|
|
Printer.frameAsShown = false;
|
|
Printer.currentPageAvail = false;
|
|
}
|
|
|
|
// The selection document may not be created yet. Directly check the dialogArguments.
|
|
Printer.selectionEnabled = !!(dialogArguments.__IE_ContentSelectionUrl);
|
|
Printer.selection = false; // Never default to selection.
|
|
|
|
#ifdef DEBUG
|
|
Log("ShowingPrintDialog " + eval(fWithPrompt));
|
|
#endif
|
|
|
|
fConfirmed = (eval(fWithPrompt)) ? Printer.showPrintDialog() : Printer.ensurePrintDialogDefaults();
|
|
|
|
if ( fConfirmed )
|
|
{
|
|
if ( Printer.selection
|
|
&& dialogArguments.__IE_ContentSelectionUrl ) // (greglett) Check this too, in case the dlg was mishandled
|
|
{
|
|
// NB: (greglett)
|
|
// We always loaded the selection document in IE55
|
|
CreateDocument(dialogArguments.__IE_ContentSelectionUrl, "S", true);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
Log("Printer: Copies:" + Printer.deviceSupports("copies") + " Collate:" + Printer.deviceSupports("collate"));
|
|
#endif
|
|
|
|
Printer.usePrinterCopyCollate = ( Printer.deviceSupports("copies") >= Printer.copies
|
|
&& ( !Printer.collate
|
|
|| Printer.deviceSupports("collate") ));
|
|
|
|
PrintAll();
|
|
}
|
|
else
|
|
{
|
|
if ( !g_fPreview )
|
|
{
|
|
Close();
|
|
}
|
|
else
|
|
{
|
|
// TODO (greglett) (104826 - but really task level work)
|
|
// We may theoretically have changes even with a Cancel for two reasons:
|
|
// 1. In NT5, the Apply button may have been clicked, followed by Cancel.
|
|
// Right now, this doesn't work because the DHUI doesn't deal with this correctly.
|
|
// 2. The user may be printing to file, have clicked OK, then Cancel on the
|
|
// file query dialog. Right now, this doesn't work in CTemplatePrinter.
|
|
// Do we want this to work like this?
|
|
// The template is not currently robust enough to survive this, even if it were to
|
|
// work correctly. TableOfLinks has problems, as does AllLinkedDocs.
|
|
Printer.tableoflinks = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// HandlePrintClick()
|
|
// this is just a helper fucntion so that we close the window properly
|
|
// even when we are using this template to print with preview.
|
|
//----------------------------------------------------------------------
|
|
function HandlePrintClick()
|
|
{
|
|
// Call the PrintNow function, but indicate that we always want a
|
|
// print dialog and never want to close preview on completion.
|
|
PrintNow(true, true);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//----------------------------------------------------------------------
|
|
// CLASS CPrintDoc FUNCTIONS BEGIN HERE
|
|
//----------------------------------------------------------------------
|
|
//----------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::ReadyToPrint
|
|
//
|
|
// Synopsis: Is the print doc in a state where we can call print?
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_ReadyToPrint()
|
|
{
|
|
if ( this._nStatus == READY_TO_PRINT
|
|
&& this._aaRect[LOADING_CONTENT][0].contentDocument.readyState == "complete")
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::Print
|
|
//
|
|
// Synopsis: Prints the document, taking into acount # of copies, a page
|
|
// range, and collation.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_Print( fRecursionOK )
|
|
{
|
|
if (!this.ReadyToPrint())
|
|
{
|
|
// Don't localize this debug string
|
|
HandleError("Printing when not ready!", document.URL, "CPrintDoc::Print");
|
|
return;
|
|
}
|
|
|
|
var nCount = (Printer.usePrinterCopyCollate) ? 1 : Printer.copies;
|
|
var nFrom;
|
|
var nTo;
|
|
|
|
AssertSz(nCount > 0, "Printing 0 or less copies"); // We should have already checked this.
|
|
|
|
// Attempt to recurse if necessary (activeFrame, allLinkedDocuments, &c...)
|
|
if (fRecursionOK)
|
|
{
|
|
var fFrameset = (this._aaRect[LOADING_CONTENT][0].contentDocument.body.tagName.toUpperCase() == "FRAMESET");
|
|
|
|
if (Printer.frameActive) // Print active frame
|
|
{
|
|
var n = parseInt(this._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("HTML").item(0).__IE_ActiveFrame);
|
|
if (n >= 0)
|
|
{
|
|
var oTargetFrame = (fFrameset)
|
|
? this._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("FRAME").item(n)
|
|
: this._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("IFRAME").item(n);
|
|
|
|
// Load active frame
|
|
if ( IsPersistedDoc()
|
|
&& ( oTargetFrame.src == "res://SHDOCLC.DLL/printnof.htm" // FRAME
|
|
|| oTargetFrame.src == "about:blank" )) // IFRAME
|
|
{
|
|
// Immediate subframe is a WebOC hosted document. Use special
|
|
// interface to print it (Trident couldn't marshall it due to external bugs)
|
|
Printer.printNonNativeFrames(this._aaRect[LOADING_CONTENT][0].contentDocument, true); // true for ActiveFrame
|
|
}
|
|
else
|
|
{
|
|
// Immediate subframe is an HTML document. Recurse.
|
|
this.CreateSubDocument(oTargetFrame.src, true);
|
|
this.PrintAllSubDocuments(true);
|
|
}
|
|
|
|
// Finish printing this document...
|
|
PrintDocumentComplete();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (fFrameset)
|
|
{
|
|
if (!Printer.frameAsShown) // Print all frames
|
|
{
|
|
this.PrintAllSubDocuments(true);
|
|
|
|
if (IsPersistedDoc())
|
|
{
|
|
// Print all Word document frames, too
|
|
Printer.printNonNativeFrames(this._aaRect[LOADING_CONTENT][0].contentDocument, false); // false for all frames
|
|
}
|
|
|
|
// Finish printing this document...
|
|
PrintDocumentComplete();
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Print all Word document frames in addition to the as laid out
|
|
Printer.printNonNativeFrames(this._aaRect[LOADING_CONTENT][0].contentDocument, false); // false for all frames
|
|
}
|
|
}
|
|
else // BODY document.
|
|
{
|
|
// Build all linked documents, if necessary.
|
|
if (Printer.allLinkedDocuments)
|
|
{
|
|
this.BuildAllLinkedDocuments();
|
|
this.PrintAllSubDocuments(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// We may be a WebOC document. If we are, and it prints itself, we're done.
|
|
if (Printer.printNonNative(this._aaRect[LOADING_CONTENT][0].contentDocument) )
|
|
{
|
|
// HACKHACK (greglett) See defnition of this variable above for details.
|
|
g_fDelayClose = !g_fPreview;
|
|
PrintDocumentComplete();
|
|
return;
|
|
}
|
|
|
|
// Clip page range to this document/subdocument.
|
|
// NB (greglett)
|
|
// Selected Page/CurrentPage don't work as expected with AllLinkedDocuments.
|
|
// (We don't print only the linked documents on the given page)
|
|
// It can't unless we can get a collection with only with particular pages on it.
|
|
// NB (greglett)
|
|
// If asked to print a table of links and a page range, do we:
|
|
// 1. Always print a table of links (for the whole document).
|
|
// 2. Print whole TOL if the page range and the TOL range is nonintersecting
|
|
// or only the intersection if the range intersects.
|
|
// 3. Print only the part of the TOL that intersects the page range.
|
|
// Remember, NT5+ has an apply button and should be able to preview the TOL (though
|
|
// they can't yet, because we don't support Apply).
|
|
// We currently take the path of least resistance: #3.
|
|
if (Printer.selectedPages)
|
|
{
|
|
nFrom = Printer.pageFrom;
|
|
nTo = Printer.pageTo;
|
|
|
|
if (nFrom < 1)
|
|
nFrom = 1;
|
|
if (nTo > this.Pages())
|
|
nTo = this.Pages();
|
|
}
|
|
// CurrentPage only applies to the document being previewed. Any subdocuments that are
|
|
// printed should print in their entirity.
|
|
else if ( Printer.currentPage
|
|
&& this._strDoc == DisplayDocument())
|
|
{
|
|
nFrom = (this.Pages() >= g_nDispPage) ? g_nDispPage : this.Pages();
|
|
nTo = nFrom;
|
|
}
|
|
else
|
|
{
|
|
// Normal print job - print the whole kit n' kabootle
|
|
nFrom = 1;
|
|
nTo = this.Pages();
|
|
}
|
|
|
|
// In this case, we've been asked to print a valid range, but the document does not have
|
|
// any pages in the range. (ex: 2 to 3 of a 1 page document - nFrom = 2, nTo = 1)
|
|
// (We really only need to do this in selected pages above.)
|
|
if (nTo < nFrom)
|
|
{
|
|
PrintDocumentComplete();
|
|
return;
|
|
}
|
|
|
|
AssertSz(nFrom <= nTo, "pageTo is smaller than pageFrom!");
|
|
AssertSz(nFrom > 0, "pageFrom value 0 or less!");
|
|
AssertSz(nTo <= this.Pages(), "pageTo greater than number of pages in document!");
|
|
|
|
|
|
|
|
// The display URL goes onto the system spooler as a job title.
|
|
if (Printer.startDoc(this._aaRect[LOADING_CONTENT][0].contentDocument.URL))
|
|
{
|
|
if (Printer.collate)
|
|
{
|
|
// (greglett) (10084)
|
|
// Printing collated, multiple documents, we need to ensure the document has an even # of pages;
|
|
// This may require an extra page.
|
|
// [1|2] [3| ] [1|2] [3| ]
|
|
var fExtraPage = ( Printer.duplex
|
|
&& ((nFrom - nTo) % 2 == 0) );
|
|
|
|
for (j = 0; j < nCount; j++)
|
|
{
|
|
for (i = nFrom; i <= nTo; i++)
|
|
{
|
|
Printer.printPage(this.Page(i).children[0]);
|
|
}
|
|
|
|
if (fExtraPage)
|
|
Printer.printBlankPage();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// (greglett) (10084)
|
|
// If we are printing duplex, multiple documents, we need to print pairs of pages.
|
|
// We print front-to-back, producing the output (for a 3 page, 2 copies):
|
|
// [1|2] [1|2] [3| ] [3| ]...
|
|
var fDuplex = Printer.duplex;
|
|
|
|
for (i = nFrom; i <= nTo; i++)
|
|
{
|
|
for (j = 0; j < nCount; j++)
|
|
{
|
|
Printer.printPage(this.Page(i).children[0]);
|
|
if (fDuplex)
|
|
{
|
|
if (i < nTo)
|
|
Printer.printPage(this.Page(i+1));
|
|
else
|
|
Printer.printBlankPage();
|
|
}
|
|
}
|
|
|
|
if (fDuplex)
|
|
i++;
|
|
}
|
|
}
|
|
|
|
Printer.stopDoc();
|
|
}
|
|
|
|
// All done.
|
|
PrintDocumentComplete();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::RectComplete
|
|
//
|
|
// Synopsis: Called whenever an onlayout complete fires for this document's
|
|
// layout rects. Requires a "callback" function OnRectComplete,
|
|
// above.
|
|
// This function determines when a document is complete, and adds
|
|
// a table of links/headers/footers if necessary.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_RectComplete(fOverflow, strElement)
|
|
{
|
|
var nStatus = parseInt(strElement.substr(5,1));
|
|
var nPage = parseInt(strElement.substr(strElement.lastIndexOf("p") + 1));
|
|
|
|
AssertSz((nStatus >= LOADING_OEHEADER) && (nStatus <= LOADING_TABLEOFLINKS), "Status within recognized bounds");
|
|
AssertSz(nPage < this._aaRect[nStatus].length, "Page # not created!");
|
|
|
|
// Ignore premature event calls. We'll deal with them when we're good and ready.
|
|
if (nStatus > this._nStatus)
|
|
return false;
|
|
|
|
// Ignore event calls from pages before this one on the sheaf
|
|
if (nPage != this._acPage[nStatus] - 1 + this._anMerge[nStatus])
|
|
return false;
|
|
|
|
// If this is from a previous document within this one...
|
|
if (nStatus != this._nStatus)
|
|
{
|
|
// ...and it's just telling us again that we're done, ignore it...
|
|
if (!fOverflow)
|
|
return false;
|
|
|
|
// ...but if there's new content, dynamically switch back into this pagination.
|
|
this.StopFixupHF(); // Stop H/F fixup - we need to do it again.
|
|
if (this._nStatus == READY_TO_PRINT) // Add ourselves back into the queue of repaginating docs
|
|
g_nDocsToCalc++;
|
|
Transition(nStatus, "Status backslide - RectComplete"); // Backslide status.
|
|
}
|
|
|
|
// Need another page...
|
|
if (fOverflow)
|
|
{
|
|
this.AddPage();
|
|
}
|
|
else
|
|
{
|
|
// No more pages needed in this phase of document calculation.
|
|
// Move into the next calculation phase.
|
|
switch (this._nStatus)
|
|
{
|
|
case LOADING_OEHEADER:
|
|
// Stream header has finished - begin content calculation.
|
|
Transition(LOADING_CONTENT, "RectComplete");
|
|
this.AddFirstPage();
|
|
this._aaRect[this._nStatus][0].contentSrc = this._strDocURL;
|
|
break;
|
|
|
|
case LOADING_CONTENT:
|
|
// Content has finished calcing - create a table of links if requested.
|
|
Transition(LOADING_TABLEOFLINKS, "RectComplete");
|
|
this.AddTableOfLinks();
|
|
break;
|
|
|
|
case LOADING_TABLEOFLINKS:
|
|
// All done with pagination. Headers and Footers, please.
|
|
Transition(PAGING_COMPLETE, "RectComplete");
|
|
if (this._strDoc == DisplayDocument())
|
|
ChangeDispPage(g_nDispPage); // Clip to the maximum page, in case we are reflowing & have fewer pages.
|
|
this.FixupHF();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Update the display to reflect the correct # of pages.
|
|
if (this._strDoc == DisplayDocument())
|
|
{
|
|
spanPageTotal.innerText = this.Pages();
|
|
|
|
// make sure the nav buttons are in an appropriate state
|
|
updateNavButtons();
|
|
}
|
|
}
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::AddPage
|
|
//
|
|
// Synopsis: Adds a page to the end of the current document.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_AddPage()
|
|
{
|
|
var newHTM = "";
|
|
var aPage = this._aaPage[this._nStatus];
|
|
var aRect = this._aaRect[this._nStatus];
|
|
|
|
AssertSz(this._nStatus < PAGING_COMPLETE, "Adding page when pagination done!");
|
|
|
|
// Increment page count in this section of the print document
|
|
(this._acPage[this._nStatus])++;
|
|
|
|
HeadFoot.URL = this.EnsureURL();
|
|
HeadFoot.title = this.EnsureTitle();
|
|
HeadFoot.pageTotal = this.Pages();
|
|
HeadFoot.page = HeadFoot.pageTotal;
|
|
|
|
// We conserve layout rects - if this page has already been created, use it.
|
|
if (this._acPage[this._nStatus] <= aPage.length)
|
|
{
|
|
// Reset H/F - it may have changed.
|
|
var oPage = aPage[this._acPage[this._nStatus] - 1];
|
|
|
|
oPage.children("header").innerHTML = HeadFoot.HtmlHead;
|
|
oPage.children("footer").innerHTML = HeadFoot.HtmlFoot;
|
|
}
|
|
else
|
|
{
|
|
|
|
// TODO: (greglett) (108939) We have to parse in the nextRect right now because it is
|
|
// the CGenericElement::Notify (ENTERTREE) that hooks up the LayoutRect. Changing
|
|
// this value *after* the EnterTree has no effect.
|
|
// NB (greglett)
|
|
// Q: Why wrap the DeviceRect in a DIV instead of just using the DeviceRect?
|
|
// A: Because the OM on the DeviceRect is messed up such that it does do a resolution change scale.
|
|
// Instead, it returns CSS pixels *within* the rect. Because we also screw up sizing the rect, this
|
|
// turns out to work for a 96DPI screen. However, for 120DPI (large fonts), we off by 1.25 (120/96).
|
|
// Since the DIV has no resolution issues, we don't have the problem when we wrap the DeviceRect in a DIV.
|
|
newHTM = "<DIV class=divPage><IE:DeviceRect media=\"print\" class=page id=mDiv" + this._nStatus + this._strDoc + "p" + aPage.length + ">";
|
|
newHTM += "<IE:LAYOUTRECT id=mRect" + this._nStatus + this._strDoc + "p" + aRect.length;
|
|
newHTM += " class=mRect nextRect=mRect" + this._nStatus + this._strDoc + "p" + (aRect.length + 1);
|
|
newHTM += " onlayoutcomplete=OnRectComplete('" + this._strDoc + "')";
|
|
newHTM += " tabindex=-1 onbeforefocusenter='event.returnValue=false;' ";
|
|
newHTM += " /><DIV class=divHead id=header>";
|
|
newHTM += HeadFoot.HtmlHead;
|
|
newHTM += "</DIV><DIV class=divFoot id=footer>";
|
|
newHTM += HeadFoot.HtmlFoot;
|
|
newHTM += " </DIV></IE:DeviceRect></DIV>";
|
|
|
|
MasterContainer.insertAdjacentHTML("beforeEnd", newHTM);
|
|
|
|
aPage[aPage.length] = eval( "document.all.mDiv" + this._nStatus + this._strDoc + "p" + aPage.length);
|
|
aRect[aRect.length] = eval("document.all.mRect" + this._nStatus + this._strDoc + "p" + aRect.length);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::AddFirstPage
|
|
//
|
|
// Synopsis: Adds a page to the end of the current document.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_AddFirstPage()
|
|
{
|
|
this._acPage[this._nStatus] = 0;
|
|
|
|
if (this._anMerge[this._nStatus] == 0)
|
|
{
|
|
this.AddPage();
|
|
}
|
|
else
|
|
{
|
|
var aRect = this._aaRect[this._nStatus];
|
|
var oPage = this._aaPage[this._nStatus - 1][this._acPage[this._nStatus - 1] - 1];
|
|
var oTop = this._aaRect[this._nStatus - 1][this._acPage[this._nStatus - 1] + this._anMerge[this._nStatus - 1] - 1];
|
|
var nTop = oTop.offsetTop + oTop.scrollHeight;
|
|
var nHeight = oTop.clientHeight - oTop.scrollHeight;
|
|
|
|
AssertSz(this._nStatus < PAGING_COMPLETE, "Merging page when pagination done!");
|
|
AssertSz(this._anMerge[this._nStatus] > 0, "Merging page when not requested!");
|
|
|
|
// We cannot dynamically get a stream header. Ergo, if we have content layout rects,
|
|
// we must be repaginating, and already have a content layout rect on a stream page.
|
|
// We (may) simply need to resize and reparent it.
|
|
if (aRect.length > 0)
|
|
{
|
|
var oNode = aRect[0];
|
|
|
|
oNode.style.marginTop = nTop + "px";
|
|
oNode.style.pixelHeight = nHeight;
|
|
|
|
// Reparent, if necessary.
|
|
if (oNode.parentElement != oPage)
|
|
oPage.insertBefore(oNode);
|
|
}
|
|
// We need to actually size & create the content layout rect to merge onto the stream page.
|
|
else
|
|
{
|
|
var newHTM;
|
|
var oNode;
|
|
|
|
// TODO: (greglett) (108939) We have to parse in the nextRect right now because it is
|
|
// the CGenericElement::Notify (ENTERTREE) that hooks up the LayoutRect. Changing
|
|
// this value *after* the EnterTree has no effect.
|
|
newHTM = "<IE:LAYOUTRECT id=mRect" + this._nStatus + this._strDoc + "p0";
|
|
newHTM += " class=mRect nextRect=mRect" + this._nStatus + this._strDoc + "p1";
|
|
newHTM += " onlayoutcomplete=OnRectComplete('" + this._strDoc + "')";
|
|
newHTM += " tabindex=-1 onbeforefocus='event.returnValue=false;' />";
|
|
|
|
oPage.insertAdjacentHTML("beforeEnd", newHTM);
|
|
|
|
oNode = eval("document.all.mRect" + this._nStatus + this._strDoc + "p0");
|
|
|
|
aRect[0] = oNode;
|
|
|
|
oNode.style.marginTop = nTop + "px";
|
|
oNode.style.height = nHeight + "px";
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::InitDocument
|
|
//
|
|
// Synopsis: Begins pagination of document. This could be merged with
|
|
// the constructor.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_InitDocument( fUseStreamHeader )
|
|
{
|
|
var fReallyUseStreamHeader = (fUseStreamHeader && (dialogArguments.__IE_OutlookHeader != null));
|
|
this._anMerge[LOADING_CONTENT] = (fReallyUseStreamHeader) ? 1 : 0;
|
|
|
|
Transition((fReallyUseStreamHeader) ? LOADING_OEHEADER : LOADING_CONTENT, "Initialize Status");
|
|
|
|
this.AddFirstPage();
|
|
|
|
this._aaRect[this._nStatus][0].contentSrc = (fReallyUseStreamHeader)
|
|
? dialogArguments.__IE_OutlookHeader
|
|
: this._strDocURL;
|
|
}
|
|
|
|
function CPrintDoc_PrintAllSubDocuments( fRecursionOK )
|
|
{
|
|
if (!this._aDoc)
|
|
return;
|
|
|
|
var nDocs = this._aDoc.length;
|
|
var i;
|
|
|
|
g_cLeftToPrint += nDocs;
|
|
|
|
for (i = 0; i < nDocs; i++)
|
|
{
|
|
PrintSentinel(this._aDoc[i]._strDoc, fRecursionOK);
|
|
}
|
|
}
|
|
|
|
function CPrintDoc_BuildAllLinkedDocuments()
|
|
{
|
|
var strURL = this._aaRect[LOADING_CONTENT][0].contentDocument.URL;
|
|
var aLinks = this._aaRect[LOADING_CONTENT][0].contentDocument.links;
|
|
var nLinks = aLinks.length;
|
|
var i;
|
|
var j;
|
|
var strLink;
|
|
|
|
for (i = 0; i < nLinks; i++)
|
|
{
|
|
strLink = aLinks[i].href;
|
|
|
|
// Check against our own URL.
|
|
// Check to make sure we are not opening a bad URL
|
|
if ( (strURL == strLink)
|
|
|| UnprintableURL(strLink) )
|
|
continue;
|
|
|
|
// Check for a duplicate in the list. Yes, this is n^2... as in IE4+
|
|
for (j = 0; j < i; j++)
|
|
{
|
|
if (strLink == aLinks[j].href)
|
|
break;
|
|
}
|
|
if (j < i) // Duplicate found.
|
|
continue;
|
|
|
|
this.CreateSubDocument(strLink, false);
|
|
}
|
|
}
|
|
|
|
function OnBuildAllFrames( strDoc )
|
|
{
|
|
// We have to gate on the loading of the original document right now for
|
|
// frameset information.
|
|
if ( !g_aDocTree[strDoc]
|
|
|| !g_aDocTree[strDoc]._aaRect[LOADING_CONTENT][0]
|
|
|| !g_aDocTree[strDoc]._aaRect[LOADING_CONTENT][0].contentDocument.body) // 89002 - may not exist yet.
|
|
{
|
|
window.setTimeout("OnBuildAllFrames('" + strDoc + "');", 100);
|
|
return;
|
|
}
|
|
|
|
g_aDocTree[strDoc].BuildAllFrames();
|
|
}
|
|
|
|
function IsPersistedDoc()
|
|
{
|
|
// Since this is only called while printing, we can be sure the following exists...
|
|
return (!!g_aDocTree["C"]._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("HTML")[0].__IE_DisplayURL);
|
|
}
|
|
|
|
|
|
function CPrintDoc_BuildAllFrames()
|
|
{
|
|
var aFrames = this._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("FRAME");
|
|
var nFrames = aFrames.length;
|
|
var nActive = parseInt(this._aaRect[LOADING_CONTENT][0].contentDocument.all.tags("HTML").item(0).__IE_ActiveFrame);
|
|
var i;
|
|
var strSrc;
|
|
var strDoc;
|
|
|
|
if (nFrames > 0)
|
|
this._fFrameset = true;
|
|
|
|
for (i = 0; i < nFrames; i++)
|
|
{
|
|
strSrc = aFrames[i].src;
|
|
|
|
// This URL was created by Trident replacing a WebOC frame that it couldn't marshall.
|
|
// These will be printed via a call to "Printer.printNonNativeFrames(false)" in the caller.
|
|
if (strSrc == "res://SHDOCLC.DLL/printnof.htm")
|
|
continue;
|
|
|
|
// Make a document for the new URL.
|
|
// We can't use the markup because it's already slaved (to the frame)
|
|
strDoc = this.CreateSubDocument(strSrc, true);
|
|
if (i == nActive)
|
|
g_strActiveFrame = strDoc;
|
|
|
|
// Increment the semaphore, indicating that we're building a deeper branch of frames
|
|
// (see OnLoadBody() for more info)
|
|
g_nFramesLeft++;
|
|
|
|
// And then recurse to build its children frames
|
|
OnBuildAllFrames(strDoc);
|
|
}
|
|
|
|
// Decrement the semaphore, indicating that we've finished building this branch
|
|
// (see OnLoadBody() for more info)
|
|
g_nFramesLeft--;
|
|
if (g_nFramesLeft <= 0)
|
|
BuildAllFramesComplete();
|
|
}
|
|
|
|
function CPrintDoc_CreateSubDocument( docURL, fUseStreamHeader )
|
|
{
|
|
if (!this._aDoc)
|
|
this._aDoc = new Array();
|
|
|
|
var nDoc = this._aDoc.length;
|
|
var strDoc = this._strDoc + "_" + nDoc;
|
|
|
|
CreateDocument(docURL, strDoc, fUseStreamHeader);
|
|
this._aDoc[nDoc] = g_aDocTree[strDoc];
|
|
|
|
return (strDoc);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::AddTableOfLinks
|
|
//
|
|
// Synopsis: Appends a table of links to the end of the current document
|
|
// (this uses the documents current page value to determine the
|
|
// "end" - do not call if this number is not determined).
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_AddTableOfLinks()
|
|
{
|
|
AssertSz(this._nStatus == LOADING_TABLEOFLINKS, "Call to AddTableOfLinks when not ready!");
|
|
|
|
// No table of links requested. Transition to header/footer work.
|
|
if (!g_fTableOfLinks)
|
|
{
|
|
Transition(PAGING_COMPLETE, "AddTableOfLinks, no table of links requested");
|
|
ChangeDispPage(g_nDispPage); // Clip to the maximum page, in case we are reflowing & have fewer pages.
|
|
this.FixupHF();
|
|
}
|
|
else
|
|
{
|
|
var oTableOfLinks = BuildTableOfLinks(this._aaRect[LOADING_CONTENT][0].contentDocument);
|
|
if (oTableOfLinks != null)
|
|
{
|
|
// NB (greglett)
|
|
// The markup for the oTableOfLinks document becomes null across the
|
|
// AddFirstPage below. The issue is timing related. A workaround is to store the body.
|
|
var oBody = oTableOfLinks.body;
|
|
|
|
this.AddFirstPage()
|
|
this._aaRect[this._nStatus][0].contentSrc = oBody.document;
|
|
}
|
|
else
|
|
{
|
|
// Table of links does not exist. Move straight to the HeadersAndFooters thing.
|
|
Transition(PAGING_COMPLETE, "AddTableOfLinks, no table");
|
|
ChangeDispPage(g_nDispPage); // Clip to the maximum page, in case we are reflowing & have fewer pages.
|
|
this.FixupHF();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::FixupHF
|
|
//
|
|
// Synopsis: Goes through all pages in the document, updating/creating
|
|
// their header/footers.
|
|
//----------------------------------------------------------------------
|
|
function OnTickHF( strDoc )
|
|
{
|
|
if (!g_aDocTree[strDoc])
|
|
{
|
|
// No need to localize the string - it is only displayed in debug mode.
|
|
HandleError("Document " + strDoc + " does not exist.", document.URL, "OnRectComplete");
|
|
return;
|
|
}
|
|
|
|
g_aDocTree[strDoc].TickHF();
|
|
}
|
|
|
|
// There are two magic numbers in this function - the n in the line iTo = nStartPage + n and the setTimeout delay.
|
|
// The first is directly proportional to the contiguous block of processor time we'll take at a time, but inversely proportional
|
|
// to the # of timeouts we'll have to set and the total amount of time required to do the job.
|
|
// The timeout delay is how long we allow Trident to update and process UI (button highlights, &c...).
|
|
function CPrintDoc_TickHF()
|
|
{
|
|
var i, j;
|
|
var iTo, jTo;
|
|
var aTok;
|
|
var oTok;
|
|
var nStartPage = this._nNextHF;
|
|
var cPages = this.Pages();
|
|
|
|
iTo = nStartPage + 2;
|
|
if (iTo > cPages)
|
|
iTo = cPages;
|
|
|
|
for (i = nStartPage; i <= iTo; i++)
|
|
{
|
|
// (greglett) Why first child? See comments in CPrintDoc_AddPage.
|
|
aTok = this.Page(i).children[0].getElementsByTagName("SPAN");
|
|
for (j=0, jTo = aTok.length; j < jTo; j++)
|
|
{
|
|
oTok = aTok[j];
|
|
|
|
if (oTok.className == "hfPageTotal")
|
|
oTok.innerText = cPages;
|
|
|
|
else if ( oTok.className == "hfUrl"
|
|
&& oTok.innerText == "" )
|
|
oTok.innerText = this.EnsureURL();
|
|
else if ( oTok.className == "hfTitle"
|
|
&& oTok.innerText == "" )
|
|
oTok.innerText = this.EnsureTitle();
|
|
}
|
|
}
|
|
|
|
// Update page # of next HF we need to fixup.
|
|
this._nNextHF = i;
|
|
|
|
#ifdef DEBUG
|
|
// DEBUG ONLY - Track H/F fixup speed visually.
|
|
spanDebugHF.innerText = this._nNextHF - 1;
|
|
#endif
|
|
|
|
// If we're not done crowning & shoeing the document yet, we need to set a timeout to get back to it.
|
|
// Timeout should be long enough to process UI.
|
|
if (iTo == cPages)
|
|
{
|
|
Transition(READY_TO_PRINT, "AddHAndF");
|
|
if (--g_nDocsToCalc == 0)
|
|
CalcDocsComplete();
|
|
}
|
|
else
|
|
{
|
|
this._nTimerHF = window.setTimeout("OnTickHF('" + this._strDoc + "');", 250);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::FixupHF
|
|
//
|
|
// Synopsis: Kicks off the
|
|
// their header/footers.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_FixupHF()
|
|
{
|
|
AssertSz(this._nStatus == PAGING_COMPLETE, "Call to FixupHF when not ready!");
|
|
|
|
#ifdef DEBUG
|
|
// DEBUG ONLY - Track H/F fixup speed visually.
|
|
spanDebugHF.innerText = this._nNextHF;
|
|
#endif
|
|
|
|
// Kick off the header/footer pass on the document.
|
|
this.TickHF();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::Pages, Page
|
|
//
|
|
// Synopsis: With multiple page arrays per CPrintDoc, these functions
|
|
// are to provide the illusion of one array. To make this
|
|
// closer to user UI, this virtual array is 1 based, not 0 based.
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_Pages()
|
|
{
|
|
var i;
|
|
var c;
|
|
|
|
for (i = 0, c = 0; i < PAGING_COMPLETE; i++)
|
|
{
|
|
c += this._acPage[i];
|
|
}
|
|
|
|
return c;
|
|
}
|
|
function CPrintDoc_Page(nPage)
|
|
{
|
|
var i;
|
|
var n = nPage;
|
|
|
|
if (n <= 0)
|
|
return null;
|
|
|
|
for (i = 0; i < PAGING_COMPLETE; i++)
|
|
{
|
|
// (greglett) Why parentElement? See comments in CPrintDoc_AddPage.
|
|
if (n <= this._acPage[i])
|
|
return this._aaPage[i][n - 1].parentElement;
|
|
|
|
n -= this._acPage[i];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function CPrintDoc_EnsureURL()
|
|
{
|
|
if (this._strURL == null)
|
|
{
|
|
if ( this._aaRect[LOADING_CONTENT][0]
|
|
&& this._aaRect[LOADING_CONTENT][0].contentDocument)
|
|
{
|
|
this._strURL = this._aaRect[LOADING_CONTENT][0].contentDocument.URL;
|
|
}
|
|
|
|
// We must return a string.
|
|
if (this._strURL == null)
|
|
return "";
|
|
}
|
|
|
|
return this._strURL;
|
|
}
|
|
function CPrintDoc_EnsureTitle()
|
|
{
|
|
if (this._strTitle == null)
|
|
{
|
|
if ( this._aaRect[LOADING_CONTENT][0]
|
|
&& this._aaRect[LOADING_CONTENT][0].contentDocument)
|
|
{
|
|
this._strTitle = this._aaRect[LOADING_CONTENT][0].contentDocument.title;
|
|
}
|
|
|
|
// We must return a string.
|
|
if (this._strTitle == null)
|
|
return "";
|
|
}
|
|
|
|
return this._strTitle;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Member CPrintDoc::ResetXXXX
|
|
//
|
|
// Synopsis: If the given quantity (Document, TableOfLinks... &c...) has been
|
|
// calculated, this will force it to be recalculated. If not, the
|
|
// functions essentially do nothing (because the quantity will be
|
|
// created as the document finishes loading).
|
|
//----------------------------------------------------------------------
|
|
function CPrintDoc_ResetDocument()
|
|
{
|
|
var i;
|
|
|
|
for (i = 0; i < PAGING_COMPLETE; i++)
|
|
{
|
|
this._acPage[i] = 0;
|
|
|
|
// HACKHACK (greglett) 94479
|
|
// The viewchain is not capable of recalcing if the layout rect properties are changed right now.
|
|
// So, we unhook the LR (HERE) change the properties, and then reload/reparse the entire document (LATER)
|
|
if (this._aaRect[i][0])
|
|
this._aaRect[i][0].contentSrc = "";
|
|
}
|
|
|
|
this.StopFixupHF();
|
|
}
|
|
function CPrintDoc_ResetTableOfLinks()
|
|
{
|
|
// A table of links will be generated as part of the document when we get to it.
|
|
if (this._nStatus <= LOADING_TABLEOFLINKS)
|
|
return;
|
|
|
|
this.StopFixupHF();
|
|
|
|
Transition(LOADING_TABLEOFLINKS, "ResetTableOfLinks");
|
|
this.AddTableOfLinks();
|
|
}
|
|
|
|
function CPrintDoc_StopFixupHF()
|
|
{
|
|
if (this._nTimerHF != -1)
|
|
window.clearTimeout(this._nTimerHF);
|
|
this._nTimerHF = -1;
|
|
this._nNextHF = 1; // Could be higher, to only reget the TOL pages.
|
|
}
|
|
|
|
//
|
|
// CPRINTDOC MEMBER FUNCTIONS
|
|
//
|
|
|
|
// This function is a constructor for the CPrintDoc Object.
|
|
// CPrintDoc contains per document information.
|
|
function CPrintDoc( nDocNum, strDocURL )
|
|
{
|
|
var i;
|
|
|
|
this._aDoc = null; // Array of frames/linked documents.
|
|
this._strDoc = nDocNum; // Document id of this document (in form "C_2_3")
|
|
this._strDocURL = strDocURL; // "Real" URL of document (for LayoutRect's contentSrc).
|
|
|
|
// _nStatus stores the phase of pagination/flow completion that the document is in:
|
|
// The values are defined in preview.h, and initialized in InitDocument
|
|
this._nStatus = 0;
|
|
|
|
this._aaPage = new Array(PAGING_COMPLETE);
|
|
this._aaRect = new Array(PAGING_COMPLETE);
|
|
this._acPage = new Array(PAGING_COMPLETE);
|
|
this._anMerge = new Array(PAGING_COMPLETE);
|
|
for (i=0; i<PAGING_COMPLETE; i++)
|
|
{
|
|
this._aaPage[i] = new Array();
|
|
this._aaRect[i] = new Array();
|
|
this._acPage[i] = 0;
|
|
this._anMerge[i] = 0;
|
|
}
|
|
|
|
this._nNextHF = 1;
|
|
this._nTimerHF = -1;
|
|
|
|
this._strURL = null;
|
|
this._strTitle = null;
|
|
|
|
this._fFrameset = false;
|
|
this._nStartingPage = 0;
|
|
}
|
|
|
|
// Pagination functions
|
|
MEMBER(CPrintDoc, RectComplete);
|
|
MEMBER(CPrintDoc, AddPage);
|
|
MEMBER(CPrintDoc, AddFirstPage);
|
|
MEMBER(CPrintDoc, AddTableOfLinks);
|
|
MEMBER(CPrintDoc, FixupHF);
|
|
|
|
MEMBER(CPrintDoc, StopFixupHF);
|
|
MEMBER(CPrintDoc, TickHF);
|
|
|
|
// Document status functions
|
|
MEMBER(CPrintDoc, InitDocument);
|
|
MEMBER(CPrintDoc, ResetDocument);
|
|
MEMBER(CPrintDoc, ResetTableOfLinks);
|
|
|
|
// Recursive document functions
|
|
MEMBER(CPrintDoc, BuildAllLinkedDocuments);
|
|
MEMBER(CPrintDoc, BuildAllFrames);
|
|
MEMBER(CPrintDoc, CreateSubDocument);
|
|
|
|
// Printing functions
|
|
MEMBER(CPrintDoc, Print);
|
|
MEMBER(CPrintDoc, PrintAllSubDocuments);
|
|
MEMBER(CPrintDoc, ReadyToPrint);
|
|
|
|
// Data access functions
|
|
MEMBER(CPrintDoc, Page);
|
|
MEMBER(CPrintDoc, Pages);
|
|
MEMBER(CPrintDoc, EnsureURL);
|
|
MEMBER(CPrintDoc, EnsureTitle);
|
|
</SCRIPT>
|
|
</HEAD>
|
|
|
|
<BODY onload="setTimeout('OnLoadBody()', 400);">
|
|
|
|
<!-- Controls for printing -->
|
|
<IE:TemplatePrinter id=Printer />
|
|
<IE:HeaderFooter id=HeadFoot />
|
|
|
|
<DIV id=idDivToolbar style="width:100%; overflow:hidden;">
|
|
|
|
<DIV style="width=100%; border:'thin threedhighlight groove';">
|
|
<TABLE><TR>
|
|
<TD class="UIPane"> <BUTTON id="butPrint" title="Print Document (Alt+P)" accesskey=p><U>P</U>rint...</BUTTON></TD>
|
|
<TD class="UISeparator"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane"> <BUTTON id="butPageSetup" accesskey=u><IMG id="printCtl" src="printctl.gif" alt="Page Setup (Alt+U)"></BUTTON></TD>
|
|
<TD class="UISeparator"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane"> <BUTTON id="butFirstPage"><IMG id="begin" src="begin_inactive.gif" alt="First Page (Alt+Home)"></BUTTON></TD>
|
|
<TD class="UIPane"> <BUTTON id="butBackPage"> <IMG id="prev" src="prev_inactive.gif" alt="Previous Page (Alt+LeftArrow)"></BUTTON></TD>
|
|
<TD class="UIPane"><SPAN style="color:windowtext;"><NOBR Loc> <ID id=idTdPageXofYLocText1>P<U>a</U>ge</ID> <INPUT type=text id="inputPageNum" title="Preview Page (Alt+A)" value="1" style="height:1.5em; width: 2em; color:windowtext;" accesskey=a><ID id=idTdPageXofYLocText2> of </ID><SPAN id="spanPageTotal"></SPAN>
|
|
#ifdef DEBUG
|
|
<SPAN id="spanDebugHF" style="color: red"></SPAN>
|
|
#endif
|
|
</SPAN></NOBR></TD>
|
|
<TD class="UIPane"> <BUTTON id="butNextPage"> <IMG id="next" src="next_inactive.gif" alt="Next Page (Alt+RightArrow)"></BUTTON></TD>
|
|
<TD class="UIPane"> <BUTTON id="butLastPage"> <IMG id="end" src="end_inactive.gif" alt="Last Page (Alt+End)"></BUTTON></TD>
|
|
<TD class="UISeparator"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane"> <BUTTON id="butZoomOut"> <IMG id="zoomOut" base="zoomOut" src="zoomout.gif" alt="Zoom Out (Alt+Minus)"></BUTTON></TD>
|
|
<TD class="UIPane"> <BUTTON id="butZoomIn"> <IMG id="zoomIn" base="zoomIn" src="zoomin.gif" alt="Zoom In (Alt+Plus)"></BUTTON></TD>
|
|
<TD class="UIPane"> <SELECT id="selectZoom" accesskey=z>
|
|
<OPTION VALUE="500" >500%
|
|
<OPTION VALUE="200" >200%
|
|
<OPTION VALUE="150" >150%
|
|
<OPTION VALUE="100" >100%
|
|
<OPTION VALUE="75" SELECTED >75%
|
|
<OPTION VALUE="50" >50%
|
|
<OPTION VALUE="25" >25%
|
|
<OPTION VALUE="10" >10%
|
|
<!-- ID's are for localization -->
|
|
<OPTION VALUE=STR_ZOOM_PAGE_WIDTH id="idPageWidth">Page Width</OPTION>
|
|
<OPTION VALUE=STR_ZOOM_WHOLE_PAGE id="idWholePage">Whole Page</OPTION>
|
|
<OPTION VALUE=STR_ZOOM_TWO_PAGES id="idTwoPages" >Two Pages </OPTION>
|
|
</SELECT></TD>
|
|
<TD class="UISeparator" id="separatorFrameset" style="display:none"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane" id="cellFrameset" style="display:none"> <SELECT id="selectFrameset" accesskey=f>
|
|
<OPTION VALUE=STR_FRAMESET_LAID_OUT id="idLaidOut">As laid out on screen</OPTION>
|
|
<OPTION VALUE=STR_FRAMESET_SELECTED id="idSelected">Only the selected frame</OPTION>
|
|
<OPTION VALUE=STR_FRAMESET_SEPARATE id="idSeparate">All frames individually</OPTION>
|
|
</SELECT></TD>
|
|
<TD class="UISeparator"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane"> <BUTTON id="butHelp" title="Print Preview Help (Alt+H)" accesskey=h><U>H</U>elp</BUTTON></TD>
|
|
<TD class="UISeparator"><IMG width=0 height=0></TD>
|
|
<TD class="UIPane"> <BUTTON id="butClose" title="Close Print Preview (Alt+C)" accessKey=c><U>C</U>lose</BUTTON></TD>
|
|
</TR></TABLE>
|
|
</DIV>
|
|
|
|
</DIV>
|
|
|
|
<DIV id=OverflowContainer onclick="this.focus();" onfocus="butPrint.scrollIntoView();" tabindex=1 style="position:absolute; left:0; width:100%; overflow:auto; border:'thin threedhighlight inset'; background:threedshadow;">
|
|
<DIV id=MasterContainer tabindex=0 style="width:100%; position:absolute;">
|
|
<!-- Pages go here -->
|
|
</DIV>
|
|
|
|
#ifdef DEBUG
|
|
<!-- Div used to log template events for debugging only. No need to localize! -->
|
|
<DIV id=LogContainer style="display:none; position:absolute; background:C0FFC0; top:0px; left:0px; height:100%; width:100%; overflow-y:scroll; overflow-x:auto;"></DIV>
|
|
#endif
|
|
|
|
</DIV>
|
|
|
|
</BODY>
|
|
</HTML>
|