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.
 
 
 
 
 
 

1049 lines
23 KiB

/* File: D:\WACKER\tdll\printset.c (Created: 02-Feb-1994)
*
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 1.39 $
* $Date: 1995/10/09 16:48:33 $
*/
#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 "tchar.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);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION:
* printsetPageSetup
*
* 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 printsetPageSetup(const HPRINT hPrint, const HWND hwnd)
{
PAGESETUPDLG psd;
if (hPrint == 0)
{
assert(0);
return -1;
}
memset(&psd, 0, sizeof(psd));
psd.lStructSize = sizeof(psd);
psd.hwndOwner = hwnd;
PageSetupDlg(&psd);
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* 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;
PRINTDLG pd;
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.
//
memset (&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.Flags = PD_NOPAGENUMS | PD_NOWARNING;
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)))
{
memcpy(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)))
{
memcpy(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.
//
if (!PrintDlg(&pd))
{
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;
if (!PrintDlg(&pd))
{
#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;
}
}
// 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 font structure currently in use by the Terminal so
// that we can select it into the print DC.
SendMessage(sessQueryHwndTerminal(hhPrint->hSession), WM_TERM_GETLOGFONT,
0, (LPARAM)&(hhPrint->lf));
// Store the printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(pd.hDevNames);
pszPrinterName = (TCHAR *)pstDevNames;
pszPrinterName += pstDevNames->wDeviceOffset;
StrCharCopy(hhPrint->achPrinterName, pszPrinterName);
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;
}
memcpy(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 = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0)
{
assert(0);
GlobalUnlock(pd.hDevNames);
goto Cleanup;
}
memcpy(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;
}
}
// 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 iStatus,
nRet;
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);
assert(FALSE);
return;
}
if (dwCnt == 0)
{
if (pV)
free(pV);
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);
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);
dwCnt = (ULONG)StrCharGetByteCount(pV);
}
// Create the DC.
//
hhPrint->hDC = printCtrlCreateDC(hPrint);
if (hhPrint->hDC == 0)
{
if (pV)
free(pV);
assert(FALSE);
return;
}
// 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);
hhPrint->nLinesPerPage = GetDeviceCaps(hhPrint->hDC, VERTRES) /
(hhPrint->tm.tmHeight +
hhPrint->tm.tmExternalLeading);
GetWindowText(sessQueryHwnd(hhPrint->hSession),
hhPrint->achDoc,
sizeof(hhPrint->achDoc));
// Create the Print Abort Dialog.
//
hhPrint->lpfnPrintDlgProc = printsetDlgProc;
hhPrint->hwndPrintDlg = CreateDialogParam(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);
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.
//
TextOut(hhPrint->hDC,
0,
hhPrint->nLinesPrinted * hhPrint->tm.tmHeight,
pLS,
(pLE - pLS) + 1);
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);
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);
DbgShowLastError();
DbgOutStr("\r\nEndDoc: %d", iStatus, 0, 0, 0, 0);
printTellError(hhPrint->hSession, hPrint, iStatus);
// Final cleanup before exit.
//
if (!hhPrint->fUserAbort)
{
dwTime1 = (DWORD)GetWindowLong(hhPrint->hwndPrintDlg, GWL_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);
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;
SetWindowLong(hwnd, DWL_USER, 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),
acPtrs);
SetDlgItemText(hwnd, 103, achMessage);
dwTime = GetTickCount();
SetWindowLong(hwnd, GWL_USERDATA, (LONG)dwTime);
return TRUE;
case WM_COMMAND:
DbgOutStr("\r\nprintsetDlgProc - CANCEL", 0, 0, 0, 0, 0);
hhPrint = (HHPRINT)GetWindowLong(hwnd, DWL_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)GetWindowLong(hwnd, DWL_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)
{
const HHPRINT hhPrint = (HHPRINT)hPrint;
PAGESETUPDLG psd;
LPDEVNAMES pstDevNames;
PDEVMODE pstDevMode;
TCHAR *pszPrinterName;
TCHAR *pTemp;
DWORD dwSize;
#if defined(_DEBUG)
TCHAR ach[100];
#endif
if (hPrint == 0)
return -1;
memset(&psd, 0, sizeof(psd));
psd.lStructSize = sizeof(psd);
psd.hwndOwner = hwnd;
psd.Flags = PSD_DISABLEMARGINS;
// 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)))
{
memcpy(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)))
{
memcpy(pstDevNames, hhPrint->pstDevNames, dwSize);
GlobalUnlock(psd.hDevNames);
}
}
}
if (!PageSetupDlg(&psd))
{
#if defined(_DEBUG)
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 printer name and location in the Print Handle
// every time.
//
pstDevNames = GlobalLock(psd.hDevNames);
pszPrinterName = (TCHAR *)pstDevNames;
pszPrinterName += pstDevNames->wDeviceOffset;
StrCharCopy(hhPrint->achPrinterName, pszPrinterName);
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 = (LPDEVMODE)malloc(dwSize);
if (hhPrint->pstDevMode == 0)
{
assert(FALSE);
GlobalUnlock(psd.hDevMode);
goto Cleanup;
}
memcpy(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 = (LPDEVNAMES)malloc(dwSize);
if (hhPrint->pstDevNames == 0)
{
assert(0);
GlobalUnlock(psd.hDevNames);
goto Cleanup;
}
memcpy(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:
* 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
{
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.
//
StrCharCopy(hhPrint->achPrintToFileName, pszPrintFile);
free(pszPrintFile);
return(0);
}