mirror of https://github.com/lianthony/NT4.0
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.
1084 lines
30 KiB
1084 lines
30 KiB
#include "precomp.h"
|
|
|
|
#define MAXPROFILELEN 60
|
|
|
|
// leading - non-zero looks a lot better
|
|
#define LEADING (max(ExtPrintLeading,yPrintChar/4))
|
|
|
|
// offset to start of body of card
|
|
#define BODYOFFSET (yPrintChar+LEADING+2*LINEWIDTH +10*LINEWIDTH)
|
|
|
|
// offset from left of card to print title or body of text
|
|
#define XTEXTOFFSET (xPrintChar/2)
|
|
|
|
// width of lines in pixels
|
|
#define LINEWIDTH 1
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Windows Cardfile - Written by Mark Cliggett */
|
|
/* (c) Copyright Microsoft Corp. 1985, 1994 - All Rights Reserved */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#if DBG
|
|
TCHAR dbuf[100];
|
|
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
|
|
|
|
NOEXPORT void NEAR PrintHeaderFooter (HDC hDC, SHORT i);
|
|
|
|
NOEXPORT void GetDateTime(TCHAR *szTime, TCHAR *szDate);
|
|
|
|
TCHAR DefaultNullStr[] = TEXT("");
|
|
|
|
HWND hAbortDlgWnd;
|
|
INT fAbort;
|
|
INT bError;
|
|
INT iTabSize;
|
|
|
|
INT xPrintChar; /* width of char on printer */
|
|
INT yPrintChar; /* height of char on printer */
|
|
INT xPrintCard; /* width of card on printer */
|
|
INT yPrintCard; /* height of card on printer */
|
|
INT yCardSpace; /* Space between card titles */
|
|
|
|
INT ExtPrintLeading;
|
|
INT xHeadFoot;
|
|
BOOL bCenter, bRight;
|
|
INT xPrintRes;
|
|
INT yPrintRes;
|
|
INT yPixelsPerInch; /* pixels/inch */
|
|
INT xPixelsPerInch; /* pixels/inch */
|
|
|
|
|
|
/* Flag if printer setup was done. */
|
|
BOOL bPrinterSetupDone=FALSE;
|
|
/*
|
|
* all of these are in device units (for printer) and are calculated
|
|
* by SetupPrinting()
|
|
*/
|
|
|
|
/* Had to use HEAD since HEADER already has another def. */
|
|
#define HEAD 0
|
|
#define FOOTER 1
|
|
|
|
int dyTop; /* width of top border */
|
|
int dyBottom; /* width of bottom border */
|
|
int dxLeft; /* width of left border */
|
|
int dxRight; /* width of right border (this doesn't get used) */
|
|
int dyHeadFoot; /* height from top/bottom of headers and footers */
|
|
|
|
int iPageNum; /* global page number currently being printed */
|
|
int xLeftSpace, xRightSpace; /* Space of margins */
|
|
INT xCharPage;
|
|
|
|
FARPROC lpfnAbortProc;
|
|
FARPROC lpfnAbortDlgProc;
|
|
FARPROC lpfnPageDlgProc;
|
|
|
|
/* We'll dynamically allocate this */
|
|
HANDLE hHeadFoot=NULL;
|
|
LPTSTR szHeadFoot;
|
|
|
|
void NEAR FreePrintHandles()
|
|
{
|
|
if(PD.hDevMode)
|
|
GlobalFree(PD.hDevMode);
|
|
if(PD.hDevNames)
|
|
GlobalFree(PD.hDevNames);
|
|
PD.hDevMode = PD.hDevNames = NULL;
|
|
bPrinterSetupDone = FALSE;
|
|
}
|
|
|
|
/* Get dafault printer data using the commdlg code for printer setup. */
|
|
BOOL NEAR GetDefaultPrinter()
|
|
{
|
|
FreePrintHandles();
|
|
|
|
PD.lStructSize = sizeof(PRINTDLG);
|
|
PD.Flags = PD_PRINTSETUP|PD_RETURNDEFAULT;
|
|
if (PrintDlg((LPPRINTDLG)&PD))
|
|
{
|
|
bPrinterSetupDone = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
FreePrintHandles();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Call the commdlg code for printer setup. */
|
|
void PrinterSetupDlg(HWND hwnd)
|
|
{
|
|
BOOL bTryAgain = (PD.hDevMode || PD.hDevNames);
|
|
DWORD dwErr;
|
|
|
|
LockData(0);
|
|
PD.Flags = PD_PRINTSETUP; /* invoke only the Setup dialog */
|
|
|
|
TryPrintSetupAgain:
|
|
bPrinterSetupDone |= PrintDlg(&PD);
|
|
|
|
/* set szPrinter and free hDevMode and hDevNames */
|
|
/* PrintDlg error. */
|
|
if(dwErr = CommDlgExtendedError()) /* Re-initialize the PD structure. */
|
|
{
|
|
PD.lStructSize = sizeof(PRINTDLG);
|
|
PD.hwndOwner = hwnd;
|
|
PD.hDC = NULL;
|
|
PD.nCopies = 1;
|
|
FreePrintHandles();
|
|
if (bTryAgain)
|
|
{
|
|
bTryAgain = FALSE;
|
|
goto TryPrintSetupAgain;
|
|
}
|
|
else if (dwErr != PDERR_NODEFAULTPRN)
|
|
{
|
|
TCHAR szError[256];
|
|
|
|
LoadString(hIndexInstance, E_PRINT_SETUP_ERROR, szError, CharSizeOf(szError));
|
|
MessageBox(hwnd, szError, szCardfile, MB_OK | MB_ICONHAND);
|
|
}
|
|
}
|
|
UnlockData(0);
|
|
}
|
|
|
|
/*
|
|
* convert floating point strings (like 2.75 1.5 2) into number of pixels
|
|
* given the number of pixels per inch
|
|
*/
|
|
INT atopix(
|
|
TCHAR *ptr,
|
|
INT pix_per_in)
|
|
{
|
|
TCHAR *dot_ptr;
|
|
TCHAR sz[20];
|
|
INT decimal;
|
|
|
|
lstrcpy(sz, ptr);
|
|
dot_ptr = _tcschr(sz, szDec[0]);
|
|
if (dot_ptr)
|
|
{
|
|
*dot_ptr++ = 0; /* terminate the inches */
|
|
if (*(dot_ptr + 1) == (TCHAR) 0)
|
|
{
|
|
*(dot_ptr + 1) = TEXT('0'); /* convert decimal part to hundredths */
|
|
*(dot_ptr + 2) = (TCHAR) 0;
|
|
}
|
|
decimal = ((int)MyAtol(dot_ptr) * pix_per_in) / 100; /* first part */
|
|
}
|
|
else
|
|
decimal = 0; /* there is not fraction part */
|
|
|
|
return ((INT)MyAtol(sz) * pix_per_in) + decimal; /* second part */
|
|
}
|
|
|
|
HDC GetPrinterDC(
|
|
void)
|
|
{
|
|
LPDEVMODE lpDevMode;
|
|
LPDEVNAMES lpDevNames;
|
|
|
|
if (!bPrinterSetupDone) /* Retrieve default printer if none selected. */
|
|
{
|
|
if (!GetDefaultPrinter())
|
|
return NULL;
|
|
}
|
|
|
|
lpDevNames = (LPDEVNAMES)GlobalLock(PD.hDevNames);
|
|
if (PD.hDevMode)
|
|
lpDevMode = (LPDEVMODE)GlobalLock(PD.hDevMode);
|
|
else
|
|
lpDevMode = NULL;
|
|
|
|
/* For pre 3.0 drivers lpDevMode will be null as these drivers don't
|
|
* use this structure.
|
|
*/
|
|
PD.hDC = CreateDC(((LPTSTR)lpDevNames)+lpDevNames->wDriverOffset,
|
|
((LPTSTR)lpDevNames)+lpDevNames->wDeviceOffset,
|
|
((LPTSTR)lpDevNames)+lpDevNames->wOutputOffset,
|
|
lpDevMode);
|
|
GlobalUnlock(PD.hDevNames);
|
|
if (PD.hDevMode)
|
|
GlobalUnlock(PD.hDevMode);
|
|
|
|
return PD.hDC;
|
|
}
|
|
|
|
HDC SetupPrintingFailed(
|
|
HDC hPrintDC)
|
|
{
|
|
if (hPrintDC)
|
|
DeleteDC(hPrintDC);
|
|
IndexOkError(ECANTPRINT);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* setup the printer, return it's DC and create printing (abort)
|
|
* dialog box.
|
|
*/
|
|
HDC SetupPrinting( BOOL bUseFont )
|
|
{
|
|
TCHAR buf[80];
|
|
DWORD nSpace;
|
|
HDC hPrintDC;
|
|
TEXTMETRIC Metrics;
|
|
DOCINFO DocInfo;
|
|
INT iErr;
|
|
HFONT hPrintFont; // font in print DC
|
|
HFONT hPrevFont; // previous font in print DC
|
|
|
|
/*
|
|
* On second print job, this was getting used
|
|
* before the dialog was created for the second time.
|
|
*/
|
|
hAbortDlgWnd = (HWND)NULL;
|
|
|
|
if (!(hPrintDC = GetPrinterDC()))
|
|
return SetupPrintingFailed(hPrintDC);
|
|
|
|
xPrintRes = GetDeviceCaps(hPrintDC, HORZRES);
|
|
yPrintRes = GetDeviceCaps(hPrintDC, VERTRES);
|
|
xPixelsPerInch = GetDeviceCaps(hPrintDC, LOGPIXELSX);
|
|
yPixelsPerInch = GetDeviceCaps(hPrintDC, LOGPIXELSY);
|
|
|
|
|
|
// if need be, use user defined font in printer
|
|
|
|
|
|
if( bUseFont )
|
|
{
|
|
LOGFONT lf; // temp version of FontStruct
|
|
|
|
lf= FontStruct;
|
|
lf.lfHeight= - (iPointSize * yPixelsPerInch ) / (72*10);
|
|
lf.lfWidth= 0; // let font mapper figure it out
|
|
lf.lfQuality= DEFAULT_QUALITY;
|
|
hPrintFont = CreateFontIndirect(&lf);
|
|
|
|
if( hPrintFont )
|
|
{
|
|
//PrintLogFont( lf );
|
|
hPrevFont= SelectObject( hPrintDC, hPrintFont );
|
|
DeleteObject( hPrevFont );
|
|
}
|
|
// if not successful, just use default font
|
|
}
|
|
|
|
GetTextMetrics(hPrintDC, &Metrics);
|
|
yPrintChar = Metrics.tmHeight + Metrics.tmExternalLeading;
|
|
ExtPrintLeading = Metrics.tmExternalLeading;
|
|
xPrintChar = Metrics.tmAveCharWidth; /* character width */
|
|
iTabSize = xPrintChar*8;
|
|
|
|
dyHeadFoot = yPixelsPerInch / 2; /* 1/2 an inch */
|
|
dyTop = atopix(chPageText[4], yPixelsPerInch);
|
|
dyBottom = atopix(chPageText[5], yPixelsPerInch);
|
|
dxLeft = atopix(chPageText[2], xPixelsPerInch);
|
|
dxRight = atopix(chPageText[3], xPixelsPerInch);
|
|
|
|
#if !defined(WIN32)
|
|
nSpace = GetTextExtent(hPrintDC, TEXT(" "), 1 )
|
|
#else
|
|
{
|
|
SIZE sz ;
|
|
|
|
GetTextExtentPoint(hPrintDC , TEXT(" "), 1, &sz);
|
|
|
|
nSpace = sz.cx;
|
|
}
|
|
#endif
|
|
xLeftSpace = dxLeft / nSpace;
|
|
xRightSpace = dxRight / nSpace;
|
|
|
|
/* Number of characters between margins */
|
|
xCharPage = (xPrintRes / xPrintChar) - xLeftSpace - xRightSpace;
|
|
|
|
/* Allocate memory for the header.footer string. Will allow any size
|
|
* of paper and still have enough for the string.
|
|
*/
|
|
hHeadFoot = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, ByteCountOf(xCharPage+2));
|
|
|
|
if (!hHeadFoot)
|
|
return SetupPrintingFailed (hPrintDC);
|
|
|
|
SetAbortProc (hPrintDC, fnAbortProc);
|
|
|
|
BuildCaption (buf, CharSizeOf(buf));
|
|
|
|
/* Gotta disable the window before doing the start doc so that the user
|
|
* can't quickly do multiple prints.
|
|
*/
|
|
EnableWindow (hIndexWnd, FALSE);
|
|
|
|
DocInfo.cbSize = sizeof (DOCINFO);
|
|
DocInfo.lpszDocName = buf;
|
|
DocInfo.lpszOutput = NULL;
|
|
DocInfo.lpszDatatype = NULL;
|
|
DocInfo.fwType = 0;
|
|
|
|
if ((iErr = StartDoc (hPrintDC, &DocInfo)) < 0)
|
|
{
|
|
DeleteDC (hPrintDC);
|
|
EnableWindow (hIndexWnd, TRUE);
|
|
if (iErr == SP_USERABORT)
|
|
SendMessage (hIndexWnd, WM_SETFOCUS, 0, 0);
|
|
else
|
|
IndexOkError (ECANTPRINT);
|
|
return NULL;
|
|
}
|
|
|
|
bError = FALSE;
|
|
fAbort = FALSE;
|
|
hAbortDlgWnd = CreateDialog(hIndexInstance, (LPTSTR) DTABORTDLG,
|
|
hIndexWnd, (DLGPROC)fnAbortDlgProc);
|
|
if (!hAbortDlgWnd)
|
|
{
|
|
EnableWindow(hIndexWnd, TRUE);
|
|
return SetupPrintingFailed(hPrintDC);
|
|
}
|
|
return hPrintDC;
|
|
}
|
|
|
|
void FinishPrinting (HDC hPrintDC)
|
|
{
|
|
if (!fAbort)
|
|
{
|
|
if (!bError)
|
|
EndDoc(hPrintDC);
|
|
EnableWindow (hIndexWnd, TRUE);
|
|
DestroyWindow (hAbortDlgWnd);
|
|
}
|
|
DeleteDC (hPrintDC);
|
|
if (hHeadFoot)
|
|
GlobalFree (hHeadFoot);
|
|
hHeadFoot = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* print out the translated header/footer string in proper position.
|
|
*
|
|
* uses global stuff like xPrintChar, dyHeadFoot...
|
|
*/
|
|
NOEXPORT void NEAR PrintHeaderFooter (HDC hDC,SHORT nHF)
|
|
{
|
|
TCHAR buf[80];
|
|
SHORT len;
|
|
|
|
lstrcpy (buf, chPageText[nHF]);
|
|
|
|
szHeadFoot = GlobalLock (hHeadFoot);
|
|
len = TranslateString (buf);
|
|
|
|
if (*szHeadFoot)
|
|
{
|
|
if (nHF == HEAD)
|
|
{
|
|
TabbedTextOut (hDC, dxLeft, dyHeadFoot - yPrintChar, szHeadFoot,
|
|
len, 1, &iTabSize, dxLeft);
|
|
}
|
|
else
|
|
{
|
|
TabbedTextOut (hDC, dxLeft, yPrintRes-yPrintChar-dyHeadFoot,
|
|
szHeadFoot, len, 1, &iTabSize, dxLeft);
|
|
}
|
|
}
|
|
GlobalUnlock (hHeadFoot);
|
|
}
|
|
|
|
void PrintList (void)
|
|
{
|
|
HDC hPrintDC;
|
|
INT curcard;
|
|
INT i, y, Start, End;
|
|
INT cCardsPerPage;
|
|
LPCARDHEADER Cards;
|
|
INT iError;
|
|
|
|
|
|
hPrintDC = SetupPrinting( TRUE );
|
|
if (!hPrintDC)
|
|
{
|
|
if (hHeadFoot)
|
|
{
|
|
GlobalFree (hHeadFoot);
|
|
hHeadFoot = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
cCardsPerPage = max (1, (yPrintRes - dyTop - dyBottom) / yPrintChar);
|
|
|
|
iPageNum = 1;
|
|
|
|
Cards = (LPCARDHEADER) GlobalLock (hCards);
|
|
|
|
y = dyTop - yPrintChar;
|
|
|
|
for (curcard = 0; curcard < cCards; )
|
|
{
|
|
iError = StartPage(hPrintDC);
|
|
if (iError < 0)
|
|
{
|
|
PrintError (iError);
|
|
break;
|
|
}
|
|
|
|
PrintHeaderFooter (hPrintDC, HEAD);
|
|
|
|
Start = curcard;
|
|
End = curcard + cCardsPerPage;
|
|
if (End > cCards)
|
|
End = cCards;
|
|
for (i = Start; i < End; ++i, curcard++)
|
|
{
|
|
TabbedTextOut (hPrintDC, dxLeft, y, Cards[i].line,
|
|
lstrlen(Cards[i].line), 1, &iTabSize, dxLeft);
|
|
y += yPrintChar;
|
|
}
|
|
|
|
PrintHeaderFooter (hPrintDC, FOOTER);
|
|
iPageNum++;
|
|
|
|
/* Reset y so printing starts at top again. */
|
|
y = dyTop - yPrintChar;
|
|
|
|
iError = EndPage(hPrintDC);
|
|
if (iError < 0)
|
|
{
|
|
PrintError (iError);
|
|
break;
|
|
}
|
|
if (fAbort)
|
|
break;
|
|
}
|
|
GlobalUnlock (hCards);
|
|
FinishPrinting (hPrintDC);
|
|
}
|
|
|
|
void PrintCards (INT count)
|
|
{
|
|
HDC hPrintDC;
|
|
INT curcard;
|
|
INT i;
|
|
INT y;
|
|
INT cCardsPerPage;
|
|
CARDHEADER CardHead;
|
|
LPCARDHEADER Cards;
|
|
CARD Card;
|
|
HDC hMemoryDC;
|
|
HWND hPrintWnd;
|
|
HANDLE hOldObject;
|
|
INT fPictureWarning;
|
|
INT iError;
|
|
TEXTMETRIC Metrics;
|
|
|
|
hPrintWnd = CreateWindow(TEXT("Edit"), NULL,
|
|
WS_CHILD | ES_MULTILINE,
|
|
0, 0, (LINELENGTH * CharFixWidth) + 1, CARDLINES * CharFixHeight,
|
|
hIndexWnd, NULL, hIndexInstance, NULL);
|
|
|
|
/* Set fixed pitched font to this edit control, so that the text does
|
|
* not get chopped off at the right when we print, because we use
|
|
* fixed pitched font;
|
|
* Fix for Bug #3760 --SANKAR-- 02-22-90
|
|
*/
|
|
if (hPrintWnd)
|
|
SendMessage(hPrintWnd, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0));
|
|
|
|
if (!hPrintWnd)
|
|
{
|
|
IndexOkError(EINSMEMORY);
|
|
if (hHeadFoot)
|
|
{
|
|
GlobalFree(hHeadFoot);
|
|
hHeadFoot=NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!(hPrintDC = SetupPrinting( TRUE )))
|
|
{
|
|
if (hHeadFoot)
|
|
{
|
|
GlobalFree(hHeadFoot);
|
|
hHeadFoot = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// length of text + offset on each end + line width
|
|
xPrintCard = (LINELENGTH * xPrintChar) + XTEXTOFFSET*2 + 2*LINEWIDTH;
|
|
|
|
// start of body + size of body
|
|
yPrintCard = BODYOFFSET + (CARDLINES * yPrintChar);
|
|
yCardSpace = yPixelsPerInch/4;
|
|
|
|
hOldObject = SelectObject(hPrintDC, GetStockObject(HOLLOW_BRUSH));
|
|
|
|
hMemoryDC = CreateCompatibleDC(hPrintDC);
|
|
fPictureWarning = FALSE;
|
|
|
|
if (count == 1)
|
|
{
|
|
iPageNum = 1;
|
|
if (!hMemoryDC && CurCard.lpObject)
|
|
IndexOkError (ENOPICTURES);
|
|
|
|
if ((iError = StartPage (hPrintDC)) < 0)
|
|
PrintError (iError);
|
|
|
|
PrintHeaderFooter (hPrintDC, HEAD);
|
|
PrintCurCard (hPrintDC, hMemoryDC, dxLeft, dyTop, &CurCardHead, &CurCard, hEditWnd);
|
|
PrintHeaderFooter (hPrintDC, FOOTER);
|
|
|
|
if ((iError = EndPage (hPrintDC)) < 0)
|
|
PrintError (iError);
|
|
}
|
|
else
|
|
{
|
|
iPageNum = 1;
|
|
|
|
// extra yCardSpace in case it spills to next page during card spacing
|
|
|
|
cCardsPerPage = max(1, (yPrintRes - dyTop - dyBottom + yCardSpace) / (yPrintCard + yCardSpace));
|
|
|
|
for (curcard = 0; curcard < count; )
|
|
{
|
|
if ((iError = StartPage (hPrintDC)) < 0)
|
|
PrintError (iError);
|
|
|
|
PrintHeaderFooter (hPrintDC, HEAD);
|
|
y = dyTop;
|
|
for (i = 0; i < cCardsPerPage && curcard < count; ++i)
|
|
{
|
|
if (curcard != iFirstCard)
|
|
{
|
|
Cards = (LPCARDHEADER) GlobalLock(hCards);
|
|
CardHead = Cards[curcard];
|
|
GlobalUnlock(hCards);
|
|
if (!ReadCurCardData(&CardHead, &Card, szText))
|
|
IndexOkError(ECANTPRINTPICT);
|
|
}
|
|
else
|
|
{
|
|
CardHead = CurCardHead;
|
|
Card = CurCard;
|
|
GetWindowText(hEditWnd, szText, CARDTEXTSIZE);
|
|
}
|
|
SetWindowText(hPrintWnd, szText);
|
|
if (!hMemoryDC && Card.lpObject && !fPictureWarning)
|
|
{
|
|
fPictureWarning++;
|
|
IndexOkError(ENOPICTURES);
|
|
}
|
|
PrintCurCard(hPrintDC, hMemoryDC, dxLeft, y, &CardHead, &Card, hPrintWnd);
|
|
|
|
if (curcard != iFirstCard && Card.lpObject)
|
|
PicDelete(&Card);
|
|
|
|
y += yPrintCard + yCardSpace;
|
|
curcard++;
|
|
}
|
|
|
|
PrintHeaderFooter(hPrintDC, FOOTER);
|
|
|
|
iPageNum++;
|
|
|
|
if ((iError = EndPage (hPrintDC)) < 0)
|
|
{
|
|
PrintError (iError);
|
|
break;
|
|
}
|
|
if (fAbort)
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
DestroyWindow (hPrintWnd);
|
|
SelectObject (hPrintDC, hOldObject);
|
|
FinishPrinting (hPrintDC);
|
|
if (hMemoryDC)
|
|
DeleteDC (hMemoryDC);
|
|
}
|
|
|
|
void PrintCurCard(
|
|
HDC hPrintDC,
|
|
HDC hMemoryDC,
|
|
INT xPos, // x offset of upper left
|
|
INT yPos, // y offset of upper left
|
|
PCARDHEADER pCardHead,
|
|
PCARD pCard,
|
|
HWND hWnd)
|
|
{
|
|
INT y;
|
|
HANDLE hOldObject;
|
|
INT level;
|
|
INT i;
|
|
INT cLines;
|
|
TCHAR buf[LINELENGTH];
|
|
INT cch;
|
|
|
|
// Draw the card outline
|
|
|
|
Rectangle(hPrintDC,
|
|
max( 0, xPos ),
|
|
max( 0, yPos ),
|
|
xPos + xPrintCard,
|
|
yPos + yPrintCard);
|
|
|
|
// draw a narrow (LINEWIDTH) box separating title from body of card
|
|
|
|
Rectangle(hPrintDC,
|
|
max( 0, xPos ),
|
|
yPos + yPrintChar + LEADING,
|
|
xPos + xPrintCard,
|
|
yPos + BODYOFFSET - LINEWIDTH );
|
|
|
|
// Draw the card title
|
|
|
|
SetBkMode(hPrintDC, TRANSPARENT);
|
|
TabbedTextOut(hPrintDC,
|
|
xPos + XTEXTOFFSET,
|
|
yPos + (LEADING/2), // center top to bottom
|
|
pCardHead->line,
|
|
lstrlen(pCardHead->line),
|
|
1,
|
|
&iTabSize,
|
|
xPos+XTEXTOFFSET);
|
|
|
|
// Print any object embedded in card! (wonder what AVI objects do?)
|
|
|
|
if (pCard->lpObject && hMemoryDC)
|
|
{
|
|
HBITMAP hBitmap;
|
|
BITMAP bm;
|
|
|
|
level = SaveDC(hPrintDC);
|
|
|
|
IntersectClipRect(hPrintDC,
|
|
xPos + 1,
|
|
yPos + BODYOFFSET,
|
|
xPos + xPrintCard-1,
|
|
yPos + yPrintCard-1);
|
|
|
|
/* Get a bitmap to print */
|
|
if (GetObjectType( pCard->lpObject) != OBJ_BITMAP)
|
|
{
|
|
hBitmap = MakeObjectCopy(pCard, hPrintDC );
|
|
}
|
|
else
|
|
{
|
|
hBitmap = (HANDLE)pCard->lpObject ;
|
|
}
|
|
|
|
GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bm);
|
|
hOldObject = SelectObject(hMemoryDC, hBitmap);
|
|
|
|
|
|
if (!StretchBlt(hPrintDC,
|
|
xPos + (pCard->rcObject.left * xPrintChar) / CharFixWidth,
|
|
yPos + BODYOFFSET + (pCard->rcObject.top * yPrintChar) / CharFixHeight,
|
|
(bm.bmWidth * xPrintChar) / CharFixWidth,
|
|
(bm.bmHeight * yPrintChar) / CharFixHeight,
|
|
hMemoryDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY))
|
|
{
|
|
IndexOkError(ECANTPRINTPICT);
|
|
}
|
|
|
|
SelectObject(hMemoryDC, hOldObject);
|
|
RestoreDC(hPrintDC, level);
|
|
|
|
if (GetObjectType( pCard->lpObject) != OBJ_BITMAP)
|
|
DeleteObject(hBitmap);
|
|
}
|
|
|
|
/* draw the text */
|
|
/* we should really be using DrawText and EM_GETHANDLE */
|
|
|
|
y = yPos + BODYOFFSET;
|
|
cLines = SendMessage(hWnd, EM_GETLINECOUNT, 0, 0L);
|
|
for (i = 0; i < cLines; ++i)
|
|
{
|
|
buf[0] = LINELENGTH;
|
|
buf[1] = 0;
|
|
cch = (INT)SendMessage(hWnd, EM_GETLINE, i, (LPARAM)buf);
|
|
TabbedTextOut(hPrintDC, xPos + 1, y, buf, cch,
|
|
1, (LPINT)&iTabSize, xPos + 1);
|
|
y += yPrintChar;
|
|
}
|
|
}
|
|
|
|
int fnAbortProc(
|
|
HDC hPrintDC, /* what is this useless parameter? */
|
|
int iReserved) /* and this one? Good question! */
|
|
{
|
|
MSG msg;
|
|
|
|
while (!fAbort && PeekMessage (&msg, NULL, 0, 0, TRUE))
|
|
if (!hAbortDlgWnd || !IsDialogMessage (hAbortDlgWnd, (LPMSG)&msg))
|
|
{
|
|
TranslateMessage ((LPMSG)&msg);
|
|
DispatchMessage ((LPMSG)&msg);
|
|
}
|
|
return(!fAbort);
|
|
|
|
hPrintDC;
|
|
iReserved;
|
|
}
|
|
|
|
HANDLE hSysMenu;
|
|
|
|
/*
|
|
* dialog procedure for the print dialog
|
|
*
|
|
* this allows the user to cancel printing
|
|
*/
|
|
int fnAbortDlgProc(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LPTSTR pchTmp;
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_COMMAND:
|
|
fAbort = TRUE;
|
|
EnableWindow(hIndexWnd, TRUE);
|
|
DestroyWindow(hwnd);
|
|
hAbortDlgWnd = NULL;
|
|
return(TRUE);
|
|
|
|
case WM_INITDIALOG:
|
|
hSysMenu = GetSystemMenu(hwnd, FALSE);
|
|
if (CurIFile[0])
|
|
pchTmp = FileFromPath(CurIFile);
|
|
else
|
|
pchTmp = szUntitled;
|
|
|
|
SetDlgItemText(hwnd, DTNAME, pchTmp);
|
|
SetFocus(hwnd);
|
|
return(TRUE);
|
|
|
|
case WM_INITMENU:
|
|
EnableMenuItem(hSysMenu, SC_CLOSE, MF_GRAYED);
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
|
|
wParam;
|
|
lParam;
|
|
}
|
|
|
|
void PrintError (int iError)
|
|
{
|
|
bError = TRUE;
|
|
if (iError & SP_NOTREPORTED)
|
|
{
|
|
switch(iError)
|
|
{
|
|
case -5:
|
|
IndexOkError(EMEMPRINT);
|
|
break;
|
|
case -4:
|
|
IndexOkError(EDISKPRINT);
|
|
break;
|
|
case -3:
|
|
case -2:
|
|
break;
|
|
default:
|
|
IndexOkError(ECANTPRINT);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
* short TranslateString(char *src)
|
|
*
|
|
* purpose:
|
|
* translate a header/footer strings
|
|
*
|
|
* supports the following:
|
|
*
|
|
* && insert a & char
|
|
* &f current file name or (untitiled)
|
|
* &d date in Day Month Year
|
|
* &t time
|
|
* &p page number
|
|
* &p+num set first page number to num
|
|
*
|
|
* params:
|
|
* IN/OUT src this is the string to translate, gets filled with
|
|
* translate string. limited by len chars
|
|
* IN len # chars src pts to
|
|
*
|
|
* used by:
|
|
* Header Footer stuff
|
|
*
|
|
* uses:
|
|
* lots of c lib stuff
|
|
*
|
|
* restrictions:
|
|
* this function uses the following global data
|
|
*
|
|
* iPageNum
|
|
* text from main window caption
|
|
* NOTE : Resides in _TEXT segment so that it can call C runtimes
|
|
* most of the print code is in _PRINT segment
|
|
*
|
|
***************************************************************************/
|
|
|
|
short TranslateString(
|
|
TCHAR *src)
|
|
{
|
|
extern int iPageNum;
|
|
extern INT xCharPage;
|
|
extern LPTSTR szHeadFoot;
|
|
|
|
TCHAR letters[15];
|
|
TCHAR chBuff[3][80], buf[80];
|
|
TCHAR *ptr, *dst=buf, *save_src=src;
|
|
int page;
|
|
short nAlign=1, foo, nx,
|
|
nIndex[3];
|
|
|
|
nIndex[0]=0;
|
|
nIndex[1]=0;
|
|
nIndex[2]=0;
|
|
|
|
LoadString(hIndexInstance, IDS_LETTERS, letters, CharSizeOf(letters));
|
|
|
|
while (*src) /* look at all of source */
|
|
{
|
|
while (*src && *src != TEXT('&'))
|
|
{
|
|
if( IsDBCSLeadByte(*src))
|
|
{
|
|
chBuff[nAlign][nIndex[nAlign]]=*src++;
|
|
nIndex[nAlign] += 1;
|
|
}
|
|
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) */
|
|
|
|
/* a bit of sleaze... get the caption from
|
|
* the main window. search for the '-' and
|
|
* look two chars beyond, there is the
|
|
* file name or (untitled) (cute huh?)
|
|
*/
|
|
|
|
GetWindowText(hIndexWnd, buf, 80);
|
|
ptr=_tcschr(buf, TEXT('-')) + 2;
|
|
|
|
/* Copy to the currently aligned string. */
|
|
lstrcpy((chBuff[nAlign]+nIndex[nAlign]), ptr);
|
|
|
|
/* Update insertion position. */
|
|
nIndex[nAlign] += lstrlen(ptr);
|
|
}
|
|
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)+(TCHAR)(*src)-48;
|
|
src++;
|
|
}
|
|
}
|
|
|
|
wsprintf(buf, TEXT("%d"), iPageNum+page);
|
|
lstrcpy((chBuff[nAlign]+nIndex[nAlign]), buf);
|
|
nIndex[nAlign] += lstrlen(buf);
|
|
src--;
|
|
}
|
|
else if (*src == letters[4] || *src == letters[5])
|
|
{ /* &t time */
|
|
|
|
GetDateTime(buf, NULL);
|
|
|
|
/* extract time */
|
|
_tcsncpy(chBuff[nAlign]+nIndex[nAlign], buf, lstrlen(buf));
|
|
nIndex[nAlign] += lstrlen(buf);
|
|
}
|
|
else if (*src == letters[6] || *src == letters[7])
|
|
{ /* &d date */
|
|
GetDateTime(NULL, buf);
|
|
/* extract day month day */
|
|
_tcsncpy(chBuff[nAlign]+nIndex[nAlign], buf, lstrlen(buf));
|
|
nIndex[nAlign] += lstrlen(buf);
|
|
}
|
|
else if (*src == TEXT('&'))
|
|
{ /* quote a single & */
|
|
chBuff[nAlign][nIndex[nAlign]]=TEXT('&');
|
|
nIndex[nAlign] += 1;
|
|
}
|
|
/* Set the alignment for whichever has last occured. */
|
|
else if (*src == letters[8] || *src == letters[9])
|
|
nAlign=1; /* &c center */
|
|
else if (*src == letters[10] || *src == letters[11])
|
|
nAlign=2; /* &r right */
|
|
else if (*src == letters[12] || *src == letters[13])
|
|
nAlign=0; /* &d date */
|
|
src++;
|
|
}
|
|
}
|
|
/* Make sure all strings are null-terminated. */
|
|
for (nAlign=0; nAlign<3; nAlign++)
|
|
chBuff[nAlign][nIndex[nAlign]]=0;
|
|
|
|
/* Initialize Header/Footer string */
|
|
for (nx=0; nx<xCharPage; nx++)
|
|
*(szHeadFoot+nx)=32;
|
|
|
|
/* Copy Left aligned text. */
|
|
for (nx=0; nx < nIndex[0]; nx++)
|
|
*(szHeadFoot+nx)=chBuff[0][nx];
|
|
|
|
/* Calculate where the centered text should go. */
|
|
foo=(xCharPage-nIndex[1])/2;
|
|
for (nx=0; nx<nIndex[1]; nx++)
|
|
*(szHeadFoot+foo+nx)=(TCHAR)chBuff[1][nx];
|
|
|
|
/* Calculate where the right aligned text should go. */
|
|
foo=xCharPage-nIndex[2];
|
|
for (nx=0; nx<nIndex[2]; nx++)
|
|
*(szHeadFoot+foo+nx)=(TCHAR)chBuff[2][nx];
|
|
|
|
|
|
return lstrlen(szHeadFoot);
|
|
}
|
|
|
|
TIME Time;
|
|
DATE Date;
|
|
|
|
/* ** Get current date and time from dos, and build string showing same.
|
|
String must be formatted according to country info obtained from
|
|
win.ini. */
|
|
static void GetDateTime(TCHAR *szTime, TCHAR *szDate)
|
|
{
|
|
register int i = 0, j = 0;
|
|
int isAM = TRUE;
|
|
BOOL bLead;
|
|
TCHAR cSep;
|
|
SYSTEMTIME st;
|
|
|
|
|
|
GetLocalTime (&st);
|
|
|
|
if (!szTime)
|
|
goto GetDate;
|
|
|
|
if (Time.iTime)
|
|
wsprintf (szTime, Time.iTLZero ? TEXT("%02d%c%02d") : TEXT("%d%c%02d"),
|
|
st.wHour, Time.szSep[0], st.wMinute);
|
|
else
|
|
{
|
|
if (st.wHour > 12)
|
|
{
|
|
st.wHour -= 12;
|
|
isAM = FALSE;
|
|
}
|
|
wsprintf (szTime, Time.iTLZero ? TEXT("%02d%c%02d%s") : TEXT("%d%c%02d%s"),
|
|
st.wHour, Time.szSep[0], st.wMinute, isAM ? Time.sz1159 : Time.sz2359);
|
|
}
|
|
|
|
GetDate:
|
|
if (!szDate)
|
|
return;
|
|
|
|
while (Date.szFormat[i] && (j < MAX_FORMAT - 1))
|
|
{
|
|
bLead = FALSE;
|
|
switch (cSep = Date.szFormat[i++])
|
|
{
|
|
case TEXT('d'):
|
|
if (Date.szFormat[i] == TEXT('d'))
|
|
{
|
|
bLead = TRUE;
|
|
i++;
|
|
}
|
|
if (bLead || (st.wDay / 10))
|
|
szDate[j++] = TEXT('0') + st.wDay / 10;
|
|
szDate[j++] = TEXT('0') + st.wDay % 10;
|
|
break;
|
|
|
|
case TEXT('M'):
|
|
if (Date.szFormat[i] == TEXT('M'))
|
|
{
|
|
bLead = TRUE;
|
|
i++;
|
|
}
|
|
if (bLead || (st.wMonth / 10))
|
|
szDate[j++] = TEXT('0') + st.wMonth / 10;
|
|
szDate[j++] = TEXT('0') + st.wMonth % 10;
|
|
break;
|
|
|
|
case TEXT('y'):
|
|
i++;
|
|
if (Date.szFormat[i] == TEXT('y'))
|
|
{
|
|
bLead = TRUE;
|
|
i+=2;
|
|
}
|
|
if (bLead)
|
|
{
|
|
szDate[j++] = (st.wYear < 2000 ? TEXT('1') : TEXT('2'));
|
|
szDate[j++] = (st.wYear < 2000 ? TEXT('9') : TEXT('0'));
|
|
}
|
|
szDate[j++] = TEXT('0') + (st.wYear % 100) / 10;
|
|
szDate[j++] = TEXT('0') + (st.wYear % 100) % 10;
|
|
break;
|
|
|
|
default:
|
|
/* copy the current character into the formatted string - it
|
|
* is a separator. BUT: don't copy a separator into the
|
|
* very first position (could happen if the year comes first,
|
|
* but we're not using the year)
|
|
*/
|
|
if (j)
|
|
szDate[j++] = cSep;
|
|
break;
|
|
}
|
|
}
|
|
while ((szDate[j-1] < TEXT('0')) || (szDate[j-1] > TEXT('9')))
|
|
j--;
|
|
szDate[j] = TEXT('\0');
|
|
}
|