⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text.c

📁 用delphi开发的有关打印的驱动实例; LIBRARY genprint EXPORTS EnumPrintProcessorDatatypesW OpenPrintProc
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1990-1999  Microsoft Corporation
All Rights Reserved

Abstract:

    Routines to facilitate printing of text jobs.

--*/

#include "local.h"

#define FLAG_CR_STATE         0x1
#define FLAG_TAB_STATE        0x2
#define FLAG_DBCS_SPLIT       0x8
#define FLAG_FF               0x10
#define FLAG_LF               0x20
#define FLAG_CR               0x40
#define FLAG_TRANSLATE_LF     0x80
#define FLAG_TRANSLATE_CR     0x100

const WCHAR gszNoTranslateCRLF[] = L"Winprint_TextNoTranslation";
const WCHAR gszNoTranslateCR[] = L"Winprint_TextNoCRTranslation";

/** Prototypes for functions in this file **/

PBYTE
GetTabbedLineFromBuffer(
    IN      PBYTE   pSrcBuffer,
    IN      PBYTE   pSrcBufferEnd,
    IN      PBYTE   pDestBuffer,
    IN      ULONG   CharsPerLine,
    IN      ULONG   TabExpansionSize,
    IN      ULONG   Encoding,
    IN OUT  PULONG  pLength,
    IN OUT  PULONG  pTabBase,
    IN OUT  PDWORD  pfdwFlags
    );


/*++
*******************************************************************
    P r i n t T e x t J o b

    Routine Description:
        Prints a text data job.

    Arguments:
        pData           => Data structure for this job
        pDocumentName   => Name of this document

    Return Value:
        TRUE  if successful
        FALSE if failed - GetLastError() will return reason.
*******************************************************************
--*/
BOOL
PrintTextJob(
    IN PPRINTPROCESSORDATA pData,
    IN LPWSTR pDocumentName)
{
    DOCINFO     DocInfo;
    LOGFONT     LogFont;
    CHARSETINFO CharSetInfo;
    HFONT       hOldFont, hFont;
    DWORD       Copies;
    BOOL        rc;
    DWORD       NoRead;
    DWORD       CurrentLine;
    DWORD       CurrentCol;
    HANDLE      hPrinter = NULL;
    BYTE        pReadBufferStart[READ_BUFFER_SIZE];
    PBYTE       pLineBuffer = NULL;
    PBYTE       pReadBuffer = NULL;
    PBYTE       pReadBufferEnd = NULL;
    ULONG       CharHeight, CharWidth, CharsPerLine, LinesPerPage;
    ULONG       PageWidth, PageHeight;
    ULONG       Length, TabBase;
    BOOL        ReadAll;
    TEXTMETRIC  tm;
    DWORD       fdwFlags;
    DWORD       Encoding;
    DWORD       SplitSize;
    BOOL        ReturnValue = FALSE;
    BOOL        bAbortDoc   = FALSE;

    DWORD       dwNeeded;
    DWORD       dwNoTranslate;
    DWORD       dwNoTranslateCR;

    DocInfo.lpszDocName = pData->pDocument;  /* Document name */
    DocInfo.lpszOutput  = NULL;              /* Output file */
    DocInfo.lpszDatatype = NULL;             /* Datatype */
    DocInfo.cbSize = sizeof(DOCINFO);        /* Size of the structure */



    //
    // Go figure out the size of the form on the printer.  We do this
    // by calling GetTextMetrics, which gives us the font size of the
    // printer font, then getting the form size and calculating the
    // number of characters that will fit. In other cases we treat it as ANSI text.
    // Currently the codepage context is fixed to the system default codepage.
    //

    Encoding = GetACP();

    //
    // Create FIXED PITCH font and select
    //

    hOldFont = 0;
    ZeroMemory(&CharSetInfo, sizeof(CHARSETINFO));
    if (TranslateCharsetInfo((PDWORD)Encoding, &CharSetInfo, TCI_SRCCODEPAGE))
    {
        ZeroMemory(&LogFont, sizeof(LOGFONT));

        LogFont.lfWeight = 400;
        LogFont.lfCharSet = (BYTE)CharSetInfo.ciCharset;
        LogFont.lfPitchAndFamily = FIXED_PITCH;

        hFont = CreateFontIndirect(&LogFont);
        hOldFont = SelectObject(pData->hDC, hFont);
    }

    if (!GetTextMetrics(pData->hDC, &tm)) {
        // Essential text processing computation failed
        goto Done;
    }

    CharHeight = tm.tmHeight + tm.tmExternalLeading;
    CharWidth  = tm.tmAveCharWidth;

    if (!CharWidth || !CharHeight) {
        // Essential text processing computation failed
        goto Done;
    }

    //
    // Calculate most fittable characters' number to one line.
    //

    PageWidth = GetDeviceCaps(pData->hDC, DESKTOPHORZRES);
    PageHeight = GetDeviceCaps(pData->hDC, DESKTOPVERTRES);

    CharsPerLine = PageWidth / CharWidth;
    LinesPerPage = PageHeight / CharHeight;

    if (!CharsPerLine || !LinesPerPage) {
        // Essential text processing computation failed
        goto Done;
    }

    /** Allocate a buffer for one line of text **/

    pLineBuffer = AllocSplMem(CharsPerLine + 5);

    if (!pLineBuffer) {
        return FALSE;
    }

    /** Let the printer know we are starting a new document **/

    if (!StartDoc(pData->hDC, (LPDOCINFO)&DocInfo)) {

        goto Done;
    }

    /** Print the data pData->Copies times **/

    Copies = pData->Copies;

    while (Copies--) {

        /**
            Loop, getting data and sending it to the printer.  This also
            takes care of pausing and cancelling print jobs by checking
            the processor's status flags while printing.  The way we do
            this is to read in some data from the printer.  We will then
            pull data, one tabbed line at a time from there and print
            it.  If the last bit of data in the buffer does not make up
            a whole line, we call GetTabbedLineFromBuffer() with a non-
            zero Length, which indicates that there are chars left
            from the previous read.
        **/

        TabBase = 0;
        Length = 0;
        fdwFlags = FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF;

        CurrentLine = 0;
        CurrentCol = 0;

        /**
            Open the printer.  If it fails, return.  This also sets up the
            pointer for the ReadPrinter calls.
        **/

        if (!OpenPrinter(pDocumentName, &hPrinter, NULL)) {

            hPrinter = NULL;
            bAbortDoc = TRUE;
            goto Done;
        }

        //
        // Call GetPrinterData to see if the queue wants no LF/CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCRLF,
                            NULL,
                            (PBYTE)&dwNoTranslate,
                            sizeof( dwNoTranslate ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslate ){
                fdwFlags &= ~( FLAG_TRANSLATE_CR | FLAG_TRANSLATE_LF );
            }
        }

        //
        // Call GetPrinterData to see if the queue wants no CR processing.
        //
        if( GetPrinterData( hPrinter,
                            (LPWSTR)gszNoTranslateCR,
                            NULL,
                            (PBYTE)&dwNoTranslateCR,
                            sizeof( dwNoTranslateCR ),
                            &dwNeeded ) == ERROR_SUCCESS ){

            if( dwNoTranslateCR ){
                fdwFlags &= ~FLAG_TRANSLATE_CR;                
            }
        }

        if (StartPage(pData->hDC) == SP_ERROR) {

            bAbortDoc = TRUE;
            goto Done;
        }

        /** ReadAll indicates if we are on the last line of the file **/

        ReadAll = FALSE;

        /**
            This next do loop continues until we have read all of the
            data for the print job.
        **/

        do {

            if (fdwFlags & FLAG_DBCS_SPLIT) {
                SplitSize = (DWORD)(pReadBufferEnd - pReadBuffer);
                memcpy(pReadBufferStart, pReadBuffer, SplitSize);
                fdwFlags &= ~FLAG_DBCS_SPLIT;
            }
            else {
                SplitSize = 0;
            }

            rc = ReadPrinter(hPrinter,
                             (pReadBufferStart + SplitSize),
                             (READ_BUFFER_SIZE - SplitSize),
                             &NoRead);

            if (!rc || !NoRead) {

                ReadAll = TRUE;

            } else {

                /** Pick up a pointer to the end of the data **/

                pReadBuffer    = pReadBufferStart;
                pReadBufferEnd = pReadBufferStart + SplitSize + NoRead;
            }

            /**
                This loop will process all the data that we have
                just read from the printer.
            **/

            do {

                if (!ReadAll) {

                    /**
                        Length on entry holds the length of any
                        residual chars from the last line that we couldn't
                        print out because we ran out of characters on
                        the ReadPrinter buffer.
                    **/

                    pReadBuffer = GetTabbedLineFromBuffer(
                                      pReadBuffer,
                                      pReadBufferEnd,
                                      pLineBuffer,
                                      CharsPerLine - CurrentCol,
                                      pData->TabSize,
                                      Encoding,
                                      &Length,
                                      &TabBase,
                                      &fdwFlags );

                    /**

                        If pReadBuffer == NULL, then we have
                        exhausted the read buffer and we need to ReadPrinter
                        again and save the last line chars.  Length holds
                        the number of characters on this partial line,
                        so the next time we call ReadPrinter we will
                        pickup where we left off.

                        The only time we'll get residual chars is if:

                        1. The last line ends w/o ff/lf/cr ("Hello\EOF")
                           In this case we should TextOutA the last line
                           and then quit.

                           (In this case, don't break here; go ahead and
                           print, then we'll break out below in the do..while.)


                        2. The ReadPrinter last byte is in the middle of a line.
                           Here we should read the next chunk and add the
                           new characters at the end of the chars we just read.

                           (In this case, we should break and leave Length
                           as it is so we will read again and append to the
                           buffer, beginning at Length.)
                    **/

                    if (!pReadBuffer || (fdwFlags & FLAG_DBCS_SPLIT))
                        break;
                }


                /** If the print processor is paused, wait for it to be resumed **/

                if (pData->fsStatus & PRINTPROCESSOR_PAUSED) {
                    WaitForSingleObject(pData->semPaused, INFINITE);
                }

                /** If the job has been aborted, clean up and leave **/

                if (pData->fsStatus & PRINTPROCESSOR_ABORTED) {

                    ReturnValue = TRUE;

                    bAbortDoc = TRUE;
                    goto Done;
                }

                /** Write the data to the printer **/

                /** Make sure Length is not zero  **/
                /** TextOut will fail if Length == 0 **/

                if (Length) {

                    /**
                        We may have a number of newlines pending, that
                        may push us to the next page (or even next-next
                        page).
                    **/

                    while (CurrentLine >= LinesPerPage) {

                        /**
                            We need a new page; always defer this to the
                            last second to prevent extra pages from coming out.
                        **/

                        if (EndPage(pData->hDC) == SP_ERROR ||
                            StartPage(pData->hDC) == SP_ERROR) {

                            bAbortDoc = TRUE;
                            goto Done;
                        }

                        CurrentLine -= LinesPerPage;
                    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -