/********************************************************************************************
    Clean OS Windows library module version 1.2.1.
    This module is part of the Clean Object I/O library and Clean 0.8 I/O library
    for the Windows platform.
********************************************************************************************/

/********************************************************************************************
    About this module:
    Routines related to printing.
********************************************************************************************/

#include "util_121.h"
#include "cpicture_121.h"

#include "cprinter_121.h"

BOOL	bUserAbort;
int		semaphor=0;

#if 0
HWND	hDlgPrint;
HWND	hwndButton,hwndText;

extern HWND   ghMainWindow;
extern HINSTANCE ghInst;
#else
#define CALLBACK
#define APIENTRY
typedef void* HANDLE;
typedef void* HWND;
typedef void* DEVMODE;
typedef void* PRINTDLG;
typedef void** LPHANDLE;
typedef char* LPCTSTR;
#endif


#define tachtig 80
void getDevmodeSizeC(int *size, HANDLE *phPrinter,
                     char **device, char **driver,  char **output)
{
#if 0
    char	szPrinter[80];
    char	*szDevice, *szDriver, *szOutput;

    GetProfileString("windows", "device", ",,,", szPrinter, 80);
    szDevice = strtok(szPrinter,",");
    szDriver = strtok(NULL,", ");
    szOutput = strtok(NULL,", ");
    *device	= g_strdup(szDevice);
    *driver	= g_strdup(szDriver);
    *output	= g_strdup(szOutput);
    if (*szDevice=='\0' || *szDriver=='\0' || *szOutput=='\0')
    {
        *size	= 0;
        return;
    };
    OpenPrinter(szDevice,phPrinter,NULL);
    *size = DocumentProperties(NULL,*phPrinter,szDevice,NULL,NULL,0);
#endif
}

void getDefaultDevmodeC(char *printSetup, LPHANDLE phPrinter,  char **device)
{
#if 0
    int		size,r1;

    size		= ((int*)printSetup)[0];
    printSetup	+=4;
    r1 = DocumentProperties(NULL,phPrinter,((char*)device)+4,
                            (DEVMODE*)printSetup,NULL,DM_OUT_BUFFER);
    ClosePrinter(phPrinter);
#endif
}

#if 0
static HDC myCreateIC(LPCTSTR driver, LPCTSTR device, DEVMODE *devmode)
{
    HDC	icPrint;

    icPrint	= CreateIC(driver,device,NULL,devmode);
    if (!icPrint)
        icPrint	= CreateIC(driver,device,NULL,devmode);
        /* try once again. Adobe printer drivers sometimes need to be told everything twice */
    return icPrint;
}
#endif

#define GetDeviceCapsWithDefault(icPrint, index, defaullt) (icPrint ? GetDeviceCaps(icPrint, index) : defaullt)

void os_getpagedimensionsC(	DEVMODE *devmode, char *device, char *driver,
                            int emulateScreenRes,
                            int *maxX, int *maxY,
                            int *leftPaper, int *topPaper,
                            int *rightPaper, int *bottomPaper,
                            int	*xRes, int *yRes
                          )
{
#if 0
    HDC	icPrint;
    int horPaperPixels, verPaperPixels,
        xResolution,yResolution,
        scNX, scNY, scDX, scDY;


    icPrint	= myCreateIC(driver,device, devmode);

    xResolution = GetDeviceCapsWithDefault(icPrint, LOGPIXELSX, 300);
    yResolution = GetDeviceCapsWithDefault(icPrint, LOGPIXELSY, 300);
    if (emulateScreenRes)						/* for emulation of the screen resolution */
        {
            scNX = WinGetHorzResolution();		/* all the deviceCaps will be scaled */
            scNY = WinGetVertResolution();
            scDX = xResolution;
            scDY = yResolution;
        }
      else
        {	scNX = 1; scNY = 1; scDX = 1; scDY = 1;	};

    horPaperPixels	= (GetDeviceCapsWithDefault(icPrint, PHYSICALWIDTH, 2246)*scNX)/scDX;
    verPaperPixels	= (GetDeviceCapsWithDefault(icPrint, PHYSICALHEIGHT, 3250)*scNY)/scDY;

    *maxX			= (GetDeviceCapsWithDefault(icPrint, HORZRES, 2241)*scNX)/scDX;
    *maxY			= (GetDeviceCapsWithDefault(icPrint, VERTRES, 3254)*scNY)/scDY;

    *leftPaper		= (-GetDeviceCapsWithDefault(icPrint, PHYSICALOFFSETX, 116)*scNX)/scDX;
    *topPaper		= (-GetDeviceCapsWithDefault(icPrint, PHYSICALOFFSETY, 129)*scNY)/scDY;
    *rightPaper		= horPaperPixels - *leftPaper;
    *bottomPaper	= verPaperPixels - *topPaper;

    if (emulateScreenRes)
        {	*xRes = scNX;	*yRes = scNY; }
      else
        {	*xRes = xResolution ;	*yRes = yResolution; };
    DeleteDC(icPrint);
#endif
}

static HANDLE setupDevnames(int deviceLength,int driverLength,int outputLength,
                            char *device,char *driver,char *output)
{
    HANDLE		hDevnames;
#if 0
    DEVNAMES	*pDevnames;
    hDevnames	= (HANDLE) LocalAlloc(LMEM_MOVEABLE, 16+deviceLength+driverLength+outputLength);
    pDevnames	= LocalLock(hDevnames);
    pDevnames->wDriverOffset	= 16;
    pDevnames->wDeviceOffset	= 16+driverLength;
    pDevnames->wOutputOffset	= 16+driverLength+deviceLength;
    pDevnames->wDefault			= 0;
    strcpy(((char*)pDevnames)+pDevnames->wDriverOffset, driver);
    strcpy(((char*)pDevnames)+pDevnames->wDeviceOffset, device);
    strcpy(((char*)pDevnames)+pDevnames->wOutputOffset, output);
    LocalUnlock(hDevnames);
#endif
    return hDevnames;
}

static HANDLE setupDevmode(int size, char *pData)
{
    HANDLE	hDevmode;
#if 0
    DEVMODE	*pDevmode;

    hDevmode	= (HANDLE) LocalAlloc(LMEM_MOVEABLE, size);
    pDevmode	= LocalLock(hDevmode);
    memcpy((char*)pDevmode, pData, size);
    LocalUnlock(hDevmode);
#endif
    return hDevmode;
}

void get_printSetup_with_PRINTDLG(PRINTDLG *pd, char **o_devmode,
                        char **o_device, char **o_driver, char **o_output)
{
#if 0
    char		*newDriver, *newDevice, *newOutput;
    DEVMODE		*pDevmode;
    DEVNAMES	*pDevnames;

    pDevmode	= LocalLock(pd->hDevMode);
    *o_devmode	= g_strdup(pDevmode->dmDeviceName);
    LocalUnlock(pd->hDevMode);
    pDevnames	= LocalLock(pd->hDevNames);
    newDriver	= ((char*)pDevnames)+(pDevnames->wDriverOffset);
    newDevice	= ((char*)pDevnames)+(pDevnames->wDeviceOffset);
    newOutput	= ((char*)pDevnames)+(pDevnames->wOutputOffset);
    *o_driver	= g_strdup(newDriver);
    *o_device	= g_strdup(newDevice);
    *o_output	= g_strdup(newOutput);
    LocalUnlock(pd->hDevNames);
#endif
}

/*	PA: called in Clean. */
int release_memory_handles(PRINTDLG *pd, int os) {
#if 0
    LocalFree(pd->hDevNames);
    LocalFree(pd->hDevMode);
#endif
    return os;
    }

/*
 * This function hooks the Print dialog. It's purpose is to set the dialog in
 * the foreground.
 */
static UINT APIENTRY DialogToFrontHook(HWND hdl, UINT msg, WPARAM wParam, LPARAM lParam)
{
#if 0
     if (msg==WM_INITDIALOG)
        { SetForegroundWindow(hdl);
        };
#endif
     return FALSE;
}

void printSetup(int calledFromCleanThread, int devmodeSize,
               char *devmode, char *device, char *driver, char *output,
               int *ok, PRINTDLG **pdPtr)
{
#if 0
    int			deviceLength, driverLength, outputLength;
    HANDLE		hDevnames,hDevmode;
    static PRINTDLG	pd;

    /* Set up DEVNAMES structure */

    /*rMessageBox(NULL, MB_APPLMODAL, "in printSetup", ""); */
    deviceLength	= strlen(device)+1;
    driverLength	= strlen(driver)+1;
    outputLength	= strlen(output)+1;

    hDevnames	= setupDevnames(deviceLength,driverLength,outputLength,device,driver,output);

    /* Set up DEVMODE structure */
    hDevmode	= setupDevmode(devmodeSize,devmode);

    /* Set up print dialog record */
    pd.lStructSize = sizeof(PRINTDLG);
    pd.hwndOwner = calledFromCleanThread ? NULL : ghMainWindow;	/* (NULL = desktop) */
/*	pd.hwndOwner = NULL;	// (NULL = desktop) */
        /*
         * The handle must belong to the active thread, otherwise PrintDlg
         * will crash.  When this function is called from the Clean thread,
         * ghMainWindow will not belong to the active thread.
         */
    pd.hDevMode = hDevmode;
    pd.hDevNames = hDevnames;
    pd.hDC = NULL;
    pd.Flags =	PD_PRINTSETUP | PD_ENABLESETUPHOOK;
    pd.nFromPage = 1;
    pd.nToPage = 1;
    pd.nMinPage = 1;
    pd.nMaxPage = USHRT_MAX;
    pd.nCopies = 1;
    pd.hInstance = NULL;
    pd.lCustData = 0L;
    pd.lpfnPrintHook = NULL;
    pd.lpfnSetupHook =  DialogToFrontHook;
    pd.lpPrintTemplateName = NULL;
    pd.lpSetupTemplateName = NULL;
    pd.hPrintTemplate = NULL;
    pd.hSetupTemplate = NULL;

    /* Open print dialog */
    *ok	= PrintDlg(&pd);
    *pdPtr = &pd;

    if (hDevnames!=pd.hDevNames) LocalFree(hDevnames);
    if (hDevmode!=pd.hDevMode) LocalFree(hDevmode);
#endif
}


int startPage(int hdc)
{
#if 0
    /*rMessageBox(NULL, MB_APPLMODAL, "in startPage", ""); */
    return StartPage((HDC) hdc) > 0;
#else
    return 0;
#endif
}

int endPage(int hdc)
{
#if 0
    /*rMessageBox(NULL, MB_APPLMODAL, "in endPage", ""); */
    return EndPage((HDC) hdc) > 0;
#else
    return 0;
#endif
}

int startDoc(int hdc)
            /* err code: >0:no error, <=0: user cancelled file dialog */
{
#if 0
    static DOCINFO docInfo = { sizeof (DOCINFO), "Clean", NULL, NULL, 0 } ;

    /*rMessageBox(NULL, MB_APPLMODAL, "in startDoc", "");*/
    bUserAbort = FALSE ;

    return StartDoc((HDC) hdc, &docInfo);
#else
    return 0;
#endif
}

void endDoc(int hdc)
{
#if 0
    /*rMessageBox(NULL, MB_APPLMODAL, "in endDoc", ""); */
    if (bUserAbort)
        AbortDoc((HDC) hdc);
      else
        EndDoc((HDC) hdc);
#endif
}

void deleteDC(int hdc)
{
#if 0
    /*rMessageBox(NULL, MB_APPLMODAL, "in deleteDC", ""); */
    DeleteDC((HDC) hdc);
#endif
}

int wasCanceled(void)
{
#if 0
    /*rMessageBox(NULL, MB_APPLMODAL, "in wasCanceled", ""); */
    return bUserAbort;
#else
    return 0;
#endif
}

/* getDC opens the print job dialog and
 * lets the user change various settings or gets the default printer
 */

/* c-strings are passed to this function ! */
void getDC( int doDialog, int emulateScreen, int calledFromCleanThread, int devmodeLength,
            char *devmode,char *device,char *driver,char *output,
            int *err,
            int *first, int *last, int *copies,
            PRINTDLG	**ppPrintDlg,
            int *deviceContext
            )
                    /* err code: -1:no error, others: non fatal error */
{
#if 0
    static PRINTDLG pd;
    HDC hdcPrint;
    int ok;

    *err = -1;

    if (doDialog)
      {	/* Set up print dialog record */
        HANDLE	hDevnames, hDevmode;
        int deviceLength,driverLength,outputLength;

        deviceLength	= strlen(device)+1;
        driverLength	= strlen(driver)+1;
        outputLength	= strlen(output)+1;

        hDevnames	= setupDevnames(deviceLength,driverLength,outputLength,
                                    device,driver,output);
        hDevmode	= setupDevmode(devmodeLength,devmode);

        pd.lStructSize = sizeof(PRINTDLG);
        pd.hwndOwner = calledFromCleanThread ? NULL : ghMainWindow;	/* (NULL = desktop) */
            /*
             * The handle must belong to the active thread, otherwise PrintDlg
             * will crash.  When this function is called from the Clean thread,
             * ghMainWindow will not belong to the active thread.
             */
        pd.hDevMode = hDevmode;
        pd.hDevNames = hDevnames;
        pd.hDC = NULL;
        pd.Flags = PD_ALLPAGES | PD_COLLATE | PD_RETURNDC | PD_NOSELECTION
                 | PD_ENABLEPRINTHOOK;
              /* hide some options from print dialog */
        pd.nFromPage = 1;
        pd.nToPage = 1;
        pd.nMinPage = 1;
        pd.nMaxPage = USHRT_MAX;
        pd.nCopies = 1;
        pd.hInstance = NULL;
        pd.lCustData = 0L;
        pd.lpfnPrintHook = DialogToFrontHook;
        pd.lpfnSetupHook = NULL;
        pd.lpPrintTemplateName = NULL;
        pd.lpSetupTemplateName = NULL;
        pd.hPrintTemplate = NULL;
        pd.hSetupTemplate = NULL;

        /* Open print dialog */

        ok = PrintDlg(&pd);

        if (hDevnames!=pd.hDevNames) LocalFree(hDevnames);
        if (hDevmode!=pd.hDevMode) LocalFree(hDevmode);

        if (!ok)
            {
            *err = CommDlgExtendedError();	/* will return 0 iff user canceled, otherwise positive value */
            release_memory_handles(&pd, 0);
            return;
            }


        if (pd.Flags & PD_PAGENUMS)
            { *first	= pd.nFromPage;
              *last		= pd.nToPage;
            }
          else
            { *first	= 1;
              *last		= 9999;
            };
        *copies			= pd.nCopies;
        *ppPrintDlg		= &pd;
        hdcPrint		= pd.hDC;
      }

    else

        {
        hdcPrint = CreateDC(driver, device, output, NULL);
        if (hdcPrint==NULL)
          { *err = 0;	/* non fatal error, iff e.g. no printer driver is installed */
            return;
          };
        *first	= 1;
        *last	= 9999;
        *copies	= 1;
        *ppPrintDlg		= NULL;
        };

    if (emulateScreen)
        {	int pXdpi,pYdpi,sXdpi,sYdpi;
            pXdpi = GetDeviceCaps(hdcPrint, LOGPIXELSX);
            pYdpi = GetDeviceCaps(hdcPrint, LOGPIXELSY);
            sXdpi = WinGetHorzResolution();
            sYdpi = WinGetVertResolution();
            SetMapMode(hdcPrint, MM_ISOTROPIC);
            SetWindowExtEx  (hdcPrint,sXdpi, sYdpi, NULL);
            SetViewportExtEx(hdcPrint,pXdpi, pYdpi, NULL);
        };

    *deviceContext	= (int) hdcPrint;
    /*rMessageBox(NULL, MB_APPLMODAL, "leaving getDC","");*/
#endif
}


#if 0
BOOL CALLBACK PrintDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
     {
     switch (msg)
          {
          case WM_INITDIALOG :
               EnableMenuItem (GetSystemMenu (hDlg, FALSE), SC_CLOSE,
                                                            MF_GRAYED) ;
               return TRUE ;
          case WM_COMMAND :
               bUserAbort = TRUE ;
               EnableWindow (ghMainWindow, TRUE) ;
               DestroyWindow (hDlg) ;
               hDlgPrint = 0 ;
               return TRUE ;
          }
     return FALSE;
     }

BOOL CALLBACK AbortProc (HDC hdcPrn, int iCode)
     {
     MSG   msg ;

     while (!bUserAbort && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
          {
          if (!hDlgPrint || !IsDialogMessage (hDlgPrint, &msg))
               {
               TranslateMessage (&msg) ;
               DispatchMessage (&msg) ;
               }
          }
     return !bUserAbort ;
     }
#endif


#define DIALOG_WIDTH 100
#define DIALOG_HEIGHT 60
    /* in dialog units */

#if 0
HWND CreateCancelDialog(void)
{
    HWND hwndButton,dlgHdl;

    WORD *p, *pdlgtemplate,baseunitX,baseunitY;
    int nchar;
    int scrnWidth,scrnHeight;
    int buttonX, buttonY, buttonWidth, buttonHeight;
    int textX, textY, textWidth, textHeight;
    DWORD lStyle,baseunits;
    HDC screen;
    LOGFONT lf;

    /* allocate some memory to play with  */
    pdlgtemplate = p = (PWORD) rmalloc (1000);

    screen = CreateDC ("DISPLAY", NULL, NULL, NULL);
    scrnWidth  = GetDeviceCaps (screen, HORZRES);
    scrnHeight = GetDeviceCaps (screen, VERTRES);
    DeleteDC (screen);
    baseunits = GetDialogBaseUnits();

    /* start to fill in the dlgtemplate information.  addressing by WORDs */
    lStyle = WS_CAPTION | DS_MODALFRAME | WS_SYSMENU;

    baseunitX=LOWORD(baseunits);
    baseunitY=HIWORD(baseunits);

    *p++ = LOWORD (lStyle);
    *p++ = HIWORD (lStyle);
    *p++ = 0;		/* LOWORD (lExtendedStyle) */
    *p++ = 0;		/* HIWORD (lExtendedStyle) */
    *p++ = 0;		/* NumberOfItems */
    *p++ = ((scrnWidth*4)/3)/baseunitX;		/* x */
    *p++ = ((scrnHeight*8)/3)/baseunitY;	/* y */
    *p++ = DIALOG_WIDTH;	/* cx */
    *p++ = DIALOG_HEIGHT;	/* cy */
    *p++ = 0;		/* Menu */
    *p++ = 0;		/* Class */

    /* copy the title of the dialog */
    nchar = NULL; /*nCopyAnsiToWideChar (p, (char *) "Printing in Progress");*/
    p += nchar;

    dlgHdl = CreateDialogIndirectParam (ghInst, (LPDLGTEMPLATE) pdlgtemplate, ghMainWindow,
                                        (DLGPROC) PrintDlgProc, (LPARAM) 0);

    rfree(pdlgtemplate);

    /* Add a text field */
    textWidth = 19*baseunitX;
    textHeight = baseunitY;
    textX =    (((DIALOG_WIDTH*baseunitX)/4) - textWidth)
               / 2;
    textY =    (((DIALOG_HEIGHT*baseunitY)/8) - textHeight)
               / 4;
    hwndText = CreateWindow ("static", "",WS_VISIBLE | WS_CHILD | SS_CENTER,
                                    textX, textY, textWidth, textHeight,
                                    dlgHdl, (HMENU) 0, ghInst, 0);


    /* Add a Cancel button: */
    buttonWidth = 10*baseunitX;
    buttonHeight = (3*baseunitY)/2;
    buttonX =    (((DIALOG_WIDTH*baseunitX)/4) - buttonWidth)
               / 2;
    buttonY =  (3 *  (((DIALOG_HEIGHT*baseunitY)/8) - buttonHeight))
               / 5;
    hwndButton = CreateWindow ("button", "Cancel", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
                                    buttonX, buttonY, buttonWidth, buttonHeight,
                                    dlgHdl, (HMENU) 0, ghInst, 0);
/*	WinSetFont (&lf,"MS Sans Serif",0,8); */
    SendMessage(hwndButton,WM_SETFONT,(WPARAM)CreateFontIndirect (&lf),MAKELPARAM (TRUE,0));
    SendMessage(hwndText,WM_SETFONT,(WPARAM)CreateFontIndirect (&lf),MAKELPARAM (TRUE,0));

    ShowWindow (dlgHdl,SW_SHOWNORMAL);
    return dlgHdl;
}
#endif

/*	PA: Called in Clean. */
int addSemaphor(int add)
{
    int old=semaphor;
    semaphor+=add;
    return old;
}

int os_printsetupvalidC(DEVMODE *devmode, char *device, char *driver)
{
#if 0
    HDC	icPrint;

    icPrint	= myCreateIC(driver,device,devmode);
    if (icPrint)
        DeleteDC(icPrint);
    return icPrint!=NULL;
#else
    return 0;
#endif
}