Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1066 lines
32 KiB

/*
* npprint.c -- Code for printing from notepad.
* Copyright (C) 1984-1995 Microsoft Inc.
*/
#define NOMINMAX
#include "precomp.h"
//#define DBGPRINT
/* indices into chBuff */
#define LEFT 0
#define CENTER 1
#define RIGHT 2
INT tabSize; /* Size of a tab for print device in device units*/
HWND hAbortDlgWnd;
INT fAbort; /* true if abort in progress */
INT yPrintChar; /* height of a character */
RECT rtMargin;
/* left,center and right string for header or trailer */
#define MAXTITLE MAX_PATH
TCHAR chBuff[RIGHT+1][MAXTITLE];
/* date and time stuff for headers */
#define MAXDATE MAX_PATH
#define MAXTIME MAX_PATH
TCHAR szFormattedDate[MAXDATE]=TEXT("Y"); // formatted date (may be internationalized)
TCHAR szFormattedTime[MAXTIME]=TEXT("Y"); // formatted time (may be internaltionalized)
SYSTEMTIME PrintTime; // time we started printing
INT xPrintRes; // printer resolution in x direction
INT yPrintRes; // printer resolution in y direction
INT yPixInch; // pixels/inch
INT xPhysRes; // physical resolution x of paper
INT yPhysRes; // physical resolution y of paper
INT xPhysOff; // physical offset x
INT yPhysOff; // physical offset y
INT dyTop; // width of top border (pixels)
INT dyBottom; // width of bottom border
INT dxLeft; // width of left border
INT dxRight; // width of right border
INT iPageNum; // global page number currently being printed
HMENU hSysMenu;
/* define a type for NUM and the base */
typedef long NUM;
#define BASE 100L
/* converting in/out of fixed point */
#define NumToShort(x,s) (LOWORD(((x) + (s)) / BASE))
#define NumRemToShort(x) (LOWORD((x) % BASE))
/* rounding options for NumToShort */
#define NUMFLOOR 0
#define NUMROUND (BASE/2)
#define NUMCEILING (BASE-1)
#define ROUND(x) NumToShort(x,NUMROUND)
#define FLOOR(x) NumToShort(x,NUMFLOOR)
/* Unit conversion */
#define InchesToCM(x) (((x) * 254L + 50) / 100)
#define CMToInches(x) (((x) * 100L + 127) / 254)
void DestroyAbortWnd(void) ;
VOID TranslateString(TCHAR *);
BOOL CALLBACK AbortProc(HDC hPrintDC, INT reserved)
{
MSG msg;
while (!fAbort && PeekMessage((LPMSG)&msg, NULL, 0, 0, TRUE))
if (!hAbortDlgWnd || !IsDialogMessage (hAbortDlgWnd, (LPMSG)&msg))
{
TranslateMessage((LPMSG)&msg);
DispatchMessage((LPMSG)&msg);
}
return (!fAbort);
UNREFERENCED_PARAMETER(hPrintDC);
UNREFERENCED_PARAMETER(reserved);
}
BOOL CALLBACK AbortDlgProc(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch( msg )
{
case WM_COMMAND:
fAbort= TRUE;
DestroyAbortWnd();
return( TRUE );
case WM_INITDIALOG:
hSysMenu= GetSystemMenu( hwnd, FALSE );
SetDlgItemText( hwnd, ID_FILENAME,
fUntitled ? szUntitled : PFileInPath (szFileName) );
SetFocus( hwnd );
return( TRUE );
case WM_INITMENU:
EnableMenuItem( hSysMenu, (WORD)SC_CLOSE, (DWORD)MF_GRAYED );
return( TRUE );
}
return( FALSE );
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
}
/*
* print out the translated header/footer string in proper position.
* uses globals xPrintWidth, ...
*
* returns 1 if line was printed, otherwise 0.
*/
INT PrintHeaderFooter (HDC hDC, INT nHF)
{
SIZE Size; // to compute the width of each string
INT yPos; // y position to print
INT xPos; // x position to print
if( *chPageText[nHF] == 0 ) // see if anything to do
return 0; // we didn't print
TranslateString( chPageText[nHF] );
// figure out the y position we are printing
if( nHF == HEADER )
yPos= dyTop;
else
yPos= yPrintRes - dyBottom - yPrintChar;
// print out the various strings
// N.B. could overprint which seems ok for now
if( *chBuff[LEFT] ) // left string
{
TextOut( hDC, dxLeft, yPos, chBuff[LEFT], lstrlen(chBuff[LEFT]) );
}
if( *chBuff[CENTER] ) // center string
{
GetTextExtentPoint32( hDC, chBuff[CENTER], lstrlen(chBuff[CENTER]), &Size );
xPos= (xPrintRes-dxRight+dxLeft)/2 - Size.cx/2;
TextOut( hDC, xPos, yPos, chBuff[CENTER], lstrlen(chBuff[CENTER]) );
}
if( *chBuff[RIGHT] ) // right string
{
GetTextExtentPoint32( hDC, chBuff[RIGHT], lstrlen(chBuff[RIGHT]), &Size );
xPos= xPrintRes - dxRight - Size.cx;
TextOut( hDC, xPos, yPos, chBuff[RIGHT], lstrlen(chBuff[RIGHT]) );
}
return 1; // we did print something
}
/*
* GetResolutions
*
* Gets printer resolutions.
* sets globals: xPrintRes, yPrintRes, yPixInch
*
*/
VOID GetResolutions(HDC hPrintDC)
{
xPrintRes = GetDeviceCaps( hPrintDC, HORZRES );
yPrintRes = GetDeviceCaps( hPrintDC, VERTRES );
yPixInch = GetDeviceCaps( hPrintDC, LOGPIXELSY );
xPhysRes = GetDeviceCaps( hPrintDC, PHYSICALWIDTH );
yPhysRes = GetDeviceCaps( hPrintDC, PHYSICALHEIGHT );
xPhysOff = GetDeviceCaps( hPrintDC, PHYSICALOFFSETX );
yPhysOff = GetDeviceCaps( hPrintDC, PHYSICALOFFSETY );
}
/* GetMoreText
*
* Gets the next line of text from the MLE, returning a pointer
* to the beginning and just past the end.
*
* linenum - index into MLE (IN)
* pStartText - start of MLE (IN)
* ppsStr - pointer to where to put pointer to start of text (OUT)
* ppEOL - pointer to where to put pointer to just past EOL (OUT)
*
*/
VOID GetMoreText( INT linenum, PTCHAR pStartText, PTCHAR* ppsStr, PTCHAR* ppEOL )
{
INT Offset; // offset in 'chars' into edit buffer
INT nChars; // number of chars in line
Offset= SendMessage( hwndEdit, EM_LINEINDEX, linenum, 0 );
nChars= SendMessage( hwndEdit, EM_LINELENGTH, Offset, 0 );
*ppsStr= pStartText + Offset;
*ppEOL= (pStartText+Offset) + nChars;
}
#ifdef DBGPRINT
TCHAR dbuf[100];
VOID ShowMargins( HDC hPrintDC )
{
INT xPrintRes, yPrintRes;
RECT rct;
HBRUSH hBrush;
xPrintRes= GetDeviceCaps( hPrintDC, HORZRES );
yPrintRes= GetDeviceCaps( hPrintDC, VERTRES );
hBrush= GetStockObject( BLACK_BRUSH );
SetRect( &rct, 0,0,xPrintRes-1, yPrintRes-1 );
FrameRect( hPrintDC, &rct, hBrush );
SetRect( &rct, dxLeft, dyTop, xPrintRes-dxRight, yPrintRes-dyBottom );
FrameRect( hPrintDC, &rct, hBrush );
}
VOID PrintLogFont( LOGFONT lf )
{
wsprintf(dbuf,TEXT("lfHeight %d\n"), lf.lfHeight ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfWidth %d\n"), lf.lfWidth ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfEscapement %d\n"), lf. lfEscapement ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfOrientation %d\n"), lf.lfOrientation ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfWeight %d\n"), lf.lfWeight ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfItalic %d\n"), lf.lfItalic ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfUnderline %d\n"), lf.lfUnderline ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfStrikeOut %d\n"), lf.lfStrikeOut ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfCharSet %d\n"), lf.lfCharSet ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfOutPrecision %d\n"), lf.lfOutPrecision ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfClipPrecison %d\n"), lf.lfClipPrecision ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfQuality %d\n"), lf.lfQuality ); ODS(dbuf);
wsprintf(dbuf,TEXT("lfPitchAndFamily %d\n"), lf.lfPitchAndFamily); ODS(dbuf);
wsprintf(dbuf,TEXT("lfFaceName %s\n"), lf.lfFaceName ); ODS(dbuf);
}
#endif
INT NpPrint (void)
{
HDC hPrintDC=NULL; // printer DC
HANDLE hText= NULL; // handle to MLE text
HFONT hPrintFont= NULL; // font to print with
HANDLE hPrevFont= NULL; // previous font in hPrintDC
BOOL fPageStarted= FALSE; // true if StartPage called for this page
BOOL fDocStarted= FALSE; // true if StartDoc called
PTCHAR pStartText= NULL; // start of edit text (locked hText)
TEXTMETRIC Metrics;
TCHAR msgbuf[MAX_PATH];
INT nLinesPerPage; // not inc. header and footer
DWORD Offset; // line offset into MLE buffer
INT nPrintedLines; // number of lines on this page
// iErr will contain the first error discovered ie it is sticky
// This will be the value returned by this function.
// It does not need to translate SP_* errors except for SP_ERROR which should be
// GetLastError() right after it is first detected.
INT iErr; // error return
INT wpNumLines; // number of lines to print
DOCINFO DocInfo;
INT xCurpos; // current x-position rel. to left margin
INT yCurpos; // current y-position rel. to top margin
PTCHAR pNextLine; // next bit of line to try printing; leftovers
INT nPixelsLeft; // number of pixels left to print in
SIZE Size; // to see if text will fit in space left
INT guess; // number of chars that can print
PTCHAR pLineEOL; // pointer to end of string from MLE
PTCHAR lpLine; // current line
INT LineNum; // current line number
LOGFONT lfPrintFont; // local version of FontStruct
LCID lcid; // locale id
fAbort = FALSE;
hAbortDlgWnd= NULL;
SetCursor( hWaitCursor );
hPrintDC= GetPrinterDC ();
if( hPrintDC == INVALID_HANDLE_VALUE )
{
SetCursor( hStdCursor );
return 0; // message already given
}
GetResolutions( hPrintDC );
// Get the time and date for use in the header or trailer.
// We use the GetDateFormat and GetTimeFormat to get the
// internationalized versions.
GetLocalTime( &PrintTime ); // use local, not gmt
lcid= GetUserDefaultLCID();
GetDateFormat( lcid, DATE_LONGDATE, &PrintTime, NULL, szFormattedDate, MAXDATE );
GetTimeFormat( lcid, 0, &PrintTime, NULL, szFormattedTime, MAXTIME );
/*
* This part is to select the current font to the printer device.
* We have to change the height because FontStruct was created
* assuming the display. Using the remembered pointsize, calculate
* the new height.
*/
lfPrintFont= FontStruct; // make local copy
lfPrintFont.lfHeight= -(iPointSize*yPixInch)/(72*10);
lfPrintFont.lfWidth= 0;
//
// convert margins to pixels
// ptPaperSize is the physical paper size, not the printable area.
// do the mapping in physical units
//
SetMapMode( hPrintDC, MM_ANISOTROPIC );
SetViewportExtEx( hPrintDC,
xPhysRes,
yPhysRes,
NULL );
SetWindowExtEx( hPrintDC,
g_PageSetupDlg.ptPaperSize.x,
g_PageSetupDlg.ptPaperSize.y,
NULL );
rtMargin = g_PageSetupDlg.rtMargin;
LPtoDP( hPrintDC, (LPPOINT) &rtMargin, 2 );
SetMapMode( hPrintDC,MM_TEXT ); // restore to mm_text mode
hPrintFont= CreateFontIndirect(&lfPrintFont);
if( !hPrintFont )
{
goto ErrorExit;
}
hPrevFont= SelectObject( hPrintDC, hPrintFont );
if( !hPrevFont )
{
goto ErrorExit;
}
SetBkMode( hPrintDC, TRANSPARENT );
if( !GetTextMetrics( hPrintDC, (LPTEXTMETRIC) &Metrics ) )
{
goto ErrorExit;
}
// The font may not a scalable (say on a bubblejet printer)
// In this case, just pick some font
// For example, FixedSys 9 pt would be non-scalable
if( !(Metrics.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE )) )
{
// remove just created font
hPrintFont= SelectObject( hPrintDC, hPrevFont ); // get old font
DeleteObject( hPrintFont );
memset( lfPrintFont.lfFaceName, 0, LF_FACESIZE*sizeof(TCHAR) );
hPrintFont= CreateFontIndirect( &lfPrintFont );
if( !hPrintFont )
{
goto ErrorExit;
}
hPrevFont= SelectObject( hPrintDC, hPrintFont );
if( !hPrevFont )
{
goto ErrorExit;
}
if( !GetTextMetrics( hPrintDC, (LPTEXTMETRIC) &Metrics ) )
{
goto ErrorExit;
}
}
yPrintChar= Metrics.tmHeight+Metrics.tmExternalLeading; /* the height */
tabSize = Metrics.tmAveCharWidth * 8; /* 8 ave char width pixels for tabs */
// compute margins in pixels
dxLeft= max(rtMargin.left - xPhysOff,0);
dxRight= max(rtMargin.right - (xPhysRes - xPrintRes - xPhysOff), 0 );
dyTop= max(rtMargin.top - yPhysOff,0);
dyBottom= max(rtMargin.bottom - (yPhysRes - yPrintRes - yPhysOff), 0 );
#ifdef DBGPRINT
{
TCHAR dbuf[100];
RECT rt= g_PageSetupDlg.rtMargin;
POINT pt;
wsprintf(dbuf,TEXT("Print pOffx %d pOffy %d\n"),
GetDeviceCaps(hPrintDC, PHYSICALOFFSETX),
GetDeviceCaps(hPrintDC, PHYSICALOFFSETY));
ODS(dbuf);
wsprintf(dbuf,TEXT("PHYSICALWIDTH: %d\n"), xPhysRes);
ODS(dbuf);
wsprintf(dbuf,TEXT("HORZRES: %d\n"),xPrintRes);
ODS(dbuf);
wsprintf(dbuf,TEXT("PHYSICALOFFSETX: %d\n"),xPhysOff);
ODS(dbuf);
wsprintf(dbuf,TEXT("LOGPIXELSX: %d\n"),
GetDeviceCaps(hPrintDC,LOGPIXELSX));
ODS(dbuf);
GetViewportOrgEx( hPrintDC, (LPPOINT) &pt );
wsprintf(dbuf,TEXT("Viewport org: %d %d\n"), pt.x, pt.y );
ODS(dbuf);
GetWindowOrgEx( hPrintDC, (LPPOINT) &pt );
wsprintf(dbuf,TEXT("Window org: %d %d\n"), pt.x, pt.y );
ODS(dbuf);
wsprintf(dbuf,TEXT("PrintRes x: %d y: %d\n"),xPrintRes, yPrintRes);
ODS(dbuf);
wsprintf(dbuf,TEXT("PaperSize x: %d y: %d\n"),
g_PageSetupDlg.ptPaperSize.x,
g_PageSetupDlg.ptPaperSize.y );
ODS(dbuf);
wsprintf(dbuf,TEXT("unit margins: l: %d r: %d t: %d b: %d\n"),
rt.left, rt.right, rt.top, rt.bottom);
ODS(dbuf);
wsprintf(dbuf,TEXT("pixel margins: l: %d r: %d t: %d b: %d\n"),
rtMargin.left, rtMargin.right, rtMargin.top, rtMargin.bottom);
ODS(dbuf);
wsprintf(dbuf,TEXT("dxLeft %d dxRight %d\n"),dxLeft,dxRight);
ODS(dbuf);
wsprintf(dbuf,TEXT("dyTop %d dyBot %d\n"),dyTop,dyBottom);
ODS(dbuf);
}
#endif
/* Number of lines on a page with margins */
/* two lines are used by header and footer */
nLinesPerPage = ((yPrintRes - dyTop - dyBottom) / yPrintChar);
if( *chPageText[HEADER] )
nLinesPerPage--;
if( *chPageText[FOOTER] )
nLinesPerPage--;
/*
** There was a bug in NT once where a printer driver would
** return a font that was larger than the page size which
** would then cause Notepad to constantly print blank pages
** To keep from doing this we check to see if we can fit ANYTHING
** on a page, if not then there is a problem so quit. MarkRi 8/92
*/
if( nLinesPerPage <= 0 )
{
MessageBox( hwndNP, szFontTooBig, szNN, MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION );
SetLastError(0); // no error
ErrorExit:
iErr= GetLastError(); // remember the first error
if (hPrevFont)
{
SelectObject( hPrintDC, hPrevFont );
DeleteObject( hPrintFont );
}
if( pStartText ) // were able to lock hText
LocalUnlock( hText );
if( fPageStarted )
EndPage( hPrintDC );
if( fDocStarted )
EndDoc( hPrintDC );
DeleteDC( hPrintDC );
DestroyAbortWnd();
SetCursor( hStdCursor );
return( iErr );
}
if( (iErr= SetAbortProc (hPrintDC, AbortProc)) < 0 )
{
goto ErrorExit;
}
// get printer to MLE text
hText= (HANDLE) SendMessage( hwndEdit, EM_GETHANDLE, 0, 0 );
if( !hText )
{
goto ErrorExit;
}
pStartText= LocalLock( hText );
if( !pStartText )
{
goto ErrorExit;
}
GetWindowText( hwndNP, msgbuf, CharSizeOf(msgbuf) );
EnableWindow( hwndNP, FALSE ); // Disable window to prevent reentrancy
hAbortDlgWnd= CreateDialog( hInstanceNP,
(LPTSTR) MAKEINTRESOURCE(IDD_ABORTPRINT),
hwndNP,
(WNDPROC) AbortDlgProc);
if( !hAbortDlgWnd )
{
goto ErrorExit;
}
DocInfo.cbSize= sizeof(DOCINFO);
DocInfo.lpszDocName= msgbuf;
DocInfo.lpszOutput= NULL;
DocInfo.lpszDatatype= NULL; // Type of data used to record print job
DocInfo.fwType= 0; // not DI_APPBANDING
if( (iErr= StartDoc( hPrintDC, &DocInfo )) < 0 )
{
goto ErrorExit;
}
fDocStarted= TRUE;
yCurpos = 0;
Offset = 0;
LineNum = 0;
nPrintedLines= 0;
iPageNum= 1;
wpNumLines= SendMessage( hwndEdit, EM_GETLINECOUNT, 0, 0 );
// if last line is empty, don't print it
GetMoreText( wpNumLines-1, pStartText, &lpLine, &pLineEOL );
if( *lpLine == 0 )
wpNumLines--;
nPrintedLines= 0; // number of lines printed on this page
fPageStarted= FALSE;
while (!fAbort && LineNum < wpNumLines)
{
GetMoreText( LineNum++, pStartText, &lpLine, &pLineEOL );
do // till lpLine == pLineEOL
{
// Print out header if we are about to print
// the first line on the page
if( nPrintedLines == 0 && !fPageStarted )
{
if( (iErr= StartPage( hPrintDC ) <= 0 ) )
{
goto ErrorExit;
}
fPageStarted= TRUE; // prevent StartPage on next partial line
// print header if one exists
yCurpos= 0;
if( PrintHeaderFooter( hPrintDC, HEADER ) )
yCurpos= yPrintChar;
xCurpos= 0;
#ifdef DBGPRINT
ShowMargins(hPrintDC);
#endif
}
// print and move print head in x-direction
// handle tabs characters as a special case
if( *lpLine == TEXT('\t') ) // tab?
{
// round up to the next tab stop
// if the current position is on the tabstop, goto next one
xCurpos= ( (xCurpos+tabSize)/tabSize ) * tabSize;
lpLine++;
}
else // first character not a tab
{
// find what to print - up to EOL or tab
pNextLine= lpLine; // find end of line or tab
while( (pNextLine!=pLineEOL) && *pNextLine != TEXT('\t') )
pNextLine++;
// find out how many characters will fit on line
nPixelsLeft= xPrintRes - dxRight - dxLeft - xCurpos;
GetTextExtentExPoint( hPrintDC, lpLine, pNextLine-lpLine,
nPixelsLeft, &guess, NULL, &Size );
if( guess )
{
// at least one character fits - print
TextOut( hPrintDC, dxLeft+xCurpos, yCurpos+dyTop, lpLine, guess);
xCurpos += Size.cx; // account for printing
lpLine += guess;
}
else // no characters fit what's left
{
// no characters will fit in space left
// if none ever will, just print one
// character to keep progressing through
// input file.
if( xCurpos == 0 )
{
if( lpLine != pNextLine ) //print something if not null line
{
// could use exttextout here to clip
TextOut(hPrintDC,dxLeft+xCurpos,yCurpos+dyTop,lpLine,1);
lpLine++;
}
}
else // perhaps the next line will get it
{
xCurpos= xPrintRes; // force to next line
}
}
} // not a tab
// move printhead in y-direction
if( (xCurpos >= (xPrintRes - dxRight - dxLeft) ) || (lpLine==pLineEOL ) )
{
yCurpos += yPrintChar;
nPrintedLines++;
xCurpos= 0;
}
if( nPrintedLines >= nLinesPerPage )
{
PrintHeaderFooter( hPrintDC, FOOTER );
if( (iErr= EndPage( hPrintDC ) ) <= 0 )
{
goto ErrorExit;
}
fPageStarted= FALSE;
// reset info
nPrintedLines= 0;
xCurpos= 0;
iPageNum++;
}
}
while( lpLine != pLineEOL && !fAbort ); // continue if more to do with line
} // continue if more lines
if( !fAbort && nPrintedLines )
{
PrintHeaderFooter( hPrintDC, FOOTER );
}
SetLastError(0); // no errors
goto ErrorExit;
}
VOID DestroyAbortWnd (void)
{
EnableWindow(hwndNP, TRUE);
DestroyWindow(hAbortDlgWnd);
hAbortDlgWnd = NULL;
}
const DWORD s_PageSetupHelpIDs[] = {
ID_HEADER_LABEL, IDH_PAGE_HEADER,
ID_HEADER, IDH_PAGE_HEADER,
ID_FOOTER_LABEL, IDH_PAGE_FOOTER,
ID_FOOTER, IDH_PAGE_FOOTER,
ID_PREVIEW_GROUP, NO_HELP,
0, 0
};
/*******************************************************************************
*
* PageSetupHookProc
*
* DESCRIPTION:
* Callback procedure for the PageSetup common dialog box.
*
* PARAMETERS:
* hWnd, handle of PageSetup window.
* Message,
* wParam,
* lParam,
* (returns),
*
*******************************************************************************/
UINT CALLBACK PageSetupHookProc(
HWND hWnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
INT id; /* ID of dialog edit controls */
POINT pt;
switch (Message)
{
case WM_INITDIALOG:
for (id = ID_HEADER; id <= ID_FOOTER; id++)
{
SendDlgItemMessage(hWnd, id, EM_LIMITTEXT, PT_LEN-1, 0L);
SetDlgItemText(hWnd, id, chPageText[id - ID_HEADER]);
}
SendDlgItemMessage(hWnd, ID_HEADER, EM_SETSEL, 0,
MAKELONG(0, PT_LEN-1));
return TRUE;
case WM_DESTROY:
// We don't know if the user hit OK or Cancel, so we don't
// want to replace our real copies until we know! We _should_ get
// a notification from the common dialog code!
for( id = ID_HEADER; id <= ID_FOOTER; id++ )
{
GetDlgItemText(hWnd, id, chPageTextTemp[id - ID_HEADER],PT_LEN);
}
break;
case WM_HELP:
//
// We only want to intercept help messages for controls that we are
// responsible for.
//
id = GetDlgCtrlID(((LPHELPINFO) lParam)-> hItemHandle);
if (id < ID_HEADER || id > ID_PREVIEW_GROUP)
break;
WinHelp(((LPHELPINFO) lParam)-> hItemHandle, szHelpFile,
HELP_WM_HELP, (DWORD) (LPVOID) s_PageSetupHelpIDs);
return TRUE;
case WM_CONTEXTMENU:
//
// If the user clicks on any of our labels, then the wParam will
// be the hwnd of the dialog, not the static control. WinHelp()
// handles this, but because we hook the dialog, we must catch it
// first.
//
if( hWnd == (HWND) wParam )
{
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
wParam = (WPARAM) ChildWindowFromPoint(hWnd, pt);
}
//
// We only want to intercept help messages for controls that we are
// responsible for.
//
id = GetDlgCtrlID((HWND) wParam);
if (id < ID_HEADER || id > ID_PREVIEW_GROUP)
break;
WinHelp((HWND) wParam, szHelpFile, HELP_CONTEXTMENU,
(DWORD) (LPVOID) s_PageSetupHelpIDs);
return TRUE;
}
return FALSE;
}
/***************************************************************************
* VOID TranslateString(TCHAR *src)
*
* purpose:
* translate a header/footer strings
*
* supports the following:
*
* && insert a & char
* &f current file name or (untitled)
* &d date in Day Month Year
* &t time
* &p page number
* &p+num set first page number to num
*
* Alignment:
* &l, &c, &r for left, center, right
*
* params:
* IN/OUT src this is the string to translate
*
*
* used by:
* Header Footer stuff
*
* uses:
* lots of c lib stuff
*
***************************************************************************/
VOID TranslateString (TCHAR * src)
{
TCHAR letters[15];
TCHAR buf[MAX_PATH];
TCHAR *ptr;
INT page;
INT nAlign=CENTER; // current string to add chars to
INT foo;
INT nIndex[RIGHT+1]; // current lengths of (left,center,right)
struct tm *newtime;
time_t long_time;
INT iLen; // length of strings
nIndex[LEFT] = 0;
nIndex[CENTER] = 0;
nIndex[RIGHT] = 0;
/* Get the time we need in case we use &t. */
time (&long_time);
newtime = localtime (&long_time);
LoadString (hInstanceNP, IDS_LETTERS, letters, CharSizeOf(letters));
while (*src) /* look at all of source */
{
while (*src && *src != TEXT('&'))
{
chBuff[nAlign][nIndex[nAlign]] = *src++;
nIndex[nAlign] += 1;
}
if (*src == TEXT('&')) /* is it the escape char? */
{
src++;
if (*src == letters[0] || *src == letters[1])
{ /* &f file name (no path) */
if (!fUntitled)
{
GetFileTitle(szFileName, buf, CharSizeOf(buf));
}
else
{
lstrcpy(buf, szUntitled);
}
/* Copy to the currently aligned string. */
if( nIndex[nAlign] + lstrlen(buf) < MAXTITLE )
{
lstrcpy( chBuff[nAlign] + nIndex[nAlign], buf );
/* Update insertion position. */
nIndex[nAlign] += lstrlen (buf);
}
}
else if (*src == letters[2] || *src == letters[3]) /* &P or &P+num page */
{
src++;
page = 0;
if (*src == TEXT('+')) /* &p+num case */
{
src++;
while (_istdigit(*src))
{
/* Convert to int on-the-fly*/
page = (10*page) + (*src) - TEXT('0');
src++;
}
}
wsprintf( buf, TEXT("%d"), iPageNum+page ); // convert to chars
if( nIndex[nAlign] + lstrlen(buf) < MAXTITLE )
{
lstrcpy( chBuff[nAlign] + nIndex[nAlign], buf );
nIndex[nAlign] += lstrlen (buf);
}
src--;
}
else if (*src == letters[4] || *src == letters[5]) /* &t time */
{
iLen= lstrlen( szFormattedTime );
/* extract time */
if( nIndex[nAlign] + iLen < MAXTITLE )
{
_tcsncpy (chBuff[nAlign] + nIndex[nAlign], szFormattedTime, iLen);
nIndex[nAlign] += iLen;
}
}
else if (*src == letters[6] || *src == letters[7]) /* &d date */
{
iLen= lstrlen( szFormattedDate );
/* extract day month day */
if( nIndex[nAlign] + iLen < MAXTITLE )
{
_tcsncpy (chBuff[nAlign] + nIndex[nAlign], szFormattedDate, iLen);
nIndex[nAlign] += iLen;
}
}
else if (*src == TEXT('&')) /* quote a single & */
{
if( nIndex[nAlign] + 1 < MAXTITLE )
{
chBuff[nAlign][nIndex[nAlign]] = TEXT('&');
nIndex[nAlign] += 1;
}
}
/* Set the alignment for whichever has last occured. */
else if (*src == letters[8] || *src == letters[9]) /* &c center */
nAlign=CENTER;
else if (*src == letters[10] || *src == letters[11]) /* &r right */
nAlign=RIGHT;
else if (*src == letters[12] || *src == letters[13]) /* &d date */
nAlign=LEFT;
src++;
}
}
/* Make sure all strings are null-terminated. */
for (nAlign= LEFT; nAlign <= RIGHT ; nAlign++)
chBuff[nAlign][nIndex[nAlign]] = (TCHAR) 0;
}
/* GetPrinterDC() - returns printer DC or INVALID_HANDLE_VALUE if none. */
HANDLE GetPrinterDC (VOID)
{
LPDEVMODE lpDevMode;
LPDEVNAMES lpDevNames;
HDC hDC;
if( !g_PageSetupDlg.hDevNames ) /* Retrieve default printer if none selected. */
{
g_PageSetupDlg.Flags |= PSD_RETURNDEFAULT;
PageSetupDlg(&g_PageSetupDlg);
g_PageSetupDlg.Flags &= ~PSD_RETURNDEFAULT;
}
if( !g_PageSetupDlg.hDevNames )
{
MessageBox( hwndNP, szLoadDrvFail, szNN, MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
return INVALID_HANDLE_VALUE;
}
lpDevNames= (LPDEVNAMES) GlobalLock (g_PageSetupDlg.hDevNames);
// bugbug - the following code is obviously old and pointless
if( g_PageSetupDlg.hDevMode )
lpDevMode= (LPDEVMODE) GlobalLock( g_PageSetupDlg.hDevMode );
else
lpDevMode= NULL;
/* For pre 3.0 Drivers,hDevMode will be null from Commdlg so lpDevMode
* will be NULL after GlobalLock()
*/
/* The lpszOutput name is null so CreateDC will use the current setting
* from PrintMan.
*/
hDC= CreateDC (((LPTSTR)lpDevNames)+lpDevNames->wDriverOffset,
((LPTSTR)lpDevNames)+lpDevNames->wDeviceOffset,
NULL,
lpDevMode);
GlobalUnlock( g_PageSetupDlg.hDevNames );
if( g_PageSetupDlg.hDevMode )
GlobalUnlock( g_PageSetupDlg.hDevMode );
if( hDC == NULL )
{
MessageBox( hwndNP, szLoadDrvFail, szNN, MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
return INVALID_HANDLE_VALUE;
}
return hDC;
}
/* PrintIt() - print the file, giving popup if some error */
void PrintIt()
{
INT iError;
TCHAR* szMsg= NULL;
TCHAR msg[400]; // message info on error
/* print the file */
if (((iError = NpPrint ()) != 0) && (iError != SP_USERABORT))
{
// translate any known spooler errors
if( iError == SP_OUTOFDISK ) iError= ERROR_DISK_FULL;
if( iError == SP_OUTOFMEMORY ) iError= ERROR_OUTOFMEMORY;
if( iError == SP_ERROR ) iError= GetLastError();
// Get system to give reasonable error message
// These will also be internationalized.
if(!FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
iError,
GetUserDefaultLangID(),
msg, // where message will end up
CharSizeOf(msg), NULL ) )
{
szMsg= szCP; // couldn't get system to say; give generic msg
}
else
{
szMsg= msg;
}
AlertBox( hwndNP, szNN, szMsg, fUntitled ? szUntitled : szFileName,
MB_APPLMODAL | MB_OK | MB_ICONEXCLAMATION);
}
}