/*++

Copyright (c) 1996  Microsoft Corporation

Module Name:

    faxview.c

Abstract:

    This file implements a simple TIFF image viewer.

Environment:

        WIN32 User Mode

Author:

    Wesley Witt (wesw) 17-Feb-1996

--*/

#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>

#include "resource.h"
#include "tifflib.h"
#include "faxutil.h"


typedef struct _PRINT_INFO {
    HWND    hwnd;
    LPWSTR  FileName;
    HDC     hdc;
    DWORD   FromPage;
    DWORD   ToPage;
    DWORD   Copies;
} PRINT_INFO, *PPRINT_INFO;


static HANDLE hDevMode = NULL;
static HANDLE hDevNames = NULL;

extern HWND   hwndStatusbar;


BOOL
ReadTiffData(
    HANDLE  hTiff,
    LPBYTE  *TiffData,
    DWORD   Width,
    LPDWORD TiffDataLinesAlloc,
    DWORD   PageNumber
    );





BOOL
PrintSetup(
    HWND hwnd
    )
{
    PRINTDLG pdlg = {0};

    pdlg.lStructSize          = sizeof(PRINTDLG);
    pdlg.hwndOwner            = hwnd;
    pdlg.hDevMode             = hDevMode;
    pdlg.hDevNames            = hDevNames;
    pdlg.Flags                = PD_PRINTSETUP;

    if (PrintDlg( &pdlg )) {
        hDevMode = pdlg.hDevMode;
        hDevNames = pdlg.hDevNames;
        return TRUE;
    }

    return FALSE;
}


DWORD
PrintThread(
    PPRINT_INFO pi
    )
{
    LPBYTE      bmiBuf[sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*2)];
    PBITMAPINFO bmi = (PBITMAPINFO) bmiBuf;
    HANDLE      hTiff;
    TIFF_INFO   TiffInfo;
    LPBYTE      TiffData;
    DWORD       TiffDataSize;
    DWORD       i;
    INT         HorzRes;
    INT         VertRes;
    INT         PrintJobId  = 0;
    DOCINFO     DocInfo;
    DWORD       TiffDataLinesAlloc;
    DWORD       VertResFactor = 1;


    hTiff = TiffOpen(
        pi->FileName,
        &TiffInfo,
        TRUE
        );
    if (!hTiff) {
        return 0;
    }

    TiffDataSize = TiffInfo.ImageHeight * (TiffInfo.ImageWidth / 8);

    TiffData = (LPBYTE) VirtualAlloc(
        NULL,
        TiffDataSize,
        MEM_COMMIT,
        PAGE_READWRITE
        );
    if (!TiffData) {
        return 0;
    }

    TiffDataLinesAlloc = TiffInfo.ImageHeight;

    bmi->bmiHeader.biSize           = sizeof(BITMAPINFOHEADER);
    bmi->bmiHeader.biWidth          = TiffInfo.ImageWidth;
    bmi->bmiHeader.biHeight         = - (INT) TiffInfo.ImageHeight;
    bmi->bmiHeader.biPlanes         = 1;
    bmi->bmiHeader.biBitCount       = 1;
    bmi->bmiHeader.biCompression    = BI_RGB;
    bmi->bmiHeader.biSizeImage      = 0;
    bmi->bmiHeader.biXPelsPerMeter  = 7874;
    bmi->bmiHeader.biYPelsPerMeter  = 7874;
    bmi->bmiHeader.biClrUsed        = 0;
    bmi->bmiHeader.biClrImportant   = 0;

    if (TiffInfo.PhotometricInterpretation) {
        bmi->bmiColors[0].rgbBlue       = 0;
        bmi->bmiColors[0].rgbGreen      = 0;
        bmi->bmiColors[0].rgbRed        = 0;
        bmi->bmiColors[0].rgbReserved   = 0;
        bmi->bmiColors[1].rgbBlue       = 0xff;
        bmi->bmiColors[1].rgbGreen      = 0xff;
        bmi->bmiColors[1].rgbRed        = 0xff;
        bmi->bmiColors[1].rgbReserved   = 0;
    } else {
        bmi->bmiColors[0].rgbBlue       = 0xff;
        bmi->bmiColors[0].rgbGreen      = 0xff;
        bmi->bmiColors[0].rgbRed        = 0xff;
        bmi->bmiColors[0].rgbReserved   = 0;
        bmi->bmiColors[1].rgbBlue       = 0;
        bmi->bmiColors[1].rgbGreen      = 0;
        bmi->bmiColors[1].rgbRed        = 0;
        bmi->bmiColors[1].rgbReserved   = 0;
    }

    if (TiffInfo.YResolution <= 100) {
        bmi->bmiHeader.biYPelsPerMeter /= 2;
        VertResFactor = 2;
    }

    HorzRes = GetDeviceCaps( pi->hdc, HORZRES );
    VertRes = GetDeviceCaps( pi->hdc, VERTRES );

    DocInfo.cbSize = sizeof(DOCINFO);
    DocInfo.lpszOutput = NULL;
    DocInfo.lpszDatatype = NULL;
    DocInfo.fwType = 0;

    DocInfo.lpszDocName = wcsrchr( pi->FileName, L'\\' );
    if (DocInfo.lpszDocName) {
        DocInfo.lpszDocName += 1;
    } else {
        DocInfo.lpszDocName = pi->FileName;
    }

    while( pi->Copies ) {

        PrintJobId = StartDoc( pi->hdc, &DocInfo );
        if (PrintJobId <= 0) {
            DeleteDC( pi->hdc );
            return FALSE;
        }

        for (i=pi->FromPage-1; i<min(pi->ToPage,TiffInfo.PageCount); i++)
        {
            DWORD Lines;
            DWORD StripDataSize;
            DWORD ImageWidth = TiffInfo.ImageWidth;
            DWORD ImageHeight = TiffInfo.ImageHeight;
            DWORD LinesAllocated = MAXVERTBITS;
            INT   DestWidth;
            INT   DestHeight;
            FLOAT ScaleX;
            FLOAT ScaleY;
            FLOAT Scale;


            SendMessage(
                hwndStatusbar,
                SB_SETTEXT,
                1,
                (LPARAM) L"Printing"
                );

            ReadTiffData( hTiff, &TiffData, TiffInfo.ImageWidth, &TiffDataLinesAlloc, i+1 );

            TiffGetCurrentPageData(
                hTiff,
                &Lines,
                &StripDataSize,
                &ImageWidth,
                &ImageHeight
                );

            ScaleX = (FLOAT) ImageWidth / (FLOAT) HorzRes;
            ScaleY = ((FLOAT) ImageHeight * VertResFactor) / (FLOAT) VertRes;

            Scale = ScaleX > ScaleY ? ScaleX : ScaleY;

            DestWidth = (int) ((FLOAT) ImageWidth / Scale);
            DestHeight = (int) (((FLOAT) ImageHeight * VertResFactor) / Scale);

            bmi->bmiHeader.biWidth = ImageWidth;
            bmi->bmiHeader.biHeight = - (INT)ImageHeight;

            StartPage( pi->hdc );

            StretchDIBits(
                pi->hdc,
                0,
                0,
                DestWidth,
                DestHeight,
                0,
                0,
                ImageWidth,
                ImageHeight,
                TiffData,
                (BITMAPINFO *) bmi,
                DIB_RGB_COLORS,
                SRCCOPY
                );

            EndPage ( pi->hdc ) ;
        }

        pi->Copies -= 1;
        EndDoc( pi->hdc );
    }

    DeleteDC( pi->hdc );
    TiffClose( hTiff );
    VirtualFree( TiffData, 0, MEM_RELEASE );
    MemFree( pi->FileName );
    MemFree( pi );

    return 0;
}


HANDLE
PrintTiffFile(
    HWND hwnd,
    LPWSTR FileName,
    LPWSTR PrinterName
    )
{
    static DWORD Flags     = PD_ALLPAGES | PD_RETURNDC | PD_HIDEPRINTTOFILE | PD_NOSELECTION | PD_NOWARNING;
    static WORD  nFromPage = 0xFFFF;
    static WORD  nToPage   = 0xFFFF;
    static WORD  nCopies   = 1;

    DWORD ThreadId;
    HANDLE hThread;
    PPRINT_INFO pi;
    PRINTDLG pd = {0};
    WCHAR DefaultPrinter[1024];


    if (hwnd) {

        pd.lStructSize = sizeof(pd);
        pd.hwndOwner   = hwnd;
        pd.hDevMode    = hDevMode;
        pd.hDevNames   = hDevNames;
        pd.Flags       = Flags;
        pd.nFromPage   = nFromPage;
        pd.nToPage     = nToPage;
        pd.nMinPage    = 1;
        pd.nMaxPage    = 65535;
        pd.nCopies     = nCopies;

        if (!PrintDlg(&pd)) {
            return NULL;
        }

        hDevMode    = pd.hDevMode;
        hDevNames   = pd.hDevNames;
        Flags       = pd.Flags;
        nFromPage   = pd.nFromPage;
        nToPage     = pd.nToPage;

        pi = (PPRINT_INFO) MemAlloc( sizeof(PRINT_INFO) );
        if (!pi) {
            return NULL;
        }

        pi->hwnd      = hwnd;
        pi->hdc       = pd.hDC;
        pi->FromPage  = Flags & PD_PAGENUMS ? pd.nFromPage : 1;
        pi->ToPage    = pd.nToPage;
        pi->Copies    = pd.nCopies;
        pi->FileName  = StringDup( FileName );

    } else {

        if (!PrinterName) {
            //
            // get the default printer name
            //

            GetProfileString(
                L"windows",
                L"device",
                NULL,
                DefaultPrinter,
                sizeof(DefaultPrinter)
                );
            if (!DefaultPrinter[0]) {
                return NULL;
            }

            PrinterName = wcschr( DefaultPrinter, L',' );
            if (PrinterName) {
                *PrinterName = 0;
            }
            PrinterName = DefaultPrinter;
        }

        pi = (PPRINT_INFO) MemAlloc( sizeof(PRINT_INFO) );
        if (!pi) {
            return NULL;
        }

        pi->hdc = CreateDC( TEXT("WINSPOOL"), PrinterName, NULL, NULL );
        if (!pi->hdc) {
            return NULL;
        }

        pi->hwnd      = NULL;
        pi->FromPage  = 1;
        pi->ToPage    = 65535;
        pi->Copies    = 1;
        pi->FileName  = StringDup( FileName );

    }

    hThread = CreateThread(
        NULL,
        1024*100,
        (LPTHREAD_START_ROUTINE) PrintThread,
        (LPVOID) pi,
        0,
        &ThreadId
        );

    if (!hThread) {
        return NULL;
    }

    return hThread;
}