/*
 * print.c --
 *
 * Copyright (c) 1994 Software Research Associates, Inc. 
 * 
 */

#include <windows.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define WIDTHBYTES(i)        ((i+31)/32*4)

WORD DibNumColors (VOID *pv)
{
    int                 bits;
    LPBITMAPINFOHEADER  lpbi;
    LPBITMAPCOREHEADER  lpbc;

    lpbi = ((LPBITMAPINFOHEADER)pv);
    lpbc = ((LPBITMAPCOREHEADER)pv);

    if (lpbi->biSize != sizeof(BITMAPCOREHEADER)){
        if (lpbi->biClrUsed != 0)
            return (WORD)lpbi->biClrUsed;
        bits = lpbi->biBitCount;
    }
    else
        bits = lpbc->bcBitCount;

    switch (bits){
        case 1:                return 2;
        case 4:
                return 16;
        case 8:
                return 256;
        default:
                return 0;
    }
}

WORD PaletteSize (VOID *pv)
{
    LPBITMAPINFOHEADER lpbi;
    WORD               NumColors;

    lpbi      = (LPBITMAPINFOHEADER)pv;
    NumColors = DibNumColors(lpbi);

    if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
        return NumColors * sizeof(RGBTRIPLE);
    else
        return NumColors * sizeof(RGBQUAD);
}

HBITMAP
ColorToMono( HBITMAP hColorBitmap, HDC hdcMono )
{
	HPALETTE hpal;
	BITMAPINFOHEADER bmih;
    BITMAPINFOHEADER *bmihp, *bmihp_new;
	BITMAP colorBitmap;
	HBITMAP hMonoBitmap;
	HDC hdcColor;
	long dwLen;

	hpal = GetStockObject(DEFAULT_PALETTE);

	GetObject( hColorBitmap, sizeof(colorBitmap), (LPSTR) &colorBitmap );
	bmih.biSize = sizeof(BITMAPINFOHEADER);
	bmih.biWidth = (DWORD) colorBitmap.bmWidth;
	bmih.biHeight = (DWORD) colorBitmap.bmHeight;
	bmih.biPlanes = 1;
	bmih.biBitCount = 1;
	bmih.biCompression = 0;
	bmih.biSizeImage = 0;
	bmih.biXPelsPerMeter = 0;
	bmih.biYPelsPerMeter = 0;
	bmih.biClrUsed = 0;
	bmih.biClrImportant = 0;

	/*
	bmih
	bmih_new
	--->|<---------dwLen--------------->|
	    |<--a-->|<---b--->|<-----c----->|

		a: (BITMAPINFOHEADER)
		b: array of RGBQUAD
		c: bit image

		a == bmih.biSize == sizeof(BITMAPINFOHEADER)
		b == PalleteSize(&bmih)
		c == bmih.biSizeImage
	 */

	dwLen = bmih.biSize + PaletteSize(&bmih);
	hdcColor = GetDC(NULL);
	hpal = SelectPalette( hdcColor, hpal, FALSE );
	RealizePalette( hdcColor );
	bmihp = (BITMAPINFOHEADER *)malloc((size_t)(sizeof(char)*dwLen));
	if( !bmihp ) {
		SelectPalette( hdcColor, hpal, FALSE );
		ReleaseDC( NULL, hdcColor );
		return NULL;
	}
	*bmihp = bmih;
	GetDIBits( hdcColor, hColorBitmap, 0, (WORD)bmih.biHeight, NULL,
		(LPBITMAPINFO)bmihp, DIB_RGB_COLORS );
	bmih = *bmihp;
	if( !bmih.biSizeImage ) {
		bmih.biSizeImage = WIDTHBYTES(colorBitmap.bmWidth) * colorBitmap.bmHeight;
	}

	dwLen = bmih.biSize + PaletteSize(&bmih) + bmih.biSizeImage;
	bmihp_new = (BITMAPINFOHEADER *)realloc( bmihp, (size_t)(sizeof(char)*dwLen) );
	if( !bmihp_new ) {
		free(bmihp);
		SelectPalette( hdcColor, hpal, FALSE );
		ReleaseDC( NULL, hdcColor );
		return NULL;
	}

	if( !GetDIBits( hdcColor, hColorBitmap, 0, (WORD)bmih.biHeight,
		(LPSTR)bmihp_new + (WORD)bmihp_new->biSize + PaletteSize(bmihp_new),
		(LPBITMAPINFO)bmihp_new, DIB_RGB_COLORS ) ) {
		free(bmihp_new);
		SelectPalette( hdcColor, hpal, FALSE );
		ReleaseDC( NULL, hdcColor );
		return NULL;
	}

	hMonoBitmap = CreateDIBitmap(hdcMono, bmihp, CBM_INIT,
		(LPSTR)bmihp_new + (WORD)bmihp_new->biSize + PaletteSize(bmihp_new),
		(LPBITMAPINFO)bmihp_new, DIB_RGB_COLORS);
	free(bmihp_new);
	SelectPalette( hdcColor, hpal, FALSE );
	ReleaseDC( NULL, hdcColor );
	return hMonoBitmap;
}

void
PrintArea( docname, src, src_x, src_y, width, height, dst_x, dst_y )
char *docname;	
HBITMAP src;
int src_x, src_y;
unsigned int width, height;
int dst_x, dst_y;
{
    char pPrintInfo[255];
    LPSTR lpPrintDevice;
    LPSTR lpPrintDriver;
    LPSTR lpPrintPort;
    HDC hdcPrint, hdcMono;
    DOCINFO DocInfo;
    HBITMAP hBitmap, hOldBitmap;

    GetProfileString( "windows", "device", ",,,", (LPSTR)pPrintInfo, 258 );
    if( !(lpPrintDevice = strtok( pPrintInfo, "," )) ||
       !(lpPrintDriver = strtok( NULL, "," )) ||
       !(lpPrintPort = strtok( NULL, "," ))
       ) {
	MessageBox( NULL, "Illegal format in WIN.INI : Check \"device=\" in [windows]", "error", MB_OK );
	return;
    }
    hdcPrint = CreateDC(lpPrintDriver, lpPrintDevice, lpPrintPort, NULL);
    if (hdcPrint == NULL) {
	MessageBox( NULL, "Can't create printer DC", "error", MB_OK );
	return;
    }
    if( !(hdcMono = CreateCompatibleDC( hdcPrint ))	) {
	MessageBox( NULL, "Can't create temporary DC", "error", MB_OK );
	DeleteDC( hdcPrint );
	return;
    }
    if( !(hBitmap=ColorToMono(src, hdcMono)) ) {
	MessageBox( NULL, "Can't create monochrome bitmap", "error", MB_OK );
	DeleteDC( hdcMono );
	DeleteDC( hdcPrint );
	return;			
    }

    hOldBitmap = SelectObject( hdcMono, hBitmap );
    DocInfo.cbSize = sizeof(DOCINFO);
    DocInfo.lpszDocName = docname;
    DocInfo.lpszOutput = (LPSTR)NULL;
    StartDoc( hdcPrint, &DocInfo );
    StartPage( hdcPrint );
#if 0
    if ( !BitBlt
	( hdcPrint, dst_x + 100, dst_y + 100, width, height,
	 hdcMono, src_x, src_y, SRCCOPY )
	) {
	AbortDoc( hdcPrint );
	MessageBox( NULL, "BitBlt() failed: Print aborted", "error", MB_OK );
    }
#endif
    if( !StretchBlt
       ( hdcPrint, dst_x + 100, dst_y + 100, width * 3, height * 3,
	hdcMono, src_x, src_y, width, height, SRCCOPY )
       ) {
	AbortDoc( hdcPrint );
	MessageBox( NULL, "StretchBlt() failed: Print aborted", "error", MB_OK );
    }
    else {
	EndPage( hdcPrint );
	EndDoc( hdcPrint );
    }
    SelectObject( hdcMono, hOldBitmap );
    DeleteObject( hBitmap );

    DeleteDC( hdcMono );
    DeleteDC( hdcPrint );
}
