Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1203 lines
29 KiB

/* File: D:\WACKER\tdll\printset.c (Created: 02-Feb-1994)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 11 $
* $Date: 7/08/02 6:46p $
*/
#include <windows.h>
#pragma hdrstop
#include <stdio.h>
#include <limits.h>
#include <term\res.h>
#include "stdtyp.h"
#include "mc.h"
#include "misc.h"
#include "assert.h"
#include "print.h"
#include "print.hh"
#include "globals.h"
#include "session.h"
#include "term.h"
#include "tdll.h"
#include "htchar.h"
#include "load_res.h"
#include "open_msc.h"
#include "open_msc.h"
#include "sf.h"
#include "file_msc.h"
static int printsetPrintToFile(const HPRINT hPrint);
static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam );
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetSetup
*
* DESCRIPTION:
* This function is used to display the common print dialogs.
*
* ARGUMENTS:
* hPrint - An external print handle.
* hwnd - owner window handle
*
* RETURNS:
* void
*
*/
void printsetSetup(const HPRINT hPrint, const HWND hwnd)
{
const HHPRINT hhPrint = (HHPRINT)hPrint;
#ifdef INCL_USE_NEWPRINTDLG
PRINTDLGEX pd;
HRESULT hResult;
#else
PRINTDLG pd;
#endif
LPDEVNAMES pstDevNames;
PDEVMODE pstDevMode;
TCHAR *pszPrinterName;
TCHAR *pTemp;
DWORD dwSize;
DWORD dwError;
#if defined(_DEBUG)
TCHAR ach[100];
#endif
if (hhPrint == 0)
{
assert(FALSE);
return;
}
// Initialize basic structure elements.
//
#ifdef INCL_USE_NEWPRINTDLG
memset (&pd, 0, sizeof(PRINTDLGEX));
pd.lStructSize = sizeof(PRINTDLGEX);
pd.Flags2 = 0;
pd.nStartPage = START_PAGE_GENERAL;
pd.dwResultAction = 0;
#else
memset (&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
#endif
pd.Flags = PD_NOWARNING | PD_NOPAGENUMS;
pd.hwndOwner = hwnd;
if (SendMessage(sessQueryHwndTerminal(hhPrint->hSession),
WM_TERM_Q_MARKED, 0, 0))
{
pd.Flags |= PD_SELECTION;
}
// Use the previously stored information to initialize the print
// common dialogs. printGetDefaults initializes this information
// when a print handle is created.
//
if (hhPrint->pstDevMode)
{
// Allocate memory for the DEVMODE information and then
// initialize it with the stored values from the Print Handle.
//
dwSize = hhPrint->pstDevMode->dmSize +
hhPrint->pstDevMode->dmDriverExtra;
if ((pd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
{
if ((pstDevMode = GlobalLock(pd.hDevMode)))
{
if (dwSize)
MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize);
GlobalUnlock(pd.hDevMode);
}
}
}
if (hhPrint->pstDevNames)
{
// Allocate memory for the DEVNAMES structure in pd, then
// initialize it with the stored values from the Print Handle.
// This sequence determines the variable structure size of
// DEVNAMES.
//
pTemp = (TCHAR *)hhPrint->pstDevNames;
pTemp += hhPrint->pstDevNames->wOutputOffset;
pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
if ((pd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
{
if ((pstDevNames = GlobalLock(pd.hDevNames)))
{
if (dwSize)
MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize);
GlobalUnlock(pd.hDevNames);
}
}
}
// Initialize the PrintToFilename array every time before we go
// into the dialog.
//
TCHAR_Fill(hhPrint->achPrintToFileName,
TEXT('\0'),
sizeof(hhPrint->achPrintToFileName) / sizeof(TCHAR));
// Display the dialog.
//
#ifdef INCL_USE_NEWPRINTDLG
pd.Flags2 = 0;
hResult = PrintDlgEx( &pd );
if ( hResult != S_OK)
#else
if (!PrintDlg(&pd))
#endif
{
dwError = CommDlgExtendedError();
#if defined(_DEBUG)
if (dwError != 0)
{
wsprintf(ach, "PrintDlg error 0x%x", dwError);
MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
}
#endif
// If user canceled, we're done
//
if (dwError == 0)
goto Cleanup;
// Some error occured, try to bring-up dialog with default
// data.
//
if (pd.hDevNames)
{
GlobalFree(pd.hDevNames);
pd.hDevNames = 0;
}
if (pd.hDevMode)
{
GlobalFree(pd.hDevMode);
pd.hDevMode = 0;
}
pd.Flags &= ~PD_NOWARNING;
#ifdef INCL_USE_NEWPRINTDLG
hResult = PrintDlgEx(&pd);
if ( hResult != S_OK)
#else
if (!PrintDlg(&pd))
#endif
{
#if defined(_DEBUG)
dwError = CommDlgExtendedError();
if (dwError != 0)
{
wsprintf(ach, "PrintDlg error 0x%x", dwError);
MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
}
#endif
goto Cleanup;
}
}
#ifdef INCL_USE_NEWPRINTDLG
// in the NT 5 print dialog, if the user cancels, the print dialog returns S_OK.
// So we need to check the result code to see if we should save the settings.
if ( pd.dwResultAction == PD_RESULT_CANCEL )
goto Cleanup;
#endif
// Store the flags returned from the dialog in the Print Handle.
// This has several pieces of info that will be used by the actual
// printing routines (i.e. print all, print selected).
//
hhPrint->nSelectionFlags = pd.Flags;
// Store the printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(pd.hDevNames);
if (!pstDevNames)
{
assert(FALSE);
GlobalUnlock(pd.hDevMode);
goto Cleanup;
}
pszPrinterName = (TCHAR *)pstDevNames;
pszPrinterName += pstDevNames->wDeviceOffset;
StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
GlobalUnlock(pd.hDevNames);
// Save the DEVMODE information in the Print Handle. This memory
// must be freed and allocated every time as the size of the
// DEVMODE structure changes.
//
pstDevMode = GlobalLock(pd.hDevMode);
dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
if (hhPrint->pstDevMode)
free(hhPrint->pstDevMode);
hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
if (hhPrint->pstDevMode == 0)
{
assert(FALSE);
GlobalUnlock(pd.hDevMode);
goto Cleanup;
}
if (dwSize)
MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize);
GlobalUnlock(pd.hDevMode);
// Save the DEVNAMES information in the Print Handle. Because the
// size of the information in this structure varies, it is freed and
// allocated each time it is saved.
//
pstDevNames = GlobalLock(pd.hDevNames);
// Determine the size of the structure.
//
pTemp = (TCHAR *)pstDevNames;
pTemp += pstDevNames->wOutputOffset;
pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
if (hhPrint->pstDevNames)
{
free(hhPrint->pstDevNames);
hhPrint->pstDevNames = NULL;
}
hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0)
{
assert(0);
GlobalUnlock(pd.hDevNames);
goto Cleanup;
}
if (dwSize)
MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize);
GlobalUnlock(pd.hDevNames);
// Has the user selected Print To File? Yes, you do need to look
// for the string "FILE:" to determinae this! If so, we will put
// up our own common dialog to get the save as file name.
//
pTemp = (CHAR *)hhPrint->pstDevNames +
hhPrint->pstDevNames->wOutputOffset;
if (StrCharCmp("FILE:", pTemp) == 0)
{
if (printsetPrintToFile(hPrint) != 0)
{
goto Cleanup;
}
}
#ifdef INCL_USE_NEWPRINTDLG
// in the NT 5 print dialog, if the user cancels or click 'apply', the print dialog returns S_OK.
// So we need to check the result code to see if we should now print
if ( pd.dwResultAction != PD_RESULT_PRINT )
goto Cleanup;
#endif
// Print the selected text.
//
printsetPrint(hPrint);
// Cleanup any memory that may have been allocated.
//
Cleanup:
if (pd.hDevNames)
GlobalFree(pd.hDevNames);
if (pd.hDevMode)
GlobalFree(pd.hDevMode);
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetPrint
*
* DESCRIPTION:
* This function prints the selected text from then terninal and/or the
* backscroll buffer.
*
* ARGUMENTS:
* hPrint - An external Print handle.
*
* RETURNS:
* void
*
*/
void printsetPrint(const HPRINT hPrint)
{
const HHPRINT hhPrint = (HHPRINT)hPrint;
int iLineHeight;
int iVertRes;
int iStatus,
nRet;
int iPrintableWidth;
RECT stRect;
DWORD dwCnt, dwTime1, dwTime2;
POINT pX, pY;
ECHAR *pechBuf;
TCHAR *pV,
*pLS,
*pLE,
*pEnd,
*pNext;
if (hPrint == 0)
{
assert(FALSE);
return;
}
// Get the text to print for selected text.
//
if (hhPrint->nSelectionFlags & PD_SELECTION)
{
if (!CopyMarkedTextFromTerminal(hhPrint->hSession,
&pV,
&dwCnt,
FALSE))
{
if (pV)
{
free(pV);
pV = NULL;
}
assert(FALSE);
return;
}
if (dwCnt == 0)
{
if (pV)
{
free(pV);
pV = NULL;
}
assert(FALSE);
return;
}
}
// Get the text to print into a buffer for an ALL selection.
//
else
{
pX.x = 0;
pX.y = INT_MIN;
pY.x = INT_MAX;
pY.y = INT_MAX;
nRet = CopyTextFromTerminal(hhPrint->hSession,
&pX,
&pY,
&pechBuf,
&dwCnt,
FALSE);
if (nRet == FALSE)
{
if (pechBuf)
{
free(pechBuf);
pechBuf = NULL;
}
assert(FALSE);
return;
}
// Strip Out Any repeated Characters in the string
StrCharStripDBCSString(pechBuf,
(long)StrCharGetEcharByteCount(pechBuf), pechBuf);
// hMem currently points to an array of ECHAR's, convert this to
// TCHARS before giving the results to the caller.
pV = malloc((ULONG)StrCharGetEcharByteCount(pechBuf) + 1);
CnvrtECHARtoMBCS(pV, (ULONG)StrCharGetEcharByteCount(pechBuf) + 1,
pechBuf,StrCharGetEcharByteCount(pechBuf)+1); // mrw:5/17/95
free(pechBuf);
pechBuf = NULL;
dwCnt = (ULONG)StrCharGetByteCount(pV);
}
// Create the DC.
//
hhPrint->hDC = printCtrlCreateDC(hPrint);
if (hhPrint->hDC == 0)
{
if (pV)
{
free(pV);
pV = NULL;
}
assert(FALSE);
return;
}
printSetFont( hhPrint );
printSetMargins( hhPrint );
// Initialize the DC. Set the abort flag, determine the number
// of lines per page, get the title of the window which will be used
// as the name of the document to print.
//
hhPrint->fError = FALSE;
hhPrint->fUserAbort = FALSE;
hhPrint->nLinesPrinted = 0;
hhPrint->nPage = 1;
EnableWindow(sessQueryHwnd(hhPrint->hSession), FALSE);
GetTextMetrics(hhPrint->hDC, &hhPrint->tm);
iLineHeight = hhPrint->tm.tmHeight + hhPrint->tm.tmExternalLeading;
iVertRes = GetDeviceCaps(hhPrint->hDC, VERTRES);
iVertRes -= (hhPrint->marginsDC.top + hhPrint->marginsDC.bottom);
if (iLineHeight == 0) //need to prevent a divide by zero error
iLineHeight = 1;
hhPrint->nLinesPerPage = max( iVertRes / iLineHeight, 1);
GetWindowText(sessQueryHwnd(hhPrint->hSession),
hhPrint->achDoc,
sizeof(hhPrint->achDoc));
// Create the Print Abort Dialog.
//
hhPrint->lpfnPrintDlgProc = printsetDlgProc;
hhPrint->hwndPrintDlg = DoModelessDialog(glblQueryDllHinst(),
MAKEINTRESOURCE(IDD_PRINTABORT),
sessQueryHwnd(hhPrint->hSession),
hhPrint->lpfnPrintDlgProc,
(LPARAM)hhPrint);
// Setup the Print Abort Procedure.
//
hhPrint->lpfnPrintAbortProc = printsetAbortProc;
nRet = SetAbortProc(hhPrint->hDC,
(ABORTPROC)hhPrint->lpfnPrintAbortProc);
// Initialize and start the document.
//
hhPrint->di.cbSize = sizeof(DOCINFO);
hhPrint->di.lpszDocName = hhPrint->achDoc;
hhPrint->di.lpszDatatype = NULL;
hhPrint->di.fwType = 0;
// Initialize di.lpszOutput for either printing to a file,
// or to a printer.
//
if (hhPrint->achPrintToFileName[0] == TEXT('\0'))
{
hhPrint->di.lpszOutput = (LPTSTR)NULL;
}
else
{
hhPrint->di.lpszOutput = (LPTSTR)hhPrint->achPrintToFileName;
}
// StartDoc.
//
iStatus = StartDoc(hhPrint->hDC, &hhPrint->di);
DbgOutStr("\r\nStartDoc: %d", iStatus, 0, 0, 0, 0);
if (iStatus == SP_ERROR)
{
printCtrlDeleteDC(hPrint);
if (IsWindow(hhPrint->hwndPrintDlg))
DestroyWindow(hhPrint->hwndPrintDlg);
printTellError(hhPrint->hSession, hPrint, iStatus);
assert(FALSE);
return;
}
// StartPage.
// Get more info on this.
//
iStatus = StartPage(hhPrint->hDC);
DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0);
printSetFont( hhPrint );
if (iStatus == SP_ERROR)
{
assert(FALSE);
}
// Move through the buffer that contins the text to print, and
// get it done.
//
// pLS = pointerLineStart
// pLE = pointerLineEnd
// pEnd = pointerEndOfBuffer
//
pLS = pV;
pLE = pV;
pEnd = pV + (dwCnt - 1);
while ((pLE <= pEnd) && !hhPrint->fError && !hhPrint->fUserAbort)
{
if (*pLE == TEXT('\r') || *pLE == TEXT('\0'))
{
pNext = pLE;
// Remove trailing CR\LF\NULL as these mean nothing to
// a Windows DC.
//
while (pLE >= pLS)
{
if (*pLE == TEXT('\r') || *pLE == TEXT('\n') ||
*pLE == TEXT('\0'))
{
pLE--;
continue;
}
break;
}
// Send the text out to the printer, bump the line count.
//
hhPrint->cx = hhPrint->marginsDC.left;
hhPrint->cy = hhPrint->nLinesPrinted * hhPrint->tm.tmHeight +
hhPrint->marginsDC.top;
iPrintableWidth = GetDeviceCaps( hhPrint->hDC, HORZRES );
iPrintableWidth -= hhPrint->marginsDC.right;
stRect.left = hhPrint->cx;
stRect.right = iPrintableWidth;
stRect.top = hhPrint->cy;
stRect.bottom = hhPrint->cy + hhPrint->tm.tmHeight;
ExtTextOut( hhPrint->hDC, hhPrint->cx, hhPrint->cy, ETO_CLIPPED,
&stRect, pLS, (UINT)((pLE - pLS) + 1), NULL );
hhPrint->nLinesPrinted += 1;
if (hhPrint->nLinesPrinted == 1)
{
DbgOutStr("\r\nPost WM_PRINT_NEWPAGE", 0, 0, 0, 0, 0);
PostMessage(hhPrint->hwndPrintDlg,
WM_PRINT_NEWPAGE,
0,
(LPARAM)hhPrint);
}
// Check for a new page condition.
//
if ((hhPrint->nLinesPrinted >= hhPrint->nLinesPerPage))
{
hhPrint->nLinesPrinted = 0;
hhPrint->nPage++;
iStatus = EndPage(hhPrint->hDC);
if (iStatus < 0)
{
hhPrint->fError = TRUE;
printTellError(hhPrint->hSession, hPrint, iStatus);
}
else
{
iStatus = StartPage(hhPrint->hDC);
DbgOutStr("\r\nStartPage: %d", iStatus, 0, 0, 0, 0);
printSetFont( hhPrint );
if (iStatus <= 0)
{
DbgShowLastError();
printTellError(hhPrint->hSession, hPrint, iStatus);
}
}
}
pLS = pLE = (pNext + 1);
continue;
}
pLE++;
}
// Did we issue an EndPage for this page yet?
//
if (hhPrint->nLinesPrinted > 0)
{
iStatus = EndPage(hhPrint->hDC);
DbgOutStr("\r\nEndPage: %d", iStatus, 0, 0, 0, 0);
if (iStatus <= 0)
{
DbgShowLastError();
printTellError(hhPrint->hSession, hPrint, iStatus);
}
}
// Call EndDoc.
//
iStatus = EndDoc(hhPrint->hDC);
if (iStatus <= 0)
{
DbgShowLastError();
DbgOutStr("\r\nEndDoc: %d", iStatus, 0, 0, 0, 0);
printTellError(hhPrint->hSession, hPrint, iStatus);
}
// Final cleanup before exit.
//
if (!hhPrint->fUserAbort)
{
dwTime1 = (DWORD)GetWindowLongPtr(hhPrint->hwndPrintDlg, GWLP_USERDATA);
dwTime2 = GetTickCount();
if (dwTime2 - dwTime1 < 3000)
Sleep( 3000 - (dwTime2 - dwTime1));
EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE);
DestroyWindow(hhPrint->hwndPrintDlg);
}
printCtrlDeleteDC(hPrint);
if (pV)
{
free(pV);
pV = NULL;
}
return;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetAbortProc
*
* DESCRIPTION:
* This is the print abort procedure used when printing selected text.
* Note that this abort proc is not used for print echo, or for host
* directed printing.
*
* ARGUMENTS:
* HDC - A printer DC.
* nCode - The status of the call.
*
* RETURNS:
* The abort status.
*
*/
BOOL CALLBACK printsetAbortProc(HDC hdcPrn, INT nCode)
{
MSG msg;
HHPRINT hhPrint = (HHPRINT)printCtrlLookupDC(hdcPrn);
DbgOutStr("\r\nprintsetAbortProc Code: %d", nCode, 0, 0, 0, 0);
while (!hhPrint->fUserAbort &&
PeekMessage((LPMSG)&msg, (HWND)0, 0, 0, PM_REMOVE))
{
if (!hhPrint->hwndPrintDlg ||
!IsDialogMessage(hhPrint->hwndPrintDlg, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return !hhPrint->fUserAbort;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetDlgProc
*
* DESCRIPTION:
* This is the dialog procedure for printing selected text. It contains
* a CANCEL button that may be used to abort the printing process.
*
* ARGUMENTS:
* Note that a print handle is passed into this procedure in the lPar
* variable.
*
* RETURNS:
*
*/
LRESULT CALLBACK printsetDlgProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar)
{
TCHAR achBuf[80];
TCHAR achMessage[80];
DWORD dwTime;
HHPRINT hhPrint;
LPTSTR acPtrs[3];
switch (uMsg)
{
case WM_INITDIALOG:
DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0);
hhPrint = (HHPRINT)lPar;
SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR)lPar);
mscCenterWindowOnWindow(hwnd, sessQueryHwnd(hhPrint->hSession));
LoadString(glblQueryDllHinst(),
IDS_PRINT_NOW_PRINTING,
achBuf,
sizeof(achBuf) / sizeof(TCHAR));
wsprintf(achMessage, achBuf, 1);
SetDlgItemText(hwnd, 101, achMessage);
LoadString(glblQueryDllHinst(),
IDS_PRINT_OF_DOC,
achBuf,
sizeof(achBuf) / sizeof(TCHAR));
wsprintf(achMessage, achBuf, hhPrint->achDoc);
SetDlgItemText(hwnd, 102, achMessage);
LoadString(glblQueryDllHinst(),
IDS_PRINT_ON_DEV,
achBuf,
sizeof(achBuf) / sizeof(TCHAR));
acPtrs[0] = hhPrint->achPrinterName;
acPtrs[1] = (TCHAR *)hhPrint->pstDevNames +
hhPrint->pstDevNames->wOutputOffset;
FormatMessage(
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
achBuf,
0, /* Message ID, ignored */
0, /* also ignored */
achMessage, /* result */
sizeof(achMessage) / sizeof(TCHAR),
(va_list *)&acPtrs[0]);
SetDlgItemText(hwnd, 103, achMessage);
dwTime = GetTickCount();
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dwTime);
return TRUE;
case WM_COMMAND:
DbgOutStr("\r\nprintsetDlgProc - CANCEL", 0, 0, 0, 0, 0);
hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER);
hhPrint->fUserAbort = TRUE;
EnableWindow(sessQueryHwnd(hhPrint->hSession), TRUE);
DestroyWindow(hwnd);
hhPrint->hwndPrintDlg = 0;
return TRUE;
case WM_PRINT_NEWPAGE:
DbgOutStr("\r\nprintsetDlgProc", 0, 0, 0, 0, 0);
hhPrint = (HHPRINT)GetWindowLongPtr(hwnd, DWLP_USER);
LoadString(glblQueryDllHinst(),
IDS_PRINT_NOW_PRINTING,
achBuf,
sizeof(achBuf) / sizeof(TCHAR));
wsprintf(achMessage, achBuf, hhPrint->nPage);
SetDlgItemText(hwnd, 101, achMessage);
return TRUE;
default:
break;
}
return FALSE;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printPageSetup
*
* DESCRIPTION:
* Invokes the common page-setup dialog
*
* ARGUMENTS:
* HPRINT hPrint - public print handle
* HWND hwnd - window handle used for parent
*
* RETURNS:
* 0=OK,else error
*
*/
int printPageSetup(const HPRINT hPrint, const HWND hwnd)
{
HHPRINT hhPrint = (HHPRINT)hPrint;
PAGESETUPDLG psd;
LPDEVNAMES pstDevNames;
PDEVMODE pstDevMode;
TCHAR *pszPrinterName;
TCHAR *pTemp;
DWORD dwSize;
RECT stMinMargins = {0,0,0,0};
if (hPrint == 0)
return -1;
memset(&psd, 0, sizeof(psd));
psd.lStructSize = sizeof(psd);
psd.hwndOwner = hwnd;
psd.hInstance = glblQueryDllHinst();
psd.Flags = PSD_ENABLEPAGESETUPTEMPLATE | PSD_ENABLEPAGESETUPHOOK |
PSD_MINMARGINS | PSD_MARGINS;
psd.rtMargin = hhPrint->margins;
psd.rtMinMargin = stMinMargins;
psd.lCustData = (LPARAM)hhPrint;
psd.lpPageSetupTemplateName = MAKEINTRESOURCE(IDD_CUSTOM_PAGE_SETUP);
psd.lpfnPageSetupHook = printPageSetupHook;
// Use the previously stored information to initialize the print
// common dialogs. printGetDefaults initializes this information
// when a print handle is created.
//
if (hhPrint->pstDevMode)
{
// Allocate memory for the DEVMODE information and then
// initialize it with the stored values from the Print Handle.
//
dwSize = hhPrint->pstDevMode->dmSize +
hhPrint->pstDevMode->dmDriverExtra;
if ((psd.hDevMode = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
{
if ((pstDevMode = GlobalLock(psd.hDevMode)))
{
if (dwSize)
MemCopy(pstDevMode, hhPrint->pstDevMode, dwSize);
GlobalUnlock(psd.hDevMode);
}
}
}
if (hhPrint->pstDevNames)
{
// Allocate memory for the DEVNAMES structure in pd, then
// initialize it with the stored values from the Print Handle.
// This sequence determines the variable structure size of
// DEVNAMES.
//
pTemp = (TCHAR *)hhPrint->pstDevNames;
pTemp += hhPrint->pstDevNames->wOutputOffset;
pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)hhPrint->pstDevNames);
if ((psd.hDevNames = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
{
if ((pstDevNames = GlobalLock(psd.hDevNames)))
{
if (dwSize)
MemCopy(pstDevNames, hhPrint->pstDevNames, dwSize);
GlobalUnlock(psd.hDevNames);
}
}
}
if (!PageSetupDlg(&psd))
{
#if defined(_DEBUG)
TCHAR ach[100];
DWORD dwError = CommDlgExtendedError();
if (dwError != 0)
{
wsprintf(ach, "PrintDlg error 0x%x", dwError);
MessageBox(hwnd, ach, "Debug", MB_ICONINFORMATION | MB_OK);
}
#endif
return -2;
}
// store the margin settings in the print handle.
//
hhPrint->margins = psd.rtMargin;
// Store the printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(psd.hDevNames);
pszPrinterName = (TCHAR *)pstDevNames;
pszPrinterName += pstDevNames->wDeviceOffset;
StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
GlobalUnlock(psd.hDevNames);
// Save the DEVMODE information in the Print Handle. This memory
// must be freed and allocated every time as the size of the
// DEVMODE structure changes.
//
pstDevMode = GlobalLock(psd.hDevMode);
dwSize = pstDevMode->dmSize + pstDevMode->dmDriverExtra;
if (hhPrint->pstDevMode)
{
free(hhPrint->pstDevMode);
hhPrint->pstDevMode = NULL;
}
hhPrint->pstDevMode = (LPDEVMODE)malloc(dwSize);
if (hhPrint->pstDevMode == 0)
{
assert(FALSE);
GlobalUnlock(psd.hDevMode);
goto Cleanup;
}
if (dwSize)
MemCopy(hhPrint->pstDevMode, pstDevMode, dwSize);
GlobalUnlock(psd.hDevMode);
// Save the DEVNAMES information in the Print Handle. Because the
// size of the information in this structure varies, it is freed and
// allocated each time it is saved.
//
pstDevNames = GlobalLock(psd.hDevNames);
// Determine the size of the structure.
//
pTemp = (TCHAR *)pstDevNames;
pTemp += pstDevNames->wOutputOffset;
pTemp += StrCharGetByteCount(pTemp) + sizeof(TCHAR);
dwSize = (DWORD)(pTemp - (TCHAR*)pstDevNames);
if (hhPrint->pstDevNames)
{
free(hhPrint->pstDevNames);
hhPrint->pstDevNames = NULL;
}
hhPrint->pstDevNames = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0)
{
assert(0);
GlobalUnlock(psd.hDevNames);
goto Cleanup;
}
if (dwSize)
MemCopy(hhPrint->pstDevNames, pstDevNames, dwSize);
GlobalUnlock(psd.hDevNames);
// Cleanup any memory that may have been allocated.
//
Cleanup:
if (psd.hDevNames)
GlobalFree(psd.hDevNames);
if (psd.hDevMode)
GlobalFree(psd.hDevMode);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printPageSetupHook
*
* DESCRIPTION:
* A hook function to process the font button on the page setup dialog
*
* ARGUMENTS:
* hdlg - handle to the dialog box window
* uiMsg - message identifier
* wParam - message parameter
* lParam - message parameter
*
* RETURNS:
* 0 = message not processed 1 = message processeed
*
* Author:
* Dwayne Newsome 02/19/97
*
*/
static UINT_PTR APIENTRY printPageSetupHook( HWND hdlg, UINT uiMsg, WPARAM wParam,
LPARAM lParam )
{
static HHPRINT hhPrint;
static PAGESETUPDLG * pPageSetup;
UINT processed = 0;
LPDEVNAMES pstDevNames;
TCHAR * pszPrinterName;
//
// on the init dialog message save a pointer to the pagesetup dialog and
// save the print handle
//
if ( uiMsg == WM_INITDIALOG )
{
pPageSetup = ( PAGESETUPDLG *) lParam;
hhPrint = (HHPRINT) pPageSetup->lCustData;
}
//
// Looking for the font button click here, if we get it set the currently
// selected printers name in the saved print handle and display the font
// dialog. We save the printer name so the font dialog can show the
// correct fonts for the currently selected printer.
//
else if ( uiMsg == WM_COMMAND )
{
if ( HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == 1027 )
{
processed = 1;
pstDevNames = GlobalLock(pPageSetup->hDevNames);
pszPrinterName = (TCHAR *)pstDevNames;
pszPrinterName += pstDevNames->wDeviceOffset;
StrCharCopyN(hhPrint->achPrinterName, pszPrinterName, PRINTER_NAME_LEN);
GlobalUnlock(pPageSetup->hDevNames);
DisplayFontDialog( hhPrint->hSession, TRUE );
}
}
return processed;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetPrintToFile
*
* DESCRIPTION:
*
*
* ARGUMENTS:
* HPRINT hPrint - public print handle
*
*
* RETURNS:
* 0=OK,else error
*
*/
static int printsetPrintToFile(const HPRINT hPrint)
{
const HHPRINT hhPrint = (HHPRINT)hPrint;
TCHAR acTitle[64],
acMask[128],
acDir[256],
acFile[256];
LPTSTR pszPrintFile;
HWND hWnd;
HINSTANCE hInst;
LPTSTR pszStr;
TCHAR_Fill(acTitle, TEXT('\0'), sizeof(acTitle) / sizeof(TCHAR));
TCHAR_Fill(acMask, TEXT('\0'), sizeof(acMask) / sizeof(TCHAR));
TCHAR_Fill(acDir, TEXT('\0'), sizeof(acDir) / sizeof(TCHAR));
TCHAR_Fill(acFile, TEXT('\0'), sizeof(acFile) / sizeof(TCHAR));
hWnd = glblQueryHwndFrame();
hInst = glblQueryDllHinst();
LoadString(hInst,
IDS_PRINT_TOFILE,
acTitle,
sizeof(acTitle) / sizeof(TCHAR));
LoadString(hInst,
IDS_PRINT_FILENAME,
acFile,
sizeof(acFile) / sizeof(TCHAR));
resLoadFileMask(hInst,
IDS_PRINT_FILTER_1,
2,
acMask,
sizeof(acMask) / sizeof(TCHAR));
// Figure out which directory to propose to the user for the 'print to'
// file. If we have a session file, use that session files directory,
// otherwise use the current directory.
//
if (sfGetSessionFileName(sessQuerySysFileHdl(hhPrint->hSession),
sizeof(acDir) / sizeof(TCHAR),
acDir) == SF_OK)
{
mscStripName(acDir);
}
else
{
//Changed to use working folder rather than current folder - mpt 8-18-99
if ( !GetWorkingDirectory( acDir, sizeof(acDir) / sizeof(TCHAR)) )
{
GetCurrentDirectory(sizeof(acDir) / sizeof(TCHAR), acDir);
}
}
pszStr = StrCharLast(acDir);
// Remove trailing backslash from the directory name if there is one.
//
if (pszStr && *pszStr == TEXT('\\'))
*pszStr = TEXT('\0');
pszPrintFile = gnrcSaveFileDialog(hWnd,
(LPCTSTR)acTitle,
(LPCTSTR)acDir,
(LPCTSTR)acMask ,
(LPCTSTR)acFile);
if (pszPrintFile == NULL)
{
return(1);
}
// pszPrintFile gets allocated in gnrcSaveFileDlg.
//
StrCharCopyN(hhPrint->achPrintToFileName, pszPrintFile, PRINTER_NAME_LEN);
free(pszPrintFile);
pszPrintFile = NULL;
return(0);
}